【问题标题】:arbor.js custom shape each nodearbor.js 自定义形状每个节点
【发布时间】:2012-02-23 14:21:08
【问题描述】:

以下代码在 html5 画布上绘制 egg 的图像

function init() {

  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");

  draw(ctx);
}

function draw(ctx) {

  // layer1/Path
  ctx.save();
  ctx.beginPath();
  ctx.moveTo(100.0, 90.0);
  ctx.bezierCurveTo(100.0, 95.5, 95.5, 100.0, 90.0, 100.0);
  ctx.lineTo(10.0, 100.0);
  ctx.bezierCurveTo(4.5, 100.0, 0.0, 95.5, 0.0, 90.0);
  ctx.lineTo(0.0, 10.0);
  ctx.bezierCurveTo(0.0, 4.5, 4.5, 0.0, 10.0, 0.0);
  ctx.lineTo(90.0, 0.0);
  ctx.bezierCurveTo(95.5, 0.0, 100.0, 4.5, 100.0, 10.0);
  ctx.lineTo(100.0, 90.0);
  ctx.closePath();
  ctx.fillStyle = "rgb(229, 229, 229)";
  ctx.fill();

  // layer1/Path
  ctx.beginPath();
  ctx.moveTo(10.0, 28.0);
  ctx.bezierCurveTo(10.0, 37.9, 18.1, 46.0, 28.0, 46.0);
  ctx.bezierCurveTo(37.9, 46.0, 46.0, 37.9, 46.0, 28.0);
  ctx.bezierCurveTo(46.0, 18.1, 37.9, 10.0, 28.0, 10.0);
  ctx.bezierCurveTo(18.1, 10.0, 10.0, 18.1, 10.0, 28.0);
  ctx.closePath();
  ctx.fillStyle = "rgb(255, 191, 30)";
  ctx.fill();
  ctx.restore();
}
<body onload="init()">
  <canvas id="canvas" width="100" height="100"></canvas>
</body>

我试图让 arbor.js 将鸡蛋显示为节点,我还将显示其他插图,例如培根、交互式餐厅菜单的面包。它意味着进入每个节点,我相信吗?但不太确定如何。

particleSystem.eachNode(function(node, pt){
          // node: {mass:#, p:{x,y}, name:"", data:{}}
          // pt:   {x:#, y:#}  node position in screen coords


          // determine the box size and round off the coords if we'll be 
          // drawing a text label (awful alignment jitter otherwise...)
          var w = ctx.measureText(node.data.label||"").width + 6
          var label = node.data.label
          if (!(label||"").match(/^[ \t]*$/)){
            pt.x = Math.floor(pt.x)
            pt.y = Math.floor(pt.y)
          }else{
            label = null
          }

          // clear any edges below the text label
          // ctx.fillStyle = 'rgba(255,255,255,.6)'
          // ctx.fillRect(pt.x-w/2, pt.y-7, w,14)


          ctx.clearRect(pt.x-w/2, pt.y-7, w,14)



          // draw the text
          if (label){
            ctx.font = "bold 11px Arial"
            ctx.textAlign = "center"

            // if (node.data.region) ctx.fillStyle = palette[node.data.region]
            // else ctx.fillStyle = "#888888"
            ctx.fillStyle = "#888888"

            // ctx.fillText(label||"", pt.x, pt.y+4)
            ctx.fillText(label||"", pt.x, pt.y+4)
          }
        })          
      },

      resize:function(){
        var w = $(window).width(),
            h = $(window).height();
        canvas.width = w; canvas.height = h // resize the canvas element to fill the screen
        particleSystem.screenSize(w,h) // inform the system so it can map coords for us
        that.redraw()
      },

        initMouseHandling:function(){
        // no-nonsense drag and drop (thanks springy.js)
        selected = null;
        nearest = null;
        var dragged = null;
        var oldmass = 1

        $(canvas).mousedown(function(e){
            var pos = $(this).offset();
            var p = {x:e.pageX-pos.left, y:e.pageY-pos.top}
            selected = nearest = dragged = particleSystem.nearest(p);

            if (selected.node !== null){
            // dragged.node.tempMass = 10000
            dragged.node.fixed = true
            }
            return false
        });

非常感谢。

【问题讨论】:

  • 我知道解决方案就在下面,但是如果您对代码的作用有疑问,请提出问题。我猜你的下一个问题是如何以正确的顺序显示不同的图像。

标签: javascript html canvas graph arbor.js


【解决方案1】:

所以,打开 arbor 0.92 中包含的示例项目。在main.js中,找到eachNode附加的匿名函数:

particleSystem.eachNode(function(node, pt){
  // node: {mass:#, p:{x,y}, name:"", data:{}}
  // pt:   {x:#, y:#}  node position in screen coords

  // draw a rectangle centered at pt
  var w = 20
  ctx.fillStyle = (node.data.alone) ? "orange" : "black"
  ctx.fillRect(pt.x-w/2, pt.y-w/2, w/2,w)
})

这是我们需要用您的“蛋”代码替换的部分。问题是你不能直接把你的draw函数放进去,因为它使用的是absolute坐标,而我们需要使用相对于节点被渲染位置的坐标。本质上,您需要修改draw(ctx) 函数中的每个调用以使用pt.xpt.y,如示例中所述。

编辑

好的,完成。用这个替换整个块:

    particleSystem.eachNode(function(node, pt){
      // node: {mass:#, p:{x,y}, name:"", data:{}}
      // pt:   {x:#, y:#}  node position in screen coords

      // draw a rectangle centered at pt

            ctx.beginPath();
  ctx.moveTo(100.0 + pt.x, 90.0 + pt.y);
  ctx.bezierCurveTo(100.0 + pt.x, 95.5 + pt.y, 95.5 + pt.x, 100.0 + pt.y, 90.0 + pt.x, 100.0 + pt.y);
  ctx.lineTo(10.0 + pt.x, 100.0 + pt.y);
  ctx.bezierCurveTo(4.5 + pt.x, 100.0 + pt.y, 0.0 + pt.x, 95.5 + pt.y, 0.0 + pt.x, 90.0 + pt.y);
  ctx.lineTo(0.0 + pt.x, 10.0 + pt.y);
  ctx.bezierCurveTo(0.0 + pt.x, 4.5 + pt.y, 4.5 + pt.x, 0.0 + pt.y, 10.0 + pt.x, 0.0 + pt.y);
  ctx.lineTo(90.0 + pt.x, 0.0 + pt.y);
  ctx.bezierCurveTo(95.5 + pt.x, 0.0 + pt.y, 100.0 + pt.x, 4.5 + pt.y, 100.0 + pt.x, 10.0 + pt.y);
  ctx.lineTo(100.0 + pt.x, 90.0 + pt.y);
  ctx.closePath();
  ctx.fillStyle = "rgb(229, 229, 229)";
  ctx.fill();

  // layer1/Path
  ctx.beginPath();
  ctx.moveTo(10.0 + pt.x, 28.0 + pt.y);
  ctx.bezierCurveTo(10.0 + pt.x, 37.9 + pt.y, 18.1 + pt.x, 46.0 + pt.y, 28.0 + pt.x, 46.0 + pt.y);
  ctx.bezierCurveTo(37.9 + pt.x, 46.0 + pt.y, 46.0 + pt.x, 37.9 + pt.y, 46.0 + pt.x, 28.0 + pt.y);
  ctx.bezierCurveTo(46.0 + pt.x, 18.1 + pt.y, 37.9 + pt.x, 10.0 + pt.y, 28.0 + pt.x, 10.0 + pt.y);
  ctx.bezierCurveTo(18.1 + pt.x, 10.0 + pt.y, 10.0 + pt.x, 18.1 + pt.y, 10.0 + pt.x, 28.0 + pt.y);
  ctx.closePath();
  ctx.fillStyle = "rgb(255, 191, 30)";
  ctx.fill();
    })

如您所见,它们没有居中,但希望这为如何继续提供了足够的理想。 :)

【讨论】:

  • 嗨,Ben 非常感谢:) 搞定了。我需要添加培根、面包和香肠我想我需要将它们声明为变量?我将查看其余的示例,看看是否可以解决。
  • 我可以通过多种方式来理解这项工作。先自己尝试一下,然后问一个具体的问题。作为提示,认为你接下来应该做的就是:将彩蛋代码从上面移到它自己的函数中。然后应该从 eachNode 调用此函数并将ctxp 作为参数。然后,更新函数以使图像以节点为中心绘制,而不是像现在这样围绕左上角绘制。完成此操作后,了解如何添加新图像会容易得多。
  • 嗨,Ben 非常感谢您抽出宝贵的时间,我会试一试的。如果我炒鸡蛋,我会发布更多问题:)
  • 嗨,如果我想使用一个相当复杂的插图;见jsfiddle.net/makingthings/SYma7我可以使用你上面描述的方法而不必将所有的x y点添加到插图中吗?
  • 嘿。简而言之,不,您总是需要使用 x 和 y 点。有一个解决方法(有一个代理类,它接受各种画布命令并添加正确的 x/y 偏移量),但更重要的问题是为什么使用画布来渲染这些图像 - 你在那里有输出,为什么不创建一个png 并渲染它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-08
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
  • 2023-03-06
相关资源
最近更新 更多