2011-10-12 98 views
10

我設法做一些黑客爲了放大拉斐爾紙張,因爲setviewbox不是爲我工作的,這裏是我寫的函數:其中viewport1元素定義爲拉斐爾紙張縮放動畫

function setCTM(element, matrix) { 
    var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")"; 

    element.setAttribute("transform", s); 
} 

Raphael.fn.zoomAndMove = function(coordx,coordy,zoom) { 

    var svg = document.getElementsByTagName("svg")[0]; 

    var z = zoom; 

    var g = document.getElementById("viewport1"); 
    var p = svg.createSVGPoint(); 

    p.x = coordx; 
    p.y = coordy; 

    p = p.matrixTransform(g.getCTM().inverse()); 

    var k = svg.createSVGMatrix().scale(z).translate(-p.x, -p.y); 
    setCTM(g, g.getCTM().multiply(k)); 
} 

var gelem = document.createElementNS('http://www.w3.org/2000/svg', 'g'); 
gelem.id = 'viewport1'; 

paper.canvas.appendChild(gelem); 
paper.canvas = gelem; 

然後我可以叫:paper.zoomAndMove(minx,miny,zoomRatio);

是否有可能轉換功能,使之順利放大?

+0

請提供一個基本示例,以瞭解縮放當前如何執行。 – zbug

回答

11

查看this JS Fiddle example利用jQuery和Raphael的setViewBox,它可以平滑地進行縮放和平移。我們在更復雜和更大的環境中使用完全相同的功能,即使在屏幕上繪製大量項目,它也能夠完美並保持平穩。

基本上,不要試圖重新發明輪子。我知道這可能不是你正在尋找的答案,但它幾乎肯定是你最好的選擇。

編輯: 我固定連接的小提琴(它被打破因的jsfiddle該網站所做的更改),但顯然讓不讓我救的jsfiddle鏈接,而不包括一些代碼,所以......

console.log("hello world!"); 
+1

你還沒有在小提琴中加入rapheal作爲依賴。剛纔提到:)。這是[**更新**](http://jsfiddle.net/9zu4U/1042/)。 – mithunsatheesh

+1

謝謝@mithunsatheesh!我修好了我的小提琴並更新了鏈接。顯然JSFiddle做了一些改變,打破了原來的小提琴。它現在正在工作。 – James

14

任何人(像我)誰希望有變焦&搖平滑的動態看看這裏:

https://groups.google.com/forum/?fromgroups#!topic/raphaeljs/7eA9xq4enDo

這個文檔片斷幫我自動化和動畫縮放的d平移到畫布上的特定點。 (道具Will Morgan

Raphael.fn.animateViewBox = function(currentViewBox, viewX, viewY, width, height, duration, callback) { 

    duration = duration || 250; 

    var originals = currentViewBox, //current viewBox Data from where the animation should start 
     differences = { 
       x: viewX - originals.x, 
       y: viewY - originals.y, 
       width: width - originals.width, 
       height: height - originals.height 
     }, 
     delay = 13, 
     stepsNum = Math.ceil(duration/delay), 
     stepped = { 
       x: differences.x/stepsNum, 
       y: differences.y/stepsNum, 
       width: differences.width/stepsNum, 
       height: differences.height/stepsNum 
     }, i, 
     canvas = this; 

    /** 
    * Using a lambda to protect a variable with its own scope. 
    * Otherwise, the variable would be incremented inside the loop, but its 
    * final value would be read at run time in the future. 
    */ 
    function timerFn(iterator) { 
      return function() { 
        canvas.setViewBox(
          originals.x + (stepped.x * iterator), 
          originals.y + (stepped.y * iterator), 
          originals.width + (stepped.width * iterator), 
          originals.height + (stepped.height * iterator) 
        ); 
        // Run the callback as soon as possible, in sync with the last step 
        if(iterator == stepsNum && callback) { 
          callback(viewX, viewY, width, height); 
        } 
      } 
    } 

    // Schedule each animation step in to the future 
    // Todo: use some nice easing 
    for(i = 1; i <= stepsNum; ++i) { 
      setTimeout(timerFn(i), i * delay); 
    } 

} 
+0

這看起來正是我在找什麼,我唯一的問題是如何生成'currentViewBox'參數?謝謝 – Chris

+4

希望這有助於嗎? (1 - (me.currZoom * settings.zoomStep)) };' – patrics

+0

它的確如此,謝謝! – Chris

2

小的mod patrics的回答擺脫 「currentViewBox」 的......這可與拉斐爾2.1.0:

Raphael.fn.animateViewBox = function(viewX, viewY, width, height, duration, callback) { 

    duration = duration || 250; 

    //current viewBox Data from where the animation should start 
    var originals = { 
      x: this._viewBox[0], 
      y: this._viewBox[1], 
      width: this._viewBox[2], 
      height: this._viewBox[3] 
    }, 
    differences = { 
      x: viewX - originals.x, 
      y: viewY - originals.y, 
      width: width - originals.width, 
      height: height - originals.height 
    }, 
    delay = 13, 
    stepsNum = Math.ceil(duration/delay), 
    stepped = { 
      x: differences.x/stepsNum, 
      y: differences.y/stepsNum, 
      width: differences.width/stepsNum, 
      height: differences.height/stepsNum 
    }, i, 
    canvas = this; 

    /** 
    * Using a lambda to protect a variable with its own scope. 
    * Otherwise, the variable would be incremented inside the loop, but its 
    * final value would be read at run time in the future. 
    */ 
    function timerFn(iterator) { 
     return function() { 
       canvas.setViewBox(
         originals.x + (stepped.x * iterator), 
         originals.y + (stepped.y * iterator), 
         originals.width + (stepped.width * iterator), 
         originals.height + (stepped.height * iterator), 
         true 
       ); 
       // Run the callback as soon as possible, in sync with the last step 
       if(iterator == stepsNum && callback) { 
         callback(viewX, viewY, width, height); 
       } 
     } 
    } 

    // Schedule each animation step in to the future 
    // Todo: use some nice easing 
    for(i = 1; i <= stepsNum; ++i) { 
     setTimeout(timerFn(i), i * delay); 
    } 
} 

Sry基因,如果它是壞的禮儀發佈一個mod。隨意將它合併到patrics的版本中,但這些評論沒有意義。

1

上述類似,但不同之處:

  • 不依賴於內部(已經因爲改變)
  • 不需要任何全球設立(它爲您處理)
  • 使用requestAnimationFrame,從而更加平滑的動畫(但不IE9或低於工作)
  • 用途Raphael's easing functionslineareaseIneaseOuteaseInOutbackInbackOutelasticbounce

由於這是一個完全重寫我沒有修改上面。

Raphael.fn.animateViewBox = function(viewX, viewY, width, height, duration, callback, easing) { 
    var start = window.performance.now(), 
     canvas = this; 

    easing = Raphael.easing_formulas[ easing || 'linear' ]; 
    duration = duration === undefined ? 250 : duration; 

    if (canvas.currentViewBox == undefined) { 
     canvas.currentViewBox = { 
      x: 0, 
      y: 0, 
      width: this._viewBox ? this._viewBox[2] : canvas.width, 
      height: this._viewBox ? this._viewBox[3] : canvas.height 
     } 
    } 

    function step(timestamp) { 
     var progress = timestamp - start; 
     var progressFraction = progress/duration; 

     if (progressFraction > 1) { 
      progressFraction = 1; 
     } 

     var easedProgress = easing(progressFraction); 
     var newViewBox = { 
      x: canvas.currentViewBox.x + (viewX - canvas.currentViewBox.x) * easedProgress, 
      y: canvas.currentViewBox.y + (viewY - canvas.currentViewBox.y) * easedProgress, 
      width: canvas.currentViewBox.width + (width - canvas.currentViewBox.width) * easedProgress, 
      height: canvas.currentViewBox.height + (height - canvas.currentViewBox.height) * easedProgress 
     }; 
     canvas.setViewBox(newViewBox.x, newViewBox.y, newViewBox.width, newViewBox.height, false); 

     if (progressFraction < 1) { 
      window.requestAnimationFrame(step); 
     } else { 
      canvas.currentViewBox = newViewBox; 
      if (callback) { 
       callback(newViewBox.x, newViewBox.y, newViewBox.width, newViewBox.height); 
      } 
     } 
    } 
    window.requestAnimationFrame(step); 
} 
+0

+1這個頁面上有最流暢的動畫。如果您的畫布設置爲寬度或高度百分比(例如「100%」),則初始版本會有一堆「NaN」。如果'this._viewBox'可用(它應該是),我做了一個編輯, – user568458