canvas实战:处理图片合集

作者: 前端辉羽 | 来源:发表于2020-01-13 16:31 被阅读0次

    本文目录:
    本文中所有的图片都使用了下面这张


    原始图片效果图.png
    • 1.底片效果


      底片效果.png
    • 2.灰度效果


      灰度效果.png
    • 3.黑白效果


      黑白效果.png
    • 4.模糊效果


      模糊效果.png
    • 5.马赛克效果


      马赛克效果.png
    • 6.毛玻璃效果


      毛玻璃效果.png
    • 7.浮雕效果


      浮雕效果.png
    • 8.水平镜像效果


      水平镜像效果.png
    • 9.刮刮乐
      创建一个灰色的画布,点击鼠标开始绘制,漏出下面的底图,模拟刮奖效果


      刮刮乐.png
    • 10.绘制饼图裁剪图片


      绘制饼图裁剪图片.png

    目录1-8的html结构代码都是统一的

    <p>
        <button id="btn">显示图片</button>
        <button id="btn2">处理成xx效果</button>
    </p>
    <canvas id="canvas" width="1000" height="600"></canvas>
    

    js部分我们都是先获取点击按钮btn和btn2,然后分别绑定generate事件和handleImg事件,所有的逻辑代码都是写在这两个事件函数中,其中generate函数都是将图片绘制到canvas画布中

    var btn = document.getElementById("btn")
    btn.onclick = generate
    function generate(){
      var img = new Image()
      img.src = '../demo1.webp'
      img.onload = function (e) {
          // 将图片绘制到canvas画布上面
          // 第一个参数是图片路径
          // 第二第三是图片在canvas画布中的起始x和y位置
          // 第四个第五个参数是图片的宽和高
          ctx.drawImage(img, 0, 0, 1000, 600)
      }
    }
    var canvas = document.getElementById("canvas")
    var ctx = canvas.getContext('2d')
    
    var btn2 = document.getElementById("btn2")
    btn2.onclick = handleImg
    function handleImg(){
    
    }
    

    1.底片效果

    底片效果就是拿到每一个像素点,把rgb的值逐个取出来,然后被255减去,重置复制色值。
    这里需要学习一下创建本地服务器的前置知识,因为canvas是不允许跨域加载资源的

    function handleImg() {
        // 第一第二参数是拿图片数据的起始x和y
        // 第三第四参数是拿到图片的宽和高
        // 下面这行代码的完整意思就是我们要从canvas中拿一个图片,
        // 图片从画布的(0,0)位置开始,宽为1000,高600
        var imgData = ctx.getImageData(0, 0, 1000, 600)
        console.log(imgData)
        for (var i = 0; i < imgData.data.length; i += 4) {
            imgData.data[i] = 255 - imgData.data[i]
            imgData.data[i + 1] = 255 - imgData.data[i + 1]
            imgData.data[i + 2] = 255 - imgData.data[i + 2]
            // 下面这个代表着rgba里面a,我们直接给设置成不透明就可以了
            imgData.data[i + 3] = 255
        }
        // 重新设置一下canvas画布的对应位置的图片
        // 第二第三个参数是设置的在画布上的起始点的坐标x和y
        ctx.putImageData(imgData, 0, 0)
    }
    

    这个时候打印的话,我们会发现了报错了,报错信息大致就是图片请求跨域了
    因为我们现在的资源是在本地路径下。
    所以我们可以通过node全局安装一下http-server,
    npm i http-server -g
    然后把这个项目的根目录下运行指令 http-server,就可以把项目变成了
    服务器运行的模式,通过对应的端口就可以对项目进行访问了

    2.灰度效果

    灰度效果就是取每个像素点的rgb,将三个数值取平均数,然后将平均数赋值给对应的色值。

    function handleImg() {
        // 第一第二参数是拿图片数据的起始x和y
        // 第三第四参数是拿到图片的宽和高
        // 下面这行代码的完整意思就是我们要从canvas中拿一个图片,
        // 图片从画布的(0,0)位置开始,宽为1000,高600
        var imgData = ctx.getImageData(0, 0, 1000, 600)
        console.log(imgData)
        for (var i = 0; i < imgData.data.length; i += 4) {
            var pxValue = (imgData.data[i] + imgData.data[i + 1] + imgData.data[i + 2]) / 3
            imgData.data[i] = pxValue
            imgData.data[i + 1] = pxValue
            imgData.data[i + 2] = pxValue
        }
        // 重新设置一下canvas画布的对应位置的图片
        // 第二第三个参数是设置的在画布上的起始点的坐标x和y
        ctx.putImageData(imgData, 0, 0)
    }
    

    3.黑白效果

    黑白效果只有两种颜色,所以色值转换不是255就是0

    function handleImg() {
        // 第一第二参数是拿图片数据的起始x和y
        // 第三第四参数是拿到图片的宽和高
        // 下面这行代码的完整意思就是我们要从canvas中拿一个图片,
        // 图片从画布的(0,0)位置开始,宽为1000,高600
        var imgData = ctx.getImageData(0, 0, 1000, 600)
        console.log(imgData)
        for (var i = 0; i < imgData.data.length; i += 4) {
            var pxValue = (imgData.data[i] + imgData.data[i + 1] + imgData.data[i + 2]) / 3 > 128 ? 255 : 0
            imgData.data[i] = pxValue
            imgData.data[i + 1] = pxValue
            imgData.data[i + 2] = pxValue
        }
        // 重新设置一下canvas画布的对应位置的图片
        // 第二第三个参数是设置的在画布上的起始点的坐标x和y
        ctx.putImageData(imgData, 0, 0)
    }
    

    4.模糊效果

    根据每一个像素点,取自身及周围的的像素点,求出rgb的平均值,然后赋值给对应中心像素点。
    我们定义了一个模板变量tmpdata,该变量存储的是图片的原始色值数据,只会被读取,不会被改变。

    function handleImg() {
        var imgData = ctx.getImageData(0, 0, 1000, 600)
        // 拿到像素数据
        var pxData = imgData.data
        // 创建和上面一样的imgData的数据对象,当做模板数据
        var tmpdata = ctx.createImageData(canvas.width, canvas.height)
        tmpdata.data.set(pxData)
        // 循环出来画布的每一个像素
        for (var i = 0; i < canvas.width; i++) {
            for (var j = 0; j < canvas.height; j++) {
                // 获取到每个像素的index值
                var op = j * canvas.width + i
                var totalR = 0, totalG = 0, totalB = 0
                // 找到当前像素为中心的周围一共9个像素
                // dx和dy决定了图片的模糊程度
                for (var dx = -2; dx <= 2; dx++) {
                    for (var dy = -2; dy <= 2; dy++) {
                        var x = i + dx
                        // 边界处理
                        if (x < 0 || x >= canvas.width) {
                            x = 0
                        }
                        var y = j + dy
                        if (y < 0 || y >= canvas.height) {
                            y = 0
                        }
                        var p = y * canvas.width + x
                        totalR += tmpdata.data[p * 4 + 0]
                        totalG += tmpdata.data[p * 4 + 1]
                        totalB += tmpdata.data[p * 4 + 2]
                    }
                }
                var newR = totalR / 25
                var newG = totalG / 25
                var newB = totalB / 25
                pxData[op * 4 + 0] = newR
                pxData[op * 4 + 1] = newG
                pxData[op * 4 + 2] = newB
                pxData[op * 4 + 3] = 255
            }
        }
        ctx.putImageData(imgData, 0, 0)
        console.log(imgData)
    }
    

    5.马赛克效果

    马赛克效果和模糊效果的区别:马赛克效果是每一个固定区域,只能一次rgb的平均值,然后赋值给这个区域的每一个像素点,最终形成的是一块一块的棱角分明的模糊效果。

    function handleImg() {
        var imgData = ctx.getImageData(0, 0, 1000, 600)
        // 拿到像素数据
        var pxData = imgData.data
        // 创建和上面一样的imgData的数据对象,当做模板数据
        var tmpdata = ctx.createImageData(canvas.width, canvas.height)
        tmpdata.data.set(pxData)
        // 设置区块大小
        var size = 4
        var totalSize = size * size
        // 循环出来画布的每一个像素
        for (var i = 0; i < canvas.width; i += 4) {
            for (var j = 0; j < canvas.height; j += 4) {
                // 获取到每个像素的index值
                var op = j * canvas.width + i
                var totalR = 0, totalG = 0, totalB = 0
                // 找到当前像素为中心的周围一共9个像素
                // dx和dy决定了图片的模糊程度
                for (var dx = 0; dx < size; dx++) {
                    for (var dy = 0; dy < size; dy++) {
                        var x = i + dx
                        var y = j + dy
                        var p = y * canvas.width + x
                        totalR += tmpdata.data[p * 4 + 0]
                        totalG += tmpdata.data[p * 4 + 1]
                        totalB += tmpdata.data[p * 4 + 2]
                    }
                }
                var newR = totalR / totalSize
                var newG = totalG / totalSize
                var newB = totalB / totalSize
                // 通过遍历赋值
                for (var dx = 0; dx < size; dx++) {
                    for (var dy = 0; dy < size; dy++) {
                        var x = i + dx
                        var y = j + dy
                        var p = y * canvas.width + x
                        pxData[op * 4 + 0] = newR
                        pxData[p * 4 + 1] = newG
                        pxData[p * 4 + 2] = newB
                    }
                }
            }
        }
        ctx.putImageData(imgData, 0, 0)
    }
    

    6.毛玻璃效果

    毛玻璃效果实现了像素点色值的指定范围内的随机改变,图形会一定程度上产生扭曲的效果。

    function handleImg() {
        var imgData = ctx.getImageData(0, 0, 1000, 600)
        // 拿到像素数据
        var pxData = imgData.data
        // 创建和上面一样的imgData的数据对象,当做模板数据
        var tmpdata = ctx.createImageData(canvas.width, canvas.height)
        tmpdata.data.set(pxData)
        for (var i = 0; i < canvas.width; i++) {
            for (var j = 0; j < canvas.height; j++) {
                var op = j * canvas.width + i
                // rand的大小决定了毛玻璃的清晰程度
                var rand = Math.floor(Math.random() * 10)
                var tp = (j + rand) * canvas.width + (i + rand)
                pxData[op * 4] = tmpdata.data[tp * 4]
                pxData[op * 4 + 1] = tmpdata.data[tp * 4 + 1]
                pxData[op * 4 + 2] = tmpdata.data[tp * 4 + 2]
                pxData[op * 4 + 3] = tmpdata.data[tp * 4 + 3]
            }
        }
        ctx.putImageData(imgData, 0, 0)
    }
    

    7.浮雕效果

    取到每一个像素点和它的后一个像素点,然后两者的rgb色值取差,然后加上128。

    function handleImg() {
        var imgData = ctx.getImageData(0, 0, 1000, 600)
        // 拿到像素数据
        var pxData = imgData.data
        // 创建和上面一样的imgData的数据对象,当做模板数据
        var tmpdata = ctx.createImageData(canvas.width, canvas.height)
        tmpdata.data.set(pxData)
        for (var i = 0; i < canvas.width; i++) {
            for (var j = 0; j < canvas.height; j++) {
                var op = j * canvas.width + i
                var tp = j * canvas.width + i + 1
                var r = pxData[op * 4] - pxData[tp * 4] + 128
                var g = pxData[op * 4 + 1] - pxData[tp * 4 + 1] + 128
                var b = pxData[op * 4 + 2] - pxData[tp * 4 + 2] + 128
                var newR = r < 0 ? 0 : (r > 255 ? 255 : r)
                var newG = g < 0 ? 0 : (g > 255 ? 255 : g)
                var newB = b < 0 ? 0 : (b > 255 ? 255 : b)
                pxData[op * 4] = newR
                pxData[op * 4 + 1] = newG
                pxData[op * 4 + 2] = newB
            }
        }
        ctx.putImageData(imgData, 0, 0)
    }
    

    8.水平镜像效果

    像素点的对称交换,这里实现的是水平位置的交换,两者canvas画布并列,一张实现镜像效果,另外一张不做处理,则可呈现出来水平镜像效果。

    function handleImg() {
        var imgData = ctx.getImageData(0, 0, 1000, 600)
        // 拿到像素数据
        var pxData = imgData.data
        // 创建和上面一样的imgData的数据对象,当做模板数据
        var tmpdata = ctx.createImageData(canvas.width, canvas.height)
        tmpdata.data.set(pxData)
        for (var i = 0; i < canvas.width; i++) {
            for (var j = 0; j < canvas.height; j++) {
                var op = j * canvas.width + i
                var tp = j * canvas.width + (canvas.width - 1 - i)
                pxData[op * 4] = tmpdata.data[tp * 4]
                pxData[op * 4 + 1] = tmpdata.data[tp * 4 + 1]
                pxData[op * 4 + 2] = tmpdata.data[tp * 4 + 2]
                pxData[op * 4 + 3] = tmpdata.data[tp * 4 + 3]
            }
        }
        ctx.putImageData(imgData, 0, 0)
    }
    

    9.刮刮乐

    我们将图片通过css设置成canvas画布的背景,然后在背景图上模拟出刮刮乐效果。
    css代码

    #canvas {
        background: url('./demo1.webp');
        background-position: center center;
        background-size: cover;
    }
    

    html结构代码

    <p>
        <button id="btn">开始刮一刮</button>
    </p>
    <canvas id="canvas" width="1000" height="600"></canvas>
    

    js代码

    var btn = document.getElementById("btn")
    btn.onclick = generate
    var canvas = document.getElementById("canvas")
    var ctx = canvas.getContext('2d')
    ctx.fillStyle = 'gray'
    ctx.fillRect(0, 0, 1000, 600)
    function generate() {
        canvas.onmousedown = function (e) {
            canvas.onmousemove = function (e) {
                var x = e.clientX - canvas.offsetLeft
                var y = e.clientY - canvas.offsetTop
                // 清除指定区域的像素
                // 第一第二个参数是清除的起始点x坐标和y坐标
                // 第三第四个参数是清除的区块大小
                //-20/2是为了让清除区域以鼠标为中心
                ctx.clearRect(x-20/2, y-20/2, 20, 20)
            }
            canvas.onmouseup = function (e) {
                canvas.onmousemove = null
            }
        }
    }
    

    10.绘制饼图裁剪图片

    不需要用css进行设置,html结构代码同“刮刮乐”,js代码部分只有generate事件函数和“刮刮乐”不同。

    function generate() {
        ctx.strokeStyle = 'red'
        ctx.moveTo(160, 120)
        // arc方法主要就是为了绘制圆形或者弧线
        // 第一第二个参数是圆心坐标
        // 第三个参数是半径
        // 第四第五个参数是弧度的开始与结束
        ctx.arc(160, 120, 120, 135 * Math.PI / 180, 45 * Math.PI / 180)
        ctx.lineTo(160, 120)
        ctx.stroke()
        // 把绘制好的形状剪切出来
        // 后面绘制的形状和图片都只能显示在剪切出来的这个区域
        ctx.clip()
        var img = new Image()
        img.src = './demo1.webp'
        img.onload = function () {
            ctx.drawImage(img,0,0,400,300)
        }
    }
    

    相关文章

      网友评论

        本文标题:canvas实战:处理图片合集

        本文链接:https://www.haomeiwen.com/subject/hecnactx.html