连接直方图顶部的简单折线图

Simple line chart joining top of histograms

在下面的示例中,我绘制了字母与频率的直方图。现在,我想要一个折线图也用于相同的数据而不做太多改变。这意味着只有一条红线连接直方图的顶部。有人可以帮我吗?

<html>

<head> 

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"></script> 

</head>

<body> 

<svg width="960" height="500"></svg>

<script>

//Our basic data 
var data = [
    {frequency:0.08, letter:"A"},
    {frequency:0.11,letter:"B"},
    {frequency:0.13,letter:"C"}
];

var svg = d3.select("svg");
var margin = {top: 40, bottom: 40, left: 40, right: 40};
var width = svg.attr("width") - margin.left - margin.right;
var height = svg.attr("height") - margin.top - margin.bottom;

var x = d3.scaleBand().rangeRound([0, width]).padding(0.6);
var y = d3.scaleLinear().rangeRound([height, 0]);

//defining our main g in svg 
var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

//Looping for data bars 
data.forEach(function(){

    x.domain(data.map(function(d) { return d.letter; }));
    y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

    g
        .append("g")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x));

    g
        .append("g")
        .call(d3.axisLeft(y).ticks(10, "%"));

    g
        .selectAll(".bar")
        .data(data)
        .enter()
        .append("rect")
        .attr("x", function(d) { return x(d.letter); })
        .attr("y", function(d) { return y(d.frequency); })
        .attr("width", x.bandwidth())
        .attr("height", function(d) { return height - y(d.frequency); });

});

</script> 

</body> 

</html> 

直方图:

首先,去掉那个data.forEach:你为什么要画3遍?

之后,定义你的线生成器:

var line = d3.line()
    .x(function(d){ return x(d.letter) + x.bandwidth()/2})
    .y(function(d){ return y(d.frequency)})
    .curve(d3.curveCardinal);;

这里,x.bandwidth()/2 会将线放在每个柱顶部的中间。我使用的是 d3.curveCardinal,但你的曲线是 other options

然后,附加行:

g.append("path")
    .datum(data)
    .attr("d", line);

这是演示:

<head> 

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"></script> 

</head>

<body> 

<svg width="960" height="500"></svg>

<script>

//Our basic data 
var data = [
    {frequency:0.08, letter:"A"},
    {frequency:0.11,letter:"B"},
    {frequency:0.13,letter:"C"}
];

var svg = d3.select("svg");
var margin = {top: 40, bottom: 40, left: 40, right: 40};
var width = svg.attr("width") - margin.left - margin.right;
var height = svg.attr("height") - margin.top - margin.bottom;

var x = d3.scaleBand().rangeRound([0, width]).padding(0.6);
var y = d3.scaleLinear().rangeRound([height, 0]);

//defining our main g in svg 
var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

//Looping for data bars 


    x.domain(data.map(function(d) { return d.letter; }));
    y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
  
  var line = d3.line()
   .x(function(d){ return x(d.letter) + x.bandwidth()/2})
   .y(function(d){ return y(d.frequency)})
        .curve(d3.curveCardinal);

    g
        .append("g")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x));

    g
        .append("g")
        .call(d3.axisLeft(y).ticks(10, "%"));

    g
        .selectAll(".bar")
        .data(data)
        .enter()
        .append("rect")
        .attr("x", function(d) { return x(d.letter); })
        .attr("y", function(d) { return y(d.frequency); })
        .attr("width", x.bandwidth())
        .attr("height", function(d) { return height - y(d.frequency); });
    
    g.append("path")
    .datum(data)
    .attr("d", line)
    .attr("stroke", "red")
    .attr("fill", "none");


</script>