一個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~

相關文章
相關標籤/搜索