java - 如何平滑地缩放 Canvas ?

标签 java gwt canvas

如何顺利地为 Canvas 创建缩放动画? GWT 提供了一个 onMouseWheel(MouseWheelEvent evt) 方法和一个 evt.getDeltaY() 来获取滚轮的数量。

这里的问题是,每次轮子移动都会执行这个方法,如果我在方法本身中调用 Canvas 重绘,事情会变得非常滞后。

所以我想到以某种方式制作一个缩放动画。但如何呢?

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

最佳答案

这是我用来放大图像的可扩展图像类,它非常快速且响应灵敏。我在某处找到了一个示例,并做了一些小的修改以使其更具响应性。我不记得原始出处,否则我会在这里注明出处。

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);
    }
}

关于java - 如何平滑地缩放 Canvas ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16284284/

相关文章:

java - HashMap 做 containsKey 的方式不符合预期

java - 物体跟踪,避免碰撞以及两个物体的当前速度

java - 在apache poi中使用for循环

internet-explorer - 带有弹出窗口和 iFrame 的 GWT/GXT 应用程序,在带有 Adob​​e reader 的 Internet Explorer 下,PDF 不会隐藏

javascript - 动态调整由 KineticJS 框架创建的 HTML5 Canvas 大小

java - 我的程序停止打印到控制台,但继续在后台运行。没有抛出异常

java - 如何使用 GWTQuery 获取对 Window 对象的引用?

java - GWT 使用异步回调进行同步/阻塞调用

Javascript绘制图像函数失败

javascript - 选择边框不正确,而 Canvas 的缩放值不是 1