d3.js标有水平条形图,但具有动画功能

时间:2018-11-05 10:24:53

标签: javascript d3.js

我已经创建了各种垂直条形图-但是需要对其进行调整以在水平模式下工作。

https://codepen.io/anon/pen/ZmJzXZ

//静态垂直图 http://jsfiddle.net/pg886/201/

//动画垂直图表 http://jsfiddle.net/Qh9X5/12073/

这将绕轴交换。

  var x = d3.scaleBand()
    .rangeRound([0, width]).padding(0.1);

  var y = d3.scaleLinear()
    .range([height, 0]);

  var xAxis = d3.axisBottom(y);
  var yAxis = d3.axisLeft(x);

但可能还需要重建它,以使其看起来像以下线框概念

enter image description here

   var data = [{
            "name": "Apples",
            "value": 20,
    },
        {
            "name": "Bananas",
            "value": 12,
    },
        {
            "name": "Grapes",
            "value": 19,
    },
        {
            "name": "Lemons",
            "value": 5,
    },
        {
            "name": "Limes",
            "value": 16,
    },
        {
            "name": "Oranges",
            "value": 26,
    },
        {
            "name": "Pears",
            "value": 30,
    }];

    //sort bars based on value
    data = data.sort(function (a, b) {
        return d3.ascending(a.value, b.value);
    })

    //set up svg using margin conventions - we'll need plenty of room on the left for labels
    var margin = {
        top: 15,
        right: 25,
        bottom: 15,
        left: 60
    };

    var width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

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

    var x = d3.scale.linear()
        .range([0, width])
        .domain([0, d3.max(data, function (d) {
            return d.value;
        })]);

    var y = d3.scale.ordinal()
        .rangeRoundBands([height, 0], .3)
        .domain(data.map(function (d) {
            return d.name;
        }));

    //make y axis to show bar names
    var yAxis = d3.svg.axis()
        .scale(y)
        //no tick marks
        .tickSize(0)
        .orient("right");

    var gy = svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)

    var bars = svg.selectAll(".bar")
        .data(data)
        .enter()
        .append("g")
        .attr("class", "bars")


    //append rects
    bars.append("rect")
        .attr("class", "bar")
        .attr("y", function (d) {
            return y(d.name);
        })
        .attr("height", y.rangeBand())
        .attr("x", 0)
        .attr("width", function (d) {
            return x(d.value);
        });

    //add a value label to the right of each bar
    bars.append("text")
        .attr("class", "label")
        //y position of the label is halfway down the bar
        .attr("y", function (d) {
            return y(d.name) + y.rangeBand() / 2 + 4;
        })
        //x position is 3 pixels to the right of the bar
        .attr("x", function (d) {
            return x(d.value) + 3;
        })
        .text(function (d) {
            return d.value;
        });

    var labels =         
        bars.append("text")
        .attr("class", "labels")
    .attr("y", function (d) {
            return y(d.name) + y.rangeBand() / 2 - 30;
        })
    .attr("x", 0)
        .text(function (d) {
            return d.name;
        });

enter image description here

2 个答案:

答案 0 :(得分:2)

此处给出了完全响应的水平条形图,侧面带有标签和动画效果:

var margin = {top: 20, right: 20, bottom: 50, left: 100},
    width = parseInt(d3.select("#chart").style("width")) - margin.left - margin.right,
    height = parseInt(d3.select("#chart").style("height")) - margin.top - margin.bottom;

var yScale = d3.scale.ordinal()
    .rangeRoundBands([height, 0], 0.1);

var xScale = d3.scale.linear()
    .range([0, width]);

var dollarFormatter = d3.format(",.0f")

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

var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom")
    .tickFormat(function(d) { return dollarFormatter(d);});

var svg = d3.select("#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 data = [
  {
    "metric": "Sales",
    "Name": "Pears",
    "total": 2020.161
  },
  {
    "metric": "Sales",
    "Name": "Apples",
    "total": 2122.545
  },
  {
    "metric": "Sales",
    "Name": "Bananas",
    "total": 4154.9
  }];


  // Filter to select a subset
  var subset = data.filter(function(el){
    return  (el["metric"]);
  });

  // Sort the data so bar chart is sorted in decreasing order
  subset = subset.sort(function(a, b) { return a["total"] - b["total"]; });

  yScale.domain(subset.map(function(d) { return d["Name"]; }));
  xScale.domain([0, d3.max(subset, function(d) { return d["total"]; })]);

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

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

  svg.selectAll(".bar")
      .data(subset)
    .enter().append("rect")
      .attr("class", "bar")
      //.attr("y", function(d) { return yScale(d["Name"]); })
      //.attr("height", yScale.rangeBand())      
			.attr("width", 0)
			.transition()
			.duration(500)
			.delay(function(d,i){ return i*250})
      .attr("width", function(d){
            return xScale(d["total"]);
      });

    setTimeout(function(){
    d3.selectAll("rect").transition()
    .duration(500)
    .delay(function(d,i){ return 250*(3-i);})
    .attr("width",function(d){ return 0;})
    },2000);

// Define responsive behavior
function resize() {
  var width = parseInt(d3.select("#chart").style("width")) - margin.left - margin.right,
  height = parseInt(d3.select("#chart").style("height")) - margin.top - margin.bottom;

  // Update the range of the scale with new width/height
  xScale.range([0, width]);
  yScale.rangeRoundBands([height, 0], 0.1);

  // Update the axis and text with the new scale
  svg.select(".x.axis")
    .call(xAxis)
    .attr("transform", "translate(0," + height + ")")
    .select(".label")
      .attr("transform", "translate(" + width / 2 + "," + margin.bottom / 1.5 + ")");

  svg.select(".y.axis")
    .call(yAxis);

  // Update the tick marks
  xAxis.ticks(Math.max(width/75, 2), " $");

  // Force D3 to recalculate and update the line
  svg.selectAll(".bar")
    .attr("width", function(d) { return xScale(d["total"]); })
    .attr("y", function(d) { return yScale(d["Name"]); })
    .attr("height", yScale.rangeBand());
};

// Call the resize function whenever a resize event occurs
d3.select(window).on('resize', resize);

// Call the resize function
resize();

// Define the format function
function format(d) {
  d.total = +d.total;
  return d;
}
@import url(https://fonts.googleapis.com/css?family=Karla);body{font-family:Karla!important}.bar{fill:#c7003b}.bar:hover{fill:#61001d}.axis{font-size:10px}.axis line,.axis path{fill:none;stroke:#D4D8DA;stroke-width:1px;shape-rendering:crispEdges}.x path{display:none}#chart{width:100%;height:100%;position:absolute}.d3-tip{line-height:1;font-size:14px;padding:12px;background:rgba(0,0,0,.8);color:#b9b9b9;border-radius:2px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>


<svg id="chart"></svg>

您可以将以上内容用作基础,然后进行相应更改。动画的主要代码是:

                .transition()
                .duration(1500)
                .delay(function(d,i){ return i*250})
    .attr("width", function(d){
        return scale(d.value);
    });

答案 1 :(得分:0)

尝试一下, https://codepen.io/anon/pen/XyJPby

   var data = [{
            "name": "Apples",
            "value": 20,
    },
        {
            "name": "Bananas",
            "value": 12,
    },
        {
            "name": "Grapes",
            "value": 19,
    },
        {
            "name": "Lemons",
            "value": 5,
    },
        {
            "name": "Limes",
            "value": 16,
    },
        {
            "name": "Oranges",
            "value": 26,
    },
        {
            "name": "Pears",
            "value": 30,
    }];

    //sort bars based on value
    data = data.sort(function (a, b) {
        return d3.ascending(a.value, b.value);
    })

    //set up svg using margin conventions - we'll need plenty of room on the left for labels
    var margin = {
        top: 15,
        right: 25,
        bottom: 15,
        left: 60
    };

    var width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

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

    var x = d3.scale.linear()
        .range([0, width])
        .domain([0, d3.max(data, function (d) {
            return d.value;
        })]);

    var y = d3.scale.ordinal()
        .rangeRoundBands([height, 0], .1)
        .domain(data.map(function (d) {
            return d.name;
        }));

    //make y axis to show bar names
    var yAxis = d3.svg.axis()
        .scale(y)
        //no tick marks
        .tickSize(0)
        .orient("left");

    var gy = svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)

    var bars = svg.selectAll(".bar")
        .data(data)
        .enter()
        .append("g")

    //append rects
    bars.append("rect")
        .attr("class", "bar")
        .attr("y", function (d) {
            return y(d.name);
        })
        .attr("height", y.rangeBand())
        .attr("x", 0)
        .attr("width", function (d) {
            return x(d.value);
        });

    //add a value label to the right of each bar
    bars.append("text")
        .attr("class", "label")
        //y position of the label is halfway down the bar
        .attr("y", function (d) {
            return y(d.name) + y.rangeBand() / 2 + 4;
        })
        //x position is 3 pixels to the right of the bar
        .attr("x", function (d) {
            return x(d.value) + 3;
        })
        .text(function (d) {
            return d.value;
        });

从这里 https://bl.ocks.org/hrecht/f84012ee860cb4da66331f18d588eee3