Javascript D3制图工具:如何在柱状图目标线(附加水平线)右侧添加标签

Javascript D3制图工具:如何在柱状图目标线(附加水平线)右侧添加标签,javascript,d3.js,Javascript,D3.js,我用D3制图工具v4绘制了以下图表。我在这篇文章的底部附上了完整的代码 红线是要实现的目标。以下代码块正在绘制这条线: var targetGoalArr = [7]; svg.selectAll(".targetgoal") .data(targetGoalArr) .enter().append("line") .attr("class", "targetgoal") .attr("x1", 0) .attr("x2", width) .attr("y1", y)

我用D3制图工具v4绘制了以下图表。我在这篇文章的底部附上了完整的代码

红线是要实现的目标。以下代码块正在绘制这条线:

var targetGoalArr = [7];
svg.selectAll(".targetgoal")
  .data(targetGoalArr)
  .enter().append("line")
  .attr("class", "targetgoal")
  .attr("x1", 0)
  .attr("x2", width)
  .attr("y1", y)
  .attr("y2", y)
  .style("stroke", "#cc0000");
现在,我需要在这一行的右侧和两行中添加文本Growth Target(7)。标签也必须分成两行

下面的屏幕截图显示了所需的输出

我怎样才能实现上述目标

还有一件事我不能画,那就是Y轴的基线。在我的图表(带红线)中,我使用自定义记号数组创建水平线。代码如下:

function draw_yAxis_gridlines() {
  return d3.axisLeft(y)
    .tickValues(yTicks);
}

svg.append("g")
  .attr("class", "grid axis")
  .call(draw_yAxis_gridlines()
  .tickSize(-width)
);
但是,如果不对Y轴使用自定义记号,则会显示基线,但缺少水平轴网线。我必须同时显示两者

这是我的全部代码:

public function evd_unitary_growth_plan_chart( $data_str ){
        ob_start(); ?>

        <style> /* set the CSS */

            .line {
                fill: none;
                stroke: steelblue;
                stroke-width: 2px;
            }

            .grid line {
                stroke: lightgrey;
                stroke-opacity: 0.5;
                shape-rendering: crispEdges;
            }

            .grid path {
                stroke-width: 0;
            }

            .axis {
                font-size: 13px;
                font-family: 'Roboto';
                color: #808888;
            }

        </style>

        <script type="text/javascript">
            var h = 300;
            var w = 750;
            var barPadding = 2;

            function barColor(data_month, current_month) {
                if( parseInt(data_month) >= current_month)
                    return "#008600";
                else
                    return "#c4c4c4";
            }

            // set the dimensions and margins of the graph
            var margin = {top: 30, right: 20, bottom: 30, left: 40},
                width = w - margin.left - margin.right,
                height = h - margin.top - margin.bottom;

            var data = <?php echo $data_str ?>;

            // set the ranges
            var x = d3.scaleBand().range([0, width]).padding(0.2);
            var y = d3.scaleLinear().range([height, 0]);

            var svg = d3.select("#ecbg_unitary").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 + ")");

            // Scale the range of the data in the domains
            x.domain(data.map(function(d) { return d.month; }));

            var y_domain_upperBound = d3.max(data, function(d) { return d.points; });
            y_domain_upperBound = Math.round(y_domain_upperBound / 10) * 10 + 10;
            y.domain([0, y_domain_upperBound]);

            // Create Y-Axis tick array to draw grid lines
            var yTicks = [];
            var tickInterval = 5;
            for(var i = 0; i <= y_domain_upperBound; i = i + tickInterval) {
                yTicks.push(i);
            }

            console.log(yTicks);

            // gridlines in y axis function
            function draw_yAxis_gridlines() {
                return d3.axisLeft(y)
                    .tickValues(yTicks);
            }

            // Reference line - The red line
            var targetGoalArr = [7];
            svg.selectAll(".targetgoal")
                .data(targetGoalArr)
                .enter().append("line")
                .attr("class", "targetgoal")
                .attr("x1", 0)
                .attr("x2", width)
                .attr("y1", y)
                .attr("y2", y)
                .style("stroke", "#cc0000");

            // append the rectangles for the bar chart
            svg.selectAll("rect")
                .data(data)
                .enter().append("rect")
                .attr("x", function(d) {
                    return x(d.month);
                })
                .attr("width", x.bandwidth())
                .attr("y", function(d) { return y(d.points); })
                .attr("height", function(d) { return height - y(d.points); })
                .attr("fill", function(d){return barColor(d.data_month_number, d.current_month_number)});



            // column labels
            svg.selectAll("text")
                .data(data)
                .enter()
                .append("text")
                .text(function(d) {
                    return d.points;
                })
                .attr("text-anchor", "middle")
                .attr("x", function(d, i) {
                    return x(d.month) + x.bandwidth() / 2;
                })
                .attr("y", function(d) {
                    return y(d.points) - 10;
                })
                .attr("font-family", "Roboto")
                .attr("font-size", "13px")
                .attr("font-weight", "bold")
                .attr("fill", "#606668");

            // add the x Axis
            svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + height + ")")
                .call(d3.axisBottom(x));


            // add the Y gridlines
            svg.append("g")
                .attr("class", "grid axis")
                .call(draw_yAxis_gridlines()
                    .tickSize(-width)
                );

        </script>

        <?php return ob_get_clean();
    }
公共职能部门evd统一增长计划图表($data\u str){
ob_start();?>
/*设置CSS*/
.线路{
填充:无;
笔画:钢蓝;
笔画宽度:2px;
}
.网格线{
笔画:浅灰色;
笔划不透明度:0.5;
形状渲染:边缘清晰;
}
.网格路径{
笔画宽度:0;
}
.安讯士{
字体大小:13px;
字体系列:“Roboto”;
颜色:#808888;
}
var h=300;
var w=750;
var=2;
功能条颜色(数据月、当前月){
if(parseInt(数据月)>=当前月)
返回“#008600”;
其他的
返回“#c4c4”;
}
//设置图形的尺寸和边距
var margin={顶部:30,右侧:20,底部:30,左侧:40},
宽度=w-边距。左侧-边距。右侧,
高度=h-边距.顶部-边距.底部;
var数据=;
//设定范围
var x=d3.scaleBand().range([0,width])。padding(0.2);
变量y=d3.scaleLinear().range([height,0]);
var svg=d3.选择(“#ecbg_酉”).追加(“svg”)
.attr(“宽度”,宽度+边距。左侧+边距。右侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.附加(“g”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
//缩放域中数据的范围
x、 域(data.map(函数(d){returnd.month;}));
var y_domain_upperBound=d3.max(数据,函数(d){返回d.points;});
y_domain_upperBound=Math.round(y_domain_upperBound/10)*10+10;
y、 域([0,y_域_上界]);
//创建Y轴记号阵列以绘制网格线
var yTicks=[];
var间隔=5;

对于(var i=0;i要向目标行添加标签,最好创建group(
g
)元素,然后向其添加
line
text
元素。可以将g元素转换为正确的y位置,以便可以相对于g定位行和文本

var targetGoalArr = [7];

var target = g.selectAll(".targetgoal")
  .data(targetGoalArr)
  .enter()
  .append("g")
  .attr("transform", function(d){
    return "translate(0, " + y(d) +")"
  })

target.append("line")
  .attr("class", "targetgoal")
  .attr("x1", 0)
  .attr("x2", width)
  .attr("y1", 0)  //these can be omitted
  .attr("y2", 0)
  .style("stroke", "#cc0000");

target.append("text")
    .text(function(d){ return "Target growth: " + d })
    .attr("x", width)
    .attr("y", "0.35em")

我想知道为什么你认为D3是一个图表工具…(提示:它不是)如果我误解了,很抱歉。我对这一点完全陌生,希望我的初学者知识能被考虑。如果您能指导我如何完成上述任务,那将是非常好的!完美的解决方案!非常感谢@Tom Shanley!!但是,我需要更改
var target=g.selectAll(.targetgoal”)
var target=svg。selectAll(.targetgoal”)
。为了将标签分成两行,我引用了(两个独立的
文本
元素)并对它们进行了相应的定位。@tom shaley,请您建议我如何完成我在这里发布的内容:?