chart = {
const svg = d3.create('svg')
.attr('viewBox', [0, 0, width, height]);
const sentenceWidth = (width - margin.left - margin.right) / data.length;
const innerHeight = (height - margin.top - margin.bottom);
let chapters = svg.append('g')
.selectAll('g')
.data(data)
.join('g')
.attr('id', (d, i) => `chapter-${i}`)
.attr('transform', (d, i) => {
let x = margin.left + halfSpacing + (i * sentenceWidth);
let y = margin.top + halfSpacing;
return `translate(${x}, ${y})`;
})
chapters.append('text')
.attr('x', sentenceWidth / 2)
.attr('y', innerHeight + (margin.bottom / 2))
.style('text-anchor', 'middle')
.text((d, i) => i + 1)
chapters.selectAll('rect')
.data(d => d.sentences_tone)
.join('rect')
.attr('id', (d, i) => `sentence-${i}`)
.attr('order', d => d.toneId)
.attr('x', 0)
.attr('y', (d, i, data) => i * (innerHeight / data.length))
.attr('width', sentenceWidth - spacing)
.attr('height', (d, i, data) => (innerHeight / data.length) - spacing)
.style('fill', d => {
let t = (d.score - scoreRange[d.toneId].min) / (scoreRange[d.toneId].max - scoreRange[d.toneId].min);
return d3.rgb(colors[d.toneId](t)).hex();
});
return svg.node();
}