2014-07-17 40 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);