canvas - 圆圈内 hover 高亮 效果

各种计算还挺繁琐的, 关键点在角度的计算, 根据鼠标位置, 利用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 高亮 效果的更多相关文章
- canvas - 圆圈内 hover效果
链接
- 用HTML5 Canvas 做擦除及扩散效果
2013年的时候曾经使用canvas实现了一个擦除效果的需求,即模拟用户在模糊的玻璃上擦除水雾看到清晰景色的交互效果.好在2012年的时候学习HTML5的时候研究过canvas了,所以在比较短的时间内 ...
- CSS实现输入框的高亮效果-------Day50
又到周末了,这一天天过的真快,明天应该回老家了.不知道会不会有机会进行编写.尽量争取吧,实在不想就这样间断.假设说从前会一天天无聊到爆,那如今自己应该是一天天忙的要死,欠缺了太多东西,那些浪费的时间可 ...
- 基于canvas的原生JS时钟效果
概述 运用html5新增画布canvas技术,绘制时钟效果,无需引用任何插件,纯js. 详细 代码下载:http://www.demodashi.com/demo/11935.html 给大家介绍一个 ...
- cesium 3dtiles模型单体化点击高亮效果
前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. c ...
- UI-切圆角、透明度、取消按钮点击高亮效果、按钮文字带下划线
一.切UIView的某个角为圆角 如果需要将UIView的4个角全部都为圆角,做法相当简单,只需设置其Layer的cornerRadius属性即可(项目需要使用QuartzCore框架).而若要指定某 ...
- UITableView或UIScrollVIew上的UIButton的高亮效果
UITableView或UIScrollVIew上的UIButton的高亮效果 原文地址:http://www.jianshu.com/p/b4331f06bd34 最近做项目的时候发现,UIScro ...
- HTML5在canvas中绘制复杂形状附效果截图
HTML5在canvas中绘制复杂形状附效果截图 一.绘制复杂形状或路径 在简单的矩形不能满足需求的情况下,绘图环境提供了如下方法来绘制复杂的形状或路径. beginPath() : 开始绘制一个新路 ...
- 经典!HTML5 Canvas 模拟可撕裂布料效果
这是一个模拟可撕裂布料效果的 HTML5 Canvas 应用演示,效果逼真.你会看到,借助 Canvas 的强大绘图和动画功能,只需很少的代码就能实现让您屏息凝神的效果. 温馨提示:为保证最佳的效果, ...
随机推荐
- XMPP环境搭建 (mac环境下 安装自己独立的mysql与服务器(openfire),实现即时聊天功能)
1简单概览 [一]XMPP简介 http://xmpp.org 即时通讯技术 IM - Instant Messaging ⽀支持⽤用户在线实时交谈.交谈双⽅方都需要⼀一个聊天窗⼝口,其中⼀一个⽤用户 ...
- String与反序
将String类型的字符串里的内容进行反序排列得到一个新的String类型字符串,下面提供两种方法实现: 法1.先将原String类型字符串转换为字符数组,通过字符数组来操作各个位上的单个字符,通过对 ...
- 第三课 Makefile文件的制作(上)
1.序言: 前面的课程讲解了从gcc编译过程到其实践,大家可以看到其实在这些步骤中有些是可以简化编译的,但由于参数多以及项目中文件数量多的原因难免会造成错误甚至是浪费大量的时间在这编译上,为此linu ...
- Bootstrap总结一
参考我的博客:http://www.isedwardtang.com/2017/08/30/bootstrap-primer-1/
- websocket redis实现集群即时消息聊天
websocket与redismq实现集群消息聊天 1.application.properties server.port=8081 #thymeleaf配置 #是否启用模板缓存. spring.t ...
- 【Flask】Flask-Migrate基本使用
# flask_migrate笔记:在实际的开发环境中,经常会发生数据库修改的行为.一般我们修改数据库不会直接手动的去修改,而是去修改ORM对应的模型,然后再把模型映射到数据库中.这时候如果有一个工具 ...
- 微信小程序获取用户信息,解密encryptedData 包括敏感数据在内的完整用户信息的加密数据
package com.iups.wx.wxservice; import java.io.UnsupportedEncodingException; import java.security.Alg ...
- struts2——上传文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- MongoError: server instance in invalid state undefined 解决办法
MongoDB关键点集锦(更新中...) 2017-01-20 09:33:48[其它数据库]点击数:15作者:Real_Bird的博客来源: 网络 随机为您推荐的文章:MongDB索引的介绍及使用 ...
- Android -- ContentProvider 内容提供者,创建和调用
1. 概述 ContentProvider 在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentPr ...