上一章讲述了怎样操做C4D图切割制做闪光效果。本章将讲述怎样在上章文章描述的效果根底上参加椭圆动态效果以及闪动控制。
如下图所示,椭圆运动重要分成两部门:外圈运动、内圈运动。此中内圈运动看似一个椭圆,实际上是由两个椭圆不同角度组成的。红色指向的是运动的小球,绿箭头是小球运动的标的目的。下面将讲述怎样展示圆球运动,重要是运用canvas画布制做的,探测小球的运动轨迹,以及到点则控制对应块的闪烁。
一、椭圆运动函数
先理解一下椭圆运动函数circleRunEllipse整体,重要使用函数:
ellipseRun — 椭圆运动执行drawCircle — 绘画指定位置的运动小球点clearRun — 停止小球运动drawEllipse — 画椭圆运动轨迹,用于调试婚配设想稿drawPoint — 起始点、终止点调试
- /**
- * 首页运维与效劳后台图动画
- * @param canvasID 画布ID
- * @param ellipseHeight 椭圆运动高度
- * @param ellipseWidth 椭圆运动宽度
- * @param type 哪一个圈,大、中、小--【1 | 2 | 3】
- */export function circleRunEllipse(canvasID, ellipseHeight, ellipseWidth, type) { // 根底变量
- let canvas: any; if (document.getElementById(canvasID)) {
- canvas = document.getElementById(canvasID);
- } else { return ;
- } let context = canvas.getContext('2d'); let width = canvas.width = 469; let height = canvas.height = 1017; let animationFrame = null; // 记录执行的动画,用于关掉
- // 椭圆运动
- let circleX = width / 2 - 127; // 椭圆运动中心点
- let circleY = height / 2; let ellipseA = ellipseWidth; // 长轴a
- let ellipseB = ellipseHeight; // 短轴b
- let speed = 0.012; // 控制运动速度
- let ellipseTime = 0; // 控制运动时间变革
- /**
- * 椭圆运动执行
- */
- function ellipseRun() { if (animationFrame) { window.cancelAnimationFrame(animationFrame);
- }
- animationFrame = window.requestAnimationFrame(ellipseRun);
- context.clearRect(0, 0, width, height); // drawEllipse(circleX, circleY);
- drawCircle(circleX + ellipseA * Math.cos(ellipseTime), circleY + ellipseB * Math.sin(ellipseTime)); if (type === 1) {
- context.clearRect(0, 80, 35, 55); // 右侧点(25,80),高宽
- context.clearRect(0, 880, 10, 5); // 左侧点(0,885)
- // 完毕点21.09
- ellipseTime += speed; if (ellipseTime > 21.09) { if (!clearAnimationFrame()) { document.getElementsByClassName('service-cloud1')[0].className += ' service-cloud'; document.getElementsByClassName('service-cloud4')[0].className = 'service-cloud4';
- } else { return ;
- }
- ellipseTime = 16.8;
- clearRun(5);
- }
- } else if (type === 2) {
- context.clearRect(0, 720, 210, 200); // 左侧点(208,720),高宽
- context.clearRect(0, 308, 20, 415); // 右侧点(2,308),高宽
- // 完毕点16.29
- ellipseTime -= speed; if (ellipseTime < 16.29) { if (!clearAnimationFrame()) { document.getElementsByClassName(&#39;service-cloud2&#39;)[0].className = &#39;service-cloud2&#39;;
- } else { return ;
- }
- ellipseTime = 19.45;
- clearRun(5);
- }
- } else {
- context.clearRect(0, 300, 43, 400); // 左侧点(40,700),高宽
- context.clearRect(0, 0, 175, 307); // 右侧点(175,305),高宽
- context.clearRect(142, 716, 30, 62); // 效劳器右侧点(142,778),高宽,左侧点(169,716)
- // 完毕点18.08
- ellipseTime -= speed; if (ellipseTime < 18.08) { if (!clearAnimationFrame()) { document.getElementsByClassName(&#39;service-cloud3&#39;)[0].className += &#39; service-cloud&#39;;
- } else { return ;
- }
- ellipseTime = 21.24;
- clearRun(5);
- }
- }
- } /**
- * 画实体圆,描述位置
- */
- function drawCircle(x, y) {
- context.save();
- context.fillStyle = &#39;#0ff&#39;;
- context.globalAlpha = 0.92;
- context.beginPath();
- context.arc(x, y, 3.5, 0, Math.PI * 2); // 半径3
- context.closePath();
- context.fill();
- context.restore();
- } /**
- * 画椭圆,用于婚配设想稿途径
- * 1、画椭圆,使用lineTo,把椭圆分割许多片段
- * 2、椭圆的三角函数表达式 x = a*cos(t), y = b * sin(t);
- */
- function drawEllipse(x, y) { // 这样能够使得每次循环所绘制的途径(弧线)接近1像素
- let step = (ellipseA > ellipseB) ? 1 / ellipseA : 1 / ellipseB;
- context.save();
- context.strokeStyle = &#39;blue&#39;;
- context.beginPath();
- context.moveTo(x + ellipseA, y); for (let i = 0; i < Math.PI * 2; i += step) {
- context.lineTo(x + ellipseA * Math.cos(i), y + ellipseB * Math.sin(i));
- }
- context.closePath();
- context.stroke();
- context.restore();
- } /**
- * 定点,用于消除隐藏多余途径
- */
- function drawPoint(x, y) {
- context.save();
- context.fillStyle = &#39;red&#39;;
- context.globalAlpha = 0.95;
- context.beginPath();
- context.arc(x, y, 3, 0, Math.PI * 2);
- context.closePath();
- context.fill();
- context.restore();
- } /**
- * 停止运动
- * @param time 时间,单元【秒】
- */
- function clearRun(time) {
- context.clearRect(0, 0, width, height); window.cancelAnimationFrame(animationFrame); let timer = null; // 提早一秒执行闪动动画
- let restartTimer = setTimeout(function() { if (clearAnimationFrame()) {
- clearTimeout(restartTimer);
- clearTimeout(timer); return ;
- } if (type === 1) { document.getElementsByClassName(&#39;service-cloud1&#39;)[0].className = &#39;service-cloud1&#39;; document.getElementsByClassName(&#39;service-cloud4&#39;)[0].className += &#39; service-cloud&#39;;
- } else if (type === 2) { document.getElementsByClassName(&#39;service-cloud2&#39;)[0].className += &#39; service-cloud&#39;;
- } else { document.getElementsByClassName(&#39;service-cloud3&#39;)[0].className = &#39;service-cloud3&#39;;
- }
- clearTimeout(restartTimer);
- }, (time - 1) * 1000);
- timer = setTimeout(function() {
- animationFrame = window.requestAnimationFrame(ellipseRun);
- clearTimeout(timer);
- }, time * 1000);
- } /**
- * 肃清运动
- */
- function clearAnimationFrame() { ... } // 指定初步点执行椭圆运动
- if (type === 1) {
- ellipseTime = 16.8; // ellipseTime = 21.09; // 完毕点
- if (document.getElementsByClassName(&#39;service-cloud4&#39;).length > 0) { document.getElementsByClassName(&#39;service-cloud4&#39;)[0].className += &#39; service-cloud&#39;;
- }
- } else if (type === 2) {
- ellipseTime = 19.45; // ellipseTime = 16.29; // 完毕点
- if (document.getElementsByClassName(&#39;service-cloud2&#39;).length > 0) { document.getElementsByClassName(&#39;service-cloud2&#39;)[0].className += &#39; service-cloud&#39;;
- }
- } else if (type === 3) {
- ellipseTime = 21.24; // ellipseTime = 18.08; // 完毕点
- } let startTimer = setTimeout(function() {
- animationFrame = ellipseRun();
- clearTimeout(startTimer);
- }, 1000);
- }
复制代码 二、椭圆运动实现
(1)从图上能够知道每个椭圆大小、倾斜角度均不同,那先得筹备三个不同的画布,能够不同的椭圆运动。在上一章的代码根底上加上轨迹canvans的html代码,如下:- <div class=&#34;servicMainOut&#34;>
- ......
- <canvas id=&#34;homeCanvasBig&#34; style=&#34;transform: rotate(90deg);position: absolute;top: -115px; left: 274px;&#34;></canvas>
- <canvas id=&#34;homeCanvasMid&#34; style=&#34;transform: rotate(90deg);position: absolute;top:-139px;left:276px;&#34;></canvas>
- <canvas id=&#34;homeCanvasSmall&#34; style=&#34;transform: rotate(90deg);position: absolute;top:-156px;left: 282px;&#34;></canvas></div>
复制代码 (2) 调用椭圆运动函数:- // 首页效劳与运维动画jscircleRunEllipse(&#39;homeCanvasBig&#39;, 487, 169, 1);
- circleRunEllipse(&#39;homeCanvasMid&#39;, 369, 123, 2);
- setTimeout(function() {
- circleRunEllipse(&#39;homeCanvasSmall&#39;, 288, 92, 3);
- }, 6014);
复制代码 编写这些代码就能够详细实现了完好的小球沿椭圆运动及到点则闪烁及运动了。
三、实现原理
下面以外圈homeCanvasBig为例讲述制做重要原理。
(1) 轨迹探测
上面的代码已详细实现了整个C4D效果了。但在初步椭圆运动之前,其实是先要探究婚配好整个椭圆的运动轨迹。开启测试的婚配轨迹函数drawEllipse(),暂时关闭小球运动drawCircle()以及注释clearRun(5)以便于调试。
效果如下:
怎样婚配椭圆轨迹,一般只要逐程序整以下变量:
ellipseHeight:调整椭圆长袖,椭圆的宽度变革。值越大,圆越大。ellipseWidth:调整椭圆向北倾斜度。值越大,越倾向北。
一般还搭配top跟left样式调整。
(2) 起始点、终止点定位
每个椭圆运动都有起始点和终止点,知道这两点的位置才能有利于我们控制隐藏不须要的轨迹以及闪烁效果。其实每个椭圆的初步都是有完好的轨迹的,通过drawPoint(x, y)函数定义到每一个点,这样就能够使用context.clearRect()函数关掉不存在的轨迹。譬如:
(3) 闪烁控制
通过上面的起点、终点的定位,我们能够console.log出对应的ellipseTime的值。根据ellipseTime的值则可控制能否应当闪烁。而且ellipseTime增值可控制小球顺时针运动,减值则控制逆时针运动。
睿江云官网链接:https://www.eflycloud.com/home?from=RJ0027 |