2014-11-14 127 views
0

有沒有辦法使用這段代碼縮放光標點?我無法做到這一點。畫布縮放,但只能從左上角放大和縮小。Javascript Cursor Zooming

var previousMousePosition = new Vector(0, 0); 
function OnMouseWheel (event) { 
    var delta = event.wheelDelta ? event.wheelDelta/40 : event.detail ? -event.detail : 0; 
    var mousePosition = new Vector(event.clientX, event.clientY); 
    var scaleFactor = 1.1; 
    if (delta) { 
     var factor = Math.pow(scaleFactor,delta); 
     context.scale(factor,factor); 
    } 
} 
+0

0,0可能是左上角? - 這將是我的猜測 – 2014-11-14 19:25:23

回答

1

畫布始終從當前原點開始縮放。默認原點是[0,0]。

如果你想從另一個點進行縮放,你可以先做context.translate(desiredX,desiredY);。這會將畫布的原點重置爲[desiredX,desiredY]。

這樣你的context.scale將從你指定的原點擴展。

由於所有上下文轉換對於每個後續繪圖均保持有效,因此您經常要在完成當前繪圖後反轉轉換(對於可能/可能不使用當前轉換的下一個繪圖,「=='resetting' )。爲了不轉換,只需使用負面參數調用轉換:例如。 context.scale(-factor,-factor)。轉換應該按照與原始轉換相反的順序進行。

所以你重構的代碼可能是:

// set the origin to mouse x,y 
context.translate(mousePosition.x,mousePosition.y); 

// scale the canvas at x,y 
context.scale(factor,factor); 

// ...draw stuff 

// reverse the previous scale 
context.scale(-factor,-factor); 

// reverse the previous translate 
context.translate(-mousePosition.x,-mousePosition.y); 
0

首先,我想指出的是,從你的代碼,它看起來像你正在聽的畫布上的「滾輪」事件。如here所述,'鼠標滾輪'事件是非標準的並且不符合標準。因此,聽到它時,您最終會得到混合的結果。 「滾動」事件幾乎在每個平臺上都可用,並且可能是捕獲用戶輸入的更好途徑。

就您的問題而言,您正在尋找您正在尋找的行爲的正確軌道,但您錯過了一步。

當您在畫布上下文對象上調用scale時,其行爲非常簡單。從左上角(0,0)開始,該方法根據提供的因子縮放畫布的點。假設你有一個10×10的畫布,並有1,1個黑點。如果畫布在兩個軸上縮放2倍,則0,0點將保持在相同位置,但是點1,1將是縮放前2,2點的位置。

爲了實現您正在尋找的'縮放'行爲,縮放後的上下文必須爲翻譯爲,以便參考點佔據與縮放前相同的物理位置。在你的情況下,參考點是當執行縮放操作時用戶光標所在的點。

幸運的是,畫布上下文對象提供了一個將上下文的原點相對於畫布的0,0點移動的方法。要翻譯它的正確ammount的,你必須:

  1. 計算比例因子
  2. 變焦
  3. 除以距離之前從畫布原點的鼠標光標的距離由值
  4. 翻譯的由來

因爲你的代碼並不表示你的HTML的結構,下面我帶了一些意見和僞標誌着它向您展示如何實現這個算法:

//You'll need to get a reference to your canvas in order to calculate the relative position of 
//the cursor to its top-left corner, and save it to a variable that is in scope inside of your 
//event handler function 

var canvas = document.getElementById('id_of_your_canvas'); 

//We're also going to set up a little helper function for returning an object indicating 
//the position of the top left corner of your canvas element (or any other element) 

function getElementOrigin(el){ 
    var boundingBox = el.getBoundingClientRect(); 
    return { x: boundingBox.left, y: boundingbox.top}; 
} 

function OnMouseWheel (event) { 
    //you probably want to prevent scrolling from happening or from bubbling so: 
    event.preventDefault(); 
    event.stopPropagation(); 

    var delta = event.wheelDelta ? event.wheelDelta/40 : event.detail ? -event.detail : 0; 

    var canvasCorner = getElementOrigin(canvas) 
    //JavaScript doesn't offer a 'vector' or 'point' class natively but we don't need them 
    var mousePosition = {x: event.clientX, y: event.clientY}; 
    var diff = {x: mousePostion.x - canvasCorner.x, y: mousePosition.y - canvasCorner.y}; 
    var scaleFactor = 1.1; 

    if (delta) { 
     var factor = Math.pow(scaleFactor,delta); 
     var transX = (-1/factor) * diff.x; 
     var transY = (-1/factor) * diff.y; 
     context.scale(factor,factor); 
     context.translate(transX, transY); 
    } 
}