国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > JS > 正文

用canvas 實現個圖片三角化(LOW POLY)效果

2024-05-06 16:28:40
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了用canvas 實現個圖片三角化(LOW POLY)效果 的相關資料,需要的朋友可以參考下
 

之前無意中看到Ovilia 用threejs做了個LOW POLY,也就是圖片平面三角化的效果,覺得很驚艷,然后就自己花了點時間嘗試了一下。 

  我是沒怎么用過threejs,所以就直接用canvas的2d繪圖API來做,因為感覺似乎這效果也用不上threejs。

  直接上demo先:http://whxaxes.github.io/canvas-test/src/Funny-demo/lowpoly/index.html (也可以在移動端看,不過因為計算量比較大,移動設備計算起來會比PC要多花些時間。)

  做這種效果主要需要把圖片三角化,以及對圖片進行邊緣化檢測。這兩個,第一個用到的delaunay三角化算法,第二個用到的sobel邊緣檢測算法。聽起來偷挺高大上的,索性兩個算法都有相應的開源組件可以直接拿來用:ironwallaby的delaunay組件 以及 Miguel Mota的sobel組件。

  這兩個算法sobel還好一點,delaunay就有點復雜了,待日后可以研究一下。不過目前只為做出個效果的話,還是可以用這些組件的。

  兩個最重要的組件都有了,剩下的事就很簡單了:

  先將圖片繪制到canvas上:

canvas.width = (img.width > 800) ? 800 : img.width;canvas.height = img.height * canvas.width/img.width;ctx.drawImage(img, 0, 0, canvas.width, canvas.height); 

然后獲取到canvas的imgData,再通過sobel計算返回新的imgData

var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);var newImgData = Sobel(imgData);

如果我們把newImgData放到canvas上,就會發現,彩色圖片變成了這樣的灰度圖片:

用canvas 實現個圖片三角化(LOW POLY)效果

由于上面說的那個Sobel組件不是很適合自己的用法,同時代碼也有不恰當的地方,所以自己做了適當修改和優化,優化了循環方法,加快了運算速度,同時加入了回調函數。詳見該項目github中的sobel.js文件  

在Sobel方法中對imgData.data進行遍歷的時候,會調用回調函數,在回調中把顏色值大于40(也就是灰度為rgb(40,40,40)以上的)的坐標點記錄下來。然后隨機獲取一部分邊緣點,再加入一些隨機出來的坐標 以及 四個邊角的坐標值。這樣,我們就可以獲取到我們需要的坐標點了

var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);// 收集色值大于40的邊緣像素點var collectors = [];Sobel(imgData , function(value , x , y){if(value > 40){collectors.push([x , y]);}});// 添加一些隨機點for(var i=0;i<300;i++){particles.push([Math.random()*canvas.width , Math.random()*canvas.height]);}// 添加隨機邊緣點,數量為邊緣點數量除于50var length = ~~(collectors.length/50), random;for(var l=0;l<length;l++){random = (Math.random()*collectors.length)<<0;particles.push(collectors[random]);collectors.splice(random , 1);}// 添加四頂點坐標particles.push([0,0] , [0,canvas.height] , [canvas.width,0] , [canvas.width,canvas.height]);

獲取到坐標點后,就可以通過delaunay組件計算,獲取到拍好次序的三角坐標數組,對這些數組里的點進行連線,就可以出現這樣的效果:

用canvas 實現個圖片三角化(LOW POLY)效果

當然,我們要的效果不是連線,而是對所有三角形進行顏色填充,也就是獲取三角形的三個坐標,然后計算出中心點的坐標,再根據中心點坐標在imgData里獲取到相應的rgb的顏色值,然后填充到三角區域就可以了:

// 使用delaunay三角化獲取三角坐標var triangles = Delaunay.triangulate(particles);var x1,x2,x3,y1,y2,y3,cx,cy;for(var i=0;i < triangles.length; i+=3) {x1 = particles[triangles[i]][0];x2 = particles[triangles[i+1]][0];x3 = particles[triangles[i+2]][0];y1 = particles[triangles[i]][1];y2 = particles[triangles[i+1]][1];y3 = particles[triangles[i+2]][1];// 獲取三角形中心點坐標cx = ~~((x1 + x2 + x3) / 3);cy = ~~((y1 + y2 + y3) / 3);// 獲取中心點坐標的顏色值index = (cy*imgData.width + cx)*4;var color_r = imgData.data[index];var color_g = imgData.data[index+1];var color_b = imgData.data[index+2];// 繪制三角形ctx.save();ctx.beginPath();ctx.moveTo(x1, y1);ctx.lineTo(x2, y2);ctx.lineTo(x3, y3);ctx.closePath();ctx.fillStyle = "rgba("+color_r+","+color_g+","+color_b+",1)";ctx.fill();ctx.restore();}

上面有一點要注意,獲取到的中心點坐標一定要取整,才能夠獲取到正確的顏色參數,如果想著不取整,而是在獲取rgb索引的時候再取整,獲取到的顏色值就是錯的。因為這樣獲取到的那個像素點就不是我們要的中心像素點。

  顏色也獲取到后,就是簡單的連線,然后填充操作了,最后出來的效果就是:

用canvas 實現個圖片三角化(LOW POLY)效果

用canvas 實現個圖片三角化(LOW POLY)效果

以上內容給大家介紹了用canvas 實現個圖片三角化(LOW POLY)效果 ,希望對大家有所幫助!



注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 玉林市| 万山特区| 浙江省| 古浪县| 思茅市| 喜德县| 长阳| 蓝山县| 高阳县| 七台河市| 宿松县| 安义县| 庆云县| 广饶县| 从化市| 凤台县| 襄垣县| 奈曼旗| 高尔夫| 靖州| 秦安县| 抚远县| 勃利县| 嘉黎县| 焉耆| 威宁| 阳西县| 龙里县| 历史| 建昌县| 唐山市| 巩留县| 喀什市| 纳雍县| 吐鲁番市| 奉节县| 页游| 隆德县| 视频| 宣化县| 靖州|