2013-04-29 95 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