gdutwyg / blog

使用issues记录笔记
0 stars 1 forks source link

canvas 实现对一张图片镂空其中一部分 #73

Open gdutwyg opened 5 years ago

gdutwyg commented 5 years ago

前菜

最近有一个需求,需要对一张图片镂空一部分,位置不确定,想用前端实现。 于是我想了一想,svg?canvas?还是css3属性mask-image 或者 clip-path? 最后用canvas 实现了。

正菜

首先你用canvas读取了原图,然后用canvas的getContext(’2d‘) 获取canvas 的上下文, 调用createImageData方法去定义镂空的区域,然后对该区域遍历,设置rgba值为透明,最后把设置好的区域调用putImageData画到canvas画布,就完成了。

下面是实现代码:demo

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
  </style>
</head>

<body>
  <p>画布:</p>
  <canvas id="canvas" width="960" height="300"></canvas>
  <p>生成的图片:</p>
  <img src="" alt="" class="generate-img">
</body>
<script>
  var sourceImg = new Image()
  sourceImg.src = 'https://sp-webfront.skypixel.com/skypixel/v2/public/website/assets/1535027674204-f6eca6369ec03e70262b58b0e25cda7b.jpg'
  sourceImg.setAttribute("crossOrigin", 'anonymous')
  var generateImg = document.querySelector(".generate-img")
  var canvas = document.getElementById("canvas")
  var ctx = canvas.getContext("2d")
  sourceImg.onload = function () {
    // img生成到画布上
    drawImageFn(sourceImg)
    //100*100 是此区域所在面积有多少个像素单位;x*y   100*100 = 10000 个rgba()
    const imgData = ctx.createImageData(400, 100)
    //imgData.data是储存rgba()的一个400 *100 * 4长度的数组 因为颜色的组成部分为rgba(R,G,B,透明度)
    for (let i = 0; i < imgData.data.length; i += 4) {
      imgData.data[i] = 0
      imgData.data[i + 1] = 0
      imgData.data[i + 2] = 0
      imgData.data[i + 3] = 0    // 透明度 0~255
    }
    //将上面for循环得到的像素数据画到canvas画布上
    ctx.putImageData(imgData, 100, 100)

    generateImgFn()
  }
  // 用canvas生成img
  function drawImageFn(img) {
    ctx.drawImage(img, 0, 0, 960, 300)
  }
  // 生成img
  function generateImgFn() {
    generateImg.src = canvas.toDataURL()
  }
</script>

</html>

如果遇到canvas.toDataURL() 报Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported 则是因为跨域问题,可参考此链接

参考

HTML5 参考手册 学习 HTML5 Canvas 这一篇文章就够了