将线条附加到D3条形图 - 绝对没有任何反应

时间:2013-06-05 14:14:31

标签: javascript d3.js

我有一个非常好的工作分组条形图脚本,我正在尝试添加简单的参考线。相关代码:

//Set up margins and dimensions according to http://bl.ocks.org/3019563
var margin = {top: 20, right: 10, bottom: 20, left: 30},
    width = 810 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

/* Set up the primary x scale */
var x0 = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1)
    .domain(data.map(function (d) {
        return options.xPrimaryScaleAccessor(d);
    }));

/* Set up the secondary x scale */
var x1 = d3.scale.ordinal()
    .domain(xSecondaryScaleValues)
    .rangeRoundBands([0, x0.rangeBand()]);

/* Set up the y scale as a linear (continous) scale with a total range of 0 - full height and a domain of 0-100 */
var y = d3.scale.linear()
    .range([height, 0])
    .domain([0, 100]);

/* Set up a color space of 20 colors */
var color = d3.scale.category20();

/* Set up the x axis using the primary x scale and align it to the bottom */
var xAxis = d3.svg.axis()
    .scale(x0)
    .orient("bottom");

/* Set up the y axis using the y scale and align it to the left */
var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

/* Create an SVG element and append it to the body, set its dimensions, append a <g> element to
 * it and apply a transform translating all coordinates according to the margins set up. */
var svg = d3.select(options.target).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 + ")");

//Create a space for definitions
var defs = svg.append("defs");

setupDropShadowFilter(defs, 3, 3, 3); //Sets up a gaussian blur filter with id 'drop-shadow'

/* Append a <g> element to the chart and turn it into a representation of the x axis */
svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

/* Append a <g> element to the chart and turn it into a representation of the y axis */
svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text(options.yLabel);

var dataArr = y.ticks(yAxis.ticks());

/* Draw the reference lines */  
svg.selectAll("line")
   .data(dataArr)
   .enter().append("line")
   .attr("x1", 0)
   .attr("x2", width)
   .attr("y1", y)
   .attr("y2", y)
   .style("stroke", "#ccc");

/* Set up the bar groups */
var group = svg.selectAll(".group")
    .data(data)
    .enter().append("g")
    .attr("class", "g")
    .attr("transform", function(d) { return "translate(" + x0(options.xPrimaryScaleAccessor(d)) + ",0)"; });

/* Draw the bars */
group.selectAll("rect")
    .data(options.valueAccessor)
    .enter().append("rect")
    .attr("width", x1.rangeBand())
    .attr("x", function(d) { return x1(d.label); })
    .attr("y", function(d) { return y(d.value); })
    .attr('rx', options.barCornerRadius)
    .attr('ry', options.barCornerRadius)
    .attr("height", function(d) { return height - y(d.value); })
    .style("fill", function(d) { return getStripedPattern(defs, color(d.label)); //Sets up a pattern and returns its ID })//Todo: fill with pattern instead. see http://tributary.io/tributary/2929255
    .style("filter", "url(#drop-shadow)");

/* Draw a legend */
var legend = svg.selectAll(".legend")
    .data(xSecondaryScaleValues)
    .enter().append("g")
    .attr("class", "legend")
    .attr("transform", function(d, i) { return "translate(0," + (xSecondaryScaleValues.length-i-.25) * (height/xSecondaryScaleValues.length) + ")"; });

legend.append("rect")
    .attr("x", width - 9)
    .attr("width", 18)
    .attr("height", 18)
    .style("fill", color);

legend.append("text")
    .attr("y", 9)
    //.attr("dy", ".35em")
    .attr("transform", "translate(" + (width - 6) + ",-8)rotate(-90)" )
    .style("text-anchor", "start")
    .text(function(d) { return d; });

编辑:我还试图用硬编码的坐标和尺寸附加rect元素,但那些也没有进入DOM。

编辑2:现在包含或多或少的完整代码。

基本上没有任何反应。没有添加任何行,控制台中没有错误。 dataArr是一个简单的数字数组,并确认y(number)可以在输出范围内返回良好的值。

我认为(和调试表明)链在append()阶段死亡,可能是因为.enter()返回了无用的东西。

.data()之后的控制台日志:

Console log after .data()

.enter()之后的控制台日志:

Console log after .enter()

.append()之后的控制台日志:

Console log after .append():

我现在已经坚持了很长一段时间,所以对任何可能出错的想法都很感激。我确定我忽略了一些明显的东西......

1 个答案:

答案 0 :(得分:1)

问题是生成轴的代码会将line元素附加到SVG。在附加参考线之前运行,调用svg.selectAll("line").data(...)会将现有行与数据匹配。行数多于数据元素,因此不需要添加新元素,.enter()选项为空。

有几种方法可以解决这个问题。您可以进一步移动生成参考线的代码。您添加包含这些行的g元素。您可以为这些行设置一个特殊类,并相应地调整选择器。或者您可以为.data()提供自定义匹配功能。