const data = [
{
label: 'M1',
color: 'red',
items: [
{label: 'A', start: 10, end: 12},
{label: 'B', start: 15, end: 20}
]
},
{
label: 'M2',
color: 'orange',
items: [
{label: 'C', start: 0, end: 4},
{label: 'D', start: 4, end: 6},
{label: 'E', start: 11, end: 17}
]
},
{
label: 'M3',
color: 'yellow',
items: [
{label: 'F', start: 0, end: 3},
{label: 'G', start: 3, end: 9},
{label: 'H', start: 9, end: 14}
]
}
];
const ticks = 25;
const left = 50;
const _top = 50;
const rowHeight = 20;
const labelWidth = 30;
const bottom = _top + data.length * rowHeight;
const svg = d3.select("svg");
const xScale = d3.scaleLinear()
.domain([0, ticks])
.range([0, 300]);
const xAxis = d3.axisBottom()
.scale(xScale);
svg.append("g")
.attr('transform', `translate(${left}, ${bottom - 1})`)
.call(xAxis);
let i, j;
for (i = 0; i <= ticks; i++)
svg.append('line')
.attr('x1', xScale(i) + left)
.attr('x2', xScale(i) + left)
.attr('y1', _top)
.attr('y2', bottom)
.style('stroke', 'black');
for (i = 0; i < data.length; i++) {
svg.append('line')
.attr('x1', left)
.attr('x2', xScale(ticks) + left)
.attr('y1', _top + i * rowHeight)
.attr('y2', _top + i * rowHeight)
.style('stroke', 'black');
svg.append('rect')
.attr('x', left - labelWidth)
.attr('y', _top + i * rowHeight)
.attr('width', labelWidth)
.attr('height', rowHeight)
.style('fill', data[i].color)
.style('stroke', 'black')
svg.append('text')
.text(data[i].label)
.attr('x', left - labelWidth / 2)
.attr('y', _top + (i + 0.5) * rowHeight)
.attr('text-anchor', 'middle')
.attr('alignment-baseline', 'middle')
.style('fill', 'black');
const items = data[i].items;
for (j = 0; j < items.length; j++) {
const x = left + xScale(items[j].start);
const width = xScale(items[j].end) - xScale(items[j].start);
svg.append('rect')
.attr('x', x)
.attr('y', _top + i * rowHeight)
.attr('width', width)
.attr('height', rowHeight)
.style('fill', data[i].color)
.style('stroke', 'black')
svg.append('text')
.text(items[j].label)
.attr('x', x + width / 2)
.attr('y', _top + (i + 0.5) * rowHeight)
.attr('text-anchor', 'middle')
.attr('alignment-baseline', 'middle')
.style('fill', 'black');
}
}
text {
font-family: 'Ubuntu';
font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200">
</svg>