Skip to content

Instantly share code, notes, and snippets.

@nukadelic
Last active November 12, 2017 16:22
Show Gist options
  • Save nukadelic/6fab5f37e0ef5bd3b367d60da8b7e360 to your computer and use it in GitHub Desktop.
Save nukadelic/6fab5f37e0ef5bd3b367d60da8b7e360 to your computer and use it in GitHub Desktop.
d3 - Transition Easing v4 (24.Oct.2017)
license: mit
<!DOCTYPE html><head><meta charset="utf-8"><script src="https://d3js.org/d3.v4.min.js"></script><link rel="stylesheet" type="text/css" href="style.css"></head><body></body><script>
// //|\ /\ //|\ /\ //|\
//
// Data
//
// \\|/ \/ \\|/ \/ \\|/
var data = ["easeLinear","easeQuadIn","easeCubicIn","easePolyIn","easeSinIn","easeExpIn","easeCircleIn","easeBounceIn","easeBackIn","easeElasticIn","easeQuadOut","easeCubicOut","easePolyOut","easeSinOut","easeExpOut","easeCircleOut","easeBounceOut","easeBackOut","easeElasticOut","easeQuadInOut","easeCubicInOut","easePolyInOut","easeSinInOut","easeExpInOut","easeCircleInOut","easeBounceInOut","easeBackInOut","easeElasticInOut"];
// //|\ /\ //|\ /\ //|\
//
// Variables
//
// \\|/ \/ \\|/ \/ \\|/
var val_w = 600;
var val_h = 500;
var val_row = val_h / data.length;
var val_padding = val_row * 0.2;
var val_radius = val_row * 0.3;
var val_anim = 1700;// animation duration , animation delay = 25% of duration
var val_x1 = 140; // left padding ot avoid collision with text
var val_x2 = val_x1 + ( val_w - val_x1 ) * 0.7; // max easing x pos ( keep's overshooting easings within the screen boudns )
// //|\ /\ //|\ /\ //|\
//
// D3 - canvas
//
// \\|/ \/ \\|/ \/ \\|/
var svg = d3.select('body').append('svg')
.attr('width', val_w)
.attr('height', val_h);
// //|\ /\ //|\ /\ //|\
//
// D3 - attribute functions
//
// \\|/ \/ \\|/ \/ \\|/
function f_getY(d,i)
{
return 2 * ( i + 0.5 ) * ( val_radius + val_padding );
}
var colors = d3.scaleOrdinal(d3.schemeCategory20c ).domain([0,8])
function f_getColor(d, i)
{
// linearEase is white, rest is calculated as groups of 9's
return i===0 ? '#fff' : colors( ((i-2)%9) );
}
// //|\ /\ //|\ /\ //|\
//
// D3 - elemnts creation
//
// \\|/ \/ \\|/ \/ \\|/
var selection_rows = svg
.selectAll('g')
.data( data )
.enter()
.append('g')
.attr('transform', (d,i)=> 'translate(0,' + f_getY(d,i) + ')' );
var selection_rects =
selection_rows.append('rect')
.attr('width', val_w)
.attr('height', (val_radius+val_padding)*2+1)
.attr('y',-val_radius-val_padding);
var selection_lines =
selection_rows.append('line')
.attr('x1', val_x1)
.attr('x2', val_x2);
var selection_texts =
selection_rows.append("text")
.attr('fill',f_getColor )
.attr("dy", ".35em")
.text((d)=>d);
var selection_circles =
selection_rows.append('circle')
.attr('fill',f_getColor )
.attr('cx', val_x1)
.attr('r', val_radius);
// //|\ /\ //|\ /\ //|\
//
// Highlight on mouse move
//
// \\|/ \/ \\|/ \/ \\|/
selection_rows.on('mouseover', function()
{
// ALL: dim, zoom-out, reset radius
selection_rows
.classed('dim', true)
.classed('focus', false)
.select('circle')
.attr('r', val_radius);
// Highlight, zoom in & enlarge radius for any row under mouse
var current = d3.select( this )
.classed('dim', false)
.classed('focus', true)
.select('circle')
.attr('r', val_row * .5);
// Get current selection index
var index = data.indexOf( d3.select( this ).datum() );
// Linear has no In,Out easing combinations
if( index === 0 ) return;
// Highlight, zoom in & enlarge easings of the same group
selection_rows
.filter(function(d,i){
if( i === 0 ) return false;
return (i - index) % 9 === 0;
})
.classed('dim', false)
.classed('focus', true)
.select('circle')
.attr('r', val_row * .5);
});
svg.on('mouseout', ()=> {
d3.selectAll('g')
.classed('dim', false)
.classed('focus', false)
.select('circle')
.attr('r', val_radius);
});
// //|\ /\ //|\ /\ //|\
//
// Transition
//
// \\|/ \/ \\|/ \/ \\|/
var _count = 0;
function animate( value )
{
//console.log( value ); // log's each element datum ( display all transitions )
if( value === 'init' || ++_count === data.length )
{
_count = 0;
// Attempt: #4 ... solved ?
d3.selectAll('circle')
.each(function(d, i) {
d3.select(this)
.transition()
.ease((t)=>d3[d](t))
.duration(val_anim)
.attr('cx', val_x2)
.delay(val_anim*0.25)
.transition()
.ease((t)=>d3[d](t))
.duration(val_anim)
.attr('cx', val_x1)
.delay(val_anim*0.25)
.on("end", animate);
}); // each
}
}
// //|\ /\ //|\ /\ //|\
//
// Start the animation
//
// \\|/ \/ \\|/ \/ \\|/
animate('init');
/*
// ---------------------------------
// Attempt: #1 - doesn't work
function loop()
{
selection_circles
.transition()
.call((s)=>{
console.log( selection ); // error!
s.ease(d3[s.selection().datum()]);
})
.duration(1000)
.attr('cx', val_w - val_radius)
.transition()
.duration(1000)
.attr('cx', val_radius)
.on("end", loop);
}
loop();
// ---------------------------------
// Attempt: #2 - work's but each transition is calling the same function on end resulting in unececerry executions
function loop()
{
selection_circles.each(function(d, i) {
d3.select(this)
.transition()
.ease((t)=>d3[d](t))
.duration(1000)
.attr('cx', val_w - val_radius)
.transition()
.ease((t)=>d3[d](t))
.duration(1000)
.attr('cx', val_radius)
.on("end", loop);
});
}
loop();
// ---------------------------------
// Attempt: #3 - Also works but something tells me this is not how d3 should be handeling selections.
function animate(singleNode)
{
var d = singleNode.datum();
singleNode
.transition()
.ease((t)=>d3[d](t))
.duration(1000)
.attr('cx', val_w - val_radius)
.transition()
.ease((t)=>d3[d](t))
.duration(1000)
.attr('cx', val_radius)
.on("end", endAnimation);
}
var _count = 0;
function endAnimation( ease )
{
if( ++_count === data.length )
{
_count = 0;
loop();
}
}
function loop()
{
selection_circles.each(function(d, i) {
d3.select(this).call(animate);
});
}
loop();
*/
</script>
html, body {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
body {
background-color: #2a2129;
display: flex;
align-items: center;
justify-content: center;
}
svg * { stroke-width: 0; }
svg rect { opacity: 0; }
svg line { stroke-width: 1px;stroke:#333; }
svg circle { stroke-width: 0; }
svg text { font-size: 18px; }
svg g.dim { opacity: 0.2; }
svg g.dim line { stroke-width: 0; }
svg g.focus line { stroke: #666; }
svg g.focus rect { opacity: 0.05;fill:white; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment