Simple x-y plot with axes, labels & margins (and a transition). Plot region resizes to fit window.innerHeight.
Last active
December 19, 2015 20:58
-
-
Save pbogden/6016415 to your computer and use it in GitHub Desktop.
fit-to-height x-y plot
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> | |
<html> | |
<head> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"> | |
<link rel="stylesheet" href="styles.css" type="text/css"> | |
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> | |
</head> | |
<body> | |
<script> | |
var defaultWidth = 960, // Default width & height of plot region | |
defaultHeight = 500, | |
defaultMinHeight = 150, | |
padding = 0.1, // fraction to pad maximum of range for y-axis | |
paddedExtent; // padded extent that results from using padding | |
var outerWidth, // dimensions of plot area | |
outerHeight, | |
marginWidth=50, // margins -- the same on all sides | |
strokeWidth=1; // this should be consistent with <style> | |
// viewport <meta> info -- diagnostic only | |
var viewportMeta = document.getElementsByName("viewport").content, // <meta> "content" string | |
viewportWidth = document.documentElement.clientWidth, // *This* gets viewport width | |
viewportHeight = document.documentElement.clientHeight; // *This* gets viewport height | |
var width = (window.innerWidth > 0) ? window.innerWidth : defaultWidth; | |
var height = (window.innerHeight > 0) ? window.innerHeight : defaultHeight; | |
outerWidth = Math.min(defaultWidth,width); | |
outerHeight = Math.min(defaultHeight,height); | |
outerHeight = Math.max(defaultMinHeight,height); | |
// Note: on iPhone in portrait: viewportWidth = window.innerWidth = screen.width = 320 | |
// '' '' landscape: viewportWidth = window.innerWidth = 568 BUT screen.width = 320 | |
// on desktop: screen.width = 1680 > viewportWidth = window.innerWidth (= variable) | |
alert("viewport Width & Height:\n" + viewportWidth + ", " + viewportHeight + "\n" + | |
"window.innerWidth & innerHeight:\n" + window.innerWidth + ", " + window.innerHeight + "\n" + | |
"screen.width & height:\n" + screen.width + ", " + screen.height + "\n" + | |
"width & height for D3:\n" + width + ", " + height); | |
// More plot dimensions (computed from previous) | |
var marginLeft = marginWidth+strokeWidth/2, // leftmost point inside the margins | |
marginTop = marginWidth+strokeWidth/2, // topmost point inside the margins | |
width = outerWidth -2*marginLeft, // width of inner plot area *and* margins | |
height = outerHeight-2*marginTop; // height of inner plot area *and* margins | |
// Eliminate default margin from <body> element | |
document.body.style.margin="0px"; | |
// Check aspect ratio and resize accordingly | |
// TBD | |
var data = [ | |
{x: 0, y: 00}, | |
{x: 1, y: 30}, | |
{x: 2, y: 40}, | |
{x: 3, y: 20}, | |
{x: 4, y: 90}, | |
{x: 5, y: 70} | |
]; | |
function xValue(d) { return d.x; } // accessors for data | |
function yValue(d) { return d.y; } | |
var x = d3.scale.linear() // interpolator for X axis -- inner plot region | |
.domain(d3.extent(data,xValue)) // equivalent to .domain([0,1.1*5]) | |
.range([0,width]); // range is inner plot area (i.e., inside margins) | |
// pads extent of graph above the max y value; makes it easier to select max value w/brush | |
paddedExtent = d3.extent(data,yValue); | |
paddedExtent[1] += padding*(paddedExtent[1]-paddedExtent[0]); | |
var y = d3.scale.linear() // interpolator for Y axis -- inner plot region | |
.domain(paddedExtent) // use the padded yxtent for plotting "y" | |
.range([height,0]); // remember, (0,0) is upper left -- this reverses "y" | |
var svg = d3.svg; | |
var line = svg.line() // SVG line generator | |
.x(function(d) { return x(d.x); } ) | |
.y(function(d) { return y(d.y); } ); | |
var xAxis = svg.axis() // x Axis | |
.scale(x) | |
.ticks(5) // request 5 ticks on the x axis | |
.orient("bottom"); | |
var yAxis = svg.axis() // y Axis | |
.scale(y) | |
.ticks(4) | |
.orient("left"); | |
var svg = d3.select("body").append("svg"); // "svg" points to the SVG node in the DOM | |
svg.attr("width", outerWidth) // SVG domain is the outer plot area (i.e., inner area plus margins) | |
.attr("height", outerHeight); // Note: ok to leave this without units, implied "px" | |
var g = svg.append("g") // <g> element is the inner plot area (i.e., inside the margins) | |
.attr("transform", "translate(" + marginLeft + "," + marginTop + ")"); | |
g.append("g") // render the Y axis in the inner plot area | |
.attr("class", "y axis") | |
.call(yAxis); | |
g.append("g") // render the X axis in the inner plot area | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") // axis runs along lower part of graph | |
.call(xAxis); | |
g.append("text") // inner x-axis label | |
.attr("class", "x label") | |
.attr("text-anchor", "end") | |
.attr("x", width - 6) | |
.attr("y", height - 6) | |
.text("inner x-axis label"); | |
g.append("text") // outer x-axis label | |
.attr("class", "x label") | |
.attr("text-anchor", "end") | |
.attr("x", width/2) | |
.attr("y", height + 2*marginWidth/3 + 6) | |
.text("outer x-axis label"); | |
g.append("text") // inner y-axis label | |
.attr("class", "y label") | |
.attr("text-anchor", "end") | |
.attr("x", -6) | |
.attr("y", 6) | |
.attr("dy", ".75em") | |
.attr("transform", "rotate(-90)") | |
.text("inner y-axis label"); | |
g.append("text") // outer y-axis label | |
.attr("class", "x label") | |
.attr("text-anchor", "middle") | |
.attr("x", -height/2) | |
.attr("y", -6 - marginWidth/3) | |
.attr("dy", "-.75em") | |
.attr("transform", "rotate(-90)") | |
.text("outer y-axis label"); | |
g.append("path") // plot the data as a line | |
.datum(data) | |
.attr("class", "line") | |
.attr("d", line); | |
g.append("rect") // plot a rectangle that encloses the inner plot area | |
.attr("width", width) | |
.attr("width", width) | |
.attr("height", height); | |
svg.append("circle") // plot a circle in the upper left of the SVG element | |
.attr("cx", 0) | |
.attr("cy", 0) | |
.attr("r", 10); | |
svg.append("circle") // plot a circle in the lower right of the SVG element | |
.attr("cx", outerWidth) | |
.attr("cy", outerHeight) | |
.attr("r", 10); | |
g.selectAll(".dot") // plot a circle at each data location | |
.data(data) | |
.enter().append("circle") | |
.attr("class", "dot") | |
.attr("cx", function(d) { return x(d.x); } ) | |
.attr("cy", function(d) { return y(d.y); } ) | |
.attr("r", 5); | |
svg.append("rect") // plot a rectangle that encloses the entire SVG element | |
.attr("x", 0) | |
.attr("y", 0) | |
.attr("width", outerWidth) | |
.attr("height", outerHeight); | |
d3.selectAll("path").transition() // data transition | |
.style("stroke", "steelblue") | |
.delay(1000) | |
.duration(2000); | |
</script> | |
</body> | |
</html> | |
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
.line { | |
fill: none; | |
stroke: white; // starts invisible, made visible with transition | |
stroke-width: 1px; // half is inside the margin, half is outside | |
} | |
rect { | |
fill: none; | |
stroke: black; | |
stroke-width: 1px; // half is inside the margin, half is outside | |
} | |
.axis path, .axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
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
<svg width="400px" height="300px" viewBox="0 0 400 300" | |
xmlns="http://www.w3.org/2000/svg"> | |
<desc>This example uses the 'switch' element to provide a | |
fallback graphical representation of a paragraph, if | |
XHTML is not supported.</desc> | |
<!-- The 'switch' element will process the first child element | |
whose testing attributes evaluate to true.--> | |
<switch> | |
<!-- Process the embedded XHTML if the requiredExtensions attribute | |
evaluates to true (i.e., the user agent supports XHTML | |
embedded within SVG). --> | |
<foreignObject width="100" height="50" | |
requiredExtensions="http://www.w3.org/1999/xhtml"> | |
<!-- XHTML content goes here --> | |
<body xmlns="http://www.w3.org/1999/xhtml"> | |
<p>Here is a paragraph that requires word wrap</p> | |
</body> | |
</foreignObject> | |
<!-- Else, process the following alternate SVG. | |
Note that there are no testing attributes on the 'text' element. | |
If no testing attributes are provided, it is as if there | |
were testing attributes and they evaluated to true.--> | |
<text font-size="10" font-family="Verdana"> | |
<tspan x="10" y="10">Here is a paragraph that</tspan> | |
<tspan x="10" y="20">requires word wrap.</tspan> | |
</text> | |
</switch> | |
</svg> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment