This is a simplified version of Elijah Meeks' Divided Line II block
that uses a d3 threshold scale instead of a custom parameters
function. The dividedLine
function takes an aesthetic
function as a parameter, which unpacks an attribute of the point object (y
, in this case) and applies the scale.
Last active
June 7, 2016 15:34
-
-
Save mimno/93337b5bd77d4217d0869b5b58c45243 to your computer and use it in GitHub Desktop.
Divided Lines from a Scale
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
<html> | |
<head> | |
<title>Divided Lines from a scale</title> | |
<meta charset="utf-8" /> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js"></script> | |
</head> | |
<style> | |
svg { | |
height: 500px; | |
width: 500px; | |
border: 1px solid gray; | |
} | |
path { | |
fill: none; | |
stroke-width: 5; | |
} | |
</style> | |
<body> | |
<div id="viz"> | |
<svg class="main"> | |
</svg> | |
</div> | |
</body> | |
<footer> | |
<script> | |
function dividedLine(aesthetic, points) { | |
var currentAesthetic = aesthetic(points[0]); | |
var currentPointsArray = []; | |
dividedLinesData = [{ aesthetic: currentAesthetic, points: currentPointsArray }]; | |
points.forEach(function (point, i) { | |
var newAesthetic = aesthetic(point) | |
if (newAesthetic === currentAesthetic) { | |
currentPointsArray.push(point); | |
} | |
else { | |
var lastPoint = currentPointsArray[currentPointsArray.length - 1]; | |
var pointA = lastPoint; | |
var pointB = point; | |
for (var x = 0; x < 10; x++) { | |
var findPoints = simpleSearchFunction(pointA, pointB, currentAesthetic, aesthetic); | |
pointA = findPoints[0]; | |
pointB = findPoints[1]; | |
} | |
currentPointsArray.push(pointB); | |
currentPointsArray = [pointB, point]; | |
dividedLinesData.push({ aesthetic: newAesthetic, points: currentPointsArray}); | |
currentAesthetic = newAesthetic; | |
} | |
}); | |
return dividedLinesData.filter(function (d) {return d.points.length > 1}); | |
} | |
function simpleSearchFunction(pointA, pointB, current, aesthetic) { | |
var pointCX = (pointA.x + pointB.x) / 2; | |
var pointCY = (pointA.y + pointB.y) / 2; | |
if (aesthetic({x: pointCX, y: pointCY}) === current) { | |
return [{x: pointCX, y: pointCY}, pointB]; | |
} | |
return [pointA, {x: pointCX, y: pointCY}]; | |
} | |
function randomLineGenerator(width, height, points) { | |
var pointDataSet = [] | |
var curY = 0.5 | |
for (var x = 0; x< points; x++) { | |
curY += Math.random() * 0.3 - 0.15; | |
curY = Math.max(curY, 0.05) | |
curY = Math.min(curY, 0.95) | |
pointDataSet.push({ x: x / points * width, y: curY * height }) | |
} | |
return pointDataSet | |
} | |
var lineData = randomLineGenerator(500,500,100); | |
var meanY = d3.mean(lineData, function (d) { return d.y; }); | |
var meanThreshold = d3.scale.threshold().domain([ meanY ]).range(["#ef8a62", "#67a9cf"]); | |
var yValue = function (d) { return meanThreshold(d.y); } | |
var line = d3.svg.line() | |
.x(function (d) {return d.x}) | |
.y(function (d) {return d.y}) | |
.interpolate("basis") | |
var dLineData = dividedLine(yValue, lineData); | |
var color = d3.scale.category20() | |
d3.select("svg") | |
.selectAll("path.segment") | |
.data(dLineData) | |
.enter() | |
.append("path") | |
.attr("d", function (d) { return line(d.points); } ) | |
.style("stroke", function (d) { return d.aesthetic; } ); | |
</script> | |
</footer> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment