Created
November 22, 2016 15:23
-
-
Save srt19170/06a032e541cb4208a3e47a64f7b4687c to your computer and use it in GitHub Desktop.
Hand-Drawn Lines Code (Javascript)
This file contains hidden or 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
// | |
// Draw a line with the given curve, and then resample it | |
// to a new set of points. <step> is the distance to step | |
// along the line when taking a new point. | |
// | |
function drawInterpolate(svg, points, step, curve) { | |
curve = curve || d3.curveCatmullRom.alpha(1.0); | |
step = step || 1; | |
var lineFunc = d3.line() | |
.curve(curve) | |
.x(function(d) {return d[0]; }) | |
.y(function(d) {return d[1];}); | |
// Draw line | |
var path = svg.append('path') | |
.attr('d', lineFunc(points)) | |
.style("stroke-linecap", "round") | |
.style("stroke-width", 1) | |
.style("stroke", "black"); | |
// Go through and find points corresponding to the line | |
var results = []; | |
var len = path.node().getTotalLength(); | |
for(var cur = 0;cur<len;cur += step) { | |
var pt = path.node().getPointAtLength(cur); | |
results.push([pt.x, pt.y]); | |
}; | |
// Remove the line now that we've measured it. | |
path.remove(); | |
return results; | |
}; | |
// | |
// "Jiggle" a series of line segments by the given magnitude. | |
// | |
function handDrawn(points, magnitude) { | |
magnitude = magnitude || 0.003; | |
// If we have a very short line, it sometimes resamples down to | |
// nothing. In this case, we can just return the original line. | |
if (points.length < 2) return result; | |
// Compute the gradients. | |
var gradients = points.map(function (a, i, d) { | |
if (i == 0) return [d[1][0] - d[0][0], d[1][1] - d[0][1]]; | |
if (i == points.length - 1) | |
return [d[i][0] - d[i - 1][0], d[i][1] - d[i - 1][1]]; | |
return [0.5 * (d[i + 1][0] - d[i - 1][0]), | |
0.5 * (d[i + 1][1] - d[i - 1][1])]; | |
}); | |
// Normalize the gradient vectors to be unit vectors. | |
gradients = gradients.map(function (d) { | |
var len = Math.sqrt(d[0] * d[0] + d[1] * d[1]); | |
if (len == 0) return [0, 0]; | |
return [d[0] / len, d[1] / len]; | |
}); | |
// Generate some perturbations. | |
var perturbations = smoothLine(points.map(d3.randomNormal()), 3); | |
// Add in the perturbations. We keep the first and last point | |
// unchanged so that we know line segments will be able to match | |
// up precisely. | |
var result = points.slice(1,-1).map(function (d, i) { | |
// Need i+1 here because we sliced off [0] | |
var p = perturbations[i+1], | |
g = gradients[i+1]; | |
return [d[0] + magnitude * g[1] * p, | |
d[1] - magnitude * g[0] * p]; | |
}); | |
// add first element and last element back | |
result.unshift(points[0]); | |
result.push(points[points.length-1]); | |
return result; | |
} | |
// | |
// This routine creates a smooth polyline of the given width | |
// and color. Points is an array of [x, y] values. | |
// | |
function drawLine(svg, points, width, color) { | |
if (points.length < 2) return null; | |
var lineFunc = d3.line() | |
.curve(d3.curveCatmullRom.alpha(1.0)) | |
.x( function(d) {return d[0]; }) | |
.y(function(d) {return d[1];}); | |
var g = svg.append('g'); | |
return g.append('path') | |
.attr('d', lineFunc(points)) | |
.style("stroke-linecap", "round") | |
.style("stroke-width", width) | |
.style("stroke", color); | |
}; | |
// | |
// This routine draws a polyline of the given width | |
// and color, with added "jiggle". Note that I'm using | |
// hard-coded domain and magnitude values that work for me. | |
// | |
function drawLineHnd(svg, points, width, color, step, magnitude) { | |
magnitude = magnitude || 0.003; | |
step = step || 1; | |
if (points.length < 2) return null; | |
var p = drawInterpolate(svg, points, step); | |
p = handDrawn(p, magnitude); | |
return drawLine(svg, p, width, color); | |
}; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment