Thanks Tom. I copied all the cells to my React module. A copy is below. The props include an array of Amazon prices. It has been used before in another D3 chart without a problem.
When I run this, I do get some part of the chart (AMZN prices) as shown in this image…
But the rest of the D3 code is a mystery to me. That’s why I want to run this demo chart, so I can experiment with all the API’s and learn D3.
class ChartCandlesticks extends Component {
componentDidMount() {
this.createChart()
}
createChart() {
const { data, width, height } = this.props
const margin = { top: 20, right: 30, bottom: 30, left: 40 }
const x = d3
.scaleBand()
.domain(d3.timeDay.range(data[0].date, +data[data.length - 1].date + 1).filter((d) => d.getDay() !== 0 && d.getDay() !== 6))
.range([margin.left, width - margin.right])
.padding(0.2)
const y = d3
.scaleLog()
.domain([d3.min(data, (d) => d.low), d3.max(data, (d) => d.high)])
.rangeRound([height - margin.bottom, margin.top])
const xAxis = (g) =>
g
.attr('transform', `translate(0,${height - margin.bottom})`)
.call(
d3
.axisBottom(x)
.tickValues(d3.timeMonday.every(width > 720 ? 1 : 2).range(data[0].date, data[data.length - 1].date))
.tickFormat(d3.timeFormat('%-m/%-d'))
)
.call((g) => g.select('.domain').remove())
const yAxis = (g) =>
g
.attr('transform', `translate(${margin.left},0)`)
.call(
d3
.axisLeft(y)
.tickFormat(d3.format('$~f'))
.tickValues(
d3
.scaleLinear()
.domain(y.domain())
.ticks()
)
)
.call((g) =>
g
.selectAll('.tick line')
.clone()
.attr('stroke-opacity', 0.2)
.attr('x2', width - margin.left - margin.right)
)
.call((g) => g.select('.domain').remove())
const formatDate = d3.timeFormat('%B %-d, %Y')
const formatValue = d3.format('.2f')
const parseDate = d3.timeParse('%Y-%m-%d')
const svg = d3
.select(this.node)
.append('svg')
.attr('width', { width })
.attr('height', { height })
.append('g')
.attr('transform', `translate( ${margin.left}, ${margin.top})`)
svg.append('g').call(xAxis)
svg.append('g').call(yAxis)
const g = svg
.append('g')
.attr('stroke-linecap', 'round')
.attr('stroke', 'black')
.selectAll('g')
.data(data)
.enter()
.append('g')
.attr('transform', (d) => `translate(${x(d.date)},0)`)
.attr('stroke', (d) => (d.open > d.close ? d3.schemeSet1[0] : d.close > d.open ? d3.schemeSet1[2] : d3.schemeSet1[8]))
g.append('line')
.attr('y1', (d) => y(d.low))
.attr('y2', (d) => y(d.high))
g.append('line')
.attr('y1', (d) => y(d.open))
.attr('y2', (d) => y(d.close))
.attr('stroke-width', x.bandwidth())
g.append('title').text(
(d) => `${formatDate(d.date)}
Open: ${formatValue(d.open)}
Close: ${formatValue(d.close)}
Low: ${formatValue(d.low)}
High: ${formatValue(d.high)}`
)
}
render() {
return <div ref={(node) => (this.node = node)} />
}
}