麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > HTML > 正文

html5如何在Canvas中實(shí)現(xiàn)自定義路徑動(dòng)畫示例

2024-08-26 00:20:01
字體:
供稿:網(wǎng)友

在最近的項(xiàng)目中筆者需要做一個(gè)新需求:在canvas中實(shí)現(xiàn)自定義的路徑動(dòng)畫。這里所謂的自定義路徑不單單包括一條直線,也許是多條直線的運(yùn)動(dòng)組合,甚至還包含了貝塞爾曲線,因此,這個(gè)動(dòng)畫也許是下面這個(gè)樣子的:

canvas實(shí)現(xiàn)路徑動(dòng)畫,Canvas自定義路徑動(dòng)畫

那么如何才能在canvas中實(shí)現(xiàn)這種動(dòng)畫效果呢?其實(shí)很簡(jiǎn)單,對(duì)于路徑的處理svg非常在行,因此在canvas中實(shí)現(xiàn)自定義路徑動(dòng)畫,我們需要借助svg的力量。

創(chuàng)建Path

制作動(dòng)畫前,先要拿到動(dòng)畫的路徑,對(duì)此我們可以直接使用svg的path定義規(guī)則,比如我們定義了一條較為復(fù)雜的路徑(它到底長(zhǎng)什么樣大家可以自己試試,這里就不展示了),然后,我們需要將定義好的路徑導(dǎo)入進(jìn)一個(gè)新生成的path元素中(我們只是借助svg的api,因此并不需要將其插到頁面內(nèi))

const path = 'M0,0 C8,33.90861 25.90861,16 48,16 C70.09139,16 88,33.90861 88,56 C88,78.09139 105.90861,92 128,92 C150.09139,92 160,72 160,56 C160,40 148,24 128,24 C108,24 96,40 96,56 C96,72 105.90861,92 128,92 C154,93 168,78 168,56 C168,33.90861 185.90861,16 208,16 C230.09139,16 248,33.90861 248,56 C248,78.09139 230.09139,96 208,96 L48,96 C25.90861,96 8,78.09139 8,56 Z';const pathElement = document.createElementNS('http://www.w3.org/2000/svg',"path"); pathElement.setAttributeNS(null, 'd', path);

getTotalLength與getPointAtLength

SVGPathElement提供的這兩個(gè)api很關(guān)鍵,可以說它是實(shí)現(xiàn)路徑動(dòng)畫的最為核心的地方(在svg內(nèi)實(shí)現(xiàn)自定義路徑動(dòng)畫一般也是通過這兩個(gè)api去解決)詳情請(qǐng)戳:SVGPathElement MDN

getTotalLength方法可以獲取SVGPathElement的總長(zhǎng)度

getPointAtLength方法,傳入一個(gè)長(zhǎng)度x,將返回距離SVGPathElement起點(diǎn)的長(zhǎng)度為x的終點(diǎn)坐標(biāo)。

利用這兩個(gè)api,通過循環(huán)的方式不斷去更新canvas內(nèi)所繪制的圖形坐標(biāo),即可實(shí)現(xiàn)路徑動(dòng)畫:

const length = pathElement.getTotalLength();const duration = 1000; // 動(dòng)畫總時(shí)長(zhǎng)const interval = length / duration;const canvas = document.querySelector('canvas');const context = canvas.getContext('2d');let time = 0, step = 0; const timer = setInterval(function() {  if (time <= duration) {    const x = parseInt(pathElement.getPointAtLength(step).x);    const y = parseInt(pathElement.getPointAtLength(step).y);    move(x, y);  // 更新canvas所繪制圖形的坐標(biāo)    step++;  } else {    clearInterval(timer)  }}, interval);function move(x, y) {   context.clearRect(0, 0, canvas.width, canvas.height);   context.beginPath();   context.arc(x, y, 25, 0, Math.PI*2, true);   context.fillStyle = '#f0f';   context.fill();   context.closePath();}

最后,我們把它封裝一下,即可實(shí)現(xiàn)一個(gè)在canvas中實(shí)現(xiàn)自定義動(dòng)畫的簡(jiǎn)易函數(shù)啦:

function customizePath(path, func) {    const pathElement = document.createElementNS('http://www.w3.org/2000/svg',"path");     pathElement.setAttributeNS(null, 'd', path);      const length = pathElement.getTotalLength();    const duration = 1000;     const interval = length / duration;    let time = 0, step = 0;         const timer = setInterval(function() {        if (time <= duration) {              const x = parseInt(pathElement.getPointAtLength(step).x);              const y = parseInt(pathElement.getPointAtLength(step).y);              func(x, y);              step++;        } else {              clearInterval(timer)        }     }, interval);}const path = 'M0,0 C8,33.90861 25.90861,16 48,16 C70.09139,16 88,33.90861 88,56 C88,78.09139 105.90861,92 128,92 C150.09139,92 160,72 160,56 C160,40 148,24 128,24 C108,24 96,40 96,56 C96,72 105.90861,92 128,92 C154,93 168,78 168,56 C168,33.90861 185.90861,16 208,16 C230.09139,16 248,33.90861 248,56 C248,78.09139 230.09139,96 208,96 L48,96 C25.90861,96 8,78.09139 8,56 Z';const canvas = document.querySelector('canvas');const context = canvas.getContext('2d');function move(x, y) {      context.clearRect(0, 0, canvas.width, canvas.height);    context.beginPath();      context.arc(x, y, 25, 0, Math.PI*2, true);      context.fillStyle = '#f0f';      context.fill();      context.closePath();}customizePath(path, move);

實(shí)現(xiàn)思路大致如上所述,然而這并不是最終成果。當(dāng)我們決定要在canvas制作自定義路徑動(dòng)畫時(shí),我們不僅要考慮如何實(shí)現(xiàn),更要考慮性能優(yōu)化,比如在這個(gè)實(shí)現(xiàn)思路中,我們是否可以減少不必要的渲染次數(shù)?幀率如何控制達(dá)到最優(yōu)?等等。

雖然它們并不在這篇文章的討論范圍中,當(dāng)也應(yīng)當(dāng)值得我們思考。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VeVb武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到HTML教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 免费视频www在线观看 | 国产九色在线播放九色 | 97青青草视频 | 久久精品二区 | 中文字幕网在线 | 国产1区2 | 久久午夜神器 | 欧美毛片 | 国产毛片在线看 | 国产一区视频在线观看免费 | 久久亚洲国产午夜精品理论片 | 亚洲性在线视频 | 蜜桃91麻豆| 午夜精品久久久久久久96蜜桃 | av在线免费看网址 | 激情小视频在线观看 | 欧美在线观看禁18 | 日日噜噜噜噜久久久精品毛片 | 欧美一级淫片免费视频1 | 深夜小视频在线观看 | 日本免费一区二区三区四区 | 黄片毛片一级 | 久久久久久久久久综合 | 久久国产成人午夜av浪潮 | 九九热在线视频免费观看 | 久久99精品久久 | 一级毛片在线观看免费 | 亚洲一区二区在线免费 | 久久精片 | 日本黄色免费片 | 99热久草 | 九一免费国产 | 久久久久久久久久久久久久久久久久 | 国产精品久久久久久久久久10秀 | 日韩中文一区 | 黄色免费小视频网站 | 中国av免费在线观看 | 久久99国产视频 | 亚洲一级簧片 | 久草在线播放视频 | 国产一级在线看 |