d3(v4):赋予元素动量的外观?

时间:2017-05-27 13:18:40

标签: javascript d3.js svg

假设您想要一个html页面,其中整个背景是一个svg,这样就会有一些动画不断进行。在这个愚蠢的例子中,我做了一个随意移动的笑脸。虽然有些人可能会发现布朗运动对眼睛有吸引力,但如果svg元素随着动量(方向和旋转)的出现而移动会更好。

有人可能会很快意识到,让一个物体沿着一条路径移动可以解决这个问题,它会......对于物体的第一次传递。但是,如果元素被屏幕限制,那么如何进行调整以适应偏转?

简而言之,问题如下:

使用d3.js v4如何在html页面中显示svg元素(例如下面的演示中的#Mr_Smiley)?*

*让浮动意味着沿着svg空间内的矢量或弧线以恒定速度平稳地移动,在击中边界时反弹并正确偏转



var mr_s = d3.select("svg").append("g").attr("id", "Mr_Smiley")
mr_s.append("circle").attr("cx", 30).attr("cy", 30).attr("r", 30).style("fill","yellow").style("stroke", "black")
mr_s.append("circle").attr("cx", 20).attr("cy", 20).attr("r", 5).style("fill","black")
mr_s.append("circle").attr("cx", 40).attr("cy", 20).attr("r", 5).style("fill","black")
mr_s.append("path").attr("d", "M20 40 A 10 10 0 0 0 40 40").style("fill","black")


mr_s.datum({"x": 30, "y": 30, "r": 1})
mr_s.attr("transform", function(d) {"translate(" + d.x + ", " + d.y + ") rotate(" + d.r + ")"})

dur = 100
step = 10
// Lets have Mr. S go for a trip
d3.select("#Mr_Smiley")
  .transition()
  .duration(dur)
  .on("start", function repeat() {
    d3.active(this)
      .attr("transform",
        function(d)
        {
          // update y
          if (Math.random() >= .5) {
            d.y += step
          } else {
            d.y -= step
            // basic bounds
            if (d.y < 0) {
              d.y = 0
            }
          }
          // update x
          if (Math.random() >= .5) {
            d.x += step
          } else {
            d.x -= step
            if (d.x < 0) {
              d.x = 0
            }
          }
          // update r
          if (Math.random() >= .5) {
            d.r += step
          } else {
            d.r -= step
          }
          return "translate(" + d.x + ", " + d.y + ") rotate(" + d.r + ")"
        })
        .transition()
        .attr("transform",
        function(d)
        {
          // update y
          if (Math.random() >= .5) {
            d.y += step
          } else {
            d.y -= step
          }
          // update x
          if (Math.random() >= .5) {
            d.x += step
          } else {
            d.x -= step
          }
          // update r
          if (Math.random() >= .5) {
            d.r += step
          } else {
            d.r -= step
          }
          return "translate(" + d.x + ", " + d.y + ") rotate(" + d.r + ")"
        })
        .transition()
        .on("start", repeat)
        })
        
        
mr_s.on("mouseover", mouseover)
mr_s.on("mouseout", mouseout)
function mouseover(d, i) {
  var svg = d3.select("svg")
  svg.append("text").attr("id", "mouseover_text").text("god help me, this is so unsmooth").attr("x", d.x).attr("y", d.y)
}

function mouseout(d, i) {
d3.select("#mouseover_text").remove()

}
&#13;
html, body {
  width: 100%; 
  height: 100%;
}
svg {
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: light-blue;
  border: 1px black solid;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
<h1>
Mr. Smiley goes on a trip
</h1>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

这是最简单的S.先生在我可以使用d3惯例编码的房间周围反弹:

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
  <script>
    var w = 250,
      h = 250,
      r = 30;

    var svg = d3.select('body')
      .append('svg')
      .attr('width', w)
      .attr('height', h)
      .style('border', '1px solid steelblue');

    var ix = Math.random() * ((Math.random() > 0.5) ? 5 : -5),
      iy = Math.random() * ((Math.random() > 0.5) ? 5 : -5),
      x = w / 2,
      y = h / 2;

    var mr_s = svg.append("g")
      .attr("id", "Mr_Smiley")

    mr_s.append("circle")
      .attr("r", r)
      .style("fill", "yellow")
      .style("stroke", "black");

    mr_s.append("circle")
      .attr("cx", -10)
      .attr("cy", -10)
      .attr("r", 5)
      .style("fill", "black");

    mr_s.append("circle")
      .attr("cx", 10)
      .attr("cy", -10)
      .attr("r", 5)
      .style("fill", "black");

    mr_s.append("path")
      .attr("d", "M-10 10 A 10 10 0 0 0 10 10")
      .style("fill", "black");

    mr_s.attr('transform', 'translate(' + x + ',' + y + ')');

    d3.interval(tick, 20);

    function tick() {

      x += ix;
      y += iy;

      if (x > (w - r) || x < r) {
        ix = -ix;
      }

      if (y > (h - r) || y < r) {
        iy = -iy;
      }

      mr_s.attr('transform', 'translate(' + x + ',' + y + ')');
    }
  </script>
</body>

</html>