【问题标题】:Drawing a lot lines between surfaces in Famo.us?在 Famo.us 中的曲面之间画很多线?
【发布时间】:2014-07-17 13:44:47
【问题描述】:

我的目标是能够以一种看起来非常好并且在添加新节点时动画流畅的方式呈现图形数据库(由线连接的节点)。我一直在关注 SVG、Canvas,现在又关注 Famo.us。

Famo.us 似乎对此有好处,因为我可以使用 Famo.us Surfaces 来渲染每个节点,包括 HTML 格式的文本和控件。问题是画线来连接节点。 Famo.us 没有像线条这样的原语。它确实有画布表面,但这似乎不是正确的方法。

我猜我必须为每条线做一些很尴尬的事情,比如创建一个又高又薄的表面,然后计算一个变换,让它连接两个表面。

【问题讨论】:

  • 你有进步吗?我也在问自己同样的问题。
  • 我放弃了 Famo.us 并决定 canvas 和 svg 是更好的选择。

标签: canvas svg famo.us


【解决方案1】:

这是 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;
}
}

【讨论】:

  • 效果很好。他们应该将其作为原始元素纳入 Famo.us。
【解决方案2】:

虽然我自己没有尝试过这样的事情。我看到了一些涉及 famo.us 检查员的开发中的东西。这基本上是一个 chrome 扩展,它绘制了 famo.us 场景的层次结构。

如果您可能分析代码,并自己安装扩展程序以查看它的运行情况,您可能会找到实现您正在寻找的结果的途径。如果我记得,层次结构被绘制为家族树样式的插图,它允许动态添加和删除节点,并通过流体线连接。

当然,它正在开发中,而且可能是一个摇摇晃晃的原型,所以不要指望任何支持或反馈。

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

【讨论】:

  • 存储库不再公开(或已删除)
【解决方案3】:

您为什么不只使用具有一个窄维度和旋转变换的表面?

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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-07
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多