最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript利用canvas實現(xiàn)炫酷的碎片切圖效果

 更新時間:2022年10月24日 10:39:51   作者:南玖  
這篇文章主要和大家分享一個炫酷的碎片式切圖效果,本文主要利用canvas來實現(xiàn),代碼量不多,但有些地方還是需要花點時間去理解的,感興趣的可以學(xué)習(xí)一下

前言

今天分享一個炫酷的碎片式切圖效果,這個其實在自己的之前的博客上有實現(xiàn)過,本人覺得這個效果還是挺炫酷的,這次還是用我們的canvas來實現(xiàn),代碼量不多,但有些地方還是需要花點時間去理解的,需要點數(shù)學(xué)幾何理解能力,老規(guī)矩,我們還是先看效果再來看實現(xiàn)步驟。

需求分析

從上面我們看到圖片在切換的時候其實是一個一個的小碎片慢慢從點擊位置往外擴(kuò)散開來,這一個個小碎片,在頁面中其實就是一個個的小方塊。這里的難點在于如何將一張完整的圖片切割成一個一個的小方塊分別進(jìn)行渲染,還有就是這個棱形圖案的位置確定。

  • 切割:這里我們可以以坐標(biāo)系的形式來進(jìn)行切割,每一個方塊都對應(yīng)著它們自己在坐標(biāo)系中的位置(x, y)
  • 繪制:這里的重點在于drawImage方法
  • 棱形擴(kuò)散:這里需要點數(shù)學(xué)幾何理解能力,后面作圖理解

實現(xiàn)過程

坐標(biāo)系

在實現(xiàn)之前,我們先來理解一個概念:「坐標(biāo)系」

注意:這里所說的坐標(biāo)系不是我們數(shù)學(xué)中的坐標(biāo)系,但兩者又有些類似,不同點在于兩者的原點位置以及y軸的方向不同。

切割

這一步主要是為了確定每一個單元格的大小,單元格的長寬最好不要是最大公約數(shù)或最小公約數(shù),因為過大效果不夠炫,過小性能會有壓力。

我這里畫板長寬為 800 * 530 ,選取 16 * 15 為單元尺寸,即整個畫布由 50 * 35 共 1750 個單元格組成。切割分完單元格之后我們需要先計算一些基本的參數(shù)備用。

this.imgW?=?800;?//?圖片原始寬
this.imgH?=?530;?//?圖片原始高

this.conW?=?800;?//?畫布寬
this.conH?=?530;?//??畫布高

this.dw?=?16;?//?單元格寬
this.dh?=?15;?//?單元格高

this.I?=?this.conH?/?this.dh;?//單元行數(shù)
this.J?=?this.conW?/?this.dw;?//?單元列數(shù)

this.DW?=?this.imgW?/?this.J;?//?原圖單元寬
this.DH?=?this.imgH?/?this.I;?//?原圖單元高

「行數(shù) = 畫布高度 / 單元格高度;列數(shù) = 畫面寬度 / 單元格寬度」

繪制

本次繪制的重點在于drawImage這個方法,我們可以先來了解一下這個方法的參數(shù)及功能

drawImage

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

這個方法一共有9個參數(shù),作用是在畫布上繪制圖像??吹竭@么多參數(shù)是不是已經(jīng)被勸退了,哈哈

  • 「image」:繪制到上下文的元素。允許任何的畫布圖像源,例如:HTMLImageElement、SVGImageElementHTMLVideoElement、HTMLCanvasElementImageBitmap、OffscreenCanvas或 VideoFrame 。
  • 「sx」:(可選)需要繪制到目標(biāo)上下文中的,image 的矩形(裁剪)選擇框的左上角 X 軸坐標(biāo)??梢允褂?3 參數(shù)或 5 參數(shù)語法來省略這個參數(shù)。
  • 「s y」:(可選)需要繪制到目標(biāo)上下文中的,image 的矩形(裁剪)選擇框的左上角 Y 軸坐標(biāo)??梢允褂?3 參數(shù)或 5 參數(shù)語法來省略這個參數(shù)。
  • 「sWidth」:(可選)需要繪制到目標(biāo)上下文中的,image 的矩形(裁剪)選擇框的寬度。如果不說明,整個矩形(裁剪)從坐標(biāo)的 sx 和 sy 開始,到 image 的右下角結(jié)束??梢允褂?3 參數(shù)或 5 參數(shù)語法來省略這個參數(shù)。使用負(fù)值將翻轉(zhuǎn)這個圖像。
  • 「sHeight」:(可選)需要繪制到目標(biāo)上下文中的,image的矩形(裁剪)選擇框的高度。使用負(fù)值將翻轉(zhuǎn)這個圖像。
  • 「dx」image 的左上角在目標(biāo)畫布上 X 軸坐標(biāo)。
  • 「dy」image 的左上角在目標(biāo)畫布上 Y 軸坐標(biāo)。
  • 「dWidth」image 在目標(biāo)畫布上繪制的寬度。允許對繪制的 image 進(jìn)行縮放。如果不說明,在繪制時 image 寬度不會縮放。注意,這個參數(shù)不包含在 3 參數(shù)語法中。
  • 「dHeight」image 在目標(biāo)畫布上繪制的高度。允許對繪制的 image 進(jìn)行縮放。如果不說明,在繪制時 image 高度不會縮放。注意,這個參數(shù)不包含在 3 參數(shù)語法中。

這9個參數(shù)我們可以這樣來記憶,第一個參數(shù)是圖像源,接下來的四個參數(shù)指的是原圖,最后四個參數(shù)指的是畫布

切割&渲染

這里我們主要是將一張圖片切割成一個個的小碎片,是這些碎片拼起來就是一張完整的圖片。

class?ChipBanner?{
??constructor()?{
????this.cvs?=?document.querySelector("#chip");
????this.ctx?=?this.cvs.getContext("2d");
????this.imgList?=?document.querySelectorAll(".bg");
????this.imgIndex?=?0;
????this.isAnimating?=?false;

????this.imgW?=?800;?//圖片原始寬/高
????this.imgH?=?530;

????this.conW?=?800;?//畫布寬/高
????this.conH?=?530;

????this.dw?=?16;?//畫布單元寬/高
????this.dh?=?15;

????this.I?=?this.conH?/?this.dh;?//單元行/列數(shù)
????this.J?=?this.conW?/?this.dw;

????this.DW?=?this.imgW?/?this.J;?//原圖單元寬/高
????this.DH?=?this.imgH?/?this.I;
??}

??init()?{
????this.ctx.beginPath();

????for?(let?i?=?0;?i?<?this.I;?i++)?{
??????for?(let?j?=?0;?j?<?this.J;?j++)?{
????????this.chipDraw(this.imgList[this.imgIndex],?i,?j);
??????}
????}

????this.ctx.closePath();
????this.ctx.stroke();
??}
??drawText()?{
????this.ctx.font?=?"150px?serif";
????this.ctx.strokeStyle?=?"white";
????this.ctx.strokeText("1024",?500,?500);
??}

??chipDraw(img,?i,?j)?{
????this.drawText();
????//負(fù)責(zé)繪制,i:?單元行號;j:?單元列號
????this.ctx.drawImage(
??????img,
??????this.DW?*?j,
??????this.DH?*?i,
??????this.DW,
??????this.DH,
??????this.dw?*?j,
??????this.dh?*?i,
??????this.dw,
??????this.dh
????);
??}
}

這里正確拼出來看到的和正常圖片沒有任何區(qū)別

再來看一張拼錯的圖

剛開始幾何坐標(biāo)那里沒寫對,拼出來就成這樣了,哈哈,看著就像動畫幀卡住的樣子。

動畫

這里主要是要找出某個點周圍棱形范圍內(nèi)的所有點的坐標(biāo),然后在清除這些坐標(biāo)圖案的同時,開始繪制下一張圖片。

「菱形線上的點與坐標(biāo)的 行號差值的絕對值 + 列號差值的絕對值 = 距離」

找出坐標(biāo)棱形范圍內(nèi)所有的點

countAround(i,?j,?dst)?{
????let?arr?=?[];
????for?(let?m?=?i?-?dst;?m?<=?i?+?dst;?m++)?{
??????for?(let?n?=?j?-?dst;?n?<=?j?+?dst;?n++)?{
????????if?(
??????????Math.abs(m?-?i)?+?Math.abs(n?-?j)?==?dst?&&
??????????m?>=?0?&&
??????????n?>=?0?&&
??????????m?<=?this.I?-?1?&&
??????????n?<=?this.J?-?1
????????)?{
??????????arr.push({?x:?m,?y:?n?});
????????}
??????}
????}
????return?arr;
??}

清除單元格畫布

chipClear(i,?j)?{
????this.ctx.clearRect(this.dw?*?j,?this.dh?*?i,?this.dw,?this.dh);
}

合并&動畫

start(i,?j)?{
????if?(this.isAnimating)?return;

????this.isAnimating?=?true;

????this.imgIndex++;

????if?(this.imgIndex?>?this.imgList.length?-?1)?this.imgIndex?=?0;

????let?_this?=?this,
??????dst?=?0,
??????timer?=?setInterval(()?=>?{
????????let?resArr?=?_this.countAround(i,?j,?dst);

????????resArr.forEach((item)?=>?{
??????????_this.chipClear(item.x,?item.y);??//?清除單元格
??????????_this.chipDraw(_this.imgList[_this.imgIndex],?item.x,?item.y);?//?繪制下一張圖片
????????});

????????if?(!resArr.length)?{
??????????clearInterval(timer);
??????????_this.isAnimating?=?false;
????????}
????????dst++;
??????},?30);
??}

大功告成,這樣就實現(xiàn)了一個炫酷的碎片式切圖效果了~

到此這篇關(guān)于JavaScript利用canvas實現(xiàn)炫酷的碎片切圖效果的文章就介紹到這了,更多相關(guān)JavaScript canvas碎片切圖效果內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

德州市| 石城县| 蒲城县| 金平| 广昌县| 崇信县| 大荔县| 安西县| 通河县| 沈阳市| 翁牛特旗| 金沙县| 镇江市| 行唐县| 剑河县| 炉霍县| 东至县| 肇庆市| 淅川县| 霍邱县| 海林市| 东辽县| 临武县| 鄢陵县| 禹州市| 务川| 庄浪县| 台州市| 鄂托克旗| 扬州市| 宁晋县| 台湾省| 滁州市| 澄迈县| 南康市| 贵州省| 上高县| 瑞丽市| 融水| 通河县| 枞阳县|