Create a gist now

Instantly share code, notes, and snippets.

@abernier /README.md
Last active May 22, 2018

Embed
What would you like to do?
Scribble.js

Trace SVG paths.

INSTALL

npm install https://gist.github.com/abernier/e082a201b0865de1a41f/archive/42f199f7137d4e5137b4e2f879f58db2c213d8c9.tar.gz

or

<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<script src="https://rawgit.com/tweenjs/tween.js/v16.3.4/src/Tween.js"></script>
<script src="https://rawgit.com/caolan/async/v1.5.2/dist/async.js"></script>
<script src="https://rawgit.com/abernier/e082a201b0865de1a41f/raw/69eeade18397b8ac525e5d022b4876d98d838ccb/index.js"></script>

USAGE

see: https://gist.github.com/abernier/e082a201b0865de1a41f#file-index-html-L31

<!DOCTYPE html>
<html class="no-js">
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,initial-scale=1,user-scalable=no">
<style>
html, body {height:100%;}
html {display:table; width:100%;}
body {display:table-cell; vertical-align:middle;}
svg {max-height:100vh; max-width:100vw;}
</style>
</head>
<body>
<svg viewBox="0 0 60.769 13.233" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M60.197,11.462c-0.42,0.636-0.96,1.271-2.447,1.271 c-1.332,0-2.471-1.08-2.471-2.507v-3.13c0-1.391,1.139-2.471,2.471-2.471c1.355,0,2.519,1.08,2.519,2.471v1.559h-4.978"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M51.187,12.613c-0.684,0-1.259-0.42-1.259-1.307V0.62"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M40.664,0.62v11.993V0.62z M40.675,10.263 c0,1.391,1.127,2.471,2.459,2.471c1.331,0,2.458-1.08,2.458-2.471V7.096c0-1.391-1.127-2.471-2.458-2.471 c-1.332,0-2.471,1.08-2.471,2.471L40.675,10.263z"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M31.171,0.62v11.993V0.62z M31.183,10.263 c0,1.391,1.127,2.471,2.459,2.471c1.331,0,2.458-1.08,2.458-2.471V7.096c0-1.391-1.127-2.471-2.458-2.471 c-1.332,0-2.471,1.08-2.471,2.471L31.183,10.263z"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M26.492,1.16V0.62V1.16z M26.492,12.613V4.686V12.613z"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M19.352,6.233c0.228-0.875,0.935-1.607,1.919-1.607 c0.551,0,0.899,0.324,1.127,0.792 M19.352,4.686v7.928V4.686z"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M15.605,10.263c0,1.391-1.127,2.471-2.458,2.471 c-1.332,0-2.471-1.08-2.471-2.471V7.096c0-1.391,1.139-2.471,2.471-2.471c1.331,0,2.458,1.08,2.458,2.471"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M6.449,3.366C6.232,1.399,5.129,0.5,3.57,0.5 c-1.571,0-2.962,1.211-2.962,2.818c0,1.248,0.54,1.655,1.547,2.255L4.854,7.18c1.163,0.696,1.763,1.235,1.763,2.687 c0,1.607-1.463,2.867-3.046,2.867c-1.751,0-3.07-1.259-3.07-2.927"/>
</svg>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<script src="https://rawgit.com/tweenjs/tween.js/v16.3.4/src/Tween.js"></script>
<script src="https://rawgit.com/caolan/async/v1.5.2/dist/async.js"></script>
<script src="index.js"></script>
<script>
(function () {
var svg = document.querySelector('svg');
function onload() {
console.log('onload');
var paths = svg.querySelectorAll('path');
var scribble = new Scribble(paths, {duration: 3000});
scribble.erase();
scribble.draw(function () {
console.log('scribbled!'); // done
});
}
svg.addEventListener('load', onload, false);
function animate() {
TWEEN.update();
requestAnimationFrame(animate);
}
animate();
}).call(this);
</script>
</body>
</html>
(function () {
var _ = this._ || require('underscore');
var TWEEN = this.TWEEN || require('tween');
var async = this.async || require('async');
// see: http://jakearchibald.com/2013/animated-line-drawing-svg/
function Path(el, options) {
options || (options = {});
_.defaults(options, {
duration: 1000
});
this.options = options;
this.el = el;
var length = el.getTotalLength();
this.length = length;
// Set up the starting positions
el.style.strokeDasharray = length + ' ' + length;
el.style.strokeDashoffset = length;
this.update(1);
}
Path.prototype.update = function (val) {
this.val = val;
};
Path.prototype.paint = function () {
this.el.style.strokeDashoffset = this.length * (1 - this.val);
};
Path.prototype.start = function (cb) {
this.tween && this.tween.stop();
var o = {t: 0};
this.tween = new TWEEN.Tween(o).to({t: 1}, this.options.duration)
.onUpdate(function () {
this.update(o.t);
this.paint();
}.bind(this))
.onComplete(function () {
//console.log('complete');
cb(null);
})
.start()
;
};
Path.prototype.stop = function () {
this.tween && this.tween.stop();
};
Path.prototype.erase = function () {
this.stop();
this.tween = undefined;
this.update(0);
this.paint();
};
function Scribble(pathsEls, options) {
options || (options = {});
_.defaults(options, {
duration: 2000,
durationPerPath: false
});
this.options = options;
var paths = []; this.paths = paths;
var arr = []; this.arr = arr;
var i = pathsEls.length;
var totalLength = 0;
while(i--) {
var path = new Path(pathsEls[i], {duration: this.options.duration});
paths.push(path);
arr.push(path.start.bind(path));
totalLength += path.length;
}
// normalize duration
if (this.options.durationPerPath !== true) {
var totalDuration = this.options.duration;
var i = pathsEls.length;
while (i--) {
var path = paths[i];
var percent = paths[i].length / totalLength;
//if (percent > 2*1/pathsEls.length) continue;
paths[i].options.duration = percent * totalDuration;
}
}
var drawing = false;
}
Scribble.prototype.draw = function (cb) {
if (this.drawing) return;
this.drawing = true;
async.series(this.arr, cb); // https://github.com/caolan/async#seriestasks-callback
};
Scribble.prototype.erase = function () {
this.paths.forEach(function (path) {
path.erase();
});
this.drawing = false;
};
// Exports
this.Scribble = Scribble;
if (typeof module !== "undefined" && module !== null) {
module.exports = this.Scribble;
}
}).call(this);
{
"name": "scribble",
"version": "1.0.0",
"description": "scribble SVG paths",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://gist.github.com/e082a201b0865de1a41f.git"
},
"author": "Antoine BERNIER",
"license": "ISC",
"dependencies": {
"async": "^1.4.0",
"tween": "^0.9.0",
"underscore": "^1.8.3"
}
}
@marijnhosten

This comment has been minimized.

Show comment
Hide comment
@marijnhosten

marijnhosten Apr 28, 2016

Would you happen to have the path data values for the each letter?

update: I found another library that tranforms text in svg paths, combined it with your animations for a nice result, thanks! :)

marijnhosten commented Apr 28, 2016

Would you happen to have the path data values for the each letter?

update: I found another library that tranforms text in svg paths, combined it with your animations for a nice result, thanks! :)

@zhongguogu

This comment has been minimized.

Show comment
Hide comment
@zhongguogu

zhongguogu May 22, 2018

@abernier how to reset the path after Animation. thank you very much! Waiting for your reply.

@abernier how to reset the path after Animation. thank you very much! Waiting for your reply.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment