简体   繁体   中英

arbor.js custom shape each node

the following code draws an image of an egg on an html5 canvas

 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> 

I' trying to get arbor.js show the egg as a node I will also be showing other illustrations such as bacon, bread for an interactive restaurant menu. It is meant to go in each node, I beleive? But not quite sure how.

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

Many thanks in advance.

So, open up the sample project included with arbor 0.92. In main.js, find the anonymous function attached to 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)
})

This is the section we need to replace with your 'egg' code. The problem is that you can't just drop your draw function in as it is because it's using absolute coordinates, whereas we need to use coordinates relative to where the node is being rendered. Essentially, you need to modify each of the calls in your draw(ctx) function to use pt.x and pt.y , as described in the sample.

Edit

Alright, done. Replace the whole block with this:

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

在此输入图像描述

They're not centered as you can see, but hopefully this gives enough of an ideal about how to continue. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM