简体   繁体   English

从更大的图像与html5画布的视口

[英]Viewport from bigger image with html5 canvas

I'm trying to use a smaller canvas as a viewport for another much bigger canvas. 我正在尝试使用较小的画布作为另一个更大画布的视口。 I really like the approach used in this the solution on a similar question. 我真的很喜欢这个解决方案中用于类似问题的方法。

He basically uses CanvasRenderingContext2D.drawImage() to "crop" the buffer/offset canvas and then displays that portion of the image on the smaller canvas (viewport). 他基本上使用CanvasRenderingContext2D.drawImage()来“裁剪”缓冲区/偏移画布,然后在较小的画布(视口)上显示该部分图像。 I'm trying to implement a simpler version of the given solution in this fiddle: https://jsfiddle.net/avvac0x8/2/ . 我试图在这个小提琴中实现给定解决方案的更简单版本: https//jsfiddle.net/avvac0x8/2/ But as you can see the viewport is not entirely in sync with the big image (and vice-versa). 但正如您所看到的那样,视口与大图像并不完全同步(反之亦然)。

It seems that the after mentioned solution does not work with different canvas sizes. 似乎后面提到的解决方案不适用于不同的画布尺寸。 So I need to make it "canvas-size agnostic". 所以我需要把它做成“画布大小不可知”。

Maybe I'm missing some kind of scalling calculations, but I don't know how to go from here, any tips are welcome. 也许我错过了一些可怕的计算,但我不知道如何从这里开始,欢迎任何提示。

EDIT: 编辑:

Updated the fiddle to work properly: https://jsfiddle.net/avvac0x8/4/ . 更新了小提琴以正常工作: https//jsfiddle.net/avvac0x8/4/ Aparently the original image should not be scaled to fit the buffer canvas. 显然原始图像不应缩放以适合缓冲画布。 What it should be done instead is that the offset/buffer canvas should be the same size as the original image. 应该做的是偏移/缓冲画布应该与原始图像的大小相同。

The simplest way is to use another canvas as a middle layer. 最简单的方法是使用另一个画布作为中间层。

Here I will ignore the offset canvas because it is not needed unless you want to display the entire map. 在这里,我将忽略偏移画布,因为除非您想要显示整个地图,否则不需要它。 Presumably all you need is the zoomed in region. 大概你需要的只是放大的区域。 If you want to zoom out, you can simply draw the full image to your viewport window ( by providing the width and height parameters to ctx.drawImage ( img, x, y, viewPort.width, viewPort.height ) ). 如果要缩小,只需将完整图像绘制到视口窗口(通过向ctx.drawImage ( img, x, y, viewPort.width, viewPort.height )提供width和height参数)。 However you want to be sure that your image is manually cropped to an appropriate size so that the image does not appear stretched OR make sure that your canvas viewport is of the same aspect ratio as the image you are using. 但是,您希望确保将图像手动裁剪为适当的大小,以使图像不会显示为拉伸或确保画布视口与您正在使用的图像具有相同的宽高比。

The below works if you want the clipping region of the background ( the actual viewing area ) to be a different size (smaller or larger) than your viewport window ( the zoomed in/out viewing area ). 如果您希望背景的剪切区域(实际查看区域)与视口窗口(放大/缩小查看区域)的大小(更小或更大)不同,则以下情况有效。 Note that this is independent of how much larger or smaller the actual background is. 请注意,这与实际背景的大小不同无关。 Presumably both the clipped area and the viewport window are smaller than the background image itself. 据推测,剪裁区域和视口窗口都小于背景图像本身。

For example: 例如:

// use these to determine where the clipping region lives
var offsetX = 0,
    offsetY = 0,
    clipWidth = <<yourChosenPixelWidth>>,
    clipHeight = <<yourChosenPixelHeight>>,
    clip = document.createElement ( "canvas" ),
    clipCtx,
    viewPort = document.getElementById ( "main-canvas" ),
    viewCtx = viewPort.getContext ( "2d" ),
    background = new Image (),
    // offsetCanvas = document.getElementById ( "offset-canvas" ),
    imgLoaded = false;

// configure the offset canvas once
background.src = "http://pixeljoint.com/files/icons/full/map__r1470206141.png";
background.onLoad = function() {
    // the fiddle scales the image, here we don't
    //offsetCanvas.width = background.width;
    //offsetCanvas.height = background.height;
    //offsetCtx = offsetCanvas.getContext ( "2d" );
    //offsetCtx.drawImage ( background, 0, 0 );
    imgLoaded = true;
}

clip.width = clipWidth;
clip.height = clipHeight;
clipCtx = clip.getContext ( "2d" );

function updateViewport () {
    if ( imgLoaded ) {
        // copy pixels from the background directly
        // to the middle layer so we have a "clipped"
        // but unscaled image object
        //clipCtx.putImageData ( offsetCtx.getImageData ( offsetX, offsetY, clip.width, clip.height ) );
        clipCtx.drawImage ( background, offsetX, offsetY );

        // this is where rescaling happens
        viewCtx.drawImage ( clip, 0, 0, viewPort.width, viewPort.height );

        // and you're done!
    }
}

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

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