javascript - 复制图像数据的更快方法

标签 javascript html canvas

我有以下脚本

// copy image data to secondary canvas
var pixelData = contextSource.getImageData(x - (lineWidth/2), y - (lineWidth/2), lineWidth, lineWidth);
var tmpCanvas = document.createElement('canvas');
tmpCanvas.width = tmpCanvas.height = lineWidth;
var tmpContext = tmpCanvas.getContext('2d');

tmpContext.putImageData(pixelData, 0, 0);

contextDest.save();
contextDest.arc(x, y, (lineWidth/2), 0, 2*Math.PI);
contextDest.clip();
contextDest.drawImage(tmpCanvas, x - (lineWidth/2), y - (lineWidth/2));
contextDest.restore();

当鼠标在源上移动时,脚本从 Canvas 源采样图像数据,然后将其复制到目标。该脚本运行良好,但有点慢。这是我将鼠标指针移动得更快时的结果。

enter image description here

有没有比我更快的方法?请帮忙

最佳答案

enter image description here

@Banana 有一个很好的观点。

与其只绘制鼠标位置,不如尝试将这些位置连接成一条连续的线..

如果你想要你的插图中的圆 Angular 效果,你可以设置:

context.lineCap='round';
context.lineJoin='round';

至于更快的掩蔽...

一种更快的屏蔽图像的方法是:

  • 在第二个 Canvas 上画一条线。
  • 使用合成使所有新绘图仅在现有像素不透明的地方可见。此合成是“source-in”并使用以下设置:context.globalCompositeOperation='source-in'
  • 将您的图像绘制到第二个 Canvas 上。该图像将仅显示线条所在的位置。

使用合成快得多,因为合成是硬件加速的并且由浏览器优化。

该合成代码可能如下所示:

function draw(){
    // clear the second canvas
    ctx1.clearRect(0,0,cw,ch);

    // draw your continuous line 
    ctx1.beginPath();
    ctx1.moveTo(points[0].x,points[0].y);
    for(var i=1;i<points.length;i++){
        p=points[i];
        ctx1.lineTo(p.x,p.y);
    }
    ctx1.stroke();

    // set compositing so new draws only appear in 
    // existing opaque pixels
    ctx1.globalCompositeOperation='source-in';

    // draw the image
    // the image will only be visible in the exising line
    ctx1.drawImage(img,0,0);

    // be tidy! return compositing to its default mode
    ctx1.globalCompositeOperation='source-over';
}

这是一个示例和演示:

var canvas1=document.getElementById("canvas1");
var ctx1=canvas1.getContext("2d");

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();

var isDown=false;
var startX;
var startY;

var points=[];
var cw,ch;

var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tempHouse%201.jpg";
function start(){
  cw=canvas.width=canvas1.width=img.width;
  ch=canvas.height=canvas1.height=img.height;

  ctx1.lineCap = "round";
  ctx1.lineJoin = "round";
  ctx1.lineWidth=20;

  ctx.drawImage(img,0,0);

  $("#canvas").mousedown(function(e){handleMouseDown(e);});
  $("#canvas").mousemove(function(e){handleMouseMove(e);});
  $("#canvas").mouseup(function(e){handleMouseUp(e);});
  $("#canvas").mouseout(function(e){handleMouseOut(e);});
}


function draw(){
  // clear the second canvas
  ctx1.clearRect(0,0,cw,ch);

  // draw your continuous line 
  ctx1.beginPath();
  ctx1.moveTo(points[0].x,points[0].y);
  for(var i=1;i<points.length;i++){
    p=points[i];
    ctx1.lineTo(p.x,p.y);
  }
  ctx1.stroke();

  // set compositing so new draws only appear in 
  // existing opaque pixels
  ctx1.globalCompositeOperation='source-in';

  // draw the image
  // the image will only be visible in the exising line
  ctx1.drawImage(img,0,0);

  // be tidy! return compositing to its default mode
  ctx1.globalCompositeOperation='source-over';
}


function handleMouseDown(e){
  e.preventDefault();
  e.stopPropagation();
  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);
  points.length=0;
  points.push({x:mouseX,y:mouseY});
  isDown=true;
}

function handleMouseUp(e){
  e.preventDefault();
  e.stopPropagation();
  isDown=false;
  draw();
}

function handleMouseOut(e){
  e.preventDefault();
  e.stopPropagation();
  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);
  points.push({x:mouseX,y:mouseY});
  isDown=false;
  draw();
}

function handleMouseMove(e){
  if(!isDown){return;}
  e.preventDefault();
  e.stopPropagation();
  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);
  points.push({x:mouseX,y:mouseY});
  draw();
}
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>
<canvas id="canvas1" width=300 height=300></canvas>

关于javascript - 复制图像数据的更快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26055344/

相关文章:

JavaScript Xpath : return result as string

javascript - 设置 iFrame 的比例

javascript - javascript中对象与数组的内存使用和速度

html - 侧边按钮在 IE Edge 中不起作用

html - 填充所有可用高度的输入

javascript - Firefox 8 for Mac 出现问题 : window. name is undefined

html - 创建带边距的带边框 Bootstrap 列

javascript - 如何修复 Flot js 上的 xaxis 标签

java - 定位 path.lineTo()

javascript - chrome 和 firefox 中 canvas.getContext ("2d").getImageData(x,y,1,1).data 的问题