2013-04-29 89 views
4

我一直在使用畫布製作素描應用。我似乎無法使用橡皮擦來處理我的代碼。我已經嘗試了很多堆棧溢出的答案,其中大部分都不起作用。素描應用的橡皮擦

例如:

  1. 設置globalcompositeoperation
  2. 設置alpha至0
  3. 使用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> 
+0

@DannyBeckett謝謝你的,但是,你可能已經離開了超鏈接的演示,與實際源代碼。不傷害。 – henryaaron 2013-04-29 03:53:57

+1

你爲什麼包含兩個jQueries? – icktoofay 2013-04-29 03:54:03

+0

@henryaaron將它添加回來;) – 2013-04-29 03:55:56

回答

10

下面是使用globalCompositeOperation =」目的地去」創造一個橡皮擦

這種複合材料將‘清除’任何的說明橡皮擦畫出的先前像素。

提示:它有助於將橡皮擦畫成圓形,因此不會留下草圖線條的「剪切」。

這是一個鼠標移動功能,說明草繪線和擦除。

我看到你處理草圖的方式不同(記錄筆畫),但是這將說明如何使用目的地合成作爲橡皮擦。

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; 
     } 
    } 

這裏是代碼和一個小提琴: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> 
+0

thnx尋求幫助。這工作正常,但它沒有平滑(線是「前衛」)。這實際上是大多數擦除方法不起作用的原因。無論如何thnx – theDarklord 2013-04-29 15:14:33

+0

**啊......你想要更少的「抖動」!**好的,PaperJS庫中有兩個功能你應該檢查:平滑和簡化。這些將這些「抖動」看作是這樣的線條:(1)通過沿路徑取出許多不需要的點來簡化線條;(2)通過在點上繪製曲線來平滑線條。這就像你在用quadratics做的事情 - 剛剛完成!即使你不使用paperJS庫,代碼也是開源的,所以只需使用平滑/簡化函數供自己使用。參見:http://paper.js/tutorials/paths/smoothing-simplifying-flattening/ – markE 2013-04-29 17:06:50