一个React版的画图工具

前言

以前看到系统自带的画图工具, 感受挺有意思, 因而用react和canvas实现了个简易画图工具, 不用react也行, 我主要是由于在原来的项目里写的, 因此用了react。react

这里是线上地址: Paintgit

源码在项目下的Library中: 源码github

实现

画笔功能

<canvas
    id="canvas"
    onMouseDown={mouseEvent}
    onMouseMove={mouseEvent}
    onMouseUp={mouseEvent}
>
</canvas>
复制代码

首先给canvas添加mousedown, mousemove, mouseup三个监听事件。canvas

当鼠标按下的时候,将isDraw开关打开,鼠标抬起时将其关闭, 这样就能控制mousemove了, 否则一进入canvas的区域就会触发mousemove事件。数组

这里为了简洁都监听的是mouseEvent事件, 在事件内部根据event.type来触发不一样的逻辑。app

来捋一捋画笔的思路:工具

  1. 鼠标按下, 将isDraw开关打开;ui

  2. 拖住鼠标滑动触发mousemove事件url

  3. 记录下鼠标点击的位置信息, 我这里用的是一个二维数组, 分别记录X轴和Y轴spa

  4. 初始化画笔的颜色和粗度以及形状

  5. 开始画线, 获取数组里鼠标画过的位置信息, 每两点之间进行一次描边, 这样点点链接就成了线

  6. 鼠标抬起, 将isDraw关闭, 禁止触发mousemove

大致思路就是这样, 下面是代码实现:

const mouseEvent = (e) => {
        let ctx = canvas2D.getContext('2d')

        e.persist()
        if (e.type === 'mousedown') {
            switch (active) {
                case 'spray':
                    return canvas2D.style.backgroundColor = color
                default:
                    isDraw = true
                    arr = []
                    return
            }

        }
        if (e.type === 'mousemove' && isDraw) {
            arr.push([e.pageX - canvas2D.offsetLeft, e.pageY - document.querySelector('.admin-box').offsetTop - 40])

            switch (active) {
                case 'pen':
                    ctx.strokeStyle = color
                    ctx.lineJoin = "round";
                    ctx.lineWidth = 5;
                    ctx.beginPath();
                    arr.length > 1 && ctx.moveTo(arr[arr.length - 2][0], arr[arr.length - 2][1]);
                    ctx.lineTo(arr[arr.length - 1][0], arr[arr.length - 1][1]);
                    ctx.closePath();
                    ctx.stroke();  //描边
                    return
                
                default:
                    return
            }

        }
        if (e.type === 'mouseup') {
            setCanvasUrl(url => {
                url.push(canvas2D.toDataURL())
                return url
            })
            isDraw = false
        }
    }

复制代码

橡皮擦

橡皮擦这里比较取巧, 是用背景色覆盖掉了画笔的颜色,这样看起来就像擦除了同样。 思路和画笔的思路是同样的, 只是将颜色改为了背景色

case 'eraser':
        ctx.strokeStyle = canvas2D.style.backgroundColor || '#ccc'
        ctx.lineJoin = "round";
        ctx.lineWidth = 50;
        ctx.beginPath();
        arr.length > 1 && ctx.moveTo(arr[arr.length - 2][0], arr[arr.length - 2][1]);
        ctx.lineTo(arr[arr.length - 1][0], arr[arr.length - 1][1]);
        ctx.closePath();
        ctx.stroke();  //描边
        return
复制代码

油漆桶

这个最简单, 获取到颜色板中的颜色, 将背景色替换掉就ok了

画矩形

画矩形要用到clearRectstrokeRect两个方法, 它们接受4个参数, 分别是起点坐标X, Y和矩形的长, 宽。

思路:

每次触发mousemove其实都会画矩形, 但咱们能够在每次画矩形前清空以前的区域。

clearRect就是清空矩形内的痕迹

这样看起来就像是咱们画了一个矩形

case 'rectangle':
    let left = arr[0][0]
    let top = arr[0][1]
    let prewidth = arr.length > 1 && arr[arr.length - 2][0] - left
    let preheight = arr.length > 1 && arr[arr.length - 2][1] - top
    let width = arr[arr.length - 1][0] - left
    let height = arr[arr.length - 1][1] - top
    ctx.beginPath();
    ctx.lineWidth = "6";
    ctx.strokeStyle = "red";
    ctx.clearRect(left, top, prewidth, preheight)
    ctx.strokeRect(left, top, width, height);
    return
复制代码

撤回上一步功能

这个要用到canvas的drawImagetoDataURL两个方法。

思路:

  1. 在每次操做以后, 将canvas经过toDataURL方法转成img存起来,push到数组中

  2. 点击recall时, 经过drawImage方法加载上次操做时的canvas图形。

  3. 移除数组最后的数据, 方便下次执行recall操做。

  4. 判断数组是否已清空, 清空了就再也不让操做了

代码以下:

const recallClick = (e) => {
    let ctx = canvas2D.getContext('2d')
    let step = canvasUrl.length - 1
    if (step >= 0) {
        step--;
        ctx.clearRect(0, 0, 1000, 1000);
        let canvasPic = new Image();
        canvasPic.src = canvasUrl[step];
        canvasPic.addEventListener('load', () => {
            ctx.drawImage(canvasPic, 0, 0);
        });

        setCanvasUrl(canvasUrl => {
            canvasUrl.pop()
            return canvasUrl
        })
    } else {
        console.log('不能再继续撤销了');
    }

}
复制代码

下载功能

经过toDataURL获取当前canvas的图形。 建立一个a标签, 将地址赋给它, 执行点击事件下载。这个实现比较简陋, 但这是通常的思路, 也能够根据场景进行弹窗, 修改下载的相关信息。

代码以下:

const downloadImg = () => {
    var url = canvas2D.toDataURL('image/png');
    var a = document.createElement('a');
    document.body.appendChild(a);
    a.href = url;
    a.download = '个人绘画';
    a.target = '_blank';
    a.click();
}
复制代码

颜色选择器

这里使用的是react-color插件。

结束

到这里,简易画板的思路就交代清楚了, 后续各位还能够在这个基础上开发更多的功能。

fighting~

相关文章
相关标签/搜索