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

时间:2016-10-16 01:08:16

标签: javascript html5 canvas html5-canvas viewport

我正在尝试使用较小的画布作为另一个更大画布的视口。 我非常喜欢this在类似问题上使用解决方案的方法。

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

似乎后面提到的解决方案不适用于不同的画布尺寸。所以我需要把它做成“画布大小不可知”。

也许我错过了某种可怕的计算方法,但我不知道如何离开这里,欢迎任何提示。

修改

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

1 个答案:

答案 0 :(得分:0)

最简单的方法是使用另一个画布作为中间层。

这里我将忽略偏移画布,因为除非您想要显示整个地图,否则不需要它。大概你需要的只是放大的区域。如果要缩小,只需将完整图像绘制到视口窗口(通过向ctx.drawImage ( img, x, y, viewPort.width, viewPort.height )提供宽度和高度参数)。但是,您希望确保将图像手动裁剪为适当的大小,以使图像不会显示为拉伸或确保画布视口与您正在使用的图像具有相同的宽高比。

如果您希望背景的剪切区域(实际查看区域)与视口窗口(放大/缩小查看区域)的大小(更小或更大)不同,则以下情况有效。请注意,这与实际背景的大小不同无关。据推测,剪裁区域和视口窗口都小于背景图像本身。

例如:

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