形状叠加而不是d3.js中的过渡

时间:2018-05-16 16:01:56

标签: d3.js transition

我试图让一个不合时宜的情节转移数据点位置无济于事。首先,我制作了一个简单的散点图,除了x轴叠加外,它可以转换为切换。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>D3: Transitioning points to randomized values, plus rescaled axes!</title>
        <script src="https://d3js.org/d3.v4.min.js"></script><style type="text/css">
            /* No style rules here yet */
        </style>
    </head>
    <body>
    <label>
        <input type="radio" name='market' value="a" checked/>a 
        <input type="radio" name='market' value="b"/>b
</label> 
        <p>Click on this text to update the chart with new data values as many times as you like!</p>

        <script type="text/javascript">

            //Width and height
            var w = 500;
            var h = 300;
            var padding = 30;

            //Dynamic, random dataset
            dataset = [
                {"id":1, 
                "value":20,
                "group":"a"},
                {"id":1, 
                "value":10,
                "group":"a"},
                {"id":1, 
                "value":30,
                "group":"a"},
                {"id":1, 
                "value":40,
                "group":"a"},
                {"id":1, 
                "value":42,
                "group":"a"},
                {"id":1, 
                "value":10,
                "group":"b"},
                {"id":1, 
                "value":12,
                "group":"b"},
                {"id":1, 
                "value":15,
                "group":"b"},
                {"id":1, 
                "value":23,
                "group":"b"},
                {"id":1, 
                "value":22,
                "group":"b"},
                {"id":1, 
                "value":54,
                "group":"b"}
                ]


            //Create scale functions
            var xScale = d3.scaleLinear()
                                 .range([padding, w - padding * 2]);

            var yScale = d3.scaleLinear()
                                 .range([h - padding, padding]);

            //Define X axis
            var xAxis = d3.axisBottom()
                              .scale(xScale)
                              .ticks(5);

            //Define Y axis
            var yAxis = d3.axisLeft()
                              .scale(yScale)
                              .ticks(5);

            //Create SVG element
            var svg = d3.select("body")
                        .append("svg")
                        .attr("width", w)
                        .attr("height", h);
        draw(dataset.filter(d=> d.group=="a"));


      //////////////////
      //toggle//
      //////////////////
      d3.selectAll("input")
      .on("change",  function() {
          var data_new = dataset.filter(d => (d.group == this.value));
          draw(data_new);
          });

      //////////////////
      //Create circles
      //////////////////
    function draw(dataset) {
         //////////////////
        //Create axis


        xScale.domain([0, d3.max(dataset, function(d) { return d.value; })])
        yScale.domain([0, 2])
        var xAxis = d3.axisBottom()
                  .scale(xScale)
                  .ticks(5);
        //Create X axis
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + (h - padding) + ")")
     .transition(2000)
            .call(xAxis);

        //Create Y axis
        svg.append("g")
            .attr("class", "y axis")
            .attr("transform", "translate(" + padding + ",0)")
            .call(yAxis);
        //////////////////
        //draw circle

        svg.selectAll("circle")
               .data(dataset)
               .enter()
               .append("circle")
               .attr("cx", function(d) {
                    return xScale(d.value);
               })
               .attr("cy", function(d) {
                    return yScale(d.id);
               })
               .attr("r", 3)
         .attr("opacity",0.2);

        //update
        svg.selectAll("circle")
        .transition()
                       .duration(1000)  
        .attr("cx", function(d) {
                    return xScale(d.value);
               })
      }


        </script>
    </body>
</html>

然而,当为beeswarm plot应用类似的代码时,这些点不会在选择上移位,它们只是在层上,就像第一个例子中的x轴一样:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
</style>
<label>
        <input type="radio" name='market' value="a" checked/>a 
        <input type="radio" name='market' value="b"/>b
</label>

<svg width="400" height="200"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var svg = d3.select("svg"),
    margin = {top: 40, right: 40, bottom: 40, left: 40},
    width = svg.attr("width") - margin.left - margin.right,
    height = svg.attr("height") - margin.top - margin.bottom;

var formatValue = d3.format(",d");

var x = d3.scaleLog()
    .rangeRound([0, width]);

var g = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

data = [
  {"id":1, 
  "value":20,
  "group":"a"},
  {"id":1, 
  "value":21,
  "group":"a"},
  {"id":1, 
  "value":30,
  "group":"a"},
  {"id":1, 
  "value":32,
  "group":"a"},
  {"id":1, 
  "value":42,
  "group":"a"},
   {"id":1, 
  "value":10,
  "group":"b"},
  {"id":1, 
  "value":12,
  "group":"b"},
  {"id":1, 
  "value":15,
  "group":"b"},
  {"id":1, 
  "value":23,
  "group":"b"},
  {"id":1, 
  "value":22,
  "group":"b"},
  {"id":1, 
  "value":24,
  "group":"b"}
]
  //default
  draw(data.filter(d=> d.group=="a"));

  d3.selectAll("input")
  .on("change", function()
{
  var newdata = draw(data.filter(d=> d.group==this.value));
  draw(newdata)

}  )


  /////////////////
//draw swarmplot
/////////////////

function draw(data) {

  // transition
  var t = d3.transition()
          .duration(750);


  x.domain(d3.extent(data, d=> d.value));

  var simulation = d3.forceSimulation(data)
      .force("x", d3.forceX(function(d) { return x(d.value); }).strength(1))
      .force("y", d3.forceY(height / 3))
      .force("collide", d3.forceCollide(18))
      .stop();

  for (var i = 0; i < 120; ++i) simulation.tick();

  //axis
  g.append("g")

      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x).ticks(20, ".0s"));

  //for mouse-over
  var cell = g.append("g")
      .attr("class", "cells")
    .selectAll("g").data(d3.voronoi()
        .extent([[-margin.left, -margin.top], [width + margin.right, height + margin.top]])
        .x(function(d) { return d.x; })
        .y(function(d) { return d.y; })
      .polygons(data)).enter().append("g");

  //circle
  cell.append("circle")
      .attr("r", 3)
      .attr("cx", function(d) { return d.data.x; })
      .attr("cy", function(d) { return d.data.y; })
      .attr("fill", d => (d.data.Food_Sub_Group))
      .attr("opacity", 0.4);
 //update circle
  cell.selectAll("circle")
        .transition()
                       .duration(1000)  
        .attr("cx", function(d) { return d.data.x; })

} 


</script>

这里有什么不对劲?感谢。

1 个答案:

答案 0 :(得分:0)

区别在于:

在第一个代码的绘图功能中,您将数据绑定到&#39; circle&#39;元素。如果之前有5个圆形元素且新数据大小为5,则不添加任何元素,更改的仅是数据。如果您之前有5个圈子且新数据大小为6,则使用&#39;输入()&#39;并且&#39;追加&#39;函数,执行后,你将有6个元素。

在第二个代码的绘图功能中,添加新元素。每次调用绘图功能都会增加新点。如果您之前有5个圆形元素且新数据大小为5,则添加5个元素,您将有10个元素。

你说什么&#39;没有转移位置&#39;实际上是在同一个地方(点似乎更暗)或不同的地方(更多点)绘制多个点。

请参阅issue,这可能有所帮助。