1. 程式人生 > 其它 >利用js結合canvas給圖片打馬賽克

利用js結合canvas給圖片打馬賽克

效果演示

什麼是canvas?

<canvas> 元素用於圖形的繪製,只是圖形容器。
元素本身並沒有繪製能力,您必須使用js指令碼來繪製圖形。
getContext() 方法可返回一個物件,該物件提供了用於在畫布上繪圖的方法和屬性

知識點簡介

  • 建立DOM元素
  // 建立DOM元素
  let img = new Image()      
  img.src = './cat.webp'
  //新增到HTML中
  document.body.appendChild(img)
  • ctx.drawImage()
  ctx.drawImage()
  // 在畫布上定點陣圖像:
  context.drawImage(img,x,y);
  // 在畫布上定點陣圖像,並規定影象的寬度和高度:
  context.drawImage(img,x,y,width,height);
  • ctx.getImageData()
  // JavaScript 語法 getImageData() 方法返回 ImageData 物件,該物件拷貝了畫布指定矩形的畫素資料。
  // 對於 ImageData 物件中的每個畫素,都存在著四方面的資訊
  // 即 RGBA 值:R - 紅色 (0-255) G - 綠色 (0-255) B - 藍色 (0-255) A - alpha 通道 (0-255; 0 是透明的,255 是完全可見的) color/alpha 以陣列形式存在,並存儲於 ImageData 物件的 data 屬性中
  var imgData=context.getImageData(x,y,width,height);  從(0,0) 到 (width,height)
  • ctx.putImageData()
  // putImageData() 方法將影象資料(從指定的 ImageData 物件)放回畫布上。
  // 更新canvas資料
  ctx.putImageData(imgData, 0, 0)

全部程式碼

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      font-size: 0;
    }
    * {
      margin: 0;
      padding: 0;
    }
    img {
      display: inline-block;
    }
  </style>
</head>
<body>
  <img src="./cat.webp">
  <button onclick="addCanvas()">生成Canvas</button>
  <button onclick="generateImg()">生成圖片</button>
  <script>
    function addCanvas() {
      let bt = document.querySelector('button')
      // 建立DOM元素
      let img = new Image()      
      img.src = './cat.webp'
      // 待圖片載入完成
      img.onload = function() { 
        // this指向圖片
        let imgWidth = this.width   
        let imgHeight = this.height
        let { canvas, ctx } = createCanvasAndCtx(imgWidth, imgHeight)
        // 在畫布上繪製該圖片,定點陣圖像以及規定影象寬高
        ctx.drawImage(this, 0, 0, imgWidth, imgHeight)
        // 把canvas插入到生成canvas按鈕前面
        document.body.insertBefore(canvas, bt)
      }
    }
    function createCanvasAndCtx(imgWidth, imgHeight) {
      let canvas = document.createElement('canvas')
      canvas.setAttribute('width', imgWidth)   // 畫布的寬高為圖片的寬高
      canvas.setAttribute('height', imgHeight)  
      canvas.setAttribute('onmousedown', 'start()')   // 滑鼠按下事件
      let ctx = canvas.getContext('2d')
      return {
        canvas,
        ctx
      }
    }
    function start() {
      let img = document.querySelector('img'),
        canvas = document.querySelector('canvas'),
        ctx = canvas.getContext('2d')
        
      imgData = ctx.getImageData(0, 0, img.clientWidth, img.clientHeight) // 畫素資料
      canvas.onmousemove = (e) => {
        let w = imgData.width, //1.獲取圖片寬高
          h = imgData.height,
          num = 10,  // 馬賽克的程式, 數字越大越模糊
          color = getXY(imgData, e.offsetX, e.offsetY)

        for (let i = 0; i < num; i++) {
          for (let j = 0; j < num; j++) {
            //設定imgData上座標為(e.offsetX + l, e.offsetY + k)的的顏色
            setXY(imgData, e.offsetX + i, e.offsetY + j, color)
          }
        }
        // 更新canvas資料
        ctx.putImageData(imgData, 0, 0)
      }
    }

    // 獲取滑鼠當前所在的畫素RGBA
    function getXY(obj, x, y) {
      var { width, height, data} = obj,
        color = []
      color[0] = obj.data[4 * (y * width + x)]
      color[1] = obj.data[4 * (y * width + x) + 1]
      color[2] = obj.data[4 * (y * width + x) + 2]
      color[3] = obj.data[4 * (y * width + x) + 3]
      return color
    }

    function setXY(obj, x, y, color) {
      var { width, height, data} = obj,
        color = []
      obj.data[4 * (y * width + x)] = color[0]
      obj.data[4 * (y * width + x) + 1] = color[1]
      obj.data[4 * (y * width + x) + 2] = color[2]
      obj.data[4 * (y * width + x) + 3] = color[3]
    }
    // 畫布匯出為 Base64 編碼的圖片
    function generateImg() {
      let canvas = document.querySelector('canvas')
      let newImg = new Image()
      newImg.src = canvas.toDataURL("image/png")
      document.body.append(newImg)
    }
  </script>
</body>
</html>