本文实例为大家分享了JavaScript Canvas绘制动态线框效果的具体代码,供大家参考,具体内容如下
本周项目,移动端页面开发,要求丰富的动效,主要技术实现 Canvas ;其中绘制动态线框,走了点弯路,所谓的弯路是逻辑问题,非技术实现方式。
一、涉及技术点,具体如下:
1.html 中引入canvas 标签,设置宽高;
<canvas id="canvas" width=xx height=xx>您的浏览器不支持canvas,请更换版本</canvas>
2.js中 定义ctx–beginPath–moveTo-lineTo-stroke–closePath;
var ctx=canvas.getContext('2d');
ctx.beginPath();
ctx.strokeStyle=#f00;
ctx.lineWidth=1;
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.lineTo(..)..
ctx.stroke();
ctx.closePath();
绘制静态折线,比较简单,直接从moveTo初始节点开始lineTo到每一个节点,项目需求是绘制线条的动画效果,那实现方式就是在每一条直线段间,通过定时器多次重回moveTo起点到lineTo直线段上有序增量的点位,代码如下:
ctx.moveTo(x1,y3);
xm1+=fre1;
ym1+=fre2;
ctx.lineTo(xm1,ym1)
二、逻辑弯路及解决
1、逻辑弯路
项目是移动端,考虑适配问题,在绘制节点的时候,开始使用的是以百分比与获取屏幕后的宽高的乘积做为判断moveTo更改的true or false; 鉴于乘积的非整数,在if语句里x,y的增量变化 只能使用++;而且是px单位的增量,所以导致在绘制时速度很慢,即便是setInterval 的时间个位毫秒
var lg01=ctx.createLinearGradient(0,.12*winH,0,.5*winH);
lg01.addColorStop(0,'#6DEAFF');
lg01.addColorStop(.5,'#78C7FF');
lg01.addColorStop(1,'#4A84FF');
var fre=4;
function drawUpBox(){
ctx.beginPath();
ctx.strokeStyle=lg01;
ctx.lineWidth=0.05*rem;
if(xm1>x2&&ym1==y1){
ctx.clearRect(x2,y1-0.025*rem,x3-x2,0.05*rem);
ctx.moveTo(x3,y1);
xm1-=fre;
ctx.lineTo(xm1,ym1)
}else if(xm1>x1&&ym1<=y2){
ctx.moveTo(x2,y1);
xm1-=fre;
ym1+=fre;
ctx.lineTo(xm1,ym1)
}else if(xm1<=x1&&ym1<y3){
ctx.clearRect(x1-0.025*rem,y2,0.05*rem,y3-y2)
ctx.moveTo(x1,y2);
ym1+=fre;
ctx.lineTo(xm1,ym1)
} else if(ym1<y4){
ctx.moveTo(x1,y3);
xm1+=fre;
ym1+=fre;
ctx.lineTo(xm1,ym1)
}else if(xm1>=x2&&ym1>=y4){
if(xm1<=winW/2){
ctx.clearRect(x1,y4-0.025*rem,winH/2-x1,0.05*rem);
ctx.moveTo(x2,y4)
xm1+=fre;
ctx.lineTo(xm1,ym1)
}
}
if(xm2<x5&&ym2==yd1){
ctx.clearRect(x4,yd1-0.025*rem,x5-x4,0.05*rem);
ctx.moveTo(x4,yd1);
xm2+=fre;
ctx.lineTo(xm2,ym2);
}else if(xm2<x6&&ym1<=yd2){
ctx.moveTo(x5,yd1);
xm2+=fre;
ym2+=fre;
ctx.lineTo(xm2,ym2)
}else if(xm2<=x6&&ym2<yd3){
ctx.clearRect(x6-0.025*rem,yd2,0.05*rem,yd3-yd2)
ctx.moveTo(x6,yd2);
ym2+=fre;
ctx.lineTo(xm2,ym2)
}else if(ym2<yd4){
ctx.moveTo(x6,yd3);
xm2-=fre;
ym2+=fre;
ctx.lineTo(xm2,ym2)
}else if(xm2<=x5&&ym2>=yd4){
if(xm2>=winW/2){
ctx.clearRect(winW/2,yd4-0.025*rem,x6-winW/2,0.05*rem);
ctx.moveTo(x5,yd4)
xm2-=fre;
ctx.lineTo(xm2,ym2)
}else{
drawOuterAndInnerLine();
clearInterval(timer01)
}
}
ctx.stroke();
ctx.closePath()
}
效果:
如果更改fre增量的值,比如改为4,就会出现如下边框不完整问题:
2.解决方案:
在判断语句中,横向100等分,节点即为100以内整数值,增量也以此累加,moveTo 和 lineTo的时候 再换算成具体px; 通过百分值,可以提高单位时间的绘制效率,此时只需控制增量每次++;再配合定时器 的周期,很容易实现不同频率的线条绘制;另外对节点封装于一个对象内,可以快速调整节点绘制不同尺寸 类型的动态线框图:
canvas3.width=winW;
canvas3.height=.15*winH;
//$('#canvas3').css('background','#eee');
var node3X={x1:20,x2:22,x3:36,x4:64,x5:78,x6:80};
var node3Y={y1:2,yh:20};
var xd=node3X.x2-node3X.x1,xml3=node3X.x3,xmr3=node3X.x4,yml3=ymr3= 0;
//var winWB=winW/100,winHB=winH/100,winCHB=winHB/2;
node3Y.y1Ready=node3Y.y1*winCHB;
node3Y.y2Ready=node3Y.y1*winCHB+(node3X.x2-node3X.x1)*winWB;
node3Y.y3Ready=node3Y.y2Ready+node3Y.yh*winCHB;
node3Y.y4Ready=node3Y.y3Ready+(node3X.x2-node3X.x1)*winWB;
var yml3Ready=node3Y.y1Ready;
var ymr3Ready=node3Y.y1Ready;
var ctx3=canvas3.getContext("2d");
var lg03=ctx3.createLinearGradient(0,0,0,canvas3.height);
lg03.addColorStop(0,'#6DEAFF');
lg03.addColorStop(.5,'#78C7FF');
lg03.addColorStop(1,'#4A84FF');
var mainBoxTimer3=setInterval(drawMainBox3,20);
function drawMainBox3(){
drawPath(ctx3,node3X.x4*winWB,node3Y.y1Ready,4,winWB,lg03)
drawPath(ctx3,node3X.x3*winWB,node3Y.y1Ready,4,winWB,lg03)
ctx3.beginPath();
ctx3.strokeStyle=lg03;
ctx3.lineWidth=.1*rem;
//绘制左半部分
if(xml3>node3X.x2&&yml3==0){
//ctx3.clearRect(0,0,winW,winH/2);
xml3--;
ctx3.moveTo(node3X.x3*winWB,node3Y.y1*winCHB)
ctx3.lineTo(xml3*winWB,node3Y.y1*winCHB);
}else if(xml3>node3X.x1&&yml3Ready<node3Y.y2Ready){
xml3--;
yml3Ready=node3Y.y1*winCHB+(node3X.x2-xml3)*winWB;
ctx3.moveTo(node3X.x2*winWB,node3Y.y1*winCHB)
ctx3.lineTo(xml3*winWB,yml3Ready)
}else if(xml3==node3X.x1&&yml3<node3Y.yh){
yml3++;
ctx3.moveTo(node3X.x1*winWB,node3Y.y2Ready);
ctx3.lineTo(node3X.x1*winWB,node3Y.y2Ready+yml3*winCHB);
}else if(yml3==node3Y.yh&&xml3<node3X.x2){
xml3++;
ctx3.moveTo(node3X.x1*winWB,node3Y.y3Ready);
ctx3.lineTo(xml3*winWB,node3Y.y3Ready+(xml3-node3X.x1)*winWB)
}else if(xml3>=node3X.x2&&xml3<50){
xml3++;
ctx3.moveTo(node3X.x2*winWB,node3Y.y4Ready);
ctx3.lineTo(xml3*winWB,node3Y.y4Ready);
}
//绘制右半部分
if(xmr3<node3X.x5&&ymr3==0){
xmr3++;
ctx3.moveTo(node3X.x4*winWB,node3Y.y1*winCHB)
ctx3.lineTo(xmr3*winWB,node3Y.y1*winCHB);
}else if(xmr3<node3X.x6&&ymr3Ready<node3Y.y2Ready){
xmr3++;
ymr3Ready=node3Y.y1*winCHB+(xmr3-node3X.x5)*winWB;
ctx3.moveTo(node3X.x5*winWB,node3Y.y1*winCHB)
ctx3.lineTo(xmr3*winWB,ymr3Ready)
}else if(xmr3==node3X.x6&&ymr3<node3Y.yh){
ymr3++;
ctx3.moveTo(node3X.x6*winWB,node3Y.y2Ready);
ctx3.lineTo(node3X.x6*winWB,node3Y.y2Ready+ymr3*winCHB);
}else if(ymr3==node3Y.yh&&xmr3>node3X.x5){
xmr3--;
ctx3.moveTo(node3X.x6*winWB,node3Y.y3Ready);
ctx3.lineTo(xmr3*winWB,node3Y.y3Ready+(node3X.x6-xmr3)*winWB)
}else if(xmr3<=node3X.x5&&xmr3>50){
xmr3--;
ctx3.moveTo(node3X.x5*winWB,node3Y.y4Ready);
ctx3.lineTo(xmr3*winWB,node3Y.y4Ready);
}else{
ctx3.clearRect(0,0,canvas3.width,canvas3.height);
ctx3.beginPath();
ctx3.moveTo(node3X.x3*winWB,node3Y.y1Ready);
ctx3.lineTo(node3X.x2*winWB,node3Y.y1Ready);
ctx3.lineTo(node3X.x1*winWB,node3Y.y2Ready);
ctx3.lineTo(node3X.x1*winWB,node3Y.y3Ready);
ctx3.lineTo(node3X.x2*winWB,node3Y.y4Ready);
ctx3.lineTo(node3X.x5*winWB,node3Y.y4Ready);
ctx3.lineTo(node3X.x6*winWB,node3Y.y3Ready);
ctx3.lineTo(node3X.x6*winWB,node3Y.y2Ready);
ctx3.lineTo(node3X.x5*winWB,node3Y.y1Ready);
ctx3.lineTo(node3X.x4*winWB,node3Y.y1Ready);
clearInterval(mainBoxTimer3);
}
ctx3.stroke();
ctx3.closePath();
}
技术实现是基础,逻辑优化是提升,是质量和效率的提升。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。