Ich baue ein gestapeltes Balkendiagramm mit d3 v4.4.4 in react.js v15.3.0. Im Folgenden finden Sie die Daten, die ich mein gestapeltes Balkendiagramm bauen bin mit:D3 stack() überspringt erstes Objekt in meinem Datenfeld
[
{ timestamp: "2006", source1: "20", source2: "20", source3: "20", source4: '20'},
{ timestamp: "2007", source1: "70", source2: "50", source3: "10", source4: '70'},
{ timestamp: "2008", source1: "80", source2: "50", source3: "60", source4: '40'},
{ timestamp: "2009", source1: "30", source2: "20", source3: "40", source4: '50'},
{ timestamp: "2010", source1: "70", source2: "20", source3: "90", source4: '20'}
]
ich das gestapeltes Balkendiagramm bis zeigen seen here bekommen habe, aber es ist nicht in der Anordnung der Daten das erste Objekt zeigt. Stattdessen dupliziert das gestapelte Balkendiagramm das letzte Objekt in dem Datenfeld und verwendet es für den ersten und den letzten gestapelten Balken im Diagramm.
const stack = d3.stack().keys(keys)
const layers = stack(chartDataWorkingCopy)
this was the result of logging layers to the console
Wie Sie aus dem obigen Screenshot der ersten und letzten Anordnungen sind die gleichen, und das erste Objekt sehen kann (dh {Zeitstempel: "2006", source1: "20", source2: "20", source3: "20", source4: '20 '}) aus den Originaldaten, die ich zum Erstellen des Diagramms verwendet habe, ist nicht vorhanden.
Kann mir jemand erklären, warum d3 über das erste Objekt im Array springt und das letzte beim Erstellen des gestapelten Balkendiagramms dupliziert?
Im Folgenden ist der Quellcode für die gestapeltes Balkendiagramm Komponente:
import React, { PropTypes } from 'react'
import * as d3 from 'd3'
import _ from 'lodash'
class StackedBarChart extends React.Component {
static propTypes = {
chartData: PropTypes.array,
barWidth: PropTypes.number,
barOffset: PropTypes.number,
chartHeight: PropTypes.number,
chartWidth: PropTypes.number
}
static defaultProps = {
chartData: [
{ timestamp: "2006", source1: "20", source2: "20", source3: "20", source4: '20'},
{ timestamp: "2007", source1: "70", source2: "50", source3: "10", source4: '70'},
{ timestamp: "2008", source1: "80", source2: "50", source3: "60", source4: '40'},
{ timestamp: "2009", source1: "30", source2: "20", source3: "40", source4: '50'},
{ timestamp: "2010", source1: "70", source2: "20", source3: "90", source4: '20'}
],
barWidth: 10,
barOffset: 5,
chartHeight: 200,
chartWidth: 300
}
componentDidMount() {
this.renderChart()
}
componentDidUpdate(prevProps){
if(!_.isEqual(this.props, prevProps)){
d3.select('svg').remove()
this.renderChart()
}
}
splitTheDifference(data) {
let str = String(data)
const points = str.split(',')
return (points[1] - points[0])
}
renderChart() {
const { chartData, barWidth, barOffset, chartHeight, chartWidth} = this.props
let chartDataWorkingCopy = [...chartData]
// keep the bars from going off the page
const maxBars = (chartWidth/(barWidth + 2))
if (chartDataWorkingCopy.length > maxBars) {
chartDataWorkingCopy = chartDataWorkingCopy.slice(-Math.floor(maxBars))
}
const keys = _.remove(_.keys(_.extend.apply({}, chartDataWorkingCopy)), (d) => {
return d !== 'timestamp'
})
const xScale = d3.scaleBand().range([0, chartWidth]).padding(0.1)
const yScale = d3.scaleLinear().range([chartHeight, 0])
const color = ['hsl(8, 82%, 50%)', 'hsl(76, 96%, 50%)', 'hsl(178, 99%, 50%)', 'hsl(302, 100%, 50%)', 'hsl(58, 98%, 50%)', 'hsl(144, 100%, 50%)']
const xAxis = d3.axisBottom(xScale).tickFormat(d3.timeFormat("%b"))
const yAxis = d3.axisLeft(yScale)
const width = chartWidth
const height = chartHeight
let svg = d3.select('.barChartContainer').append("svg")
.attr('width', width)
.attr('height', height)
.append('g')
const stack = d3.stack().keys(keys)
const layers = stack(chartDataWorkingCopy)
xScale.domain(chartDataWorkingCopy.map(function(d) { return d.timestamp }))
yScale.domain([0, d3.max(layers[layers.length - 1], function(d) {
return d[0] + d[1]
}) ]).nice()
const layer = svg.selectAll('.layer')
.data(layers)
.enter().append('g')
.attr('class', 'layer')
.style('fill', function(d, i) { return color[i] })
layer.selectAll("rect")
.data(function(d) {
return d
})
.enter().append("rect")
.attr("x", function(d, i) {
return i * 12
})
.attr("y", function(d) { return yScale(d[1]) })
.attr("height", function(d) { return yScale(d[0]) - yScale(d[1]) })
.attr("width", 10)
.on('mouseover', (d) => {
d3.select('#tooltip')
.classed('hidden', false)
.style('position', 'absolute')
.style('background', '#333333')
.style('color', '#fff')
.style('padding', 10)
.style('left', `${d3.event.pageX}px`)
.style('top', `${d3.event.pageY - 80}px`)
.select('#value')
.text(this.splitTheDifference(d))
})
.on('mouseout', (d) => {
d3.select('#tooltip')
.classed('hidden', true)
})
}
render(){
return(
<div className={ 'barChartContainer' }>
<div id='tooltip' className='hidden'>
<p id='value'></p>
</div>
</div>
)
}
}
export default StackedBarChart