console
document.body.addEventListener('contextmenu', e => e.preventDefault() & e.stopPropagation());
document.body.addEventListener('mousedown', onMouseDown);
document.body.addEventListener('touchstart', e => onMouseDown(e.touches[0]));
document.body.addEventListener('mouseup', onMouseUp);
document.body.addEventListener('touchend', e => onMouseUp(e.touches[0]));
document.body.addEventListener('mousemove', onMouseMove);
document.body.addEventListener('touchmove', e => onMouseMove(e.touches[0]));
let showing, anchorX, anchorY, min = 100;
const wheel = document.querySelector('.wheel');
function onMouseDown({ clientX: x, clientY: y }) {
showing = true;
anchorX = x;
anchorY = y;
wheel.style.setProperty('--x', `${x}px`);
wheel.style.setProperty('--y', `${y}px`);
wheel.classList.add('on');
}
function onMouseUp() {
showing = false;
wheel.setAttribute('data-chosen', 0);
wheel.classList.remove('on');
}
function onMouseMove({ clientX: x, clientY: y }) {
if (!showing) return;
let dx = x - anchorX;
let dy = y - anchorY;
let mag = Math.sqrt(dx * dx + dy * dy);
let index = 0;
if (mag >= min) {
let deg = Math.atan2(dy, dx) + 0.625 * Math.PI;
while (deg < 0) deg += Math.PI * 2;
index = Math.floor(deg / Math.PI * 4) + 1;
}
wheel.setAttribute('data-chosen', index);
}
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://kit.fontawesome.com/b1ca6c3895.js"></script>
</head>
<body>
<h1>点击并拖拽鼠标</h1>
<div class="wheel">
<div class="arc"><i class="fas fa-home"></i></div>
<div class="arc"><i class="fas fa-question"></i></div>
<div class="arc"><i class="fas fa-bell"></i></div>
<div class="arc"><i class="fas fa-camera"></i></div>
<div class="arc"><i class="fas fa-trash-alt"></i></div>
<div class="arc"><i class="fas fa-save"></i></div>
<div class="arc"><i class="fas fa-flag"></i></div>
<div class="arc"><i class="fas fa-search"></i></div>
</div>
</body>
</html>
* {
box-sizing: border-box;
}
html {
user-select: none;
overflow: hidden;
body {
background-color: #222;
width: 100vw;
height: 100vh;
overflow: hidden;
position: relative;
padding: 0;
margin: 0;
}
}
h1 {
position: absolute;
top: 30%;
color: rgba(255, 255, 255, 0.3);
padding: 0 1rem;
text-align: center;
width: 100%;
}
.wheel {
--x: 0px;
--y: 0px;
position: absolute;
top: var(--y);
left: var(--x);
width: 500px;
height: 500px;
transform: translate(-50%, -50%);
transform-origin: 0% 0%;
&.on {
.arc {
opacity: 0.8;
transform: scale(1) rotate(var(--rotation)) !important;
transition-timing-function: cubic-bezier(0, 0.5, 0.5, 1.5);
}
}
.arc {
position: absolute;
top: 0;
right: 0;
width: 50%;
height: 50%;
transform-origin: 0% 100%;
background-image: radial-gradient(circle at 0% 100%, transparent, transparent 29.5%, var(--color-border) 30%, var(--color-border) 30.5%, var(--color) 31%, var(--color) 50%, var(--color-border) 50.25%, var(--color-border) 51.5%, transparent 51.75%, transparent);
transition-property: transform, opacity;
transition-duration: 0.3s;
transition-timing-function: cubic-bezier(0.4, -0.4, 0.7, -0.3);
-webkit-clip-path: polygon(0 0, 0 99%, 99% 0);
clip-path: polygon(0 0, 0 99%, 99% 0);
opacity: 0;
transform: scale(0) rotate(var(--rotation));
i {
position: absolute;
top: 40%;
left: 15%;
font-size: 2rem;
transform: rotate(calc(var(--rotation) * -1));
color: rgba(255, 255, 255, 0.8);
transition: color 0.3s;
}
}
@for $i from 1 through 8 {
&[data-chosen='#{$i}'] {
.arc {
&:nth-child(#{$i}) {
opacity: 1;
transform: scale(1.1) rotate(var(--rotation)) !important;
filter: brightness(150%);
i {
color: rgba(0, 0, 0, 0.5);
}
}
}
}
.arc {
&:nth-child(#{$i}) {
--rotation: #{-22.5 + ($i - 1) * 45}deg;
--color: hsl(calc(#{($i - 1) * 45} * 1deg), 36%, 60%);
--color-border: hsl(calc(#{($i - 1) * 45} * 1deg), 36%, 40%);
transition-delay: #{($i % 2) * 0.015}s;
}
}
}
}