2016-04-02 82 views
5

在你認爲「爲什麼這個人在這個問題上尋求幫助,當然這已經實現了1000倍」 - 雖然你基本上是正確的,但我試圖通過幾次打開來解決這個問題源代碼庫,但我在這裏。SVG放大鼠標 - 數學模型

我試圖從頭開始實現基於SVG的「放大鼠標滾輪,重點放在鼠標上」。

我知道有很多庫可以實現這一點,d3和svg-pan-zoom來命名一對夫婦。不幸的是,我使用這些庫的實現沒有達到我的預期。我希望能從這個社區獲得一些幫助,幫助他們瞭解這種UI功能的基礎數學模型。

基本上,所需的行爲就像Google地圖,用戶將鼠標懸停在某個位置上,滾動鼠標滾輪(向內),地圖圖像的比例增加,而位置懸停的位置成爲視口的水平和垂直中心。

當然,我可以訪問視口的寬度/高度和鼠標的x/y。

在本例中,我將只集中在x軸上,視口是900個單位寬,正方形爲100個單位寬,它的x偏移量是400個單位,和比例爲1:1

<g transform="translate(0 0) scale(1)"> 

enter image description here

假設鼠標x位置是在或接近450個單位,如果用戶車輪在直到規模達到2:1,我期望的x偏移量達到-450單位,圍繞焦點的像這樣的點。

<g transform="translate(-450 0) scale(2)"> 

enter image description here

的x和y偏移需要在車輪滾動的每個增量爲當前尺度/小鼠偏移的函數重新計算。

我所有的嘗試已經完全沒有達到預期的行爲,任何建議表示讚賞。

雖然我很感激任何幫助,但請不要回答建議第三方庫,jQuery插件和這種性質的東西。我的目標是從一般意義上理解這個問題背後的數學模型,我使用SVG主要是說明性的。

回答

5

我通常做的是我維護三個可變的偏移量x偏移量y和比例。它們將作爲轉換應用於容器組,如元素<g transform="translate(0 0) scale(1)">

如果鼠標位於原點之上,新的轉換將會很微不足道。你只是在規模乘以偏移x和y的區別:

offsetX = offsetX * newScale/scale 
offsetY = offsetY * newScale/scale 

你可以做的是翻譯的偏移,使鼠標在原點。然後你縮放,然後你把所有的東西都翻譯回來。看一看具有scaleRelativeTo方法只是做這個打字稿類,你想要什麼:

export class Point implements Interfaces.IPoint { 
    x: number; 
    y: number; 

    public constructor(x: number, y: number) { 
     this.x = x; 
     this.y = y; 
    } 

    add(p: Interfaces.IPoint): Point { 
     return new Point(this.x + p.x, this.y + p.y); 
    } 

    snapTo(gridX: number, gridY: number): Point { 
     var x = Math.round(this.x/gridX) * gridX; 
     var y = Math.round(this.y/gridY) * gridY; 
     return new Point(x, y); 
    } 

    scale(factor: number): Point { 
     return new Point(this.x * factor, this.y * factor); 
    } 

    scaleRelativeTo(point: Interfaces.IPoint, factor: number): Point { 

     return this.subtract(point).scale(factor).add(point); 
    } 

    subtract(p: Interfaces.IPoint): Point { 
     return new Point(this.x - p.x, this.y - p.y); 
    } 

    } 

所以,如果你給變換鑑於translate(offsetX,offsetY) scale(scale)和滾動事件發生在(mouseX, mouseY)引領到一個新的規模newScale你將通過以下方式計算新變換:

offsetX = (offsetX - mouseX) * newScale/scale + mouseX 
offsetY = (offsetY - mouseY) * newScale/scale + mouseY 
+0

在那裏,最後,只是美麗 - 謝謝你 – James