利用js结合canvas给图片打马赛克

效果演示

动画.gif

什么是canvas?

<canvas> 元素用于图形的绘制,只是图形容器。
元素本身并没有绘制能力,您必须使用js脚本来绘制图形。
getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性

image.png

知识点简介

  • 创建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>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是利用electron框架结合canvas画波形图的全部过程以及代码: 1. 创建一个新的electron项目,安装必要的依赖项(electron、canvas)。 2. 在项目中创建一个HTML文件,添加一个canvas元素用于绘制波形图。例如: ``` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Waveform</title> </head> <body> <canvas id="waveform"></canvas> </body> </html> ``` 3. 在项目中创建一个JavaScript文件,用于绘制波形图。首先,获取canvas元素和其上下文: ``` const canvas = document.getElementById('waveform'); const ctx = canvas.getContext('2d'); ``` 4. 创建一个AudioContext对象,用于加载音频并解码: ``` const audioCtx = new AudioContext(); ``` 5. 加载音频文件并解码: ``` const audioElement = document.getElementById('audio'); const audioSource = audioCtx.createMediaElementSource(audioElement); const analyser = audioCtx.createAnalyser(); audioSource.connect(analyser); analyser.connect(audioCtx.destination); ``` 6. 设置analyser的参数,包括FFT大小、频域数据长度等: ``` analyser.fftSize = 2048; const bufferLength = analyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); ``` 7. 在requestAnimationFrame函数中周期性地更新波形图: ``` function draw() { requestAnimationFrame(draw); analyser.getByteTimeDomainData(dataArray); ctx.fillStyle = 'rgb(200, 200, 200)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.lineWidth = 2; ctx.strokeStyle = 'rgb(0, 0, 0)'; ctx.beginPath(); const sliceWidth = canvas.width * 1.0 / bufferLength; let x = 0; for(let i = 0; i < bufferLength; i++) { const v = dataArray[i] / 128.0; const y = v * canvas.height / 2; if(i === 0) { ctx.moveTo(x, y); } else { ctx.lineTo(x, y); } x += sliceWidth; } ctx.lineTo(canvas.width, canvas.height / 2); ctx.stroke(); }; draw(); ``` 完整的JavaScript代码如下: ``` const canvas = document.getElementById('waveform'); const ctx = canvas.getContext('2d'); const audioCtx = new AudioContext(); const audioElement = document.getElementById('audio'); const audioSource = audioCtx.createMediaElementSource(audioElement); const analyser = audioCtx.createAnalyser(); audioSource.connect(analyser); analyser.connect(audioCtx.destination); analyser.fftSize = 2048; const bufferLength = analyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); function draw() { requestAnimationFrame(draw); analyser.getByteTimeDomainData(dataArray); ctx.fillStyle = 'rgb(200, 200, 200)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.lineWidth = 2; ctx.strokeStyle = 'rgb(0, 0, 0)'; ctx.beginPath(); const sliceWidth = canvas.width * 1.0 / bufferLength; let x = 0; for(let i = 0; i < bufferLength; i++) { const v = dataArray[i] / 128.0; const y = v * canvas.height / 2; if(i === 0) { ctx.moveTo(x, y); } else { ctx.lineTo(x, y); } x += sliceWidth; } ctx.lineTo(canvas.width, canvas.height / 2); ctx.stroke(); }; draw(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值