各种计算还挺繁琐的, 关键点在角度的计算, 根据鼠标位置, 利用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. PHP函数的创建

    看代码 PHP函数的创建,包括参数,和其他的语言一样 <?php #PHP crate function function writeName($name) { echo 'Name is '. ...

  2. Xcode 错误问题以及解决方法(后期遇到还会添加)

    1,/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhon ...

  3. C#转义字符(好记性不如烂笔头)

    C#转义字符: ·一种特殊的字符常量:·以反斜线"\"开头,后跟一个或几个字符.·具有特定的含义,不同于字符原有的意义,故称“转义”字符.·主要用来表示那些用一般字符不便于表示的控 ...

  4. unity,如何手动或者使用代码更换材质

    在unity中,我们可能需要更换怪物的贴图,来达到以下效果 方法1:手动配置 找到自己配置好的扩展名为.mat的文件,在怪物的节点找到带Mesh Render的子元素,将其拖放到如图位置 方法2:代码 ...

  5. LVS基本介绍

    一.LVS概念 LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器.这是一个由章文嵩博士发起的一个开源项目,它的官方网站是http://www.linuxvirtual ...

  6. $python数据分析基础——初识numpy库

    numpy库是python的一个著名的科学计算库,本文是一个quickstart. 引入:计算BMI BMI = 体重(kg)/身高(m)^2 假如有如下几组体重和身高数据,让求每组数据的BMI值: ...

  7. NIO复习02

    Selector 1. Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样,一个单独的线程可以管理多个channel,从而管 ...

  8. xx-net***简明使用教程

    简介 继psiphon3.lantern.shadowsocks后,翻 土啬 界就来个新角色:xx-net 这张图是.2016.8.30日Google最新的搜索结果,还是可以看出这款工具的火爆程度的, ...

  9. 编译lineageos

    lineageos 2 -- 编译rom包 fu*k小米,手机老是1年左右出现充不进去电.前段时间我的红米note4x突然充不进去电了,只好新买了个手机(买手机先看lineageos支持列表 ^_^) ...

  10. DevExpress的GridControl选择一行,不显示单元格焦点的设置

    grid控件默认选择一行时,focused的cell并不是蓝色的,而是白色的 要想实现一次选择一行全都是蓝色的只要改一个属性就可以了 this.gridView1.OptionsSelection.E ...