Viewport from bigger image with html5 canvas

时间秒杀一切 提交于 2021-02-11 08:30:54

问题


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

EDIT:

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.


回答1:


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


来源:https://stackoverflow.com/questions/40065828/viewport-from-bigger-image-with-html5-canvas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!