Last active
December 5, 2017 22:59
-
-
Save tgotwig/4536d70352fc1149b437f78f61361763 to your computer and use it in GitHub Desktop.
Arrows (+tooltip)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<svg width="960" height="500" | |
></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://unpkg.com/tippy.js@2.0.2/dist/tippy.all.min.js"></script> | |
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"> | |
<script> | |
;(function (window, d3) { | |
document.addEventListener("DOMContentLoaded", function(event) { | |
window.draw = draw | |
}) | |
let draw = (data, selector) => { | |
const svg = d3.select('svg') | |
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 | |
// bar colors | |
const getTypeColor = function (type) { | |
switch (type) { | |
case 'feature': return 'gold' | |
case 'gene': return '#bdbdbd' // greyLighten | |
case 'cds': return '#757575' // greyDarken | |
case 'rrna': return '#795548' // brown | |
case 'trna': return '#4caf50' // green | |
case 'ncrna': return '#ff9800' // orange | |
default: return -1 | |
} | |
} | |
// bar constants | |
const barHeight = height * 0.7 | |
const peakWidth = 10 | |
const peakMid = barHeight * 0.5 | |
const opacity = 0.6 | |
// x setup | |
const xScale = d3.scaleLinear() | |
.domain([data.start, data.end]) | |
.range([0, width]) | |
const xAxis = d3.axisBottom(xScale) | |
svg | |
.attr('width', width + margin.left + margin.right) // width + 2x padding | |
.attr('height', height + margin.top + margin.bottom) // height + 2x padding | |
.append('g') | |
.attr('transform', `translate(${margin.left}, ${margin.top})`) | |
// x axis | |
svg.append('g') | |
.attr('transform', 'translate(0,' + height + ')') | |
.call(xAxis) | |
const lineGenerator = d3.line() | |
svg.selectAll('.arrow') | |
.data(data.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)) { // draw bar | |
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) { // draw right arrow | |
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) { // draw left arrow | |
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 + `"`) // error | |
}) | |
.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 | |
}) | |
} | |
const data = { | |
'start': 1000, | |
'end': 20100, | |
'features': [ | |
{ | |
'name': 'A', | |
'desc': 'xyz in detail.', | |
'start': 1000, | |
'end': 1900, | |
'strand': 1, | |
'type': 'feature' | |
}, | |
{ | |
'name': 'B', | |
'desc': 'xyz in detail.', | |
'start': 2000, | |
'end': 2100, | |
'strand': 1, | |
'type': 'gene' | |
}, | |
{ | |
'name': 'C', | |
'desc': 'xyz in detail.', | |
'start': 2500, | |
'end': 6500, | |
'strand': 1, | |
'type': 'cds' | |
}, | |
{ | |
'name': 'D', | |
'desc': 'mitf', | |
'start': 7000, | |
'end': 9000, | |
'strand': -1, | |
'type': 'rrna' | |
}, | |
{ | |
'name': 'E', | |
'desc': 'mitf', | |
'start': 9000, | |
'end': 13000, | |
'strand': -1, | |
'type': 'trna' | |
}, | |
{ | |
'name': 'F', | |
'desc': 'mitf', | |
'start': 14000, | |
'end': 20000, | |
'strand': 1, | |
'type': 'ncrna' | |
} | |
] | |
} | |
draw(data, 'svg') | |
tippy('[title]', { | |
performance: true, | |
arrow: true, | |
size: 'large', | |
animation: 'scale', | |
}) | |
}(window, window.d3)) | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment