【问题标题】:Horizontal Bar chart using d3 js使用 d3 js 的水平条形图
【发布时间】:2016-08-08 05:22:37
【问题描述】:

我正在使用 d3.js 绘制条形图。我想在两个输入值之间显示条形图,但在 x 轴上以字符串值而不是整数值的形式显示。

[![我要达到的目标的一个例子][1]][1]

var y-axis= ['Accessories', 'Audiophile', 'Camera & Photo', 'Cell Phones', 'Computers','eBook Readers'];

var x-axis= ['development', 'design', 'testing', 'UAT', 'LiveDeployment'];

我使用的参考网址是[D3 js 简单水平条形图][2]

代码包含以下功能: 1) 使用 D3 js 和自定义 x 轴标签的单杠 2) 将 x 轴线显示为文本换行:(2016 年 1 月 1 日生产开始日期) 3) 将 y 轴线显示为文本换行:(Category 1Category 1Category 1Category 1)

function wrap(text, width) {
  text.each(function() {
    var text = d3.select(this),
        words = text.text().split(/\s+/).reverse(),
        word,
        line = [],
        lineNumber = 0,
        lineHeight = 1.1, // ems
        y = text.attr("y"),
        dy = parseFloat(text.attr("dy")),
        tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
    while (word = words.pop()) {
      line.push(word);
      tspan.text(line.join(" "));
      if (tspan.node().getComputedTextLength() > width) {
        line.pop();
        tspan.text(line.join(" "));
        line = [word];
        tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
      }
    }
  });
}

data = [
    {label:"Category 1Category 1Category 1", value:25},
    {label:"Category 2", value:50},
    {label:"Category 3", value:100},
    {label:"Category 4", value:75},
    {label:"Category 5", value:40},
    {label:"Category 6", value:20}
];

var axisMargin = 10,
margin = 20,
valueMargin = 2,
width = parseInt(d3.select('#barchart').style('width'), 9),
height = parseInt(d3.select('body').style('height'), 9),
barHeight = (height-axisMargin-margin*2)* 0.6/data.length,
barPadding = (height-axisMargin-margin*2)*0.4/data.length,
data, bar, svg, scale, scale2, xAxis, labelWidth = 0;

max = d3.max(data, function(d) { return d.value; });

svg = d3.select('#barchart')
        .append("svg")
        .attr("width", width)
        .attr("height", height);


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

bar.attr("class", "bar")
        .attr("cx",0)
        .attr("transform", function(d, i) {
            return "translate(" + margin + "," + (i * (barHeight + barPadding) + barPadding) + ")";
        });

bar.append("text")
        .attr("class", "label")
        .attr("y", barHeight / 2)
        .attr("dy", ".35em") //vertical align middle
        .text(function(d){
            return d.label;
        }).each(function() {
            labelWidth = 150; //Math.ceil(Math.max(labelWidth, this.getBBox().width));
        })
        .call(wrap, 150);


scale = d3.scale.linear()
        .domain([0, max])
        .range([0, width - margin*2 - labelWidth]);

/*scale = d3.scale.linear()
        .domain([0, max])
        .range([0, width - margin*2 - labelWidth]);

xAxis = d3.svg.axis()
        .scale(scale)
        .tickSize(-height + 2*margin + axisMargin);
        .orient("bottom");*/

var scale2 = d3.scale.ordinal()
      .domain(["01/01/2016 Production Start Date", "01/01/2016 Production End Date", "Transcoding", "Encryption", "Published", "Published Release Date"])
      .rangePoints([0, width - margin*2 - labelWidth]);

var xAxis = d3.svg.axis()
        .scale(scale2)
        .tickSize(-height + 2*margin + axisMargin)
        .orient("bottom");        

bar.append("rect")
    .attr("transform", "translate("+labelWidth+", 0)")
    .attr("height", barHeight)
    .attr("width", function(d){
        return scale(d.value);
});

bar.append("text")
    .attr("class", "value")
    .attr("y", barHeight / 2)
    .attr("dx", -valueMargin + labelWidth) //margin right
    .attr("dy", ".35em") //vertical align middle
    .attr("text-anchor", "end")
    .text(function(d){
            return (d.value+"%");
        })
    .attr("x", function(d){
        var width = this.getBBox().width;
        return Math.max(width + valueMargin, scale(d.value));
});

svg.insert("g",":first-child")
        .attr("class", "axisHorizontal")
        .attr("transform", "translate(" + (margin + labelWidth) + ","+ (height - axisMargin - margin)+")")
        .call(xAxis)
        .selectAll(".tick text")
        .call(wrap, 100);

【问题讨论】:

  • 我只能推荐 c3.js。它使用 d3,但处理起来要简单得多。

标签: javascript php jquery angularjs d3.js


【解决方案1】:

您当然可以格式化刻度,但有一个简单的解决方法:为刻度创建 另一个 刻度,并为您的 x 轴调用此替代刻度:

var xScaleString = d3.scale.ordinal()
      .domain(["design", "development", "testing", "UAT"])
      .rangePoints([0, width]);

使用这种不同寻常的方法的优点是您可以按照您想要的方式沿 x 轴展开字符串。缺点是您可能无法完美匹配原始刻度的值(10、20、30 等)。

请记住保留原始比例(用于矩形的比例)。

【讨论】:

  • 是的,我已经尝试过使用它,它现在似乎可以工作了。这里要求的更多功能。您能否相应地更新代码 1)显示 x 轴线。 2) X 轴文本很大,所以我需要把它分成两行。请参考问题中的给定代码。
  • 为了显示轴,就像你调用原始轴一样调用它。为了包装长文本,你需要一个像这样的函数:bl.ocks.org/mbostock/7555321
  • 谢谢,我在给定链接的帮助下完成了这项工作。工作代码在帖子本身中更新,因此其他需要或有问题的成员可以参考。非常感谢您的支持。
猜你喜欢
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-03
  • 2015-02-08
  • 2017-02-19
  • 1970-01-01
相关资源
最近更新 更多