D3 JS条形图平移

时间:2018-10-06 21:56:56

标签: javascript d3.js charts

我尝试使用d3 js创建具有缩放/平移功能的条形图。缩放效果很好,但是当我向左或向右平移图表时,条形在最小和最大X值旁边消失。我做错了什么? please check this image with issue described  这是小提琴:https://jsfiddle.net/Cayman/vpn8mz4g/1/

function render_chart(){
    var stack = d3.layout.stack();
    var dataset = {
                "categories": ['2018-06-01T00:00:00.000+03:00',
                                '2018-06-02T00:00:00.000+03:00',
                                '2018-06-03T00:00:00.000+03:00',
                                '2018-06-04T00:00:00.000+03:00',
                                '2018-06-05T00:00:00.000+03:00',
                                '2018-06-06T00:00:00.000+03:00',
                                '2018-06-07T00:00:00.000+03:00',
                                '2018-06-08T00:00:00.000+03:00',
                                '2018-06-09T00:00:00.000+03:00',
                                '2018-06-10T00:00:00.000+03:00',
                                '2018-06-11T00:00:00.000+03:00',
                                '2018-06-12T00:00:00.000+03:00'],
                "series": ["New York","Mumbai","Bengaluru"],
                "colors": ["#3498db","#e74c3c","#2ecc71"],
                "layers": [
                        [
                            {"y":1,"y0":20,"month":"2018-06-01T00:00:00.000+03:00"},
                            {"y":2,"y0":18,"month":"2018-06-02T00:00:00.000+03:00"},
                            {"y":5,"y0":18,"month":"2018-06-03T00:00:00.000+03:00"},
                            {"y":10,"y0":20,"month":"2018-06-04T00:00:00.000+03:00"},
                            {"y":14,"y0":23,"month":"2018-06-05T00:00:00.000+03:00"},
                            {"y":18,"y0":29,"month":"2018-06-06T00:00:00.000+03:00"},
                            {"y":20,"y0":31,"month":"2018-06-07T00:00:00.000+03:00"},
                            {"y":20,"y0":29,"month":"2018-06-08T00:00:00.000+03:00"},
                            {"y":16,"y0":24,"month":"2018-06-09T00:00:00.000+03:00"},
                            {"y":10,"y0":19,"month":"2018-06-10T00:00:00.000+03:00"},
                            {"y":5,"y0":23,"month":"2018-06-11T00:00:00.000+03:00"},
                            {"y":3,"y0":20,"month":"2018-06-12T00:00:00.000+03:00"}
                        ],
                        [
                            {"y":12,"y0":24,"month":"2018-06-01T00:00:00.000+03:00"},
                            {"y":14,"y0":25,"month":"2018-06-02T00:00:00.000+03:00"},
                            {"y":13,"y0":31,"month":"2018-06-03T00:00:00.000+03:00"},
                            {"y":16,"y0":32,"month":"2018-06-04T00:00:00.000+03:00"},
                            {"y":18,"y0":33,"month":"2018-06-05T00:00:00.000+03:00"},
                            {"y":19,"y0":29,"month":"2018-06-06T00:00:00.000+03:00"},
                            {"y":20,"y0":27,"month":"2018-06-07T00:00:00.000+03:00"},
                            {"y":18,"y0":26,"month":"2018-06-08T00:00:00.000+03:00"},
                            {"y":20,"y0":31,"month":"2018-06-09T00:00:00.000+03:00"},
                            {"y":17,"y0":29,"month":"2018-06-10T00:00:00.000+03:00"},
                            {"y":18,"y0":26,"month":"2018-06-11T00:00:00.000+03:00"},
                            {"y":14,"y0":24,"month":"2018-06-12T00:00:00.000+03:00"}
                        ],[
                            {"y":8,"y0":24,"month":"2018-06-01T00:00:00.000+03:00"},
                            {"y":14,"y0":26,"month":"2018-06-02T00:00:00.000+03:00"},
                            {"y":12,"y0":31,"month":"2018-06-03T00:00:00.000+03:00"},
                            {"y":15,"y0":33,"month":"2018-06-04T00:00:00.000+03:00"},
                            {"y":18,"y0":37,"month":"2018-06-05T00:00:00.000+03:00"},
                            {"y":16,"y0":29,"month":"2018-06-06T00:00:00.000+03:00"},
                            {"y":17,"y0":27,"month":"2018-06-07T00:00:00.000+03:00"},
                            {"y":19,"y0":25,"month":"2018-06-08T00:00:00.000+03:00"},
                            {"y":25,"y0":30,"month":"2018-06-09T00:00:00.000+03:00"},
                            {"y":23,"y0":31,"month":"2018-06-10T00:00:00.000+03:00"},
                            {"y":11,"y0":26,"month":"2018-06-11T00:00:00.000+03:00"},
                            {"y":12,"y0":23,"month":"2018-06-12T00:00:00.000+03:00"}
                        ]
                    ]
                }
    dataset["categories"].forEach(function(d2) {
        d = new Date(d2);
    });

    dataset["layers"].forEach(function(d) {
        d.forEach(function(d2) {
            d2.month = new Date(d2.month);
        });
    });


    n = dataset["series"].length, // Number of Layers
    m = dataset["layers"].length, // Number of Samples in 1 layer

    yGroupMax = d3.max(dataset["layers"], function(layer) { return d3.max(layer, function(d) { return d.y0; }); });
    yGroupMin = d3.min(dataset["layers"], function(layer) { return d3.min(layer, function(d) { return d.y; }); });

    var pWidth = document.getElementById('chart1').offsetWidth;
    var margin = {top: 50, right: 0, bottom: 50, left: 100},
        width = pWidth - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

    var x = d3.time.scale()
        .domain([new Date(dataset["categories"][0]),new Date(dataset["categories"][11]),])
        .range([0, width]);

    var y = d3.scale.linear()
        .domain([yGroupMin, yGroupMax])
        .range([height, 0]);

    var xAxis = d3.svg.axis()
        .scale(x)
        .tickSize(dataset["categories"].length)
        .tickPadding(6)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left");

    var zoom = d3.behavior.zoom()
        .x(x)
        .scaleExtent([0, Infinity])
        .on("zoom", zoomed);

    var svg = d3.select("#chart1").append("svg")
        .call(zoom)
        .attr("class", "chart")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var layer = svg.selectAll(".layer")
        .data(dataset["layers"])
        .enter().append("g")
        .attr("class", "layer");

    var rect = layer.selectAll("rect")
        .data(function(d,i){d.map(function(b){b.colorIndex=i;return b;});return d;})
        .enter().append("rect")
        .transition()
        .duration(500)
        .delay(function(d, i) { return i * 10; })
        .attr("x", function(d, i, j) {
                var qqq = x(d.month);
                var qqq2 = x(d.month) + 30 / n * j;
                return x(d.month) + 30 / n * j; 
            })
        .attr("width", 30 / n)
        .transition()
        .attr("y", function(d) { return y(d.y0); })
        .attr("height", function(d) { return height - y(d.y0-0)})
        .attr("class","bar")
        .style("fill",function(d){return dataset["colors"][d.colorIndex];})

        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis);

        svg.append("text")
        .attr("x", width/3)
        .attr("y", 0)
        .attr("dx", ".71em")
        .attr("dy", "-.71em")
        .text("Min - Max Temperature (Month wise)");

        svg.append("clipPath")
    .attr("id", "clip")
    .append("rect")
    .attr("width", width)
    .attr("height", height);

    function zoomed() {
        console.warn("zoom");
        svg.select(".x.axis").call(xAxis);
        console.log(d3.event.translate[0] + " " + d3.event.translate[1]);
        svg.selectAll(".chart rect").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");
    }


    enter code here

}

1 个答案:

答案 0 :(得分:0)

您需要在混合中添加一个剪切路径:

  var svg = d3.select("#chart1").append("svg")
    .call(zoom)
    .attr("class", "chart")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom);

  // create clip-path that's the same size as drawing area
  svg.append('defs')
    .append('clipPath')
    .attr('id', 'clip')
    .append('rect')
    .attr('x', 0)
    .attr('y', 0)
    .attr('width', width)
    .attr('height', height);

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

  var layer = svg.selectAll(".layer")
    .data(dataset["layers"])
    .enter().append("g")
    .attr("class", "layer")
    .attr('clip-path', 'url(#clip)'); //<-- clip drawing area

运行代码:

$(document).ready(function() {
  render_chart();
});

function render_chart() {
  var stack = d3.layout.stack();
  var dataset = {
    "categories": ['2018-06-01T00:00:00.000+03:00',
      '2018-06-02T00:00:00.000+03:00',
      '2018-06-03T00:00:00.000+03:00',
      '2018-06-04T00:00:00.000+03:00',
      '2018-06-05T00:00:00.000+03:00',
      '2018-06-06T00:00:00.000+03:00',
      '2018-06-07T00:00:00.000+03:00',
      '2018-06-08T00:00:00.000+03:00',
      '2018-06-09T00:00:00.000+03:00',
      '2018-06-10T00:00:00.000+03:00',
      '2018-06-11T00:00:00.000+03:00',
      '2018-06-12T00:00:00.000+03:00'
    ],
    "series": ["New York", "Mumbai", "Bengaluru"],
    "colors": ["#3498db", "#e74c3c", "#2ecc71"],
    "layers": [
      [{
          "y": 1,
          "y0": 20,
          "month": "2018-06-01T00:00:00.000+03:00"
        },
        {
          "y": 2,
          "y0": 18,
          "month": "2018-06-02T00:00:00.000+03:00"
        },
        {
          "y": 5,
          "y0": 18,
          "month": "2018-06-03T00:00:00.000+03:00"
        },
        {
          "y": 10,
          "y0": 20,
          "month": "2018-06-04T00:00:00.000+03:00"
        },
        {
          "y": 14,
          "y0": 23,
          "month": "2018-06-05T00:00:00.000+03:00"
        },
        {
          "y": 18,
          "y0": 29,
          "month": "2018-06-06T00:00:00.000+03:00"
        },
        {
          "y": 20,
          "y0": 31,
          "month": "2018-06-07T00:00:00.000+03:00"
        },
        {
          "y": 20,
          "y0": 29,
          "month": "2018-06-08T00:00:00.000+03:00"
        },
        {
          "y": 16,
          "y0": 24,
          "month": "2018-06-09T00:00:00.000+03:00"
        },
        {
          "y": 10,
          "y0": 19,
          "month": "2018-06-10T00:00:00.000+03:00"
        },
        {
          "y": 5,
          "y0": 23,
          "month": "2018-06-11T00:00:00.000+03:00"
        },
        {
          "y": 3,
          "y0": 20,
          "month": "2018-06-12T00:00:00.000+03:00"
        }
      ],
      [{
          "y": 12,
          "y0": 24,
          "month": "2018-06-01T00:00:00.000+03:00"
        },
        {
          "y": 14,
          "y0": 25,
          "month": "2018-06-02T00:00:00.000+03:00"
        },
        {
          "y": 13,
          "y0": 31,
          "month": "2018-06-03T00:00:00.000+03:00"
        },
        {
          "y": 16,
          "y0": 32,
          "month": "2018-06-04T00:00:00.000+03:00"
        },
        {
          "y": 18,
          "y0": 33,
          "month": "2018-06-05T00:00:00.000+03:00"
        },
        {
          "y": 19,
          "y0": 29,
          "month": "2018-06-06T00:00:00.000+03:00"
        },
        {
          "y": 20,
          "y0": 27,
          "month": "2018-06-07T00:00:00.000+03:00"
        },
        {
          "y": 18,
          "y0": 26,
          "month": "2018-06-08T00:00:00.000+03:00"
        },
        {
          "y": 20,
          "y0": 31,
          "month": "2018-06-09T00:00:00.000+03:00"
        },
        {
          "y": 17,
          "y0": 29,
          "month": "2018-06-10T00:00:00.000+03:00"
        },
        {
          "y": 18,
          "y0": 26,
          "month": "2018-06-11T00:00:00.000+03:00"
        },
        {
          "y": 14,
          "y0": 24,
          "month": "2018-06-12T00:00:00.000+03:00"
        }
      ],
      [{
          "y": 8,
          "y0": 24,
          "month": "2018-06-01T00:00:00.000+03:00"
        },
        {
          "y": 14,
          "y0": 26,
          "month": "2018-06-02T00:00:00.000+03:00"
        },
        {
          "y": 12,
          "y0": 31,
          "month": "2018-06-03T00:00:00.000+03:00"
        },
        {
          "y": 15,
          "y0": 33,
          "month": "2018-06-04T00:00:00.000+03:00"
        },
        {
          "y": 18,
          "y0": 37,
          "month": "2018-06-05T00:00:00.000+03:00"
        },
        {
          "y": 16,
          "y0": 29,
          "month": "2018-06-06T00:00:00.000+03:00"
        },
        {
          "y": 17,
          "y0": 27,
          "month": "2018-06-07T00:00:00.000+03:00"
        },
        {
          "y": 19,
          "y0": 25,
          "month": "2018-06-08T00:00:00.000+03:00"
        },
        {
          "y": 25,
          "y0": 30,
          "month": "2018-06-09T00:00:00.000+03:00"
        },
        {
          "y": 23,
          "y0": 31,
          "month": "2018-06-10T00:00:00.000+03:00"
        },
        {
          "y": 11,
          "y0": 26,
          "month": "2018-06-11T00:00:00.000+03:00"
        },
        {
          "y": 12,
          "y0": 23,
          "month": "2018-06-12T00:00:00.000+03:00"
        }
      ]
    ]
  }
  var parseDate = d3.time.format("%Y-%m-%d").parse;
  dataset["categories"].forEach(function(d2) {
    d = new Date(d2);
  });

  dataset["layers"].forEach(function(d) {
    d.forEach(function(d2) {
      d2.month = new Date(d2.month);
    });
  });


  n = dataset["series"].length, // Number of Layers
    m = dataset["layers"].length, // Number of Samples in 1 layer

    yGroupMax = d3.max(dataset["layers"], function(layer) {
      return d3.max(layer, function(d) {
        return d.y0;
      });
    });
  yGroupMin = d3.min(dataset["layers"], function(layer) {
    return d3.min(layer, function(d) {
      return d.y;
    });
  });

  var pWidth = document.getElementById('chart1').offsetWidth;
  var margin = {
      top: 50,
      right: 0,
      bottom: 50,
      left: 100
    },
    width = pWidth - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

  var x = d3.time.scale()
    .domain([new Date(dataset["categories"][0]), addDays(new Date(dataset["categories"][11]), 1)])
    .range([0, width]);

  var y = d3.scale.linear()
    .domain([yGroupMin, yGroupMax])
    .range([height, 0]);

  var xAxis = d3.svg.axis()
    .scale(x)
    .tickSize(dataset["categories"].length)
    .tickPadding(6)
    .orient("bottom");

  var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

  var zoom = d3.behavior.zoom()
    .x(x)
    .scaleExtent([0, Infinity])
    .on("zoom", zoomed);

  var svg = d3.select("#chart1").append("svg")
    .call(zoom)
    .attr("class", "chart")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom);

  svg.append('defs')
    .append('clipPath')
    .attr('id', 'clip')
    .append('rect')
    .attr('x', 0)
    .attr('y', 0)
    .attr('width', width)
    .attr('height', height);

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

  var layer = svg.selectAll(".layer")
    .data(dataset["layers"])
    .enter().append("g")
    .attr("class", "layer")
     .attr('clip-path', 'url(#clip)');

  var rect = layer.selectAll("rect")
    .data(function(d, i) {
      d.map(function(b) {
        b.colorIndex = i;
        return b;
      });
      return d;
    })
    .enter().append("rect")
    .transition()
    .duration(500)
    .delay(function(d, i) {
      return i * 10;
    })
    .attr("x", function(d, i, j) {
      var qqq = x(d.month);
      var qqq2 = x(d.month) + 30 / n * j;
      return x(d.month) + 30 / n * j;
    })
    .attr("width", 30 / n)
    .transition()
    .attr("y", function(d) {
      return y(d.y0);
    })
    .attr("height", function(d) {
      return height - y(d.y0 - 0)
    })
    .attr("class", "bar")
    .style("fill", function(d) {
      return dataset["colors"][d.colorIndex];
    })

  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

  svg.append("text")
    .attr("x", width / 3)
    .attr("y", 0)
    .attr("dx", ".71em")
    .attr("dy", "-.71em")
    .text("Min - Max Temperature (Month wise)");

  svg.append("clipPath")
    .attr("id", "clip")
    .append("rect")
    .attr("width", width)
    .attr("height", height);

  var tooltip = d3.select("body")
    .append('div')
    .attr('class', 'tooltip');

  tooltip.append('div')
    .attr('class', 'month');
  tooltip.append('div')
    .attr('class', 'tempRange');

  svg.selectAll("rect")
    .on('mouseover', function(d) {
      if (!d.month) return null;

      tooltip.select('.month').html("<b>" + d.month + "</b>");
      tooltip.select('.tempRange').html(d.y + "&#8451; to " + d.y0 + "&#8451;");

      tooltip.style('display', 'block');
      tooltip.style('opacity', 2);

    })
    .on('mousemove', function(d) {

      if (!d.month) return null;

      tooltip.style('top', (d3.event.layerY + 10) + 'px')
        .style('left', (d3.event.layerX - 25) + 'px');
    })
    .on('mouseout', function() {
      tooltip.style('display', 'none');
      tooltip.style('opacity', 0);
    });

  function zoomed() {
    console.warn("zoom");
    svg.select(".x.axis").call(xAxis);
    console.log(d3.event.translate[0] + " " + d3.event.translate[1]);
    svg.selectAll(".chart rect").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");


  }

  function addDays(startDate, numberOfDays) {
    var returnDate = new Date(
      startDate.getFullYear(),
      startDate.getMonth(),
      startDate.getDate() + numberOfDays,
      startDate.getHours(),
      startDate.getMinutes(),
      startDate.getSeconds());
    return returnDate;
  }

}
<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8">
    <title>Multi Series Span Chart (Vertical)</title>
    <link rel="stylesheet" type="text/css" href="style.css" />
  </head>

  <body>
    <div id="chart1" class="chart" style="width: 100%;"></div>
    <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
  </body>
  <script type="text/javascript" src="main.js"></script>

</html>