2

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

//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()

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

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

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

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

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

我已经坚持了很长一段时间了,非常感谢任何关于可能出错的想法。我确定我忽略了一些明显的东西......

4

1 回答 1

4

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

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

于 2013-06-07T16:11:55.590 回答