在 Canvas 内平移图像后获取完整的 ImageData

Posted

技术标签:

【中文标题】在 Canvas 内平移图像后获取完整的 ImageData【英文标题】:Get full ImageData after Panning the image inside Cavnas 【发布时间】:2020-10-27 14:45:11 【问题描述】:

我有一种情况,即使在平移图像之后,我也需要在画布内获取完整的 ImageData

提前致谢

小提琴中的示例:https://jsfiddle.net/z46cvm9h/

<canvas id="canvas"></canvas>
<button onclick="showImage()">
Show panned Image
</button>
<img id="image" src='' />
var context     = canvas.getContext("2d");
canvas.width    = 400;
canvas.height   = 300;

var global = 
scale : 1,
offset    : 
 x : 0,
 y : 0,
,
;
var pan = 
start : 
 x : null,
 y : null,
,
offset : 
 x : 0,
 y : 0,
,
;

function draw() 
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);

context.translate(pan.offset.x, pan.offset.y);

context.beginPath();
context.rect(50, 50, 100, 100);
context.fillStyle = 'skyblue';
context.fill();

context.beginPath();
context.arc(350, 250, 50, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();



draw();

canvas.addEventListener("mousedown", startPan);
canvas.addEventListener("mouseleave", endPan);
canvas.addEventListener("mouseup", endPan);

function startPan(e) 
canvas.addEventListener("mousemove", trackMouse);
canvas.addEventListener("mousemove", draw);
pan.start.x = e.clientX;
pan.start.y = e.clientY;


function endPan(e) 
canvas.removeEventListener("mousemove", trackMouse);
pan.start.x = null;
pan.start.y = null;
global.offset.x = pan.offset.x;
global.offset.y = pan.offset.y;


function trackMouse(e) 
var offsetX    = e.clientX - pan.start.x;
var offsetY    = e.clientY - pan.start.y;
pan.offset.x = global.offset.x + offsetX;
pan.offset.y = global.offset.y + offsetY;


function showImage()
document.getElementById('image').src = canvas.toDataURL();

PS:JSFiddle 是为了演示,我不能把确切的场景放到 JSFiddle 中。在应用程序中,我平移图像,然后使用鼠标使用mousedownmousemove 事件在画布上绘制一些东西。在mouseup 事件中,我需要将ImageData 与我绘制的完整图像一起使用,但是当使用getImageData 时,我只会让图像出现在画布上。平移后的图像被裁剪为画布大小。

【问题讨论】:

使用足够大的第二个画布来容纳您想要获取的所有像素并在其上绘制内容,然后使用第二个画布中的 getImageData。 @Blindman67 不是很清楚,能否请您多解释一下,举个例子 抱歉,报告的问题是关于getImageData,但我无法在您的代码中找到您调用它的方式和时间。很难回答。 不仅如此,您还说您正在使用 mouseDown 和 mouseMove 来绘制某些东西,但是在您的代码中,这些事件用于移动图像....尝试回答这个问题真的太难了 【参考方案1】:

正如@Blindman67 建议的那样,您可以制作第二张画布。

创建一个对象来存储图像中最远的点。

const imagePadding = 
  top: 0,
  right: 0,
  bottom: 0,
  left: 0

top 应该是绘图的最高点,right 应该是最右边的点,依此类推。出于演示目的,填充设置为等于您在每个方向上平移的距离。您需要将其设置为每个方向上最远的图形/点(上、右、下和左——这些是我所说的方向)。

function panImage(e) 
  pan.x += e.movementX
  pan.y += e.movementY
  drawPreview()
  
  imagePadding.top = Math.max(imagePadding.top, pan.y)
  imagePadding.left = Math.max(imagePadding.left, pan.x)
  imagePadding.bottom = Math.max(imagePadding.bottom, -pan.y)
  imagePadding.right = Math.max(imagePadding.right, -pan.x)

要绘制完整的图像,您可以编写如下函数:

function drawFinalImage() 
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  const pannedImage = document.getElementById('image')

  canvas.width = previewCanvas.width + imagePadding.left + imagePadding.right
  canvas.height = previewCanvas.height + imagePadding.top + imagePadding.bottom

  ctx.translate(imagePadding.left, imagePadding.top)
  drawShapes(ctx)

  pannedImage.src = canvas.toDataURL()

请参阅JSFiddle 以获取演示以及如何实现代码。如果有什么我应该更好地解释的,请告诉我。

您可以使用 JSFiddle 控制台来调整填充。输入imagePadding.top = 200,回车,点击画布更新最终图片。

【讨论】:

以上是关于在 Canvas 内平移图像后获取完整的 ImageData的主要内容,如果未能解决你的问题,请参考以下文章

如何在固定的canvas画布内缩放

OpenCV 完整例程25. 图像的平移

HTML5 Canvas 中旋转矩形内的鼠标位置

如何用几何画板平移抛物线

使用OpenCV对图像进行两种平移操作(图像的尺寸变化与图像的尺寸不变)

iOS 为 UIImageView 获取图像的可见部分