使用html5画布从更大图像显示视口 [英] Viewport from bigger image with html5 canvas

查看:55
本文介绍了使用html5画布从更大图像显示视口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用较小的画布作为另一个更大的画布的视口.我真的很喜欢类似问题的解决方案中使用的方法.

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.

他基本上使用 CanvasRenderingContext2D.drawImage()裁剪"缓冲区/偏移画布,然后在较小的画布(视口)上显示图像的该部分.我正在尝试在此提琴中实现给定解决方案的简单版本: https://jsfiddle.net/avvac0x8/2/.但是正如您所看到的,视口并不完全与大图像同步(反之亦然).

He basically uses CanvasRenderingContext2D.drawImage() to "crop" the buffer/offset canvas and then displays that portion of the image on the smaller canvas (viewport). I'm trying to implement a simpler version of the given solution in this fiddle: 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.

更新了小提琴以使其正常工作: https://jsfiddle.net/avvac0x8/4/.显然,不应缩放原始图像以适合缓冲画布.应该做的是,偏移量/缓冲画布的大小应与原始图像的大小相同.

Updated the fiddle to work properly: 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.

在这里,我将忽略偏移画布,因为除非您要显示整个地图,否则不需要它.大概您需要的只是放大区域.如果要缩小,可以简单地将整个图像绘制到视口窗口中(通过向 ctx.drawImage(img,x,y,viewPort.width,viewPort.height)提供width和height参数)).但是,您需要确保将图像手动裁剪为合适的尺寸,以使图像不会显得过长,或者确保画布视口的纵横比与所使用的图像相同.

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 ) ). 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.

例如:

// 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!
    }
}

这篇关于使用html5画布从更大图像显示视口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆