参考资料:https://juejin.cn/post/7266641059282927650
效果:
源码:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>使用css3绘制任意角度扇形</title><style>.sector {position: relative;display: inline-block;width: 80px;height: 80px;background-color: transparent;border-radius: 50%;overflow: hidden;transform: rotate(45deg);}.sector::before {display: inline-block;content: '';width: 100%;height: 100%;background: linear-gradient(90deg,#4D84FF 25%,#eee 0,#eee 50%,#4D84FF 0,#4D84FF 75%,#eee 0);background-size: 30px;clip-path: polygon(50% 50%, 0 0, 100% 0);opacity: .7;}.sector::after {position: absolute;display: inline-block;content: '';width: 80px;height: 80px;top: calc(50% - 40px);left: calc(50% - 40px);border-radius: 50%;background-color: #fff;z-index: 1;}</style> </head> <body><div class="sector"></div> </body><script>/*** @param {Number} radius: 半径* @param {Number} minRadius: 内半径* @param {Number} angles: 角度* @param {Number} direct: 方向**/function drawPie({radius, minRadius, angles, direct, selector}) {let points = ['50% 50%', '0 0'],residue = angles%45? angles%45:45,percent = 0direct = direct || 45;angles > 90 && points.push('100% 0');angles > 180 && points.push('100% 100%');angles > 270 && points.push('0 100%');//let percent = (100/2) * (Math.tan(2*Math.PI/360 * residue).toFixed(4)); // tan算出来的是相对半径的占比 percent = (100/2) * (Math.tan(2*Math.PI/360 * residue).toFixed(4)); if(angles<=45) {points.push(percent + '%' + ' 0');}else if(angles<=90) {points.push(percent + 50 + '%' + ' 0');}else if(angles<=135) {points.push('100% ' + percent + '%');}else if(angles<=180) {points.push('100% ' + (percent + 50) + '%');}else if(angles<=225) {points.push(100 - percent + '%' + ' 100%');}else if(angles<=270) {points.push(50 - percent + '%' + ' 100%');}else if(angles<=315) {points.push('0 ' + (100 - percent) + '%');}else if(angles<=360) {points.push('0 ' + (50 - percent) + '%');}let path = 'polygon(' + points.join(', ') + ')';// 外扇面 addCSSRule(selector + '::before', {'clip-path': path});// 内扇面 addCSSRule(selector + '::after', {'clip-path': path,width: minRadius + 'px',height: minRadius + 'px',top: 'calc(50% - ' + minRadius/2 + 'px)', left: 'calc(50% - ' + minRadius/2 + 'px)' });// 容器大小和方向 addCSSRule(selector, {width: radius + 'px',height: radius + 'px',transform: 'rotate(' + direct + 'deg)'});}// 绘制扇面 drawPie({selector: '.sector',radius: 400,minRadius: 180,angles: 120, direct: 100});function addCSSRule(selector, rules, index) {// 创建一个style元素var style = document.createElement('style');// 设置type属性为text/css style.type = 'text/css';// 插入到head中 document.head.appendChild(style);// 获取sheetvar sheet = style.sheet;// 如果index未提供,则添加到末尾 index = index || null;// 如果是CSS规则字符串if (typeof rules === 'string') {// 直接添加 sheet.insertRule(selector + ' {' + rules + '}', index);} else { // 如果是一个对象// 遍历对象中的所有属性for (var prop in rules) {if (rules.hasOwnProperty(prop)) {// 将属性和值转换为字符串var rule = prop + ': ' + rules[prop];// 添加到样式表中 sheet.insertRule(selector + ' {' + rule + '}', index);}}}}/*addCSSRule('.my-other-class', 'color: red; background-color: yellow;', 0); // 添加到顶部*/ </script></html>