简体   繁体   English

使用背景图像移动HTML5 Canvas

[英]Move HTML5 Canvas with a background image

I want to visualize a huge diagram that is drawn in a HTML5 canvas. 我想要想象一个在HTML5画布中绘制的巨大图表。 As depicted below, let's imagine the world map, it's impossible to visualize it all at the same time with a “decent” detail. 如下图所示,让我们想象一下世界地图,用“体面”细节同时将它们全部可视化是不可能的。 Therefore, in my canvas I would like to be able to pan over it using the mouse to see the other countries that are not visible. 因此,在我的画布中,我希望能够使用鼠标平移它以查看其他不可见的国家。

Does anyone know how to implement this sort of panning in a HTML5 canvas? 有谁知道如何在HTML5画布中实现这种平移? Another feature would be the zoom in and out. 另一个功能是放大和缩小。

画布图 I've seen a few examples but I couldn't get them working nor they seam to address my question. 我已经看过几个例子,但是我无法让它们工作,也不能解决我的问题。

Thanks in advance! 提前致谢!

To achieve a panning functionality with a peep-hole it's simply a matter of two draw operations, one full and one clipped. 为了实现具有窥视孔的平移功能,它只需要两个绘制操作,一个完整和一个剪切。

To get this result you can do the following ( see full code here ): 要获得此结果,您可以执行以下操作( 请参阅此处的完整代码 ):

Setup variables: 设置变量:

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

Set up the main functions that you use to set size according to window size (including on resize): 根据窗口大小设置用于设置大小的主要功能(包括调整大小):

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

The main function in this is the draw function. 其中的主要功能是绘图功能。 Here we draw the image on the position calculated by mouse moving (see next section). 这里我们在鼠标移动计算的位置上绘制图像(参见下一节)。

  • First step to get that washed-out look is to set alpha down to about 0.2 (you could also draw a transparent rectangle on top but this is more efficient). 获得褪色外观的第一步是将alpha设置为约0.2(您还可以在顶部绘制透明矩形,但效率更高)。
  • Then draw the complete image. 然后绘制完整的图像。
  • Reset alpha 重置alpha
  • Draw the peep-hole using clipping with corrected offsets for the source. 使用具有校正的源偏移的削波来绘制窥视孔。

- -

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

Now it's a matter of handling mouse down, move and up and calculate the offsets - 现在这是处理鼠标按下,移动和向上并计算偏移量的问题 -

In the mouse down we store current mouse positions that we'll use for calculating deltas on mouse move: 在鼠标按下时,我们存储当前鼠标位置,我们将用它来计算鼠标移动时的增量:

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

Here we use the deltas to avoid image jumping setting the corner to mouse position. 在这里,我们使用增量来避免图像跳跃将角落设置为鼠标位置。 The deltas are transferred as offsets to the update function: 增量作为偏移量传输到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();
    }
}

And finally on mouse up we make the offsets a permanent part of the image position: 最后,在鼠标上移动时,我们将偏移作为图像位置的永久部分:

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

For zooming the canvas I believe this is already answered in this post - you should be able to merge this with the answer given here: 对于缩放画布我相信这已经在这篇文章中得到了解答 - 你应该能够将其与这里给出的答案合并:
Zoom Canvas to Mouse Cursor 将画布缩放到鼠标光标

To do something like you have requested, it is just a case of having 2 canvases, each with different z-index. 为了做你所要求的事情,只需要有2幅画布,每幅画都有不同的z-index。 one canvas smaller than the other and position set to the x and y of the mouse. 一个画布比另一个小,并且位置设置为鼠标的x和y。

Then you just display on the small canvas the correct image based on the position of the x and y on the small canvas in relation to the larger canvas. 然后,您只需在小画布上显示基于小画布上x和y相对于较大画布的位置的正确图像。

However your question is asking for a specific solution, which unless someone has done and they are willing to just dump their code, you're going to find it hard to get a complete answer. 然而,你的问题是要求一个特定的解决方案,除非有人做了,他们愿意只是转储他们的代码,你会发现很难得到一个完整的答案。 I hope it goes well though. 我希望它顺利。

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

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