这个是用canvas做的, 因为我喜欢那个跟抽奖似的那种效果, 所以每个菜单转的方向都是一样的
不懂得可以在下边评论, 我会回复的
html:
<div class="menu">
<!-- canvas就是一块画布, 宽度默认是300, 高度是150, 改变不能用CSS -->
<canvas></canvas>
<div class="outer">
<!-- 外面的圆圈 -->
</div>
<div class="inner">
<!-- 里面的圆圈 -->
</div>
</div>
js
var isToggle = false; // 标识当前是否处于菜单切换状态
var curDeg = 0; // 标识menu当前旋转的度数
var menuText = ['神王盖伦', '神王诺手', '黑夜使者亚索', '光明使者瑞文', '青年瑞兹', '吕布', '赵云', '源计划·薇恩']
var menuMapRegion = [0,1,2,3,4,5]; // 将菜单和区域绑定
// 画菜单
var canvas = document.querySelector('canvas')
// 动态设置canvas的大小
canvas.setAttribute('width', canvas.parentNode.offsetWidth);
canvas.setAttribute('height', canvas.parentNode.offsetHeight);
// 算出外圈和内圈的半径
var outerRadius = canvas.width / 2;
var innerRadius = outerRadius / 2;
function drawMenu() {
console.log(outerRadius, innerRadius)
// 获取canvas画布画布的上下文对象
var ctx = canvas.getContext('2d')
// 平移ctx坐标系, 方便后序的划线操作
ctx.translate(outerRadius, outerRadius);
ctx.save(); // 存档, 方便下次获取
// 画线
// 进入for循环前, 先让ctx坐标系先旋转30度
ctx.rotate(Math.PI / 6);
for (var i = 0; i < 6; i++) {
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(outerRadius, 0);
ctx.strokeStyle = '#0094ff';
ctx.stroke(); // 对beginPathhe closePath中间的所有操作进行描边
ctx.closePath();
ctx.rotate(Math.PI / 3); // 不断旋转ctx坐标系方便画线
}
// 画字
ctx.restore(); // 重置坐标系, 调用存档
// ctx.rotate(-Math.PI/8)
var y = innerRadius + (outerRadius - innerRadius) / 2;
ctx.font = 'normal 16px april';
ctx.fillStyle = '#0094ff'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.rotate(Math.PI / 6);
for (var i = 0; i < 6; i++) {
ctx.fillText(menuText[i], 0, y);
ctx.rotate(-Math.PI / 3);
}
ctx.restore()
}
drawMenu();
document.querySelector('.outer').onclick = function(e) {
if(isToggle) return; // 如果当前正在发生切换状态, 点击无效
// 找出用户点击的是哪个区域
var regionIndex = getRegionIndex(e.offsetX, e.offsetY);
if(regionIndex === 0) return;
isToggle = true; // 标识进入了菜单切换状态
toggleMenu(regionIndex);
// 找出用户点击的 哪个菜单
console.log('你激活了下标为:' + menuMapRegion[regionIndex] + '的菜单');
// 调用
updataMenuMapRegion(regionIndex)
}
function getRegionIndex(x, y) {
x = x - outerRadius;
y = y - outerRadius;
if(Math.abs(y)/Math.abs(x) < Math.tan(Math.PI/6)) {
return x >0 ? 0 :3;
} else {
if(x > 0) return y > 0 ? 5 :1;
else return y > 0 ? 4 : 2;
}
}
function toggleMenu(regionIndex) {
let deg = 0;
switch(regionIndex) {
case 1: deg = curDeg + 60 ;break;
case 2: deg = curDeg + 60 * 2 ;break;
case 3: deg = curDeg + 60 * 3;break;
case 4: deg = curDeg + 60 * 4;break;
case 5: deg = curDeg + 60 * 5;break;
}
curDeg = deg;
canvas.style.transform = `rotate(${ deg }deg)`;
setTimeout(function() {
isToggle = false;
}, 620);
}
function updataMenuMapRegion(regionIndex) {
var temp = menuMapRegion.slice(0, regionIndex);
menuMapRegion.splice(0, regionIndex);
menuMapRegion = menuMapRegion.concat(temp)
}
CSS
* { margin:0; padding:0; }
.menu { width: 600px; height: 600px; position: relative;margin:100px auto; }
.menu>canvas { transition: all .6s ease-out; }
.menu>.outer, .menu>.inner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
box-sizing: border-box;
}
.menu>.outer {
width: 100%; height: 100%;
border: 1px solid #0094ff;
cursor: pointer;
}
.menu>.inner {
background-color: #0094FF;
width: 50%; height: 50%;
}