如何将裁剪后的图像向下移动100px并在画布内放置50px?包括jsfiddle链接。
的Javascript
// Grab the Canvas and Drawing Context
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
// Create an image element
var img = document.createElement('IMG');
// When the image is loaded, draw it
img.onload = function () {
// Save the state, so we can undo the clipping
ctx.save();
// Create a shape, of some sort
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(100, 30);
ctx.lineTo(180, 10);
ctx.lineTo(200, 60);
ctx.arcTo(180, 70, 120, 0, 10);
ctx.lineTo(200, 180);
ctx.lineTo(100, 150);
ctx.lineTo(70, 180);
ctx.lineTo(20, 130);
ctx.lineTo(50, 70);
ctx.closePath();
// Clip to the current path
ctx.clip();
ctx.drawImage(img, 0, 0);
// Undo the clipping
ctx.restore();
}
// Specify the src to load the image
img.src = "http://i.imgur.com/gwlPu.jpg";
html
<canvas id="c" width="400" height="400"></canvas>
的jsfiddle http://jsfiddle.net/dDUC3/3805/
答案 0 :(得分:0)
您应该首先在所需位置创建形状,这将是合适的解决方案。
但是,在此阶段,您可以使用 getImageData()
和 putImageData()
方法来完成动作......
// Grab the Canvas and Drawing Context
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
// Create an image element
var img = document.createElement('IMG');
// When the image is loaded, draw it
img.onload = function() {
// Save the state, so we can undo the clipping
ctx.save();
// Create a shape, of some sort
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(100, 30);
ctx.lineTo(180, 10);
ctx.lineTo(200, 60);
ctx.arcTo(180, 70, 120, 0, 10);
ctx.lineTo(200, 180);
ctx.lineTo(100, 150);
ctx.lineTo(70, 180);
ctx.lineTo(20, 130);
ctx.lineTo(50, 70);
ctx.closePath();
// Clip to the current path
ctx.clip();
ctx.drawImage(img, 0, 0);
// Undo the clipping
ctx.restore();
move(50, 100); //move left: 50px, down: 100px
}
// Set cross origin for the image, as it's not hosted on local server
img.crossOrigin = 'anonymous';
// Specify the src to load the image
img.src = "http://i.imgur.com/gwlPu.jpg";
function move(left, down) {
var croppedImage = ctx.getImageData(0, 0, 200, 200);
ctx.clearRect(0, 0, canvas.width, canvas.height); //clear canvas
ctx.putImageData(croppedImage, 0 + left, 0 + down);
}
&#13;
canvas {
background: #CEF;
}
&#13;
<canvas id="c" width="400" height="400"></canvas>
&#13;
答案 1 :(得分:0)
由于与ctx.getImageData
相关联的跨域安全违规行为以及您域外的图片,给定答案在许多情况下都会失败。
如果您将图像移动为方形区域,或者它与原始图像不重叠,则可以直接从画布中复制。
ctx.drawImage(ctx.canvas, 0, 0, 200, 200, 100, 100, 200, 200);
由于您需要清除一些重叠,您可以分两部分复制
// move bottom half
ctx.drawImage(ctx.canvas, 0, 100, 200, 100, 100, 200, 200, 100);
// clear bottom half
ctx.clearRect(0, 100, 200, 100);
// move top half
ctx.drawImage(ctx.canvas, 0, 0, 200, 100, 100, 100, 200, 100);
// lear top half
ctx.clearRect(0, 0, 200, 100);
但这仍然有点问题。
理想的解决方案是创建一个临时画布来保存图像,以便可以移动它。它不会受到重叠的影响,如果画布被交叉原始数据污染也不会失败。
function cutFromCanvas(ctx, x, y, w, h){
const cut = document.createElement("canvas");
cut.width = w;
cut.height = h;
cut.getContext("2d").drawImage(ctx.canvas, -x, -y, w, h, 0, 0, w, h);
ctx.clearRect(x, y, w, h);
return cut;
}
然后在新位置过去只绘制图像
ctx.drawImage(cutFromCanvas(ctx, 0, 0 200, 200), 100, 100);
答案 2 :(得分:0)
正如@gaand所说,最好的方法是将你的剪裁形状移动到应有的位置。
这可以在不使用setTransform
修改路径声明的情况下完成。
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var img = document.createElement('IMG');
img.onload = function() {
// move everything
ctx.setTransform(1, 0, 0, 1, 100, 100);
ctx.save();
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(100, 30);
ctx.lineTo(180, 10);
ctx.lineTo(200, 60);
ctx.arcTo(180, 70, 120, 0, 10);
ctx.lineTo(200, 180);
ctx.lineTo(100, 150);
ctx.lineTo(70, 180);
ctx.lineTo(20, 130);
ctx.lineTo(50, 70);
ctx.closePath();
ctx.clip();
ctx.drawImage(img, 0, 0);
// to restore the original matrix
ctx.setTransform(1, 0, 0, 1, 100, 100);
// but it's also restored here anyway...
ctx.restore();
};
img.src = "http://i.imgur.com/gwlPu.jpg";
&#13;
canvas {
background: lightblue
}
&#13;
<canvas id="c" width="500" height="300"></canvas>
&#13;
但是如果你真的需要在绘制后移动你的绘图,那么最好的方法是使用一个屏幕外的画布,你将在其上生成剪切的图像,最后在可见的一个上绘制你想要的屏幕外画布:
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var img = document.createElement('IMG');
var clippedCanvas = document.createElement('canvas');
var clippedCtx = clippedCanvas.getContext('2d');
img.onload = function() {
//prepare our offscreen canvas
clippedCanvas.width = this.width;
clippedCanvas.height = this.height;
// generate the drawing on the offscreen ctx
clippedCtx.save();
clippedCtx.beginPath();
clippedCtx.moveTo(10, 10);
clippedCtx.lineTo(100, 30);
clippedCtx.lineTo(180, 10);
clippedCtx.lineTo(200, 60);
clippedCtx.arcTo(180, 70, 120, 0, 10);
clippedCtx.lineTo(200, 180);
clippedCtx.lineTo(100, 150);
clippedCtx.lineTo(70, 180);
clippedCtx.lineTo(20, 130);
clippedCtx.lineTo(50, 70);
clippedCtx.closePath();
clippedCtx.clip();
clippedCtx.drawImage(img, 0, 0);
// now we can our composed image anywhere in th visible canvas
ctx.drawImage(clippedCanvas, 100,100);
};
img.src = "http://i.imgur.com/gwlPu.jpg";
&#13;
canvas {
background: lightblue
}
&#13;
<canvas id="c" width="500" height="300"></canvas>
&#13;
但是对于一次性,您可能会发现声明一个新的canvas元素很麻烦。所以第三种选择是使用globalCompositeOperation
'copy'
,它允许我们在不保留以前状态的情况下绘制画布:
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var img = document.createElement('IMG');
img.onload = function() {
ctx.save();
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(100, 30);
ctx.lineTo(180, 10);
ctx.lineTo(200, 60);
ctx.arcTo(180, 70, 120, 0, 10);
ctx.lineTo(200, 180);
ctx.lineTo(100, 150);
ctx.lineTo(70, 180);
ctx.lineTo(20, 130);
ctx.lineTo(50, 70);
ctx.closePath();
ctx.clip();
ctx.drawImage(img, 0, 0);
ctx.restore();
// the magic
ctx.globalCompositeOperation = 'copy';
// draw the canvas over itself, at 100 100
ctx.drawImage(canvas, 100,100);
};
img.src = "http://i.imgur.com/gwlPu.jpg";
&#13;
canvas {
background: lightblue
}
&#13;
<canvas id="c" width="500" height="300"></canvas>
&#13;
现在我们已经发现了gCO,我们甚至可以删除这个裁剪操作:
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var img = document.createElement('IMG');
img.onload = function() {
// move everything
ctx.setTransform(1,0,0,1,100,100);
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(100, 30);
ctx.lineTo(180, 10);
ctx.lineTo(200, 60);
ctx.arcTo(180, 70, 120, 0, 10);
ctx.lineTo(200, 180);
ctx.lineTo(100, 150);
ctx.lineTo(70, 180);
ctx.lineTo(20, 130);
ctx.lineTo(50, 70);
// we draw this shape
ctx.fill();
// new pixels will be drawn only where they do overlap with existing ones
ctx.globalCompositeOperation = 'source-in';
ctx.drawImage(img, 0, 0);
// restore the matrix
ctx.setTransform(1,0,0,1,0,0);
};
img.src = "http://i.imgur.com/gwlPu.jpg";
&#13;
canvas {
background: lightblue
}
&#13;
<canvas id="c" width="500" height="300"></canvas>
&#13;