Skip to content

Instantly share code, notes, and snippets.

@eesur
Last active May 23, 2017 11:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eesur/c2e3e7aa916038da8995e0c388b2949b to your computer and use it in GitHub Desktop.
Save eesur/c2e3e7aa916038da8995e0c388b2949b to your computer and use it in GitHub Desktop.
d3 | path animation
function drawLine(data, path1, path2) {
// the line accessor function
var line = d3.line()
.x(function (d) { return d.x; })
.y(function (d) { return d.y; })
.curve(d3.curveLinear)
d3.select(path1)
.datum(data)
.transition()
.duration(2000)
.attr('d', line)
d3.select(path2)
.datum(data)
.transition()
.duration(2000)
.attrTween('d', function (d) {
// console.log(d)
var previous = d3.select(this).attr('d')
var current = line(d)
// console.log(current)
// d3.select('#path-data').text(current)
return d3.interpolatePath(previous, current)
})
d3.select('#path-data').text(line(data))
}
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("d3-interpolate")):"function"==typeof define&&define.amd?define(["exports","d3-interpolate"],t):t(e.d3=e.d3||{},e.d3)}(this,function(e,t){"use strict";function n(e){e=e.trim().replace(/ /g,",");var t=e[0],n=e.substring(1).split(",");return l[t.toUpperCase()].reduce(function(e,t,r){return e[t]="x"===t?parseFloat(n[r]):n[r],e},{type:t})}function r(e){var t=e.type,n=l[t.toUpperCase()];return""+t+n.map(function(t){return e[t]}).join(",")}function a(e,t){var n={x1:"x",y1:"y",x2:"x",y2:"y"},r=["xAxisRotation","largeArcFlag","sweepFlag"];return e.type!==t.type&&"M"!==t.type.toUpperCase()&&!function(){var a={};Object.keys(t).forEach(function(i){var o=t[i],p=e[i];void 0===p&&(r.includes(i)?p=o:(void 0===p&&n[i]&&(p=e[n[i]]),void 0===p&&(p=0))),a[i]=p}),a.type=t.type,e=a}(),e}function i(e,t,n){var r=void 0;r=e.length>1&&"M"===e[0].type?1:0;for(var a=t.reduce(function(t,n,a){if(0===a&&"M"===n.type)return t[0]=1,t;for(var i=Math.abs(e[r].x-n.x),o=r,p=r+1;p<e.length;p++){var l=Math.abs(e[p].x-n.x);if(!(l<i))break;i=l,o=p}return t[o]=(t[o]||0)+1,t},{}),i=[],o=0,l=0;l<e.length;l++){i.push(e[l]);for(var u=1;u<a[l]&&o<n;u++){var y=p({},e[l]);"M"===y.type?y.type="L":(void 0!==y.x1&&(y.x1=y.x,y.y1=y.y),void 0!==y.x2&&(y.x2=y.x,y.y2=y.y)),i.push(y),o+=1}}return i}function o(e,o){var p=null==e?"":e.replace(/[Z]/gi,"").replace(/([MLCSTQAHV])\s*/gi,"$1"),l=null==o?"":o.replace(/[Z]/gi,"").replace(/([MLCSTQAHV])\s*/gi,"$1"),u=""===p?[]:p.split(/(?=[MLCSTQAHV])/gi),y=""===l?[]:l.split(/(?=[MLCSTQAHV])/gi);if(!u.length&&!y.length)return function(){return""};u.length?y.length||y.push(u[0]):u.push(y[0]);var c=u.map(n),x=y.map(n),f=Math.abs(y.length-u.length);0!==f&&(x.length>c.length?c=i(c,x,f):x.length<c.length&&(x=i(x,c,f))),c=c.map(function(e,t){return a(e,x[t])});var s=c.map(r).join(""),g=x.map(r).join("");null!=e&&"Z"!==e[e.length-1]||null!=o&&"Z"!==o[o.length-1]||(s+="Z",g+="Z");var h=t.interpolateString(s,g);return function(e){return 1===e?null==o?"":o:h(e)}}var p=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},l={M:["x","y"],L:["x","y"],H:["x"],V:["y"],C:["x1","y1","x2","y2","x","y"],S:["x2","y2","x","y"],Q:["x1","y1","x","y"],T:["x","y"],A:["rx","ry","xAxisRotation","largeArcFlag","sweepFlag","x","y"]};e.interpolatePath=o,Object.defineProperty(e,"__esModule",{value:!0})});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- http://www.basscss.com/ -->
<link href="//npmcdn.com/basscss@8.0.2/css/basscss.min.css" rel="stylesheet">
<!-- http://clrs.cc/ -->
<link href="//s3-us-west-2.amazonaws.com/colors-css/2.2.0/colors.min.css" rel="stylesheet">
<style>
body {
font-family: Consolas, monaco, monospace;
background: #dfe0e2;
color: #2f292b;
}
path {
fill: none;
stroke: #f45844;
stroke-width: 2;
}
</style>
</head>
<body>
<section>
<h1 class="h5 caps">standard</h1>
<svg width="960" height="200">
<g translate="transform(10, 10)">
<path id="path-normal"></path>
</g>
</svg>
</section>
<hr>
<section>
<h1 class="h5 caps">using interpolate</h1>
<svg width="960" height="200">
<g translate="transform(10, 10)">
<path id="path-interpolate"></path>
</g>
</svg>
</section>
<hr>
<footer>
<h1 class="h5 caps">svg path: (same for both)</h1>
<p id="path-data"></p>
</footer>
<script src="//d3js.org/d3.v4.min.js" charset="utf-8"></script>
<script src="d3-interpolate-path.min.js" charset="utf-8"></script>
<!-- d3 code -->
<script src=".script-compiled.js" charset="utf-8"></script>
<!-- render code -->
<script>
// create array of random objects for line data
function data() {
let _data = d3.range(Math.floor(d3.randomUniform(10, 90)()))
.map(function(n, i) {
return {
'x': i *10, // constrain x
'y': Math.floor(d3.randomUniform(200)()) }
})
// console.info(_data)
return _data
}
drawLine('#path', data())
d3.interval(function() {
return drawLine(data(), '#path-normal', '#path-interpolate')
}, 3000)
d3.select(self.frameElement).style('height', '670px');
</script>
</body>
</html>
function drawLine(data, path1, path2) {
// the line accessor function
const line = d3.line()
.x(d => d.x)
.y(d => d.y)
.curve(d3.curveLinear)
d3.select(path1)
.datum(data)
.transition()
.duration(2000)
.attr('d', line)
d3.select(path2)
.datum(data)
.transition()
.duration(2000)
.attrTween('d', function (d) {
// console.log(d)
let previous = d3.select(this).attr('d')
let current = line(d)
// console.log(current)
// d3.select('#path-data').text(current)
return d3.interpolatePath(previous, current)
})
d3.select('#path-data').text(line(data))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment