各种计算还挺繁琐的, 关键点在角度的计算, 根据鼠标位置, 利用atan(y/x) 得到反正切值 , 角度  (tan输入的是r和x围成的那个角,输出的是y/x。反tan就是输入y/x输出角。)

<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="800" height="950" style="border:1px solid #d3d3d3;margin-top:10px">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const PI = Math.PI;
const number = 4;//画4个外圆;
const reduceRadio = 15;//递减半径;
const maxRadius = 80;//最大半径
const minRadio = maxRadius-number*reduceRadio;
const translateX = 100;//canvas移动位置
const translateY = 100;
//canvas移动位置
ctx.translate(translateX,translateY);
//画所有圆
function drawAllOuterCircle(number,reduceRadio,maxRadius){ //画虚线
ctx.setLineDash([2,2]);
for(let i=0;i<number;i++){
ctx.beginPath();
//半径递减
ctx.arc(0,0, maxRadius-i*reduceRadio, 0, 2*PI); if(i+n == 4){
ctx.strokeStyle = 'red';
}else{
ctx.strokeStyle = 'black';
} ctx.stroke();
ctx.closePath(); } //重置
ctx.restore();
//最里面小圆
ctx.beginPath();
ctx.arc(0,0,maxRadius-number*reduceRadio,0,2*PI);
ctx.fillStyle="red";
ctx.fill();
ctx.closePath();
ctx.restore();
}
drawAllOuterCircle(number,reduceRadio,maxRadius);
 
//画分割直线
const lineNum = 8;//分割线条数
const minAngel = 2*PI/lineNum;//最小角度
function drawSplitLine(lineNum,maxRadius){
for(let i=0;i<lineNum;i++){
ctx.setLineDash([]);
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(0,maxRadius);
ctx.strokeStyle = 'black';
ctx.stroke();
//旋转
ctx.rotate(2*PI/lineNum);
ctx.closePath();
}
}
drawSplitLine(lineNum,maxRadius);
 
//画阴影部分
function drawShadowPanel(ceilMouseRadio,floorMouseRadio,ceilMouseAngel,floorMouseAngel){ //清屏
ctx.beginPath();
ctx.moveTo(0,0);
ctx.arc(0,0,ceilMouseRadio+reduceRadio,0,2*PI);
ctx.fillStyle = "white";
ctx.fill();
ctx.closePath(); //调试: 先画一个大的绿色扇形
ctx.beginPath();
ctx.moveTo(0,0);
ctx.arc(0,0,ceilMouseRadio,floorMouseAngel,ceilMouseAngel);
ctx.fillStyle = "green";
ctx.fill();
ctx.closePath(); //再画一个小的白色扇形 覆盖 大的扇形, 视觉上形成一个弧形
ctx.beginPath();
ctx.moveTo(0,0);
ctx.arc(0,0,floorMouseRadio,floorMouseAngel,ceilMouseAngel);
ctx.fillStyle = "white";
ctx.fill();
ctx.closePath();
}
const maxN = (maxRadius-minRadio)/reduceRadio;
var n; //获取ceilMouseRadio,floorMouseAngel,ceilMouseAngel
//获取canvas 的 位移
const canvasX = canvas.getBoundingClientRect().left + document.documentElement.scrollLeft +translateX;
const canvasY = canvas.getBoundingClientRect().top + document.documentElement.scrollTop +translateY;
function getMouseDetail(mouseX,mouseY){
//利用勾股定理 算出鼠标 离 canvas原点的距离
let mouseRadio = Math.sqrt( Math.pow(mouseX-canvasX, 2) + Math.pow(mouseY-canvasY, 2)); //因为 cavas原点已经移动到 100 100, 判断鼠标是否在圆圈内
if(mouseRadio>maxRadius||mouseRadio<=minRadio){
return {ceilMouseRadio:0,floorMouseRadio:0,floorMouseAngel:0,ceilMouseAngel:0};
} //计算鼠标半径和最小半径的比例,画阴影块的大小半径 reduceRadio:15
n = Math.ceil((mouseRadio-minRadio)/reduceRadio); let ceilMouseRadio = minRadio+n*reduceRadio;
let floorMouseRadio = minRadio+(n-1)*reduceRadio; //角度
let mouseAngel; if(mouseX-canvasX<0){
//计算当前鼠标 相对原点的的弧度值 , x轴 顺时针
// 比如 Math.atan(1)/Math.PI*180 是 45度
mouseAngel = Math.atan((mouseY-canvasY)/(mouseX-canvasX)) + PI;
}else{
mouseAngel = Math.atan((mouseY-canvasY)/(mouseX-canvasX));
} // 计算当前鼠标 有多少个象限
let m = Math.ceil(mouseAngel/minAngel);
let floorMouseAngel = (m-1)*minAngel;
let ceilMouseAngel = m*minAngel; return {ceilMouseRadio,floorMouseRadio,floorMouseAngel,ceilMouseAngel};
}
//监听事件画图
canvas.addEventListener('mousemove', (e)=>{
let mouseX = e.pageX;
let mouseY = e.pageY;
getMouseDetail(mouseX,mouseY);
let mouseDetail = getMouseDetail(mouseX,mouseY);
let {ceilMouseRadio,floorMouseRadio,floorMouseAngel,ceilMouseAngel} = mouseDetail; if(ceilMouseRadio){
//先画阴影,
drawShadowPanel(ceilMouseRadio,floorMouseRadio,ceilMouseAngel,floorMouseAngel);
//再画圆圈
drawAllOuterCircle(number,reduceRadio,maxRadius);
drawSplitLine(lineNum,maxRadius);
}
});
</script>
</body>
</html>

链接

canvas - 圆圈内 hover 高亮 效果的更多相关文章

  1. canvas - 圆圈内 hover效果

    链接

  2. 用HTML5 Canvas 做擦除及扩散效果

    2013年的时候曾经使用canvas实现了一个擦除效果的需求,即模拟用户在模糊的玻璃上擦除水雾看到清晰景色的交互效果.好在2012年的时候学习HTML5的时候研究过canvas了,所以在比较短的时间内 ...

  3. CSS实现输入框的高亮效果-------Day50

    又到周末了,这一天天过的真快,明天应该回老家了.不知道会不会有机会进行编写.尽量争取吧,实在不想就这样间断.假设说从前会一天天无聊到爆,那如今自己应该是一天天忙的要死,欠缺了太多东西,那些浪费的时间可 ...

  4. 基于canvas的原生JS时钟效果

    概述 运用html5新增画布canvas技术,绘制时钟效果,无需引用任何插件,纯js. 详细 代码下载:http://www.demodashi.com/demo/11935.html 给大家介绍一个 ...

  5. cesium 3dtiles模型单体化点击高亮效果

    前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. c ...

  6. UI-切圆角、透明度、取消按钮点击高亮效果、按钮文字带下划线

    一.切UIView的某个角为圆角 如果需要将UIView的4个角全部都为圆角,做法相当简单,只需设置其Layer的cornerRadius属性即可(项目需要使用QuartzCore框架).而若要指定某 ...

  7. UITableView或UIScrollVIew上的UIButton的高亮效果

    UITableView或UIScrollVIew上的UIButton的高亮效果 原文地址:http://www.jianshu.com/p/b4331f06bd34 最近做项目的时候发现,UIScro ...

  8. HTML5在canvas中绘制复杂形状附效果截图

    HTML5在canvas中绘制复杂形状附效果截图 一.绘制复杂形状或路径 在简单的矩形不能满足需求的情况下,绘图环境提供了如下方法来绘制复杂的形状或路径. beginPath() : 开始绘制一个新路 ...

  9. 经典!HTML5 Canvas 模拟可撕裂布料效果

    这是一个模拟可撕裂布料效果的 HTML5 Canvas 应用演示,效果逼真.你会看到,借助 Canvas 的强大绘图和动画功能,只需很少的代码就能实现让您屏息凝神的效果. 温馨提示:为保证最佳的效果, ...

随机推荐

  1. python16_day06【类、RE模块、subprocess模块、xml模块、shelve模块】

    一.shelve模块 import shelve # 基于pickle模块, d = shelve.open('shelve_test') class Test(object): def __init ...

  2. ImageMagick来处理图片,缩放,调整高度等操作

    单个缩放图片 convert 911.jpg -resize 25% 911.jpg 前面是要处理的图片路径,后面是输出的图片路径,我这么写就把原先图片缩放了 批量缩放图片 mogrify -samp ...

  3. String与反序

    将String类型的字符串里的内容进行反序排列得到一个新的String类型字符串,下面提供两种方法实现: 法1.先将原String类型字符串转换为字符数组,通过字符数组来操作各个位上的单个字符,通过对 ...

  4. 在Windows上以服务方式运行 Redis

    ServiceStack.Redis 使用教程里提到Redis最好还是部署到Linux下去,Windows只是用来 做开发环境,现在这个命题发生改变了,在Windows上也可以部署生产环境的Redis ...

  5. git指令整理汇总

    Git 1.git init 创建版本库,初始化 2.git add  向git添加文件,把文件添加到版本库 3.git log   告诉我们历史记录 4.git commit -m ‘’ 提交修改 ...

  6. HashMap与ConcurrentHashMap、HashTable

    (1)HashMap的线程不安全原因一:死循环 原因在于HashMap在多线程情况下,执行resize()进行扩容时容易造成死循环. 扩容思路为它要创建一个大小为原来两倍的数组,保证新的容量仍为2的N ...

  7. Javascript中类型: undefined, number ,string ,object ,boolean

    var a1; var a2 = true;var a3 = 1;var a4 = "Hello";var a5 = new Object();var a6 = null;var ...

  8. C#中各种数据类型可以表示的数据的范围

    C#中各种数据类型可以表示的数据的范围 BOOL型为int型,一般认为占4个字节,取值TRUE/FALSE/ERROR. sbyte型为有符号8位整数,占1个字节,取值范围在-128 - 127之间. ...

  9. Python MySQL数据库连接模块

    1. MySQLdb只支持在Python 2版本使用MySQLdb是用于Python链接Mysql数据库的接口.a.pip安装 直接使用pip进行安装,在此之前需要安装一些系统依赖包. ● CentO ...

  10. VRChat简易教程4-使用VRC的接口实现物体的移动(VRC的action和trigger接口)

    这个教程我们学习如何实现载具的驾驶 一.准备工作 1 最简单的载具驾驶需要至少两个元素,一是需要一个载具,二是需要一个前进的按钮(这里我们只做前进功能),为了直观的能感受到载具的移动,我们还得创造一个 ...