JavaScript Canvas繪制動(dòng)態(tài)線框效果
本文實(shí)例為大家分享了JavaScript Canvas繪制動(dòng)態(tài)線框效果的具體代碼,供大家參考,具體內(nèi)容如下
本周項(xiàng)目,移動(dòng)端頁面開發(fā),要求豐富的動(dòng)效,主要技術(shù)實(shí)現(xiàn) Canvas ;其中繪制動(dòng)態(tài)線框,走了點(diǎn)彎路,所謂的彎路是邏輯問題,非技術(shù)實(shí)現(xiàn)方式。
一、涉及技術(shù)點(diǎn),具體如下:
1.html 中引入canvas 標(biāo)簽,設(shè)置寬高;
<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();
繪制靜態(tài)折線,比較簡單,直接從moveTo初始節(jié)點(diǎn)開始lineTo到每一個(gè)節(jié)點(diǎn),項(xiàng)目需求是繪制線條的動(dòng)畫效果,那實(shí)現(xiàn)方式就是在每一條直線段間,通過定時(shí)器多次重回moveTo起點(diǎn)到lineTo直線段上有序增量的點(diǎn)位,代碼如下:
ctx.moveTo(x1,y3); xm1+=fre1; ym1+=fre2; ctx.lineTo(xm1,ym1)
二、邏輯彎路及解決
1、邏輯彎路
項(xiàng)目是移動(dòng)端,考慮適配問題,在繪制節(jié)點(diǎn)的時(shí)候,開始使用的是以百分比與獲取屏幕后的寬高的乘積做為判斷moveTo更改的true or false; 鑒于乘積的非整數(shù),在if語句里x,y的增量變化 只能使用++;而且是px單位的增量,所以導(dǎo)致在繪制時(shí)速度很慢,即便是setInterval 的時(shí)間個(gè)位毫秒
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,就會出現(xiàn)如下邊框不完整問題:
2.解決方案:
在判斷語句中,橫向100等分,節(jié)點(diǎn)即為100以內(nèi)整數(shù)值,增量也以此累加,moveTo 和 lineTo的時(shí)候 再換算成具體px; 通過百分值,可以提高單位時(shí)間的繪制效率,此時(shí)只需控制增量每次++;再配合定時(shí)器 的周期,很容易實(shí)現(xiàn)不同頻率的線條繪制;另外對節(jié)點(diǎn)封裝于一個(gè)對象內(nèi),可以快速調(diào)整節(jié)點(diǎn)繪制不同尺寸 類型的動(dòng)態(tài)線框圖:
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(); }
技術(shù)實(shí)現(xiàn)是基礎(chǔ),邏輯優(yōu)化是提升,是質(zhì)量和效率的提升。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Web網(wǎng)站都變成灰色有哪些方法可以快速實(shí)現(xiàn)(解決方案)
有些時(shí)候我們需要把網(wǎng)站頁面變成黑白色或灰色,特別是對于一些需要悼念的日子,以及一些影響力很大的偉人逝世或紀(jì)念日的時(shí)候,都會讓網(wǎng)站的全部網(wǎng)頁變成灰色(黑白色),以表示我們對逝者或者英雄的緬懷和悼念2022-12-12javascript實(shí)現(xiàn)base64 md5 sha1 密碼加密
本篇文章給大家介紹了javascript實(shí)現(xiàn)密碼加密,通過base64、md5、sha1文件,調(diào)用相關(guān)方法實(shí)現(xiàn)密碼加密,非常簡單,需要的朋友可以參考下2015-09-09uni-app如何用JS動(dòng)態(tài)修改scss樣式變量
對于uni-app中的組件,可以通過修改它們的樣式來自定義它們的外觀,下面這篇文章主要給大家介紹了關(guān)于uni-app如何用JS動(dòng)態(tài)修改scss樣式變量的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07異步j(luò)avascript的原理和實(shí)現(xiàn)技巧介紹
因?yàn)楣ぷ鞯男枰?,我要在網(wǎng)頁端編寫一段腳本,把數(shù)據(jù)通過網(wǎng)頁批量提交到系統(tǒng)中去。所以我就想到了Greasemonkey插件,于是就開始動(dòng)手寫,發(fā)現(xiàn)問題解決得很順利2012-11-11JavaScript設(shè)計(jì)模式之策略模式實(shí)例
這篇文章主要介紹了JavaScript設(shè)計(jì)模式之策略模式實(shí)例,本文分析了Jquery源碼并給出了自己的實(shí)現(xiàn),需要的朋友可以參考下2014-10-10js multiple全選與取消全選實(shí)現(xiàn)代碼
本文章總結(jié)了利用jquery與js實(shí)現(xiàn)multiple全選與取消全選代碼有需要參考的朋友可參考下2012-12-12如何解決attachEvent函數(shù)時(shí),this指向被綁定的元素的問題?
如何解決attachEvent函數(shù)時(shí),this指向被綁定的元素的問題?...2007-04-04js中設(shè)計(jì)一段程序,讓它能夠打印自己的方法收集藏
js中設(shè)計(jì)一段程序,讓它能夠打印自己的方法收集藏...2007-03-03