各种计算还挺繁琐的, 关键点在角度的计算, 根据鼠标位置, 利用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. qt下通过socket传送中文

    zz 1.在main函数里我之前就加了一句QTextCodec::setCodecForTr( QTextCodec::codecForLocale() ); 现在再加一句QTextCodec::se ...

  2. sublime txet 3 python 开发环境安装配置

    下载python 下载地址:https://www.python.org/downloads/windows/ 下载sublime text 3 下载地址:https://www.sublimetex ...

  3. Mootools遮罩层练习(原为网上的jquery写法)

    <html > <head> <meta charset="utf-8" /> <title>mootools 遮罩层</ti ...

  4. 199. Binary Tree Right Side View -----层序遍历

    Given a binary tree, imagine yourself standing on the right side of it, return the values of the nod ...

  5. 亿能测试大讲堂 - YY在线课程[ 测试人员需要掌握的Shell脚本编程 ]

    亿能测试大讲堂 - YY在线课程[ 测试人员需要掌握的Shell脚本编程 ]http://automationqa.com/forum.php?mod=viewthread&tid=2453& ...

  6. 保护你的代码,生成.a文件以及.framework文件需要注意的地方

    一个好的设计,一个方便使用的控件封装,一个酷炫的动画... 是不是迫不及待要分享给大家你的每一个突然蹦出来的好的idea,那就下手吧! 可是,你想要的只是让大家使用它,而不是把所有技术点都公开给每个人 ...

  7. 字符数组(char)和字符串(string)的转换

    #include<iostream>#include<string>using namespace std;void main(){ string LyuS = "W ...

  8. Asp.Net中OnClientClick与OnClick的区别

    当我们当击这个按钮时,自动先执行的客户端,再执行服务器端的.如果客户端返回的是false,那么服务器端对应的方法永远不会执行.这样就达到检测,只有通过才去执行服务器端的方法.

  9. bzoj 3479: [Usaco2014 Mar]Watering the Fields

    3479: [Usaco2014 Mar]Watering the Fields Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 174  Solved ...

  10. 定制kali linux

    Kali Linux Ps: Kali发布撸~ 写了个如此装13的标题.这是一个Guide… 都是些基本操作撸.定制为王实推 ArchLinux.  各位看官继续………………………………………号外.L ...