手势解锁,移动端支持TouchEvent

清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>

$width: 40px;
$border: 2px;

body {
    -webkit-user-select: none;
    user-select: none;
    cursor: crosshair;
}

    body > div {
        width: $width * 3 + $width / 2 * 6 + $border * 6;
        margin: 0 auto;
    }

        body > div.error-text {
            color: red;
            font-family: 黑体;
            font-size: 18px;
            opacity: 0;
            text-align: center;
        }

    body.error > div.error-text {
        opacity: 1;
        transition: opacity .5s .2s;
    }

div.row > div {
    margin: $width / 2;
    float: left;
    width: $width;
    height: $width;
    text-align: center;
    line-height: $width;
    border-radius: 50%;
    border: $border solid lightgray;
    position: relative;
}

    div.row > div > div.line {
        height: 0;
        width: $width;
        border: ($border / 2) solid transparent;
        position: absolute;
        transform-origin: -($width/2 + $border) ($border/2);
        top: $width / 2 - $border / 2;
        left: $width + $border;
        pointer-events: none;
    }

        div.row > div > div.line.active {
            border-color: black;
        }

        div.row > div > div.line.r_ {
            transform: rotate(0);
        }

        div.row > div > div.line.Rd {
            width: sqrt(power($width * 2 + $border * 2, 2) + power($width * 4 + $border * 4, 2)) - ($width + $border * 2);
            transform: rotate(#{rad-to-deg(atan2(1, 2)) * 1deg} );
        }
        
        div.row > div > div.line.rd {
            width: sqrt(power($width * 2 + $border * 2, 2) * 2) - ($width + $border * 2);
            transform: rotate(45deg);
        }

        div.row > div > div.line.rD {
            width: sqrt(power($width * 2 + $border * 2, 2) + power($width * 4 + $border * 4, 2)) - ($width + $border * 2);
            transform: rotate(#{rad-to-deg(atan2(2, 1)) * 1deg} );
        }

        div.row > div > div.line._d {
            transform: rotate(90deg);
        }

        div.row > div > div.line.Ru {
            width: sqrt(power($width * 2 + $border * 2, 2) + power($width * 4 + $border * 4, 2)) - ($width + $border * 2);
            transform: rotate(#{rad-to-deg(atan2(1, 2)) * -1deg} );
        }

        div.row > div > div.line.ru {
            width: sqrt(power($width * 2 + $border * 2, 2) * 2) - ($width + $border * 2);
            transform: rotate(-45deg);
        }

        div.row > div > div.line.rU {
            width: sqrt(power($width * 2 + $border * 2, 2) + power($width * 4 + $border * 4, 2)) - ($width + $border * 2);
            transform: rotate(#{rad-to-deg(atan2(2, 1)) * -1deg} );
        }

    div.row > div.selected {
        border-color: black;
    }

    div.row > div:hover:not(.selected) {
        border-color: gray;
    }

    div.row > div.selected::before {
        display: block;
        width: $width / 2.5;
        height: $width / 2.5;
        background: black;
        border-radius: 50%;
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        margin: auto;
    }

div.row::after {
    visibility: hidden;
    content: "";
    display: table;
    clear: both;
}

div.row div.arrow {
    transform-origin: $width/10 ($width/2 - $width/10);
    position: absolute;
    top: $width / 10;
    left: $width / 2 - $width / 10;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 $width/10 $width/10 $width/10;
    border-color: transparent transparent black transparent;
    pointer-events: none;
}

body.error div.row div.arrow {
    border-color: transparent transparent red transparent;
}

body.error div.row > div.selected, body.error div.row > div > div.line.active {
    border-color: red;
}

    body.error div.row > div.selected::before {
        background: red;
    }

@keyframes anime_error {
    from {
        transform: translateX(-8px);
    }

    50% {
        transform: translateX(8px);
    }

    to {
        transform: translateX(-8px);
    }
}

body.error div.row {
    animation: anime_error 0.1s ease-in-out 2 alternate;
}

body.ok div.row div.arrow {
    border-color: transparent transparent green transparent;
}

body.ok div.row > div.selected, body.ok div.row > div > div.line.active {
    border-color: green;
}

    body.ok div.row > div.selected::before {
        background: green;
    }