我一直在使用 Canvas 开发草图应用程序。我似乎无法使用橡皮擦来处理我的代码。我从 Stack Overflow 上尝试了很多答案,但大多数都不起作用。

例如:

  • 设置globalcompositeoperation
  • alpha 设置为 0
  • 使用 clearRect 擦除。这有效,但使浏览器非常慢。

  • 所以我希望有人可以帮助我解决这个问题。

    这是 a demo ,这是我的代码:
    <html>
        <head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
            <style type="text/css">
                /*#canvas{background: #F6F683}*/
                .canvasBackground{ position: absolute; top: 8px; left: 8px; width: 1000px; height: 2400px;z-index: -10;}
                #main { position: fixed; top: 5px; left: 1020px; width: 280px; height: 250px;}
                .icon{ cursor: pointer; cursor: hand; }
            </style>
            <script type="text/javascript" src="../js/jquery-1.9.1.js"></script>
            <script type="text/javascript">
                var lWidthE = 15;    //Line width eraser
                var lWidthM = 2;    //Line width marker
    
                $(document).ready(function() {
                    $('.canvasBackground').css("background-image", "url(http://s22.postimg.org/i83b7ztch/notepad_page.png)");
                });
    
                var canvas;
                var ctx;
    
                var started = false;
                var lastx = 0;
                var lasty = 0;
    
                var memCanvas;
                var memCtx;
    
                var pointerCanvas;
                var pCtx;
    
                var points = [];
    
                function init() {
                    // Bind canvas to listeners
                    canvas = document.getElementById('canvas');
                    canvas.addEventListener('mousedown', mouseDown, false);
                    document.addEventListener('mousemove', mouseMove, false);
                    document.addEventListener('mouseup', mouseUp, false);
    
                    ctx = canvas.getContext('2d');
    
                    // create an in-memory canvas
                    memCanvas = document.createElement('canvas');
                    memCanvas.width = 1000;
                    memCanvas.height = 2400;
                    memCtx = memCanvas.getContext('2d');
                    ctx.lineJoin = 'round';
                    ctx.lineCap = 'round';
                }
    
                function ctx_stuff() {
                    if (v) {
                        ctx.lineWidth = lWidthE;
                        ctx.globalCompositeOperation = "source-over";
                        ctx.strokeStyle = "rgba(246,246,131,0)";
                    }
                    else {
                        ctx.lineWidth = lWidthM;
                        ctx.globalCompositeOperation = "source-over";
                        ctx.strokeStyle = "rgba(0,0,0,1)";
                    }
                }
    
                function mouseDown(e) {
                    var m = getMouse(e, canvas);
                    points.push({
                        x: m.x,
                        y: m.y
                    });
                    started = true;
                    ctx.clearRect(0, 0, 1000, 2400);
                    // put back the saved content
                    ctx.drawImage(memCanvas, 0, 0);
                    memCtx.clearRect(0, 0, 1000, 2400);
                    memCtx.drawImage(canvas, 0, 0);
                    drawPoints(ctx, points);
                }
    
                function mouseMove(e) {
                    if (started) {//to doodle
                        ctx.clearRect(0, 0, 1000, 2400);
    //                    // put back the saved content
                        ctx.drawImage(memCanvas, 0, 0);
                        var m = getMouse(e, canvas);
                        points.push({
                            x: m.x,
                            y: m.y
                        });
                        drawPoints(ctx, points);
                    } else {//to show where start point of doodle
                        var m = getMouse(e, canvas);
                        points.push({
                            x: m.x,
                            y: m.y
                        });
                        ctx.clearRect(0, 0, 1000, 2400);
                        // put back the saved content
                        ctx.drawImage(memCanvas, 0, 0);
                        drawPoints(ctx, points);
                        points = [];
                    }
                }
    
                function mouseUp(e) {
                    if (started) {
                        started = false;
                        // When the pen is done, save the resulting context
                        // to the in-memory canvas
                        memCtx.clearRect(0, 0, 1000, 2400);
                        memCtx.drawImage(canvas, 0, 0);
                        ctx.drawImage(memCanvas, 0, 0);
                        points = [];
                    }
                }
    
                // clear both canvases!
                function clear123() {
                    ctx.clearRect(0, 0, 1000, 2400);
                    memCtx.clearRect(0, 0, 1000, 2400);
                    cleanUpArray();
                }
    
                var small_x = 0, small_y = 0, big_x = 0, big_y = 0;
    
                function drawPoints(ctx, points) {
                    ctx_stuff();
                    // draw a basic circle instead
                    if (points.length < 6) {
                        var b = points[0];
                        if (v) {
                            ctx.beginPath(), ctx.arc(b.x, b.y, ctx.lineWidth / 2, 0, Math.PI * 2, !0), ctx.closePath(), ctx.fillStyle = "rgba(246,246,131,0)", ctx.fill();
    //                        ctx.clearRect(b.x - (lWidthE / 2), b.y - (lWidthE / 2), (lWidthE), (lWidthE));
    
                        } else {
                            ctx.beginPath(), ctx.arc(b.x, b.y, ctx.lineWidth / 2, 0, Math.PI * 2, !0), ctx.closePath(), ctx.fillStyle = "rgba(0,0,0,1)", ctx.fill();
                        }
                        return;
                    }
    
                    ctx.beginPath(), ctx.moveTo(points[0].x, points[0].y);
                    // draw a bunch of quadratics, using the average of two points as the control point
                    for (var i = 1; i < points.length - 2; i++) {
                        var c = (points[i].x + points[i + 1].x) / 2,
                                d = (points[i].y + points[i + 1].y) / 2;
    //                    if (v) {
    //                        ctx.clearRect(points[i].x - (lWidthE / 2), points[i].y - (lWidthE / 2), lWidthE, lWidthE);
    //                    }
    //                    else {
                            ctx.quadraticCurveTo(points[i].x, points[i].y, c, d);
    //                    }
                    }
    //                if (!v) {
                        ctx.quadraticCurveTo(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y), ctx.stroke();
    //                }
                }
    
                // Creates an object with x and y defined,
                // set to the mouse position relative to the state's canvas
                // If you wanna be super-correct this can be tricky,
                // we have to worry about padding and borders
                // takes an event and a reference to the canvas
                function getMouse(e, canvas) {
                    var element = canvas, offsetX = 0, offsetY = 0, mx, my;
    
                    // Compute the total offset. It's possible to cache this if you want
                    if (element.offsetParent !== undefined) {
                        do {
                            offsetX += element.offsetLeft;
                            offsetY += element.offsetTop;
                        } while ((element == element.offsetParent));
                    }
    
                    mx = e.pageX - offsetX;
                    my = e.pageY - offsetY;
    
                    ex = mx;
                    ey = my;
    
                    var tr;
                    if (v) {
                        tr = lWidthE + 250;
                    } else {
                        tr = lWidthM + 250;
                    }
                    if (mx < small_x || small_x === 0) {
                        small_x = mx - tr;
                        if (small_x < 0) {
                            small_x = 0;
                        }
                    }
                    if (mx > big_x || big_x === 0) {
                        big_x = mx + tr;
                        if (big_x > 1000) {
                            big_x = 1000;
                        }
                    }
                    if (my < small_y || small_y === 0) {
                        small_y = my - tr;
                        if (small_y < 0) {
                            small_y = 0;
                        }
                    }
                    if (my > big_y || big_y === 0) {
                        big_y = my + tr;
                        if (big_y > 2400) {
                            big_y = 2400;
                        }
                    }
    
                    // We return a simple javascript object with x and y defined
                    return {x: mx, y: my};
                }
    
                var v = false;
    
                function erase() {
                    if (v) {
                        v = false;
                    }
                    else {
                        v = true;
                    }
                }
            </script>
        </head>
        <body onload="init();">
            <div class="canvasBackground"></div>
            <div class="canvasBackground"></div>
        <canvas id='canvas' width='1000' height='2400'></canvas>
        <div id="main">
            <p>
                <label for="amountM">Marker size:</label>
                <input type="text" id="amountM" style="border: 0; color: #f6931f; font-weight: bold;"/>
            </p>
            <div title="Slide the bar to change size of marker" id="slider-range-minM"></div>
            <p>
                <label for="amountE">Eraser size:</label>
                <input type="text" id="amountE" style="border: 0; color: #f6931f; font-weight: bold;"/>
            </p>
            <div title="Slide the bar to change size of eraser" id="slider-range-minE"></div>
            <br/>
            <button title="Clear the canvas area." onclick='clear123();'>Clear</button>
            <input type="button" id="btnErase" title="Click to change between eraser and marker." onclick='erase();' value="Eraser/Marker"/>
            <img class="icon" src="icons/undo-icon.png" alt="Undo." title="Undo" onclick="javascript:undo();">
            <img class="icon" src="icons/redo-icon.png" alt="Redo." title="Redo" onclick="javascript:redo();">
        </div>
    </body>
    </html>
    

    最佳答案

    这是使用 globalCompositeOperation="destination-out"创建橡皮擦的说明

    此合成将“擦除”橡皮擦绘制的任何先前像素。

    提示:将橡皮擦画成一个圆圈是有帮助的,这样你就不会留下草图线条的“片段”。

    这是一个 mousemove 函数,它说明了绘制的线条和擦除。

    我看到您以不同的方式处理草图(记录笔画),但这将说明如何将目的地合成用作橡皮擦。

        function handleMouseMove(e){
          mouseX=parseInt(e.clientX-offsetX);
          mouseY=parseInt(e.clientY-offsetY);
    
          // Put your mousemove stuff here
          if(isMouseDown){
              ctx.beginPath();
              if(mode=="pen"){
                  ctx.globalCompositeOperation="source-over";
                  ctx.moveTo(lastX,lastY);
                  ctx.lineTo(mouseX,mouseY);
                  ctx.stroke();
              }else{
                  ctx.globalCompositeOperation="destination-out";
                  ctx.arc(lastX,lastY,5,0,Math.PI*2,false);
                  ctx.fill();
              }
              lastX=mouseX;
              lastY=mouseY;
          }
        }
    

    这是代码和 fiddle :http://jsfiddle.net/m1erickson/uSMxU/
    <!doctype html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    <!--[if lt IE 9]><script type="text/javascript" src="../excanvas.js"></script><![endif]-->
    
    <style>
        body{ background-color: ivory; }
        canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
        var lastX;
        var lastY;
        var strokeColor="red";
        var strokeWidth=2;
        var mouseX;
        var mouseY;
        var canvasOffset=$("#canvas").offset();
        var offsetX=canvasOffset.left;
        var offsetY=canvasOffset.top;
        var isMouseDown=false;
    
    
        function handleMouseDown(e){
          mouseX=parseInt(e.clientX-offsetX);
          mouseY=parseInt(e.clientY-offsetY);
    
          // Put your mousedown stuff here
          lastX=mouseX;
          lastY=mouseY;
          isMouseDown=true;
        }
    
        function handleMouseUp(e){
          mouseX=parseInt(e.clientX-offsetX);
          mouseY=parseInt(e.clientY-offsetY);
    
          // Put your mouseup stuff here
          isMouseDown=false;
        }
    
        function handleMouseOut(e){
          mouseX=parseInt(e.clientX-offsetX);
          mouseY=parseInt(e.clientY-offsetY);
    
          // Put your mouseOut stuff here
          isMouseDown=false;
        }
    
        function handleMouseMove(e){
          mouseX=parseInt(e.clientX-offsetX);
          mouseY=parseInt(e.clientY-offsetY);
    
          // Put your mousemove stuff here
          if(isMouseDown){
              ctx.beginPath();
              if(mode=="pen"){
                  ctx.globalCompositeOperation="source-over";
                  ctx.moveTo(lastX,lastY);
                  ctx.lineTo(mouseX,mouseY);
                  ctx.stroke();
              }else{
                  ctx.globalCompositeOperation="destination-out";
                  ctx.arc(lastX,lastY,5,0,Math.PI*2,false);
                  ctx.fill();
              }
              lastX=mouseX;
              lastY=mouseY;
          }
        }
    
        $("#canvas").mousedown(function(e){handleMouseDown(e);});
        $("#canvas").mousemove(function(e){handleMouseMove(e);});
        $("#canvas").mouseup(function(e){handleMouseUp(e);});
        $("#canvas").mouseout(function(e){handleMouseOut(e);});
    
        var mode="pen";
        $("#pen").click(function(){ mode="pen"; });
        $("#eraser").click(function(){ mode="eraser"; });
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <canvas id="canvas" width=300 height=300></canvas></br>
        <button id="pen">Pen</button>
        <button id="eraser">Eraser</button>
    </body>
    </html>
    

    10-07 17:23