HTML5Canvas实现简易画图工具(铅笔,直线,矩形,圆,文本框,橡皮擦等)

初学Canvas,用canvas做了简单的画图工具体会并熟悉了一下大致的实现方案。开发完也算是基本了解canvas的用法了。

HTML部分:

    <div class="app">
        <div class="menu">
            <div class="toollist">
                <button class="menu-item" style="width: fit-content;" onclick="clearCanvas()">clear</button>
                <button class="menu-item" onclick="restoreMouse()">
                    <svg>//图标
                    </svg>
                </button>
                <button class="menu-item" onclick="pencilDraw()">
                    <svg>//图标
                    </svg>
                </button>
                <button class="menu-item" onclick="lineDraw()">
                    <svg>
                    </svg>
                </button>
                <button class="menu-item" onclick="saveCanvas()">
                    <svg>
                    </svg>
                </button>
                <button class="menu-item" onclick="useEraser()">
                    <svg>
                    </svg>
                </button>
                <button class="menu-item" onclick="RectDraw()">
                    <svg>
                    </svg></button>
                <button class="menu-item" onclick="circleDraw()">
                    <svg>
                    </svg>
                </button>
                <button class="menu-item" onclick="insertText()">A</button>
            </div>
            <div>
                <input type="color" style="margin-top: 10px;" onchange="handleColorChange(this)">
            </div>
        </div>
        <div style="background-color: #fff; position: relative;" class="canvas-area">
            <canvas id="canvas" width="1000" height="1000"></canvas>
        </div>
        <!-- <input type="text" style="border: 1px dashed #ccc; position:absolute;top:0;left:10%;outline:none"> -->
    </div>

JS部分:

根据选择的画笔工具分别进行处理,实际上直线,圆,矩形的绘画代码除了使用的方法不同外,唯一的小难点可能就是没办法在画布上重复地绘画,此时需要用到两个方法来实现:

ctx.putImageData(convasData, 0, 0, 0, 0, canvas.offsetWidth, canvas.offsetHeight);
ctx.getImageData(convasData, 0, 0, 0, 0, canvas.offsetWidth, canvas.offsetHeight);

 get方法用来保存当前画布的信息,在onmouseup时,保存此次操作后的画布状态。而put方法则在每次落笔清除绘画轨迹后,将之前保存的数据进行还原,从而实现多次重复绘画的效果。

        var canvas = document.getElementById('canvas');
        var ctx = canvas.getContext('2d');
        var drawdown = false;
        var startPointX, startPointY;
        var toolcontrol = {
            pencil: false,
            line: false,
        }
        var convasData = null;
        var drawcolor = "#000";
        var curtool;
        var textvalue;
        function setUsingTool(tool) {
            for (const key in toolcontrol) {
                toolcontrol[key] = false;
            }
            toolcontrol[tool] = true;
            curtool = tool;
            // curtool=='line'?
            //     ctx=canvas2.getContext('2d'):
            // ctx=canvas.getContext('2d');
        }
        //function clearCanvas() {
        //  ctx.clearRect(0, 0, 1000, 1000)
        //}
        function drawToolHandler(tool) {
            canvas.addEventListener('mousedown', handleMouseDown);
            canvas.addEventListener('mousemove', handleMouseMove);
            canvas.addEventListener('mouseup', handleMouseUp);
        }

        var handleMouseDown = (e) => {
            switch (curtool) {
                case 'pencil':
                    drawdown = true;
                    ctx.beginPath();
                    ctx.moveTo(e.offsetX, e.offsetY);
                    break;
                case 'line':
                case 'rect':
                case 'ring':
                case 'text':
                    drawdown = true;
                    startPointX = e.offsetX;
                    startPointY = e.offsetY;
                    break;
                case 'eraser':
                    drawdown = true;
                    break;
                default: return;
            }
        }
        var handleMouseMove = (e) => {
            switch (curtool) {
                case 'pencil':
                    if (drawdown) {
                        ctx.lineTo(e.offsetX, e.offsetY)
                        ctx.strokeStyle = drawcolor.toString();
                        ctx.stroke();
                    }
                    break;
                case 'line':
                    if (drawdown) {
                        ctx.beginPath();
                        ctx.clearRect(0, 0, 1000, 1000);
                        if (convasData != null) {
                            ctx.putImageData(convasData, 0, 0, 0, 0, canvas.offsetWidth, canvas.offsetHeight);
                        }
                        ctx.moveTo(startPointX, startPointY);
                        ctx.lineTo(e.offsetX, e.offsetY);
                        ctx.closePath();
                        ctx.strokeStyle = drawcolor;
                        ctx.stroke();
                    }
                    break;
                case 'rect':
                    if (drawdown) {
                        ctx.beginPath();
                        ctx.clearRect(0, 0, 1000, 1000);
                        if (convasData != null) {
                            ctx.putImageData(convasData, 0, 0, 0, 0, canvas.offsetWidth, canvas.offsetHeight);
                        }
                        ctx.strokeStyle = drawcolor;
                        ctx.strokeRect(startPointX, startPointY, e.offsetX - startPointX, e.offsetY - startPointY);
                        ctx.closePath();
                    }
                    break;
                case 'ring':
                    if (drawdown) {
                        ctx.beginPath();
                        ctx.clearRect(0, 0, 1000, 1000);
                        if (convasData != null) {
                            ctx.putImageData(convasData, 0, 0, 0, 0, canvas.offsetWidth, canvas.offsetHeight);
                        }
                        ctx.strokeStyle = drawcolor;
                        ctx.arc(startPointX, startPointY, (e.offsetY - startPointY) / 2, 0, 2 * Math.PI, false);
                        ctx.stroke()
                        ctx.closePath();
                    }
                    break;
                case 'text':
                    if (drawdown) {
                        ctx.beginPath();
                        ctx.clearRect(0, 0, 1000, 1000);
                        if (convasData != null) {
                            ctx.putImageData(convasData, 0, 0, 0, 0, canvas.offsetWidth, canvas.offsetHeight);
                        }
                        ctx.strokeStyle = '#000';
                        ctx.strokeRect(startPointX, startPointY, e.offsetX - startPointX, e.offsetY - startPointY);
                        ctx.closePath();
                    }
                case 'eraser':
                    if (drawdown) {
                        ctx.beginPath();
                        ctx.moveTo(startPointX, startPointY);
                        ctx.clearRect(e.offsetX, e.offsetY, 50, 50);
                    }
                    break;
                default: return;
            }
        }
        var handleMouseUp = (e) => {
            if (curtool == 'text'&&e.offsetX - startPointX>=10&&e.offsetY - startPointY>=10) {
                // ctx.clearRect(0, 0, 1000, 1000);
                let input = document.createElement('input');
                let canvasArea = document.getElementsByClassName('canvas-area')[0];
                canvasArea.appendChild(input);
                input.style.position = "absolute";
                input.style.left = `${startPointX}px`;
                input.style.top = `${startPointY}px`;
                input.style.width = `${e.offsetX - startPointX}px`;
                input.style.height = `${e.offsetY - startPointY}px`;
                input.style.fontSize =`${parseInt(input.style.height)/2}px`;
                input.style.border = "2px dashed #ccc";
                input.style.outline = 'none'
                input.addEventListener('input',(e)=>{
                    textvalue=e.target.value
                })
                input.addEventListener('blur',()=>{
                    ctx.clearRect(0, 0, 1000, 1000);
                    if (convasData != null) {
                            ctx.putImageData(convasData, 0, 0, 0, 0, canvas.offsetWidth, canvas.offsetHeight);
                    }
                    ctx.font=`${parseInt(input.style.height)/2}px sans-serif`;
                    ctx.fillText(textvalue,parseInt(input.style.left)+20,parseInt(input.style.top)+0.6*parseInt(input.style.height));
                    canvasArea.removeChild(input);
                    convasData = ctx.getImageData(0, 0, canvas.offsetWidth, canvas.offsetHeight);

                })
                
                drawdown = false;
            } else {
                convasData = ctx.getImageData(0, 0, canvas.offsetWidth, canvas.offsetHeight);
                drawdown = false;
            }

        }
        function restoreMouse() {
            canvas.removeEventListener('mousedown', handleMouseDown);
            canvas.removeEventListener('mousemove', handleMouseMove);
            canvas.removeEventListener('mouseup', handleMouseUp);
        }
        function pencilDraw() {
            setUsingTool('pencil');
            drawToolHandler('pencil');
        }
        function lineDraw() {
            setUsingTool('line');
            drawToolHandler('line');
        }
        function useEraser() {
            setUsingTool('eraser');
            drawToolHandler('eraser');
        }
        function RectDraw() {
            setUsingTool('rect');
            drawToolHandler('rect');
        }
        function circleDraw() {
            setUsingTool('ring');
            drawToolHandler('ring');
        }
        function insertText() {
            setUsingTool('text');
            drawToolHandler('text');
        }
        function handleColorChange(e) {
            console.log(e.value);
            drawcolor = e.value
        }

        function saveCanvas() {
            var a = document.createElement("a");
            a.href = canvas.toDataURL();
            var fileName = prompt("命名你的图画");
            a.download = fileName || "canvaspic"
            a.click();
        }

其中插入文本相对特殊一些,需要先在页面根据鼠标移动画出一个矩形,鼠标松开时,创建一个矩形大小的input,输入文字且失去焦点后,将input输入的值画在canvas上。

效果:

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值