HTML5画布橡皮擦工具,避免过度涂白色。

18

我有画布和绘画工具,如铅笔和橡皮。我该如何擦除图案而不用白色覆盖(overdraw)呢?

这是我使用白色颜色擦除图案的代码: http://jsfiddle.net/66z12xb0/

在后端,我会保存绘画后的图像。

<?php
$images = scandir(ROOT_FS . FINISH_DRAW_PATH, 1);
$imageData = $GLOBALS['HTTP_RAW_POST_DATA'];
$filteredData = substr($imageData, strpos($imageData, ",") + 1);
$unencodedData = base64_decode($filteredData);

$fileName = "photo.png"; 
$fp = fopen(ROOT_FS .  SAVE_DRAW_PATH . $fileName, 'wb');
fwrite($fp, $unencodedData);
fclose($fp);
?>

使用Windows照片查看器打开并查看以下结果:

在此输入图片描述 在此输入图片描述

附加上传的照片:

$("#upload_foto").click(function() {
    var data = canvas.toDataURL('image/png'); 
    var ajax = new XMLHttpRequest();
    ajax.open('POST', 'backend.php', false);
    ajax.setRequestHeader('Content-Type', 'application/upload');
    ajax.send(data);
}); 

<button type='button' id='upload_foto'>Upload</button>
2个回答

50

使用合成技术来创建橡皮擦是一个好主意。

destination-out will remove existing drawings where a new drawing overlaps those existing drawings.

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var lastX;
var lastY;
var strokeColor="red";
var strokeWidth=5;
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,8,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"; });
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="canvas" width=300 height=300></canvas></br>
<button id="pen">Pen</button>
<button id="eraser">Eraser</button>


3
但是如果画布后面有一张图片,它就无法工作。 - Madhu
2
是的,我尝试了相同的方法,也删除了图像,还有其他解决方案吗? - user9088454
我也希望它在图像上。 - Hidayt Rahman

4

如果您想要擦除线条,那么您有两个选项:

  1. 使用ctx.clearRect()或用与背景相匹配的颜色进行覆盖
  2. 使用图层。

如果您需要具有背景图像,以便无法使用单一颜色擦除,则图层是一种通用解决方案。如果您决定使用图层,我建议使用类似于paper.jskineticJS的框架,它们已经内置了此功能。如果您决定自己实现图层,则可以在背景画布上方创建另一个<canvas>,或者您需要将绘图信息存储在列表中,并每次重新绘制整个画布。


也许我可以使用globalCompositeOperation制作橡皮擦工具 globalCompositeOperation = 'destination-out'; fillStyle = 'rgba(0,0,0,1)'; strokeStyle = 'rgba(0,0,0,1)'; - Asker
KineticJS 变成了 KonvaJS。 - Mahdi Alkhatib

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接