简体   繁体   English

在HTML5画布中移动裁剪的图像

[英]Move cropped image in HTML5 canvas

How can I move the cropped image with the crop down by 100px and left by 50px inside the canvas? 如何在画布内将裁剪后的图像向下移动100px,向左移动50px? Included jsfiddle link. 包含的jsfiddle链接。

Javascript 使用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 HTML

<canvas id="c" width="400" height="400"></canvas>

jsFiddle http://jsfiddle.net/dDUC3/3805/ jsFiddle http://jsfiddle.net/dDUC3/3805/

You should create the shape at your desired location in the first place, that would be the appropriate solution. 首先,您应该在所需位置创建形状,这将是合适的解决方案。

However, at this stage, you can use getImageData() and putImageData() methods to accomplish the movements ... 但是,在此阶段,您可以使用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); } 
 canvas { background: #CEF; } 
 <canvas id="c" width="400" height="400"></canvas> 

A safe canvas cut and paste 安全的画布剪切和粘贴

The given answer will fail in many situations due to cross origin security violations associated with ctx.getImageData and images outside your domain. 在许多情况下,由于与ctx.getImageDatactx.getImageData图像相关联的跨源安全性违规,给出的答案将失败。

Direct copy & paste 直接复制并粘贴

If you are moving the image as a square region or so that it does not overlap with the original you can copy directly from within the canvas. 如果将图像移动为正方形区域或与原始图像不重叠,则可以直接在画布内复制。

ctx.drawImage(ctx.canvas, 0, 0, 200, 200, 100, 100, 200, 200);

Direct cut & paste 直接剪切并粘贴

As you have some overlap that will need to be cleared you can copy in two parts 由于有些重叠需要清除,因此可以分为两部分进行复制

// 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);

But that is still a little problematic. 但这还是有问题的。

General cut and paste 一般剪切粘贴

The Ideal solution is to create a temporary canvas to hold the image so that it can be moved. 理想的解决方案是创建一个临时画布来保存图像,以便可以移动图像。 It will not be effected by overlap, nor will it fail if the canvas is tainted by cross origin data. 如果画布被交叉原点数据污染,则不会受到重叠的影响,也不会失败。

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

Then to past at the new location just draw the image 然后过去到新的位置,只需绘制图像

  ctx.drawImage(cutFromCanvas(ctx, 0, 0 200, 200), 100, 100);

As said by @gaand, the best is to move your clipping-shape where it should be. 正如@gaand所说,最好的方法是将剪切形状移动到应该的位置。 This can be done without modifying your path declaration, with setTransform . 无需使用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"; 
 canvas { background: lightblue } 
 <canvas id="c" width="500" height="300"></canvas> 

But if you really need to move your drawing once it has been drawn, then the best is to use an offscreen canvas on which you will generate your clipped image, and finally draw this offscreen canvas where you want on the visible one : 但是,如果您确实需要在绘制后将其移动,那么最好的方法是使用屏幕外的画布,在该画布上生成您的裁剪图像,最后在可见的位置上将该屏幕外的画布绘制在所需的位置:

 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"; 
 canvas { background: lightblue } 
 <canvas id="c" width="500" height="300"></canvas> 

But for a one-shot, you may find it cumbersome to declare a new canvas element. 但是,对于一个镜头,您可能会发现声明一个新的canvas元素很麻烦。 So a third option is to make use of globalCompositeOperation 'copy' which allow us to draw a canvas over itself without keeping the previous state : 因此,第三个选择是利用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"; 
 canvas { background: lightblue } 
 <canvas id="c" width="500" height="300"></canvas> 

And now that we have discovered gCO, we can even remove this clipping operation : 现在,我们已经发现了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"; 
 canvas { background: lightblue } 
 <canvas id="c" width="500" height="300"></canvas> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM