D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
GeneExplorer
Full window
Github gist
Gene Map
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <style> body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } polygon:hover { stroke: pink; stroke-width: 7px; } rect:hover { stroke: cyan; stroke-width: 3px; } text:hover { stroke: lightgray; } </style> </head> <body> <script> var Orientation = { FORWARD: 1, REVERSE: 2, BACKWARD: 2, // Alias for REVERSE }; // Object Constructors function Point(x = 0, y = 0) { this.x = x; this.y = y; } function GeneArrow(name, offset, width, height, orientation) { // GeneArrow object attributes. this.name = name; this.offset = offset; this.width = width; this.height = height; this.orientation = orientation; if (orientation == Orientation.FORWARD) this.color = "blue"; else this.color = "red"; this.arrowHeadPercentWidth = 30.0; // Default arrow head % width this.arrowHeadPercentHeight = 80.0; // Default arrow head % height this.arrowBodyPercentHeight = 40.0; // Default arrow body % height this.showTickMarks = false; this.tickMarks = []; // GeneArrow object functions. this.points = function() { // Create the arrow shape using 7 points. var oX = this.offset.x; var oY = this.offset.y; var w = this.width; var h = this.height; var x1 = oX; var x2 = oX + (1.0 - (this.arrowHeadPercentWidth / 100)) * w; var x3 = oX + w; var x4 = oX + (this.arrowHeadPercentWidth / 100) * w; var y1 = oY + (0.5 - (this.arrowHeadPercentHeight / 100)/2) * h; var y2 = oY + (0.5 - (this.arrowBodyPercentHeight / 100)/2) * h; var y3 = oY + 0.5 * h; var y4 = oY + (0.5 + (this.arrowBodyPercentHeight / 100)/2) * h; var y5 = oY + (0.5 + (this.arrowHeadPercentHeight / 100)/2) * h; if (orientation == Orientation.FORWARD) { return [ new Point(x1, y4), new Point(x2, y4), new Point(x2, y5), new Point(x3, y3), new Point(x2, y1), new Point(x2, y2), new Point(x1, y2) ]; } else // Arrow going backwards. { return [ new Point(x1, y3), new Point(x4, y5), new Point(x4, y4), new Point(x3, y4), new Point(x3, y2), new Point(x4, y2), new Point(x4, y1) ]; } } this.nameTagLocation = function() { var xCoord = offset.x + (0.5 * width) - (this.name.length*5); var yCoord = offset.y + (0.5 * height) + 5; return new Point(xCoord, yCoord); } } function drawGeneArrow(geneArrow, svgWidth, rangeX) { var polygon = svg.append("polygon"); var pointData = ""; var p = geneArrow.points(); for (var i = 0; i < p.length; i++) { pointData += p[i].x + "," + p[i].y + " "; } polygon.attr("points", pointData); polygon.attr("fill", geneArrow.color); polygon.attr("stroke", "black"); polygon.append("title").text(geneArrow.name); // Tooltip shows gene name. if (geneArrow.showTickMarks == true) { var t = geneArrow.tickMarks; for (var j = 0; j < t.length; j++) { var rect = svg.append("rect"); var tickMarkHeight = geneArrow.height * (geneArrow.arrowBodyPercentHeight / 100) * 1.4; var tickMarkX = t[j] * svgWidth / rangeX; var tickMarkY = geneArrow.offset.y + (geneArrow.height / 2) - (tickMarkHeight / 2); rect.attr("x", tickMarkX).attr("y", tickMarkY) .attr("width", 6).attr("height", tickMarkHeight) .attr("fill", "green"); var bpTag = svg.append("text"); var bpTagX = tickMarkX; var bpTagY = tickMarkY - 5; bpTag.text(t[j]) .attr("x", bpTagX) .attr("y", bpTagY) .style("font-size", 12) .style("font-family", "Verdana"); } } var nameTag = svg.append("text"); var nameTagLocation = geneArrow.nameTagLocation(); nameTag.text(geneArrow.name) .attr("x", nameTagLocation.x) .attr("y", nameTagLocation.y) .style("font-size", 20) .style("font-family", "Verdana"); } // Create the svg canvas. var svgWidth = 960; var svgHeight = 600; var svg = d3.select("body").append("svg").attr("width", svgWidth).attr("height", svgHeight); // Load and draw gene data. d3.json("data.json", function(error, data) { if (error) console.warn(error); else console.log(data); var geneArrows = []; var genes = data.genes; var arrowYOffset = 120; var arrowHeight = 120; var minX = 1000000; var maxX = -1; for (var i = 0; i < genes.length; i++) { var name = '' + genes[i].name; var start = genes[i].start; var stop = genes[i].stop; if (genes[i].orientation == "forward") var orientation = Orientation.FORWARD; else var orientation = Orientation.REVERSE; var offset = new Point(start, arrowYOffset); var arrowWidth = stop - start; var geneArrow = new GeneArrow(name, offset, arrowWidth, arrowHeight, orientation); geneArrow.tickMarks.push(start); geneArrow.tickMarks.push(stop); geneArrow.showTickMarks = true; if (start < minX) minX = start; if (stop > maxX) maxX = stop; geneArrows.push(geneArrow); } // Normalize distances so that all gene data fits on the screen. var svgWidth = 960; var bufferPercentage = 16.0; // Add some buffer space at the right margin. var rangeX = (maxX - minX) * (1 + (bufferPercentage / 100)); // Draw the dna sequence bar. var dnaSequenceBarStartLocation = new Point(0, 220); var dnaSequenceBar = new GeneArrow("dna sequence bar", dnaSequenceBarStartLocation, svgWidth, 100, Orientation.FORWARD); dnaSequenceBar.color = "orange"; dnaSequenceBar.arrowHeadPercentWidth = 3; dnaSequenceBar.arrowHeadPercentHeight = 40; // Add interval tick marks. var showIntervalTickMarks = true; if (showIntervalTickMarks) { dnaSequenceBar.showTickMarks = true; var intervalBasePairs = 50; for (var k = 0; k < svgWidth; k += intervalBasePairs) { dnaSequenceBar.tickMarks.push(k); } } drawGeneArrow(dnaSequenceBar, svgWidth, rangeX); // Draw all the gene arrows. for (i = 0; i < genes.length; i++) { geneArrows[i].offset.x = geneArrows[i].offset.x * svgWidth / rangeX; geneArrows[i].width = geneArrows[i].width * svgWidth / rangeX; drawGeneArrow(geneArrows[i], svgWidth, rangeX); } }); </script> </body>
https://d3js.org/d3.v4.min.js