chart = {
const svg = d3.create("svg")
.attr("width", 900)
.attr("height", 100)
const margin = {top: 20, right: 0, bottom: 30, left: 40}
const height = +svg.attr('height') - margin.top - margin.bottom
const width = +svg.attr('width') - margin.left - margin.right
const getTypeColor = function (type) {
switch (type) {
case 'feature': return 'gold'
case 'gene': return '#bdbdbd'
case 'cds': return '#757575'
case 'rrna': return '#795548'
case 'trna': return '#4caf50'
case 'ncrna': return '#ff9800'
default: return -1
}
}
const barHeight = height * 0.8
const peakWidth = 10
const peakMid = barHeight * 0.5
const opacity = 0.6
const xScale = d3.scaleLinear()
.domain([data[0].start, data[0].end])
.range([0, width])
const xAxis = d3.axisBottom(xScale)
svg
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
svg.append('g')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis)
const lineGenerator = d3.line()
svg.selectAll('.arrow')
.data(data[0].features)
.enter()
.append('path')
.attr('class', 'arrow')
.attr('title', d => `<div style="text-align: left; font-family: 'Roboto Mono', monospace;">
<b>name</b> ${' '.repeat(2)}${d.name}<br>
<b>start</b> ${' '.repeat(1)}${d.start}<br>
<b>end</b> ${' '.repeat(3)}${d.end}<br>
</div>`)
.attr('data-placement', 'bottom')
.attr('d', d => {
if (d.type === 'feature' && (d.strand === 1 || d.strand === -1)) {
const points = [
[xScale(d.start), 0],
[xScale(d.end), 0],
[xScale(d.end), barHeight],
[xScale(d.start), barHeight]
]
return lineGenerator(points)
} else if (d.strand === 1 && getTypeColor(d.type) !== -1) {
if (xScale(d.end) - xScale(d.start) <= peakWidth) {
const points = [
[xScale(d.start), 0],
[xScale(d.end), peakMid],
[xScale(d.start), barHeight]
]
return lineGenerator(points)
} else {
const points = [
[xScale(d.start), 0],
[xScale(d.end) - peakWidth, 0],
[xScale(d.end), peakMid],
[xScale(d.end) - peakWidth, barHeight],
[xScale(d.start), barHeight]
]
return lineGenerator(points)
}
} else if (d.strand === -1 && getTypeColor(d.type) !== -1) {
if (xScale(d.end) - xScale(d.start) <= peakWidth) {
console.log(true)
const points = [
[xScale(d.end), 0],
[xScale(d.start), peakMid],
[xScale(d.end), barHeight]
]
return lineGenerator(points)
} else {
const points = [
[xScale(d.start), peakMid],
[xScale(d.start) + peakWidth, 0],
[xScale(d.end), 0],
[xScale(d.end), barHeight],
[xScale(d.start) + peakWidth, barHeight]
]
return lineGenerator(points)
}
} else console.log(`unknown type: "` + d.type + `" or unknown strand: "` + d.strand + `"`)
})
.style('fill', d => {
return getTypeColor(d.type)
})
.style('opacity', opacity)
.on('mouseover', function (element) {
this.style.opacity = 1
})
.on('mouseout', function (element) {
this.style.opacity = opacity
})
return svg.node();
}