如何在其他形状的顶部绘制形状

时间:2018-03-27 13:40:52

标签: d3.js

我试图在另一层较短和较粗的矩形上绘制矩形/条形图,但结果是出乎意料的 - 只显示了一个图层:



var margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 40
  },
  w = 600 - margin.left - margin.right,
  h = 300 - margin.top - margin.bottom;

var data = [{
  "Food": "Apples",
  "Deliciousness": 9,
  "new": 4
}, {
  "Food": "Green Beans",
  "Deliciousness": 5,
  "new": 4
}, {
  "Food": "Egg Salad Sandwich",
  "Deliciousness": 4,
  "new": 4
}, {
  "Food": "Cookies",
  "Deliciousness": 10,
  "new": 4
}, {
  "Food": "Liver",
  "Deliciousness": 2,
  "new": 4
}, ];



// format the data
data.forEach(function(d) {
  d.Deliciousness = +d.Deliciousness;
});


var svg = d3.select("body")
  .append("svg")
  .attr("width", w + margin.left + margin.right)
  .attr("height", h + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," +
    margin.top + ")");

var xScale = d3.scaleBand()
  .domain(d => d.Food)
  .range([0, w])
  .paddingInner(0.2);
xScale.domain(data.map(function(d) {
  return d.Food;
}));


var xAxis = d3.axisBottom()
  .scale(xScale)
  .ticks(5);

var yScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.Deliciousness)])
  .rangeRound([h, 0]);

var yAxis = d3.axisLeft()
  .scale(yScale)
  .ticks(5);

var chartgroup = svg.append("g");

chartgroup.selectAll('rect')
  .data(data)
  .enter()
  .append('rect')
  .attr('x', (d, i) => margin.left + i * w / data.length)
  .attr('y', d => yScale(d.Deliciousness))
  .attr('width', xScale.bandwidth())
  .attr('height', d => h - yScale(d.Deliciousness))
  .attr('fill', "blue");

chartgroup.selectAll('rect')
  .data(data)
  .enter()
  .append('rect')
  .attr('x', (d, i) => margin.left + i * w / data.length)
  .attr('y', d => yScale(d.Deliciousness))
  .attr('width', xScale.bandwidth() / 2)
  .attr('height', d => h - yScale(d.Deliciousness) / 2)
  .attr('fill', "yellow");

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!DOCTYPE html>
<html lang="en">

<head>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <meta charset="utf-8">
  <title>D3: Loading data from a CSV file</title>
</head>

<body>
  <!-- <p>click to see changes</p> -->
</body>

</html>
&#13;
&#13;
&#13;

我也添加了一个小组,但这并没有解决问题。

我在这里错过了什么吗?

chartgroup.selectAll('rect')
        .data(data)
        .enter()
        .append('rect')
        .attr('x',(d,i) => margin.left + i*w/data.length)
        .attr('y',d=>yScale(d.Deliciousness))
        .attr('width', xScale.bandwidth()/2)
        .attr('height',d =>h-yScale(d.Deliciousness)/2)
        .attr('fill',"yellow");

有什么建议吗?

1 个答案:

答案 0 :(得分:2)

当你第二次这样做时......

chartgroup.selectAll('rect')

...您正在选择已在该SVG中绘制的元素。因此,您的第二个输入选择为空。让我们证明一下:

var margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 40
  },
  w = 600 - margin.left - margin.right,
  h = 300 - margin.top - margin.bottom;

var data = [{
  "Food": "Apples",
  "Deliciousness": 9,
  "new": 4
}, {
  "Food": "Green Beans",
  "Deliciousness": 5,
  "new": 4
}, {
  "Food": "Egg Salad Sandwich",
  "Deliciousness": 4,
  "new": 4
}, {
  "Food": "Cookies",
  "Deliciousness": 10,
  "new": 4
}, {
  "Food": "Liver",
  "Deliciousness": 2,
  "new": 4
}, ];



// format the data
data.forEach(function(d) {
  d.Deliciousness = +d.Deliciousness;
});


var svg = d3.select("body")
  .append("svg")
  .attr("width", w + margin.left + margin.right)
  .attr("height", h + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," +
    margin.top + ")");

var xScale = d3.scaleBand()
  .domain(d => d.Food)
  .range([0, w])
  .paddingInner(0.2);
xScale.domain(data.map(function(d) {
  return d.Food;
}));


var xAxis = d3.axisBottom()
  .scale(xScale)
  .ticks(5);

var yScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.Deliciousness)])
  .rangeRound([h, 0]);

var yAxis = d3.axisLeft()
  .scale(yScale)
  .ticks(5);

var chartgroup = svg.append("g");

chartgroup.selectAll("rect")
  .data(data)
  .enter()
  .append('rect')
  .attr('x', (d, i) => margin.left + i * w / data.length)
  .attr('y', d => yScale(d.Deliciousness))
  .attr('width', xScale.bandwidth())
  .attr('height', d => h - yScale(d.Deliciousness))
  .attr('fill', "blue");

var secondSelection = chartgroup.selectAll("rect")
  .data(data)
  .enter()
  .append('rect')
  .attr('x', (d, i) => margin.left + i * w / data.length)
  .attr('y', d => yScale(d.Deliciousness))
  .attr('width', xScale.bandwidth() / 2)
  .attr('height', d => h - yScale(d.Deliciousness) / 2)
  .attr('fill', "yellow");

console.log("Enter selection size is: " + secondSelection.size())
<script src="https://d3js.org/d3.v4.min.js"></script>

而不是(假设您不打算进行更新选择),请选择不存在的内容,例如null

chartgroup.selectAll(null)

为了更好地了解选择null的原因(有时为何不这样做),请查看Selecting null: what is the reason of using 'selectAll(null)' in D3.js?

以下是您更改的代码:

var margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 40
  },
  w = 600 - margin.left - margin.right,
  h = 300 - margin.top - margin.bottom;

var data = [{
  "Food": "Apples",
  "Deliciousness": 9,
  "new": 4
}, {
  "Food": "Green Beans",
  "Deliciousness": 5,
  "new": 4
}, {
  "Food": "Egg Salad Sandwich",
  "Deliciousness": 4,
  "new": 4
}, {
  "Food": "Cookies",
  "Deliciousness": 10,
  "new": 4
}, {
  "Food": "Liver",
  "Deliciousness": 2,
  "new": 4
}, ];

// format the data
data.forEach(function(d) {
  d.Deliciousness = +d.Deliciousness;
});

var svg = d3.select("body")
  .append("svg")
  .attr("width", w + margin.left + margin.right)
  .attr("height", h + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," +
    margin.top + ")");

var xScale = d3.scaleBand()
  .range([0, w])
  .paddingInner(0.2)
  .domain(data.map(function(d) {
  return d.Food;
}));

var xAxis = d3.axisBottom()
  .scale(xScale)
  .ticks(5);

var yScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.Deliciousness)])
  .rangeRound([h, 0]);

var yAxis = d3.axisLeft()
  .scale(yScale)
  .ticks(5);

var chartgroup = svg.append("g");

chartgroup.selectAll(null)
  .data(data)
  .enter()
  .append('rect')
  .attr('x', d => xScale(d.Food))
  .attr('y', d => yScale(d.Deliciousness))
  .attr('width', xScale.bandwidth())
  .attr('height', d => h - yScale(d.Deliciousness))
  .attr('fill', "blue");

chartgroup.selectAll(null)
  .data(data)
  .enter()
  .append('rect')
  .attr('x', d => xScale(d.Food))
  .attr('y', d => yScale(d.Deliciousness))
  .attr('width', xScale.bandwidth() / 2)
  .attr('height', d => h - yScale(d.Deliciousness) / 2)
  .attr('fill', "yellow");
<script src="https://d3js.org/d3.v4.min.js"></script>

相关问题