2014-07-17 106 views
2

我的目標是能夠以一種看起來非常好的方式渲染圖形數據庫(通過線條連接的節點),並在添加新節點時平滑地進行動畫。我一直在看SVG,Canvas,現在是Famo.us.在Famo.us中的曲面之間繪製很多線條?

Famo.us似乎可能對此很好,因爲我可以使用Famo.us曲面渲染包括HTML格式文本和控件的每個節點。問題是繪製線連接節點。 Famo.us沒有像線條一樣的基元。它確實有帆布表面,但這看起來不是正確的方法。

我在猜測我不得不爲每條線做一些非常尷尬的事情,比如創建一個高而薄的表面並計算一個使它在兩個曲面之間連接的變換。

+0

你取得任何進展?我在問自己同樣的問題。 – Alp

+0

我放棄了Famo.us,並決定畫布和svg是更好的選擇。 – user800268

回答

3

這是一個2個可拖動表面的示例,它們之間有一條直線。該線是用另一個表面創建的。

運行演示http://gazibit.com/widget/31

var Engine = famous.core.Engine; 
var Surface = famous.core.Surface; 
var Modifier = famous.core.Modifier; 
var Transform = famous.core.Transform; 
var Draggable = famous.modifiers.Draggable; 
var StateModifier = famous.modifiers.StateModifier; 

var mainContext = Engine.createContext(); 


var lineOptions = {thickness:2, 
       lineColor:'#FA5C4F'}; 

//line surface 
var ls = new Surface({ 
    origin:[0,.5], 
    properties:{ 
     backgroundColor:lineOptions.lineColor 
    } 
}); 
initLine(); 
//Add the 2 blocks that will be joined by the line 
ls.s1 = createBlock("s1",[100,100]); 
ls.s2 = createBlock("s2",[300,100]); 


//---------------------- 
// HELPER FUNCTIONS 
//---------------------- 
function initLine(){ 
var canvasModifier = new Modifier({ 
    size:function(){ 
     var len = _getLineLength()+5; 
     return [len,lineOptions.thickness]; 
    }, 
    transform: function() { 
     var p = _getPosition(); 
     return Transform.translate(p[0], p[1], 0); 
    } 
    }); 

var rotateModifier = new Modifier({ 
    transform: function(){ 
    var _s = _getRect(); 
    var angle = Math.atan2(_s[1],_s[0]); 
    return Transform.rotateZ(angle); 
    } 
}); 

mainContext.add(canvasModifier).add(rotateModifier).add(ls); 
} 

function createBlock(cnt,initialPosition){ 
var s = new Surface(
{ size:[100,100], 
    content:cnt, 
    properties:{ 
    color: 'white', 
    textAlign: 'center', 
    backgroundColor: '#FA5C4F' 
    } 
}); 
//Save the current position of the new surface 
s.currentPosition = initialPosition; 
var draggable = new Draggable(); 
draggable.obj = s; 
s.pipe(draggable); 
mainContext.add(draggable).add(s); 
draggable.setPosition(initialPosition); 
draggable.on('update',function(e){ 
    this.obj.currentPosition = e.position; 
}); 
return s; 
} 

//gets the position of where the line should start 
function _getPosition(){ 
var dta = _getObjects(); 
var pnts = _getEndPoints(dta); 
return pnts[0]; 
} 

//Gets the Dx and Dy of line to calculate hypotenous 
function _getRect(){ 
var res = [0,0]; 
var dta = _getObjects(); 
var pnts = _getEndPoints(dta); 
var p1 = pnts[0]; 
var p2 = pnts[1]; 
res[0] = p2[0]-p1[0]; 
res[1] = p2[1]-p1[1]; 
return res; 
} 
function _getLineLength(){ 
var res = _getRect(); 
return Math.sqrt(((res[0] * res[0]) + (res[1] * res[1]))); 
} 


function _getEndPoints(dta){ 
var dx = dta.rm.currentPosition[0]-dta.lmredge; 
var dy = dta.bm.currentPosition[1]-dta.tmbedge; 
if ((dx <= 0) && (dy <= 0)) { 
    //objects are overlapping. Draw no line 
    return [[0,0],[0,0]]; 
} 
else if (dx > dy){ 
    //draw line from R and L edges 
    var lmYMidPoint = dta.lm.currentPosition[1]+(dta.lm.size[1]/2); 
    var rmYMidPoint = dta.rm.currentPosition[1]+(dta.rm.size[1]/2); 
    var p1 = [dta.lmredge,lmYMidPoint]; 
    var p2 = [dta.rm.currentPosition[0],rmYMidPoint]; 
    return [p1,p2]; 
} 
else { 
    //draw line from B and Top edges 
    var tmXMidPoint = dta.tm.currentPosition[0]+(dta.tm.size[0]/2); 
    var bmXMidPoint = dta.bm.currentPosition[0]+(dta.bm.size[0]/2); 
    var p1 = [tmXMidPoint,dta.tmbedge]; 
    var p2 = [bmXMidPoint,dta.bm.currentPosition[1]]; 
    return [p1,p2]; 
} 
} 

//Mark the objects as 
//top most, left most, bottom most, right most 
function _getObjects(){ 
var lm = _getLeftMost(ls); 
var rm = ls.s1; 
if (lm == rm){ 
    rm = ls.s2; 
} 
var tm = _getTopMost(ls); 
var bm = ls.s1; 
if (tm == bm){ 
    bm = ls.s2; 
} 

var lm_redge = (lm.currentPosition[0]+lm.size[0]); 
var lm_bedge = (lm.currentPosition[1]+lm.size[1]); 
var rm_redge = (rm.currentPosition[0]+rm.size[0]); 
var rm_bedge = (rm.currentPosition[1]+rm.size[1]); 

var tm_redge = (tm.currentPosition[0]+tm.size[0]); 
var tm_bedge = (tm.currentPosition[1]+tm.size[1]); 
var bm_redge = (bm.currentPosition[0]+bm.size[0]); 
var bm_bedge = (bm.currentPosition[1]+bm.size[1]); 


return {lm:lm,rm:rm,tm:tm,bm:bm, 
     lmredge:lm_redge, 
     lmbedge:lm_bedge, 
     rmredge:rm_redge, 
     rmbedge:rm_bedge, 
     tmredge:tm_redge, 
     tmbedge:tm_bedge, 
     bmredge:bm_redge, 
     bmbedge:bm_bedge}; 
} 

function _getLeftMost(obj){ 
if (obj.s1.currentPosition[0] <= obj.s2.currentPosition[0]){ 
    return obj.s1; 
} else { 
    return obj.s2; 
} 
} 

function _getTopMost(obj){ 
if (obj.s1.currentPosition[1] <= obj.s2.currentPosition[1]){ 
    return obj.s1; 
} else { 
    return obj.s2; 
} 
} 
+0

這很好。他們應該將其作爲一個原始語言融入到Famo.us中。 – user800268

0

雖然我沒有嘗試過這樣的事情,我自己。我看到一些涉及famo.us檢查員的開發內容。這基本上是一個鍍鉻擴展,它繪製了famo.us場景的層次結構。

如果您可能會分析代碼並親自安裝擴展程序以查看它的實際運行情況,您可能會找到實現所需結果的途徑。如果我記得,這個層次結構被描繪成一個家族樹樣式的插圖,它允許動態添加和移除由流體線連接的節點。

當然,它在開發中,可能是一個搖搖晃晃的原型,所以不要期待任何支持或反饋。

https://github.com/FamousInternal/famous-inspector

+0

存儲庫不再公開(或刪除) – Alp

0

你爲什麼不只是使用的表面與一個窄尺寸和旋轉變換?

var lineSurface = new Surface({ 
    size: [150,1], 
    properties: { 
    backgroundColor: 'white' 
    } 
}); 

var rotateModifier = new StateModifier({ 
    transform: Transform.rotateZ(Math.PI/4) 
}); 

mainContext.add(rotateModifier1).add(lineSurface);