2013-04-29 53 views
0

我怎樣才能平滑地爲畫布創建縮放動畫? GWT提供onMouseWheel(MouseWheelEvent evt)方法和evt.getDeltaY()來獲取滾輪的數量。如何平滑放大畫布?

這裏的問題是,每個輪子運動都執行這個方法,如果我在方法本身中調用畫布重繪,事情會變得非常遲緩。

所以我想到了爲縮放製作動畫。但是如何?

我想過創造一個Timer,但沒有真正的想法,因爲只有在的MouseWheelEvent爲出發點,但沒有終點用戶完成與滾輪縮放...

回答

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

我已經創建了一個擁有廣泛的動畫一些其他的帆布小部件,我發現它很好的做法,一旦呈現這些動畫,然後保存他們後來只放回畫布。這使得快速渲染效率更高。 – 2013-04-29 17:43:27

+0

這是一個關於畫布表現的優秀教程,我用它來優化畫布元素。 http://www.html5rocks.com/en/tutorials/canvas/performance/ – 2013-04-30 13:44:09