【问题标题】:Move HTML5 Canvas with a background image使用背景图像移动 HTML5 Canvas
【发布时间】:2013-08-06 03:24:39
【问题描述】:

我想可视化一个在 HTML5 画布中绘制的巨大图表。如下图所示,让我们想象一下世界地图,不可能同时用“体面”的细节将其全部可视化。因此,在我的画布中,我希望能够使用鼠标平移它以查看其他不可见的国家/地区。

有谁知道如何在 HTML5 画布中实现这种平移?另一个功能是放大和缩小。

我看过一些例子,但我无法让它们发挥作用,也无法解决我的问题。

提前致谢!

【问题讨论】:

  • 所以你基本上想在 HTML5 画布对象中移动(平移)图像,由鼠标控制?也可以放大/缩小它。
  • 没错!我想拖动图像。

标签: javascript html canvas pan


【解决方案1】:

要实现带有窥视孔的平移功能,只需进行两次绘制操作,一次是完整的,一次是剪切的。

To get this result您可以执行以下操作(see full code here):

设置变量:

var ctx = canvas.getContext('2d'),

    ix = 0, iy = 0,           /// image position
    offsetX = 0, offsetY = 0, /// current offsets
    deltaX, deltaY,           /// deltas from mouse down
    mouseDown = false,        /// in mouse drag
    img = null,               /// background
    rect,                     /// rect position
    rectW = 200, rectH = 150; /// size of highlight area

设置用于根据窗口大小设置大小的主要功能(包括调整大小):

/// calc canvas w/h in relation to window as well as
/// setting rectangle in center with the pre-defined
/// width and height
function setSize() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    rect = [canvas.width * 0.5 - rectW * 0.5,
            canvas.height * 0.5 - rectH * 0.5,
            rectW, rectH]
    update();
}

/// window resize so recalc canvas and rect
window.onresize = setSize;

这里的主要功能是绘图功能。这里我们在鼠标移动计算的位置上绘制图像(见下节)。

  • 获得褪色外观的第一步是将 alpha 设置为大约 0.2(您也可以在顶部绘制一个透明矩形,但这更有效)。
  • 然后绘制完整的图像。
  • 重置阿尔法
  • 使用剪裁并修正源偏移量来绘制窥视孔。

-

/// main draw
function update() {
    if (img === null) return;

    /// limit x/y as drawImage cannot draw with negative
    /// offsets for clipping
    if (ix + offsetX > rect[0]) ix = rect[0] - offsetX;
    if (iy + offsetY > rect[1]) iy = rect[1] - offsetY;

    /// clear background to clear off garbage
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    /// make everything transparent
    ctx.globalAlpha = 0.2;

    /// draw complete background
    ctx.drawImage(img, ix + offsetX, iy + offsetY);

    /// reset alpha as we need opacity for next draw
    ctx.globalAlpha = 1;

    /// draw a clipped version of the background and
    /// adjust for offset and image position
    ctx.drawImage(img, -ix - offsetX + rect[0],  /// sx
                       -iy - offsetY + rect[1],  /// sy
                       rect[2], rect[3],         /// sw/h

                       /// destination
                       rect[0], rect[1], rect[2], rect[3]);

    /// make a nice sharp border by offsetting it half pixel
    ctx.strokeRect(rect[0] + 0.5, rect[1] + 0.5, rect[2], rect[3]);
}

现在是处理鼠标向下、移动和向上以及计算偏移量的问题 -

在鼠标按下时,我们存储当前鼠标位置,用于计算鼠标移动的增量:

canvas.onmousedown = function(e) {

    /// don't do anything until we have an image
    if (img === null) return;

    /// correct mouse pos
    var coords = getPos(e),
        x = coords[0],
        y = coords[1];

    /// store current position to calc deltas
    deltaX = x;
    deltaY = y;

    /// here we go..
    mouseDown = true;
}

这里我们使用增量来避免图像跳转,将角设置为鼠标位置。增量作为偏移量传输到update 函数:

canvas.onmousemove = function(e) {

    /// in a drag?
    if (mouseDown === true) {

        var coords = getPos(e),
            x = coords[0],
            y = coords[1];

        /// offset = current - original position
        offsetX = x - deltaX;
        offsetY = y - deltaY; 

        /// redraw what we have so far
        update();
    }
}

最后在鼠标上移时,我们将偏移设置为图像位置的永久部分:

document.onmouseup = function(e) {

    /// was in a drag?
    if (mouseDown === true) {
        /// not any more!!!
        mouseDown = false;

        /// make image pos. permanent
        ix += offsetX;
        iy += offsetY;

        /// so we need to reset offsets as well
        offsetX = offsetY = 0;
    }
}

对于缩放画布,我相信这篇文章已经回答了这个问题 - 您应该能够将其与此处给出的答案合并:
Zoom Canvas to Mouse Cursor

【讨论】:

  • 您肯定发布了答案,非常感谢!我现在有填充工作,但是关于缩放我已经看到了那个帖子,但是在那种情况下,每当我们想要缩放时,我们都必须重新绘制整个背景图片(平移、缩放),对吧?我试图使用 drawImage 函数来通过捕获更多的背景图像来进行缩放,这样可以避免重绘背景。这可能吗?
  • @Emanuel 你的意思是喜欢用正方形作为放大镜?如果是这样,你可以这样做:jsfiddle.net/AbdiasSoftware/Us9nH/3
  • 再次感谢您的帮助!确实和你发的一样,但是我希望能够根据鼠标的滚动进行放大和缩小。顺便说一句,你有没有注意到当你用鼠标转圈时,当你向地图底部移动时会有一种放大效果?谢谢!
  • 其实我认为这个效果是由于到达图像的末尾。高亮帧到达图像的末端,并将捕获帧的宽度调整为矩形,从而产生这种拉伸效果。
  • @KenFyrstenberg :先生,我怎样才能让可移动功能只能在画布内使用?以及如何隐藏相对于画布的图像溢出?
【解决方案2】:

要执行您要求的操作,只需拥有 2 个画布,每个画布具有不同的 z-index。一个画布比另一个小,位置设置为鼠标的 x 和 y。

然后,您只需根据小画布上 x 和 y 相对于大画布的位置,在小画布上显示正确的图像。

但是,您的问题是要求一个特定的解决方案,除非有人已经这样做并且他们愿意转储他们的代码,否则您会发现很难获得完整的答案。我希望一切顺利。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-30
    • 2013-07-07
    • 1970-01-01
    相关资源
    最近更新 更多