• canvas基础二


    canvas基础

    一、文本
    1.1 文本绘制方法
    • 填充文字 fillText(text, x, y, maxWidth)
    • 描边文字 strokeText(text, x, y, maxWidth)
    1.2 文本属性
    • 字体:font
      可以设置文本的粗细、字号、字体
    ctx.font = 'bold 100px Arial'
    
    • 1
    • 水平对齐: textAlign
    const canvas = document.getElementById('canvas')
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    const ctx = canvas.getContext('2d')
    
    // 辅助线
    ctx.strokeStyle = '#999'
    ctx.setLineDash([8, 8])
    ctx.moveTo(300, 50)
    ctx.lineTo(300, 600)
    ctx.stroke()
    
    // font 设置字号字体
    ctx.font = "24px Arial"
    
    /*
    * textAlign
    * start:基于文本起始位对齐,默认
    * end:基于文本结束位对齐
    * left:左对齐
    * right:右对齐
    * center:居中对齐
    * */
    ctx.textAlign = 'start'
    ctx.fillText('start', 300, 50)
    ctx.textAlign = 'end'
    ctx.fillText('end', 300, 100)
    ctx.textAlign = 'left'
    ctx.fillText('left', 300, 150)
    ctx.textAlign = 'right'
    ctx.fillText('right', 300, 200)
    ctx.textAlign = 'center'
    ctx.fillText('center', 300, 250)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述

    • 垂直对齐:textBaseline
    const canvas = document.getElementById('canvas')
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    const ctx = canvas.getContext('2d')
    
    // 辅助线
    ctx.strokeStyle = '#999'
    ctx.setLineDash([8, 8])
    ctx.moveTo(30, 200)
    ctx.lineTo(700, 200)
    ctx.stroke()
    
    // font 设置字号字体
    ctx.font  =  "24px Arial"
    
    /*
    * textBaseline
    * top:上对其
    * middle:垂直居中对齐
    * bottom:下对齐
    * hanging:悬挂基线对齐
    * alphabatic:标准字母基线对齐,默认
    * ideographic:表意文字基线
    * */
    ctx.textBaseline = 'top'
    ctx.fillText('top', 50, 200)
    ctx.textBaseline = 'middle'
    ctx.fillText('middle', 100, 200)
    ctx.textBaseline = 'bottom'
    ctx.fillText('bottom', 200, 200)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

    1.3 获取文字宽度

    ctx.measureText(text): 可以让某些元素随文字宽度的变化而变化

    const canvas = document.getElementById('canvas')
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    const ctx = canvas.getContext('2d')
    
    // 文字内容
    const text = 'canvas-------------'
    // 矩形左上角位置
    const [x, y] = [50, 100]
    // 矩形宽度
    const height = 60
    
    // 字体
    ctx.font = '36px Arial'
    // 水平居中
    ctx.textAlign = 'center'
    // 垂直居中
    ctx.textBaseline = 'middle'
    // 文字宽度
    const width = ctx.measureText(text).width + 36
    // 绘制矩形
    ctx.strokeRect(x, y, width, height)
    // 绘制文字
    ctx.fillText(text ,x + width / 2, y + height / 2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    二、图像
    2.1 drawImage
    • 绘图 + 位移:drawImage(image, x, y)
    • 绘图 + 位移 + 缩放:drawImage(image, x, y,width,height)
    • 绘图 + 裁切 + 位移 + 缩放:drawImage(image, x1, y1,w1,h1,x2,y2,w2,h2)
    const canvas = document.getElementById('canvas')
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    const ctx = canvas.getContext('2d')
    
    const img = new Image()
    img.src = 'https://img-blog.csdnimg.cn/2a9fb7b01db54ec48be865fc02902e30.png'
    img.onload = function() {
        const { width, height } = img
        // 绘图 + 移动 drawImage(image, x, y)
        // ctx.drawImage(img, 100, 50)
    
        // 绘图 + 移动 + 缩放 drawImage(image,  x,  y, width, height)
        // ctx.drawImage(img, 200, 100, width / 2, height / 2)
    
        // 绘图 + 裁剪 + 移动 + 缩放 drawImage(image, x1, y1, w1, h1, x2, y2, w2, h2) */
        ctx.drawImage(img, width / 2, 0, width / 2, height / 2,  100, 50, width / 2, height / 2)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    以下为上面三种示例的效果展示:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    2.1 getImageData

    ctx.getImageData(x, y, width, height)获取canvasImageData()对象(可以以此原理获取真实图片的数据)
    canvas 中显示ImageData:putImageData(ImageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight)

    首先我们要理解 ImageData 中的像素集合和图像栅格的对应关系:

    • ImageData 对象的属性
    const imgDt = ctx.getImageData(0, 0, 1, 1)
    console.log(imgDt)
    
    • 1
    • 2

    以下是打印出来的属性:
    在这里插入图片描述

    • data 中的数值与栅格的对应关系

    先从第一行开始,遍历每一列,遍历完成后;进入下一行,遍历每一列,遍历完成后;进入下一行,遍历每一列,遍历完成后…直到遍历完最后一行的最后一列。
    在这里插入图片描述
    下面举两个个简单的例子说明其中的用处:

    • 置灰效果
      这是灰度算法: 0.299*r+0.587*g+0.114*b,这是固定不变的
    const canvas = document.getElementById('canvas')
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    const ctx = canvas.getContext('2d')
    
    const img = new Image()
    // 需注意的是,这个只能处理本地的图片,线上的图片是不能置灰的
    img.src = './images/1.png'
    img.onload = draw
    
    function draw() {
        // 图像尺寸
        const { width, height } = img
    
        // 1.在canvas 中绘制图像
        ctx.drawImage(img, 0, 0)
    
        // 2.从canvas 中获取图像的ImageData
        const imgDt = ctx.getImageData(0, 0, width, height)
        const data = imgDt.data
    
        // 像素遍历
        for (let i = 0; i < data.length; i += 4) {
            const [r, g, b] = [
                data[i],
                data[i + 1],
                data[i + 2],
            ]
            const lm = 0.299 * r + 0.587 * g + 0.114 * b
            data[i] = lm
            data[i + 1] = lm
            data[i + 2] = lm
        }
    
        // 3.在canvas 中显示ImageData
        ctx.putImageData(imgDt, 800, 0)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    这是效果图:
    在这里插入图片描述

    • 马赛克效果
    const canvas = document.getElementById('canvas')
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    const ctx = canvas.getContext('2d')
    
    const img = new Image()
    img.src = './images/1.png'
    img.onload = render
    
    // 色块尺寸
    let size = 20
    
    function render() {
        // 图像尺寸
        const { width, height } = img
    
        // *1.在canvas 中绘制图像
        ctx.drawImage(img, 0, 0)
    
        // 2.从canvas 中获取图像的ImageData
        const imgDt = ctx.getImageData(0, 0, width, height)
        const data = imgDt.data
    
        // 行列遍历
        // 首先获取一个size的宽高的区域,然后获取左上角的第一个像素,并画一个矩形,然后再每隔一个size遍历一次,以此类推
        for (let y = 0; y < height; y += size) {
            for (let x = 0; x < width; x += size) {
                const ind = (y * width + x) * 4
                // [r, g, b]即左上角的点的颜色
                const [r, g, b] = [
                    data[ind],
                    data[ind + 1],
                    data[ind + 2],
                ]
                ctx.fillStyle = `rgb(${r},${g},${b})`
                ctx.fillRect(x, y, size, size)
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    可以修改size的大小来控制马赛克的程度。效果如下:
    在这里插入图片描述

    三、变换
    3.1 上下文对象的状态

    上下文对象的状态就是上下文对象的属性。比如描边颜色,填充颜色,投影,线条样式,变换信息等等。
    管理上下文状态的方法:save() restore()

    • save() 保存当前状态
    • restore()恢复上一次保存的状态
    const canvas = document.getElementById('canvas')
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    const ctx = canvas.getContext('2d')
    
    // 在此时保存了初始颜色#000
    ctx.save()
    ctx.fillStyle = 'red'
    ctx.fillRect(0, 0, 400, 200)
    // 在此时还原了上次保存的颜色
    ctx.restore()
    
    // 最终这个长方形的颜色是黑色的
    ctx.fillRect(0, 0, 300, 200)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    最终效果:
    在这里插入图片描述

    3.2 变换
    const canvas = document.getElementById('canvas')
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    const ctx = canvas.getContext('2d')
    
    // 向左以及上都偏移100
    ctx.translate(100, 100)
    // 整体顺时针旋转 1/4
    ctx.rotate(Math.PI / 4)
    // 整体缩小0.5倍
    ctx.scale(0.5, 0.5)
    ctx.fillRect(0, 0, 400, 200)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    最终效果:
    在这里插入图片描述
    总结:对canvas 坐标系进行变换后,以后绘制的图形都会受这种变换影响。而我们有时会不想让其它图形受此影响,这样我们就需要用save() 和restore() 将变换方法和绘制图形的方法包裹起来。

  • 相关阅读:
    Spring Security 实现动态权限菜单方案(附源码)
    Java并发机制的底层实现原理
    科技云报道:走入商业化拐点,大模型“开箱即用”或突破行业困局
    【C++】stack | queue | priority_queue | deque
    android 多张图片合成一张
    LeetCode算法心得——打家劫舍(记忆化搜索)
    更高效的构建工具-vite
    Golang 接口 interface
    曲线艺术编程 coding curves 第九章 旋轮曲线(ROULETTE CURVES)
    InnoDB 数据页结构
  • 原文地址:https://blog.csdn.net/qq_40864647/article/details/125000366