function dotTileV4 (data, {
title = null,
threshold = null,
w = 500,
h = 90,
radius = 6,
margin = {left: 300, top: 30, right: 50, bottom: 10},
xDomain = [0, 100],
bgdCol = '#f1f2f0',
lineCol = '#bfbabe',
circleFill = '#37bbe4',
thresholdCol = '#08327d',
circleTextFill = bgdCol,
titleCol = '#555',
subTitleCol = '#bfbabe',
} = {}) {
const min = (xDomain) ? xDomain[0] : d3.min(data, d => d.value);
const max = (xDomain) ? xDomain[1] : d3.max(data, d => d.value);
const yScale = d3.scaleLinear()
.domain([0, data.length])
.range([margin.top, h]);
const xScale = d3.scaleLinear()
.domain([min, max])
.range([0, w - (margin.left + margin.right)]);
const svg = DOM.svg(w, h);
const sel = d3.select(svg);
sel.append('rect')
.attr('width', w)
.attr('height', h)
.attr('rx', 10)
.attr('fill', bgdCol);
// append the title
sel.append('text')
.attr('class', 'title')
.attr('y', margin.top + 5)
.attr('x', margin.left -50)
.attr('text-anchor', 'end')
.style('font-size', '13px')
.style('fill', titleCol)
.style('line-height', '160%')
.text(title);
sel.select('text.title')
.each(function(d, i) { wrap_text(d3.select(this), (margin.left * 0.5), 1.4) });
// group for each segment
const join = sel.selectAll('g')
.data(data)
.join('g').append('g')
.attr('transform', (d, i) => {
return `translate(${margin.left}, ${yScale(i)})`
});
// lines for each row
join.append('line')
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', w - (margin.left + margin.right))
.attr('y2', 0)
.attr('stroke', lineCol)
.attr('stroke-dasharray', 2);
if (threshold) {
// threshold line vertical
join.append('line')
.attr('x1', d => xScale(threshold))
.attr('x2', d => xScale(threshold))
.attr('y1', -10)
.attr('y2', 10)
.attr('stroke', thresholdCol)
.attr('stroke-width', 2)
.attr('stroke-dasharray', 3);
// show threshold value
sel.append('text')
.attr('text-anchor', 'middle')
.style('font-size', '11px')
.attr('y', 13)
.attr('x', d => xScale(threshold) + margin.left)
.style('fill', thresholdCol)
.text(d => `${threshold}%`);
}
join.append('circle')
.attr('fill', circleFill)
.attr('r', radius)
.attr('cx', d => xScale(d.value))
.style('opacity', 0.9);
// show pct
join.append('text')
.attr('text-anchor', 'right')
.style('font-size', '11px')
.attr('dy', 3)
.attr('x', w - (margin.left + margin.right))
.attr('dx', 8)
.text((d, i) => (i === 0) ? `${d.value}%` : d.value); // show % on first value only
// show date/cat
join.append('text')
.attr('text-anchor', 'right')
.style('font-size', '11px')
.attr('dy', 3)
.attr('x', -35)
.style('fill', subTitleCol)
.text(d => d.label);
return svg;
}