2012-12-23 50 views
0

一個路徑是否有可能限制一個物品(如Image)到Polygon的中風?約束圖片到在KineticJS

的jsfiddle:http://jsfiddle.net/CZzpZ/

在的jsfiddle,我會喜歡尤達Image到了它的阻力限制在多邊形poly的行程。進去看了Complex Drag Bounds KineticJS教程,但沒有得到關於約束的路徑,只在一個區域內限制任何線索。

+0

我能拼湊僞劣黑客(否則這將是一個答案,而不是評論),這似乎** **工作,但是當組偏移以外的任何其他失敗(0,0)。我想這個問題源於這樣的事實:我不知道從「poly.getPoints」獲得的點是絕對的還是與組相關的。不過,我想這是值得入手:http://jsfiddle.net/7H2sj/7/ – Rikonator

回答

1

這樣做的一種方法是,在dragBoundFunc中獲取Polygon的點,然後應用一些基本矢量數學來找出位置最接近的多邊形上的哪個點。

Demo

我必須指出,我不喜歡這樣對於每個可能的阻力,能夠形象,你就必須設置不同的dragBoundFunc,因爲他們有不同的多邊形。所以,我做了一個泛型函數polyStrokeBoundDragFunc(富有想象力的,對不對?),把它假設多邊形被作爲參數傳遞。

因此,dragBoundFunc貌似

... 

dragBoundFunc: function(pos) { 
      return polyStrokeBoundDragFunc(pos, poly, group); 
     } 
... 

組包括在這裏,因爲我們需要的組多邊形,以及該位置轉換從絕對到本地。這是必需的,因爲如果多邊形在一個組中,polygon.getPoints將給出本地點。傳遞給dragBoundFunc的位置似乎是絕對的。現在

的問題,這還是蠻生的肉(因爲它未優化的肉,你看)!該功能可以找出與給定位置相距的最近點,然後比較距離。選擇距離該位置最小距離的一側。

var polyStrokeBoundDragFunc = function(pos, poly, group) { 
    //Check if the poly is usable as a polygon 
    if(!poly || !poly.getPoints) { 
     return pos; 
    } 

    //Convert the drag position from absolute to local to the group 
    //if, of course, there is a group 
    if(group && group.getAbsolutePosition) { 
     pos.x = pos.x - group.getAbsolutePosition().x; 
     pos.y = pos.y - group.getAbsolutePosition().y; 
    } 

    var newX = pos.x, newY = pos.y, 
     diff = 9999; //A bloated diff, for minimum comparision 

    //Get the list of points from the polygon 
    var points = poly.getPoints(); 

    //The algorithm is simple, iterate through the list of points 
    //and select a pair which forms a side of the polygon. 
    //For this side, pick a main point. Find the direction vector 
    //with respect to this main point, and find the position vector 
    //from this main point to the drag position. 
    //Dot product of position vector and direction vector give us 
    //the projection of the point on the current side. 
    //A simple bounds checking to ensure that the projection is on 
    //the side, then a distance calculation. 
    //If the distance found is less than the current minimum difference 
    //update diff, newX and newY. 
    for(var i=0; i<points.length; i++) { 
     //Get point pair. 
     var p1 = points[i]; 
     var p2 = points[(i+1)%points.length]; 

     //Find the bounds for checking projection bounds later on   
     var minX = (p1.x < p2.x ? p1.x : p2.x), 
      minY = (p1.y < p2.y ? p1.y : p2.y), 
      maxX = (p1.x > p2.x ? p1.x : p2.x), 
      maxY = (p1.y > p2.y ? p1.y : p2.y); 

     //Select p2 as the main point. 
     //Find the direction vector and normalize it.  
     var dir = {x: p1.x - p2.x, y: p1.y - p2.y}; 
     var m = Math.sqrt(dir.x*dir.x + dir.y*dir.y); 
     if(m !== 0) { 
      dir.x = dir.x/m; 
      dir.y = dir.y/m; 
     } 

     //Find the position vector   
     var pVec = {x: pos.x - p2.x, y: pos.y - p2.y}; 

     //Dot product   
     var dot = pVec.x * dir.x + pVec.y * dir.y; 

     //Find the projection along the current side   
     var p = {x: p2.x + dir.x*dot, y: p2.y + dir.y*dot};  

     //Bounds checking to ensure projection remains 
     //between the point pair.  
     if(p.x < minX) 
      p.x = minX; 
     else if(p.x > maxX) 
      p.x = maxX; 

     if(p.y < minY) 
      p.y = minY; 
     else if(p.y > maxY) 
      p.y = maxY; 

     //Distance calculation. 
     //Could have simply used squared distance, but I figured 9999 may 
     //not be bloated enough for that.  
     var d = Math.sqrt((p.x-pos.x)*(p.x-pos.x) + (p.y-pos.y)*(p.y-pos.y)); 

     //Minimum comparision.  
     if(d < diff) { 
       diff = d; 
       newX = p.x; 
       newY = p.y; 
     } 
    } 

    //If in a group's local, convert back to absolute  
    if(group && group.getAbsolutePosition) { 
     newX += group.getAbsolutePosition().x; 
     newY += group.getAbsolutePosition().y; 
    } 

    //Return updated drag position. 
    return { 
     x: newX, 
     y: newY 
    } 
}; 

這似乎工作,但我仍然覺得解決方案有點混亂。可能有更好的辦法,我想不出來。

+0

謝謝Rikonator,你真是個天才! – Nyxynyx