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
    评论
以下是一个简单的Java代码,实现了基本的绘图工具功能,包括直线矩形、椭绘制,以及文本框的添加和颜色选择功能。 ```java import java.awt.*; import java.awt.event.*; import javax.swing.*; public class DrawingTool extends JFrame implements MouseListener, MouseMotionListener { private int startX, startY, endX, endY; private String shapeType; private Color shapeColor; private String textContent; private JTextField textField; private JPanel canvas; public DrawingTool() { setSize(500, 500); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setTitle("Drawing Tool"); // create buttons for shape selection JButton lineButton = new JButton("Line"); lineButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { shapeType = "line"; } }); JButton rectButton = new JButton("Rectangle"); rectButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { shapeType = "rect"; } }); JButton ovalButton = new JButton("Oval"); ovalButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { shapeType = "oval"; } }); // create button for color selection JButton colorButton = new JButton("Color"); colorButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { shapeColor = JColorChooser.showDialog(null, "Select a color", shapeColor); } }); // create text field for adding text boxes textField = new JTextField(20); JButton textButton = new JButton("Add Text"); textButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { textContent = textField.getText(); shapeType = "text"; } }); // create canvas panel for drawing canvas = new JPanel(); canvas.addMouseListener(this); canvas.addMouseMotionListener(this); // add components to frame JPanel controls = new JPanel(new FlowLayout()); controls.add(lineButton); controls.add(rectButton); controls.add(ovalButton); controls.add(colorButton); controls.add(textField); controls.add(textButton); add(controls, BorderLayout.NORTH); add(canvas, BorderLayout.CENTER); setVisible(true); } public void mousePressed(MouseEvent e) { startX = e.getX(); startY = e.getY(); } public void mouseDragged(MouseEvent e) { endX = e.getX(); endY = e.getY(); canvas.repaint(); } public void mouseReleased(MouseEvent e) { endX = e.getX(); endY = e.getY(); canvas.repaint(); } public void paint(Graphics g) { super.paint(g); if (shapeType != null) { g.setColor(shapeColor); if (shapeType.equals("line")) { g.drawLine(startX, startY, endX, endY); } else if (shapeType.equals("rect")) { g.drawRect(Math.min(startX, endX), Math.min(startY, endY), Math.abs(endX - startX), Math.abs(endY - startY)); } else if (shapeType.equals("oval")) { g.drawOval(Math.min(startX, endX), Math.min(startY, endY), Math.abs(endX - startX), Math.abs(endY - startY)); } else if (shapeType.equals("text")) { g.drawString(textContent, startX, startY); } } } public static void main(String[] args) { new DrawingTool(); } // unused MouseListener and MouseMotionListener methods public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseMoved(MouseEvent e) {} } ``` 这个绘图工具包含了一个按钮面板,用于选择绘制的形状类型和颜色,以及添加文本框的功能。在画布上按下鼠标并拖动,可以按拉橡皮筋的方法绘制直线矩形或椭。松开鼠标后,将绘制所选形状。如果选择了文本框,会在画布上添加一个带有文本内容的文本框

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值