您现在的位置是:网站首页> 编程资料编程资料

使用html5 canvas绘制圆环动效HTML5实现的3D立体圆环旋转动画效果源码

2023-10-12 313人已围观

简介 这篇文章主要介绍了使用html5 canvas绘制圆环动效,需要的朋友可以参考下

最近笔者有个需求,需求内容为:一组文字显示在圆环的周围,用户可添加文字,文字围绕着圆环,每个词对应圆环周围的的蓝色小圆点,当用户鼠标放在圆环上方小蓝点时时,实现放射出三角形,再显示出文字,先看看动图效果吧!

​ ​​

如上图所示,当鼠标放在对应蓝色小圆点上时,需要放射出射类似三角形的射线,并在三角形外侧显示对应文字,且小蓝点变小白点。

当用户在上方输入内容后,将内容添加至下方的圆环周围。如上图所示。

笔者本来一开始的想法是使用css来实现,就像下图的动态二级菜单一样。

​ ​​

但是考虑到圆环边缘的内容可变,又要定位到圆环周围,css可能会比较难实现。所以哇,笔者决定使用canvas来实现。(笔者最近才学的canvas,有什么不对的,接受大家的指正)。

实现过程:

首先:

html部分代码如下:

 您的浏览器当前版本不支持canvas

具体实现步骤如下:

1、绘制大圆环。

使用canvas方法:context.arc(x, y, radius, startAngle, endAngle [, anticlockwise]);

x,y:圆心坐标,radius:圆心半径,startAngle:绘制起始弧度,endAngle:绘制结束弧度, [, anticlockwise]:可选参数,顺时针还是逆时针绘制圆弧。

为了绘制方便,笔者将画布的原点由之前的左上角,移动至画布的中心。

笔者计算的圆环的半径为 r-80

 canvas.width = 500 canvas.height = 500 //计算画布中心位置的半径 let r = 500 / 2 // 界面初始化的时候将画布的原点移动至画布中心 ctx.translate(r,r) //将画笔移动到圆形

具体代码如下:

 // 画布初始化 let canvas = document.getElementById('canvas') let ctx= canvas.getContext('2d') let ratio = getPixelRato(ctx) canvas.width = 500 canvas.height = 500 //计算画布中心位置的半径 let r = 500 / 2 // 界面初始化的时候将画布的原点移动至画布中心 ctx.translate(r,r) //将画笔移动到圆形 ctx.lineWidth = 3; //设置画笔的线宽 ctx.beginPath(); //画笔开始 // 绘制圆环边缘渐变边缘颜色 var arcColor = ctx.createLinearGradient(-170, -170, 0, 170) arcColor.addColorStop(0, '#8ec1ff') arcColor.addColorStop(0.2, '#83beff') arcColor.addColorStop(0.5, '#75b1ff') arcColor.addColorStop(0.7,'#5998ff') arcColor.addColorStop(1, '#2065ff') ctx.strokeStyle= arcColor;//设置画笔的颜色 ctx.arc(0,0,r - 80,0,2*Math.PI,false) //绘制圆形,坐标0,0,半径250-80,整圆(0-360度),false表示顺时针 ctx.closePath() ctx.stroke() //绘图

​绘制结果如下

2、绘制圆环中部背景图片(当前画布原点为画布中心)

 drawImage(image, dx, dy, dWidth, dHeight)

image:Canvas图片资源,如图片,SVG图像,Canvas元素本身等。

dx、dy:在Canvas画布上规划一片区域用来放置图片,dx就是这片区域的左上角横、纵坐标。

dWidth、dHeight:在Canvas画布上规划一片区域用来放置图片,这片区域的宽度、高度。

以下坐标都是笔者计算得出

 let image = new Image() image.src = 'image/quan.png' image.onload = () => { // 原点移动至中心 ctx.drawImage(image,-140,-140,280,280) }

绘制结果如下:

3、绘制圆环上的文字,小圆点(当前画布原点为画布中心)

文字和小圆点的绘制目标:

3.1 小圆点均匀的显示在大圆环上

3.2 文字散落在小圆点外方一点点

解决思路:

1、笔者使用一个数组来存储当前的词语

 let textArr = ['海阔天空','技术能力','资金雄厚','维修控制','安居乐业','走马观花','画龙点睛','去其糟粕','逆风而行','职业发展']

2、因为小圆点的个数以及词语的个数是一样的,它们两个的个数也就是上方数组textArr的length

3、一个整圆的弧度是2π,要让小圆点们均分圆环,笔者首先计算出每个小圆点所在点的弧度

 for(let i = 0;i

4、根据三角函数可以计算出当前小圆点在画布上的坐标(x,y)(当前画布原点为画布中心)

其中弧度,小圆点,圆环,圆环半径,画布原点关系,笔者画了一个图来描述它们。

计算文字的坐标:

 // 计算小圆心坐标 let x = (r - 40)*Math.cos(rad) let y = (r - 40)*Math.sin(rad)

计算小圆点的坐标:因为小圆点的圆心都要落在圆环上,所以其计算横纵坐标是,

 // 计算文字的坐标 let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)

具体代码如下:

 // 绘制文字 ctx.font = '13px Arial' ctx.textAlign = 'center' ctx.textBaseline = 'middle' ctx.fillStyle="#000000" let lengths = textArr.length textArr.forEach(function(text,i){ //弧度 let rad = 2*Math.PI/lengths*i // 计算小圆心坐标 let x = (r - 40)*Math.cos(rad) let y = (r - 40)*Math.sin(rad) ctx.fillText(text,x+0.5,y+0.5) }); // 绘制小圆点 for(let i = 0;i

绘制结果如下:

4、绘制每个小圆点外面的三角形(当前画布原点为画布中心)

4.1 因为要绘制出三角形的形状,绘制三角形的思路就是,以当前小圆点的圆心为起点向两侧画条线,然后使用ctx.fill()封闭图形,并使用渐变色填充内部。

绘制三角形:坐标自行计算。笔者是横坐标加减35.纵坐标加上70(随意随意,看你喜欢,哈哈哈)

 //画笔开始 ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath()

绘制三角形下方的文字:(为了和之前的文字有区别,这里我文字我使用了红色)

 ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)

具体代码如下:

 for(let i = 0;i从中心向两边添加颜色 var sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129,200,224,0.5)') sColor.addColorStop(0.8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75) }

绘制结果如下:

4.2 需求是每个三角形的方向是向外散发,而现在三角形的方向都是朝下方,所以现在需要使用canvas的旋转方法。

 ctx.save() ctx.translate(x,y) // 旋转角度以每个小圆点为中心 ctx.rotate( rad - Math.PI/2 ) // 因为一开始小圆点 ctx.translate(-x, -y) . 省略画三角形和文字的代码 . . ctx.restore()

由计算可得,以小圆点的圆心为旋转起点,三角形的旋转的弧度应该是当前小圆点的弧度减去π/2,因为旋转的起始位置都是从x坐标轴正方向开始,即弧度为0处开始,但是现在三角形的已经都处于π/2弧度处,所以:

旋转的弧度 = 小圆点的弧度 - π/2

记得旋转的时候一定要使用Canvas状态的存储方法save()。

restore(),依次从堆栈的上方弹出存储的Canvas状态,如果没有任何存储的Canvas状态,则执行此方法没有任何变化。

一定要记得最后要使用restore()方法,说到这里,笔者留下了悔恨的泪水。。。

具体代码:

 for(let i = 0;i从中心向两边添加颜色 var sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129,200,224,0.5)') sColor.addColorStop(0.8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75) ctx.restore() }

绘制结果:

定睛一看,what???有些文字因为旋转问题,颠倒了,通过观察得出结果,当弧度大于π的时候,文字才出现颠倒问题。

是时候写一波if判断了。。。。

旋转文字的方法:

 function rotateContext(ctx, x, y, degree) { // 旋转文字 ctx.translate(x, y) // ctx.rotate(degree * Math.PI / 180) ctx.rotate(degree) ctx.translate(-x, -y) }

判断弧度大于π的小圆点

 if (rad > Math.PI) { // 因为文字需要显示在三角形的边缘,所以文字应该随着三角形旋转,才能一直维持在 // 三角形的边缘,由于旋转后当弧度大于π的值都会出现文字倒转问题,于是将文字进行旋转翻转 ctx.save() ctx.beginPath() // 旋转文字 rotateContext(ctx, x, y+75, Math.PI) ctx.font = '13px Arial' ctx.textAlign = 'center' ctx.fillStyle = "#ff2238" ctx.fillText(textArr[i], x, y+ 75) ctx.restore() } else { ctx.fillStyle = '#ff2238' ctx.fillText(textArr[i], x, y + 75) }

绘制结果如下:

胜利再望,快要成功了,至少大概布局有了,革命尚未成功,同志仍需努力!!

5、下面就是实现,鼠标在小圆点上方,让边缘的三角形和三角形边缘文字显示,而圆环边的文字不显示

思路:

1、给画布绑定鼠标进入事件

2、判断当前鼠标所在画布位置的坐标是否等于某个小圆点的附近的坐标,如果等于就显示对应小圆点的三角形。

5.1给canvas画布绑定mousemove事件:鼠标在上方事件

 canvas.addEventListener('mousemove',clickEvent)

5.2 计算鼠标当前在画布上的坐标

计算方法是:使用鼠标当前在dom上的坐标减去,画布距离左方或上方的距离,计算出画布的距离

下图的drawOne方法为绘制方法,文章后续会说到。

 function clickEvent() { // 鼠标所在位置坐标 let x = event.clientX - canvas.getBoundingClientRect().left let y = event.clientY - canvas.getBoundingClientRect().top drawOne(x,y) }

5.3,因为上方计算出来的鼠标在画布上的坐标是以画布的左上角为原点计算的坐标,但是当前画布的原点早已移动到画布中心(250,250)处,所以当用来判断是否是点击某个小圆点的时候需要横纵坐标都减去250,才能与当前画布的小圆点坐标进行比哦对,笔者在判断的时候,发现 一个问题,不知道为啥笔者的y方向的差量是260而不是250,所以笔者y方向上都减去了260。

代码如下:

其中Cx,Cy为鼠标在画布上的坐标(以画布左上角为原点),x,y为当前小圆点的坐标,

笔者直接计算出小圆点圆心附近15px的

相关内容

-六神源码网