What follows is a brute force implementation of displaying running javascript and d3 visualizations in a jekyll post. The methods used here are for illustration. A cleaner approach would be to store all 3rd-party javascript libraries under the site’s /assets
directory and conditionally import the .js
files only in posts that contain a front matter custom variable (e.g. load_d3_libs: true
).
Read more about conditional resource inclusion.
3rd-party libraries may be loaded directly using the <script>
command.
<script src= 'https://d3js.org/d3.v4.min.js' ></script>
<script src= 'https://d3js.org/d3-scale-chromatic.v1.min.js' ></script>
Target deployment element(s) are added to the post.
<div id= "pie" />
In this example, local javascript is pasted directly into the post.
<script type= "text/javascript" >
var keys = [
" Pineapple "
, " Banana "
, " Apple "
, " Orange "
, " Watermelon "
, " Peach " ];
var width = 250 ,
height = 250 ,
radius = Math . min ( width , height ) / 2 ;
var svg = d3 . select ( " #pie " )
. append ( " svg " )
. attr ( " width " , width )
. attr ( " height " , height )
. append ( " g " )
. attr ( " transform " , " translate( " + width / 2 + " , " + height / 2 + " ) " );
svg . append ( " g " ). attr ( " class " , " slices " );
var pie = d3 . pie ()
. sort ( null )
. value ( function ( d ) {
return d . value ;
});
var arc = d3 . arc ()
. outerRadius ( radius * 1.0 )
. innerRadius ( radius * 0.0 );
var outerArc = d3 . arc ()
. innerRadius ( radius * 0.5 )
. outerRadius ( radius * 1 );
var key = function ( d ) { return d . data . label ; };
var color = d3 . scaleOrdinal ( d3 . schemePastel1 )
. domain ( keys );
update ( makeData ());
var inter = setInterval ( function () {
update ( makeData ());
}, 2000 );
function mergeWithFirstEqualZero ( first , second ){
var secondSet = d3 . set ();
second . forEach ( function ( d ) { secondSet . add ( d . label ); });
var onlyFirst = first
. filter ( function ( d ){ return ! secondSet . has ( d . label ) })
. map ( function ( d ) { return { label : d . label , value : 0 }; });
var sortedMerge = d3 . merge ([ second , onlyFirst ])
. sort ( function ( a , b ) {
return d3 . ascending ( a . label , b . label );
});
return sortedMerge ;
}
function makeData () {
var data = Array ();
for ( i = 0 ; i < keys . length ; i ++ ) {
if ( Math . random () < 0.7 ) {
var ob = {};
ob [ " label " ] = keys [ i ];
ob [ " value " ] = randomCount ( 1 , 100 );
data . push ( ob );
}
}
var sortedData = data . sort ( function ( a , b ) {
return d3 . ascending ( a . label , b . label );
});
return sortedData ;
}
function randomCount ( min , max ) {
return Math . floor ( Math . random () * ( max - min + 1 )) + min ;
}
function update ( data ) {
var duration = 500 ;
var oldData = svg . select ( " .slices " )
. selectAll ( " path " )
. data (). map ( function ( d ) { return d . data });
if ( oldData . length == 0 ) oldData = data ;
var was = mergeWithFirstEqualZero ( data , oldData );
var is = mergeWithFirstEqualZero ( oldData , data );
var slice = svg . select ( " .slices " )
. selectAll ( " path " )
. data ( pie ( was ), key );
slice . enter ()
. insert ( " path " )
. attr ( " class " , " slice " )
. style ( " fill " , function ( d ) { return color ( d . data . label ); })
. each ( function ( d ) {
this . _current = d ;
});
slice = svg . select ( " .slices " )
. selectAll ( " path " )
. data ( pie ( is ), key );
slice . transition ()
. duration ( duration )
. attrTween ( " d " , function ( d ) {
var interpolate = d3 . interpolate ( this . _current , d );
var _this = this ;
return function ( t ) {
_this . _current = interpolate ( t );
return arc ( _this . _current );
};
});
slice = svg . select ( " .slices " )
. selectAll ( " path " )
. data ( pie ( data ), key );
slice . exit ()
. transition ()
. delay ( duration )
. duration ( 0 )
. remove ();
};
</script>
Reference