Created
February 19, 2015 21:17
-
-
Save eswak/35409a9f2ef30f35025d to your computer and use it in GitHub Desktop.
Progressively draw SVG to create a hand drawn effect
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
(function closure () { | |
// progressively draw each <svg> without .no-draw class | |
Array.prototype.forEach.call(document.querySelectorAll('svg:not(.no-draw)'), function(svg) { | |
// animation duration & delay (default values overriden by data attributes) | |
var animationTimeInSeconds = Number(svg.getAttribute('data-draw-time')) || 2; | |
var animationStartDelay = Number(svg.getAttribute('data-draw-start-delay'))*1000 || 0; | |
// init, hide all svgs | |
var totalFrames = animationTimeInSeconds * 60; | |
svg.style.display = 'none'; | |
// start to draw each <svg> after "data-draw-start-delay" (attribute) time (in seconds) | |
setTimeout(function() { | |
svg.style.display = 'inline-block'; | |
svg.id = svg.id || Math.random().toString(36).substring(2); | |
// store paths in an array | |
var paths = Array.prototype.slice.call(document.querySelectorAll('#' + svg.id + ' path')); | |
// for each path | |
paths.forEach(function(path, i) { | |
var handle = 0; | |
var l = path.getTotalLength(); | |
path.style.strokeDasharray = l + ' ' + l; | |
path.style.strokeDashoffset = l; | |
// start to draw them after a delay | |
// ex: if <svg> is composed of 2 paths, and draws in 1s, | |
// path 1 will start to draw immediatly and will be drawn in 500ms, | |
// while path 2 will be drawn between 500ms and 1s | |
setTimeout(function() { | |
drawPath(path, l, 0, totalFrames/paths.length, handle, function() { | |
// add .drawn class to every svg <path> that have been completely drawn | |
path.classList.add('drawn'); | |
if (i === paths.length -1) { | |
// add .all-paths-drawn class to <svg> dom element when all | |
// its paths have been drawn | |
svg.classList.add('all-paths-drawn'); | |
} | |
}); | |
}, i*(animationTimeInSeconds/paths.length)*1000); | |
}); | |
}, animationStartDelay); | |
}); | |
function drawPath(path, pathLength, currentFrame, totalFrames, handle, drawn) { | |
var progress = currentFrame/totalFrames; | |
if (progress > 1) { | |
window.clearTimeout(handle); | |
path.style.strokeDashoffset = 0; | |
drawn && drawn(); | |
} else { | |
currentFrame++; | |
path.style.strokeDashoffset = Math.floor(pathLength * (1 - progress)); | |
handle = window.setTimeout(function() { | |
drawPath(path, pathLength, currentFrame, totalFrames, handle, drawn); | |
}, 1000/60); | |
} | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I found a solution to the "not a valid selector" problem. The thing is, selectors cannot start with a digit. But as it is randomly generated, there is a chance that it will. So you can just add a prefix to avoid this. Like so:
svg.id = svg.id || "something_"+Math.random().toString(36).substring(2);