如何平滑放大画布? [英] How to smoothly zoom a canvas?

查看:108
本文介绍了如何平滑放大画布?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我怎样才能平滑地为画布创建缩放动画?
GWT提供了一个 onMouseWheel(MouseWheelEvent evt)方法和一个 evt.getDeltaY()来获得金额



这里的问题是,每个轮子运动都会执行这个方法,如果我在方法本身中调用一个画布重绘,事情会变得非常迟缓。 p>

所以我想到为缩放制作一个动画。但是怎么做?



我想过创建一个 Timer ,但没有真正的想法,因为只有mousewheelevent作为起点,但没有结束点,用户完成了与轮子的缩放...

解决方案

这是我的可缩放图像类我用来放大图像,这是非常快速和响应。我在某处找到了一个示例,并进行了一些小修改以使其更具响应性。

  public class ScalableImage extends Composite实现MouseWheelHandler,MouseDownHandler, MouseMoveHandler,MouseUpHandler {

Canvas canvas = Canvas.createIfSupported();
Context2d context = canvas.getContext2d();

Canvas backCanvas = Canvas.createIfSupported();
Context2d backContext = backCanvas.getContext2d();

int width;
int height;
图片图片;
ImageElement imageElement;

double zoom = 1;
double totalZoom = 1;
double offsetX = 0;
double offsetY = 0;

boolean mouseDown = false;
double mouseDownXPos = 0;
double mouseDownYPos = 0;


public Sc​​alableImage(Image image){
initWidget(canvas);

// width = Window.getClientWidth() - 50;

width = image.getWidth()+ 200;
height = image.getHeight()+ 200;


//canvas.setWidth (width +px);
//canvas.setHeight(height +px);
canvas.setCoordinateSpaceWidth(width);
canvas.setCoordinateSpaceHeight(height);

//backCanvas.setWidth (width +px);
//backCanvas.setHeight(height +px);
backCanvas.setCoordinateSpaceWidth(width);
backCanvas.setCoordinateSpaceHeight(height);

canvas.addMouseWheelHandler(this);
canvas.addMouseMoveHandler(this);
canvas.addMouseDownHandler(this);
canvas.addMouseUpHandler(this);

this.image = image;
this.imageElement =(ImageElement)image.getElement()。cast();

mainDraw();
}

public void onMouseWheel(MouseWheelEvent event){
int move = event.getDeltaY();

double xPos =(event.getRelativeX(canvas.getElement()));
double yPos =(event.getRelativeY(canvas.getElement()));

if(move <0){
zoom = 1.1;
} else {
zoom = 1 / 1.1;
}

double newX =(xPos - offsetX)/ totalZoom;
double newY =(yPos - offsetY)/ totalZoom;

double xPosition =(-newX * zoom)+ newX;
double yPosition =(-newY * zoom)+ newY;

backContext.clearRect(0,0,width,height);

backContext.translate(xPosition,yPosition);

backContext.scale(zoom,zoom);

mainDraw();

offsetX + =(xPosition * totalZoom);
offsetY + =(yPosition * totalZoom);

totalZoom = totalZoom * zoom;

buffer(backContext,context);
}

public void onMouseDown(MouseDownEvent event){
this.mouseDown = true;
mouseDownXPos = event.getRelativeX(image.getElement());
mouseDownYPos = event.getRelativeY(image.getElement());
}

public void onMouseMove(MouseMoveEvent event){
if(mouseDown){
backContext.setFillStyle(white);
backContext.fillRect(-5,-5,width + 5,height + 5);
backContext.setFillStyle(black);
double xPos = event.getRelativeX(image.getElement());
double yPos = event.getRelativeY(image.getElement());
backContext.translate((xPos - mouseDownXPos)/ totalZoom,(yPos - mouseDownYPos)/ totalZoom);

offsetX + =(xPos - mouseDownXPos);
offsetY + =(yPos - mouseDownYPos);

mainDraw();
mouseDownXPos = xPos;
mouseDownYPos = yPos;
}
}

public void onMouseUp(MouseUpEvent event){
this.mouseDown = false;
}

public void mainDraw(){
backContext.drawImage(imageElement,100,100);

buffer(backContext,context);


public void buffer(Context2d back,Context2d front){
front.beginPath();
front.clearRect(0,0,width,height);
front.drawImage(back.getCanvas(),0,0);
}
}


How could I smoothly create a zoom animation for a canvas? GWT provides a onMouseWheel(MouseWheelEvent evt) method and a evt.getDeltaY() to get the amount of scroll wheel.

Problem here is, that every wheel movement executes this method, and if I call a canvas redraw in the method itself, things get very laggy.

So I thought of somehow making an animation for the zooming. But how?

I thought about creating a Timer, but have no real idea, as there is only the mousewheelevent as starting point, but no end point that the user finished zooming with the wheel...

解决方案

Here is my scalable image class that I use to zoom into images, it is very quick and responsive. I found an example somewhere and made some minor modifications to make it more responsive. I don't remember the original source or I would give them credit here.

public class ScalableImage extends Composite implements MouseWheelHandler, MouseDownHandler, MouseMoveHandler, MouseUpHandler {

    Canvas canvas = Canvas.createIfSupported();
    Context2d context = canvas.getContext2d();

    Canvas backCanvas = Canvas.createIfSupported();
    Context2d backContext = backCanvas.getContext2d();

    int width;
    int height;
    Image image;
    ImageElement imageElement; 

    double zoom = 1;
    double totalZoom = 1;
    double offsetX = 0;
    double offsetY = 0;

    boolean mouseDown = false;
    double mouseDownXPos = 0;
    double mouseDownYPos = 0;


    public ScalableImage(Image image) {
        initWidget(canvas);

        //width = Window.getClientWidth() - 50;

        width = image.getWidth() + 200;
        height = image.getHeight() + 200;


        //canvas.setWidth(width + "px");
        //canvas.setHeight(height + "px");
        canvas.setCoordinateSpaceWidth(width);
        canvas.setCoordinateSpaceHeight(height);

        //backCanvas.setWidth(width + "px");
        //backCanvas.setHeight(height + "px");
        backCanvas.setCoordinateSpaceWidth(width);
        backCanvas.setCoordinateSpaceHeight(height);

        canvas.addMouseWheelHandler(this);
        canvas.addMouseMoveHandler(this);
        canvas.addMouseDownHandler(this);
        canvas.addMouseUpHandler(this);

        this.image = image;
        this.imageElement = (ImageElement) image.getElement().cast();

        mainDraw();
    }

    public void onMouseWheel(MouseWheelEvent event) {
        int move = event.getDeltaY();

        double xPos = (event.getRelativeX(canvas.getElement()));
        double yPos = (event.getRelativeY(canvas.getElement()));

        if (move < 0) {
            zoom = 1.1;
        } else {
            zoom = 1 / 1.1;
        }

        double newX = (xPos - offsetX) / totalZoom;
        double newY = (yPos - offsetY) / totalZoom;

        double xPosition = (-newX * zoom) + newX;
        double yPosition = (-newY * zoom) + newY;

        backContext.clearRect(0, 0, width, height);

        backContext.translate(xPosition, yPosition);

        backContext.scale(zoom, zoom);

        mainDraw();

        offsetX += (xPosition * totalZoom);
        offsetY += (yPosition * totalZoom);

        totalZoom = totalZoom * zoom;

        buffer(backContext, context);
    }

    public void onMouseDown(MouseDownEvent event) {
        this.mouseDown = true;
        mouseDownXPos = event.getRelativeX(image.getElement());
        mouseDownYPos = event.getRelativeY(image.getElement());
    }

    public void onMouseMove(MouseMoveEvent event) {
        if (mouseDown) {
            backContext.setFillStyle("white");
            backContext.fillRect(-5, -5, width + 5, height + 5);
            backContext.setFillStyle("black");
            double xPos = event.getRelativeX(image.getElement());
            double yPos = event.getRelativeY(image.getElement());
            backContext.translate((xPos - mouseDownXPos) / totalZoom, (yPos - mouseDownYPos) / totalZoom);

            offsetX += (xPos - mouseDownXPos);
            offsetY += (yPos - mouseDownYPos);

            mainDraw();
            mouseDownXPos = xPos;
            mouseDownYPos = yPos;
        }
    }

    public void onMouseUp(MouseUpEvent event) {
        this.mouseDown = false;
    }

    public void mainDraw() {
        backContext.drawImage(imageElement, 100, 100);

        buffer(backContext, context);
    }

    public void buffer(Context2d back, Context2d front) {
        front.beginPath();
        front.clearRect(0, 0, width, height);
        front.drawImage(back.getCanvas(), 0, 0);
    }
}

这篇关于如何平滑放大画布?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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