🔧用canvas做一个百吨王表情图

1,162 阅读3分钟

image-20250626223028862.png

前言

前段时间看到一个百吨王的表情包特别有意思,再加上最近这段时间`ai`特别的火,就想着做一个类似的表情图.

百吨王表情包.png

思路

  1. canvas加载图片
  2. fillRect盖住上下两个地方的文字
  3. fillText写入文字
  4. 最后用a标签下载

初始化画布

创建一个cavas画布

<!DOCTYPE html>
<html lang="zh-ch">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>表情包改造</title>
    <style>
      html,
      body {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      canvas {
        box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
        border-radius: 4px;
      }
    </style>
  </head>
  <body>
    <canvas id="canvas" width="1000" height="1000"></canvas>
    <script></script>
  </body>
</html>

image-20250626222818010.png

载入图片

const loadImage = (url) => {
    return new Promise((resolve, reject) => {
      const img = new Image()
      img.setAttribute('crossOrigin', 'anonymous')
      img.src = url
      img.onload = () => {
        resolve(img)
      }
      img.onerror = () => {
        reject(new Error('图像加载失败'))
      }
    })
  }
;(async () => {
    const canvas = document.getElementById('canvas')
    const ctx = canvas.getContext('2d')
    // 加载图片
    const img = await loadImage('./百吨王表情包.png')
    ctx.drawImage(img, 0, 0, 1000, 1000)
})()

这里我写了一个loadImage函数,为了实现同步加载图片. 你也可以不要.

效果如下

image-20250626223028862.png

清理上下端的文字

ctx.fillStyle = '#282932'
// 消除原先的文字
ctx.fillRect(0, 0, 1000, 250)
ctx.fillRect(0, 720, 1000, 255)

直接画一个黑色的矩形盖住

image-20250626223028862.png

写入文字

ctx.fillStyle = '#fff'

ctx.font = 'bold 60px Arial'
ctx.fillText('没看到', 50, 100)

ctx.font = 'bold 60px Arial'
ctx.fillText('滑太快了', 250, 100)

ctx.font = 'bold 48px Arial'
ctx.fillText('我们都在用力的编码', 550, 100)

ctx.font = 'bold 48px Arial'
ctx.fillText('哪来的BUG', 50, 180)

ctx.font = 'bold 78px Arial'
ctx.fillText('以为是冗余代码', 350, 190)

ctx.font = 'bold 48px Arial'
ctx.fillText('需求不是我做的,', 50, 800)

ctx.font = 'bold 68px Arial'
ctx.fillText('你问下别人', 420, 800)

ctx.font = 'bold 100px Arial'
ctx.fillText('和我的大模型说去吧!', 50, 950)

效果如下

image-20250626223028862.png

下载图片

经过上面的操作,这个表情包就改造完毕,之后`a`用标签下载下来即可
 // 保存图片
const dataUrl = canvas.toDataURL('image/png')
const a = document.createElement('a')
a.href = dataUrl
a.download = 'AI版百吨王.png'
a.click()

完整代码

<!DOCTYPE html>
<html lang="zh-ch">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>表情包改造</title>
    <style>
      html,
      body {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      canvas {
        box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
        border-radius: 4px;
      }
    </style>
  </head>
  <body>
    <canvas id="canvas" width="1000" height="1000"></canvas>
    <script>
      // url 图片路径
      const loadImage = (url) => {
        return new Promise((resolve, reject) => {
          const img = new Image()
          img.setAttribute('crossOrigin', 'anonymous')
          img.src = url
          img.onload = () => {
            resolve(img)
          }
          img.onerror = () => {
            reject(new Error('图像加载失败'))
          }
        })
      }
      ;(async () => {
        const canvas = document.getElementById('canvas')
        const ctx = canvas.getContext('2d')
        // 加载图片
        const img = await loadImage('./百吨王表情包.png')
        ctx.drawImage(img, 0, 0, 1000, 1000)
        ctx.fillStyle = '#282932'
        // 消除原先的文字
        ctx.fillRect(0, 0, 1000, 250)
        ctx.fillRect(0, 720, 1000, 255)
        ctx.fillStyle = '#fff'

        ctx.font = 'bold 60px Arial'
        ctx.fillText('没看到', 50, 100)

        ctx.font = 'bold 60px Arial'
        ctx.fillText('滑太快了', 250, 100)

        ctx.font = 'bold 48px Arial'
        ctx.fillText('我们都在用力的编码', 550, 100)

        ctx.font = 'bold 48px Arial'
        ctx.fillText('哪来的BUG', 50, 180)

        ctx.font = 'bold 78px Arial'
        ctx.fillText('以为是冗余代码', 350, 190)

        ctx.font = 'bold 48px Arial'
        ctx.fillText('需求不是我做的,', 50, 800)

        ctx.font = 'bold 68px Arial'
        ctx.fillText('你问下别人', 420, 800)

        ctx.font = 'bold 100px Arial'
        ctx.fillText('和我的大模型说去吧!', 50, 950)

        // 保存图片
        const dataUrl = canvas.toDataURL('image/png')
        const a = document.createElement('a')
        a.href = dataUrl
        a.download = 'AI版百吨王.png'
        a.click()
      })()
    </script>
  </body>
</html>

结尾

这个`demo`还有很多可以开发的功能点
  • 自定义文字
  • 自定义底图
  • 文字拖拽

加上这三个功能,就可以开发出一个简易版的表情包生成器,虽然没什么用.