几行代码实现canvas画板

1,144 阅读4分钟

我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!

前言

大家好,我是小阵 🔥,一路奔波不停的码字业务员
如果喜欢我的文章,可以关注 ➕ 点赞,与我一同成长吧~😋
加我微信:zzz886885,邀你进群,一起学习交流,摸鱼学习两不误🌟

开开心心学技术大法~~

开心

来了来了,他真的来了~

正文

实现思路

  • 看到了画板就想到了canvas

  • 可以看到我们需要捕捉mousedownmousemovemouseup事件,mousedown的时候捕捉到当前的位置

    • 通过moveTo来确定canvas的笔触起点
    • 然后每次mousemove的时候,捕捉到mousemove的每次当前位置
    • 从上次的canvas的起点,通过canvas的lineTo到当前mousemove的位置画上路径
    • 然后再次触发mousemove,将新的位置信息与老的作比较
    • 老的位置作为canvas的moveTo的起点,新的位置作为canvas的lineTo的终点划上路径
    • 以此类推
  • 我们可以直接选择路径来绘制,也就是直接用lintTo来绘制

    • 但是这里有个坑,如果我们的路径宽度lineWidth比较小的时候,我们看上去是这样的

      image-20220915220242778

      可以看到是正常的,但是当lineWidth比较大时

      image-20220915220334065

      可以看到已经出现了锯齿,当lineWidth20

      image-20220915220405319

      所以我们需要另外绘制一些东西来补上这些锯齿部分

  • 我们可以选择矩形、椭圆或圆形,联想到我们的画笔笔触一般都是圆形,所以使用arc再画一条路径即可

    • 当然,因为arc不能单独话路径,还需要通过fill来填充满颜色
  • 主体内容就是上面了,通过arcmoveTolineTo绘制完整的轨迹路径

  • 接下来就是画笔粗细了,每次+或者-的时候改变路径的lineWidtharc直径

    • 我这里用的是lineWidth*2,与半径
    • 可以根据你的需要来设置画笔的宽度
  • 颜色可以通过input标签来实现,只需要设置typecolor即可使用最原生的颜色选择器
  • 然后最后次的清空画布用的就是ctx.clearRect()方法

具体实现

基础html

  <body>
    <canvas id="canvas" width="800" height="700"></canvas>
    <div class="toolbox">
      <button id="decrease">-</button>
      <span id="size">10</span>
      <button id="increase">+</button>
      <input type="color" id="color">
      <button id="clear">X</button>
    </div>
​
    <script src="script.js"></script>
  </body>

css样式

* {
  box-sizing: border-box;
}
​
body {
  background-color: #f5f5f5;
  font-family: 'Roboto', sans-serif;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  margin: 0;
}
​
canvas {
  border: 2px solid steelblue;
}
​
.toolbox {
  background-color: steelblue;
  border: 1px solid slateblue;
  display: flex;
  width: 804px;
  padding: 1rem;
}
​
.toolbox > * {
  background-color: #fff;
  border: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  height: 50px;
  width: 50px;
  margin: 0.25rem;
  padding: 0.25rem;
  cursor: pointer;
}
​
.toolbox > *:last-child {
  margin-left: auto;
}

canvas逻辑

定义基础变量

const canvas = document.getElementById('canvas');
const increaseBtn = document.getElementById('increase');
const decreaseBtn = document.getElementById('decrease');
const sizeEL = document.getElementById('size');
const colorEl = document.getElementById('color');
const clearEl = document.getElementById('clear');
​
const ctx = canvas.getContext('2d');
​
let size = 10
let isPressed = false
colorEl.value = 'black'
let color = colorEl.value
let x
let y

创建canvas。这里的color与size后续都会随时变化,所以是全局变量

落笔

canvas.addEventListener('mousedown', (e) => {
    isPressed = true
​
    x = e.offsetX
    y = e.offsetY
})

画笔移动

canvas.addEventListener('mousemove', (e) => {
    if(isPressed) {
        const x2 = e.offsetX
        const y2 = e.offsetY
​
        // 这里是画圆形与路径
        drawCircle(x2, y2)
        drawLine(x, y, x2, y2)
​
        x = x2
        y = y2
    }
})

抬笔

document.addEventListener('mouseup', (e) => {
    isPressed = false
​
    x = undefined
    y = undefined
})

绘制圆形与路径

function drawCircle(x, y) {
    ctx.beginPath();
    ctx.arc(x, y, size, 0, Math.PI * 2)
    ctx.fillStyle = color
    ctx.fill()
}
​
function drawLine(x1, y1, x2, y2) {
    ctx.beginPath()
    ctx.moveTo(x1, y1)
    ctx.lineTo(x2, y2)
    ctx.strokeStyle = color
    ctx.lineWidth = size * 2
    ctx.stroke()
}

注意圆形需要填充fill,而路径只需要画stroke即可。

调整画笔大小

function updateSizeOnScreen() {
    sizeEL.innerText = size
}
​
increaseBtn.addEventListener('click', () => {
    size += 5
​
    if (size > 50) {
        size = 50
    }
​
    updateSizeOnScreen()
})
​
decreaseBtn.addEventListener('click', () => {
    size -= 5
​
    if (size < 5) {
        size = 5
    }
​
    updateSizeOnScreen()
})

改变画笔颜色

colorEl.addEventListener('change', (e) => color = e.target.value)

清空画布

clearEl.addEventListener('click', () => ctx.clearRect(0, 0, canvas.width, canvas.height))

完整代码

总结

  • 重点是canvas的使用
  • 还有画笔的arcmoveTolineTo的配合使用消除画笔锯齿
  • 调整颜色的input设置typecolor也是一个小知识点

结语

如果文章真的有帮到你,希望可以多多点赞、收藏、关注支持一波呀!!小阵会很开心哒~

热爱开源,支持开源,拥抱开源!

文章如有错误或不严谨之处,还望指出,感谢感谢!!!

加油!

往期好文推荐