如何平滑地缩放画布?

时间:2013-04-29 17:04:10

标签: java gwt canvas

如何为画布平滑创建缩放动画? GWT提供了onMouseWheel(MouseWheelEvent evt)方法和evt.getDeltaY()来获取滚轮的数量。

问题在于,每个轮子运动都会执行此方法,如果我在方法本身中调用画布重绘,则事情变得非常迟缓。

所以我想到了以某种方式为缩放制作动画。但是如何?

我考虑创建一个Timer,但没有真正的想法,因为只有mousewheelevent作为起点,但没有终点,用户完成了使用滚轮进行缩放...

1 个答案:

答案 0 :(得分:4)

这是我用于放大图像的可缩放图像类,它非常快速且响应迅速。我在某个地方找到了一个例子并进行了一些小修改以使其更具响应性。我不记得原始来源,或者我会在这里给予他们赞誉。

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);
    }
}
相关问题