Reusable Bumpchart

by ramnathv

HTML

<script src="//rawgit.com/ramnathv/9a84e7c70d2998aac784/raw/34e80c398a8b53cf297c03052eb161d8f609168b/soccerData.js"></script>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//rawgit.com/kristw/75b61f9beeab9b530612/raw/389e984e4041117a9185cf6edad9f6b85a38097a/d3kit.min.js"></script>
<script src="//rawgit.com/gka/d3-jetpack/master/d3-jetpack.js"></script>
<script src="//rawgit.com/Caged/d3-tip/master/index.js"></script>
<link rel="stylesheet" href="//rawgit.com/Caged/d3-tip/master/examples/example-styles.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="//keen.github.io/dashboards/assets/css/keen-dashboards.css">
<script src="//rawgit.com/DarkMarmot/kodama/master/kodama.js"></script>
<script src="//rawgit.com/ramnathv/a5a3199538f86817ec1b/raw/f6627fc544e65d8e6186ba87556f743caa3f2730/visutils.js"></script>
<script src="//rawgit.com/ramnathv/618966cca456cbaf30c7/raw/f53525e69fb4d7760df48cdf0ddce1ce96ab49f7/soccerData2.js"></script>
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
    <div class="container-fluid">
      <div class="navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="../">
          <span class="glyphicon glyphicon-chevron-left"></span>
        </a>
        <a class="navbar-brand" href="./">Lap Chart</a>
      </div>
      <div class="navbar-collapse collapse">
        <ul class="nav navbar-nav navbar-left">
          <li><a href="https://keen.io">Home</a></li>
          <li><a href="https://keen.io/team">Team</a></li>
        </ul>
      </div>
   ...

CSS

.line {
  fill: none;
  stroke-opacity: 0.5;
}
.line-hover{
  stroke-opacity: 1;
  stroke-width: 3px;
}
.polygons-layer path{
  fill: none;
  pointer-events: all;
}
.focus-layer{
  pointer-events: none;
}
.line-layer {
  pointer-events: none;
}
.y-axis-layer line,
.y-axis-layer path{
   fill: none;
}
.y-axis2-layer line,
.y-axis2-layer path{
   fill: none;
}
.y-axis-layer text{
  font-size: 10px;
  pointer-events: all;
}
.y-axis2-layer text{
  font-size: 10px;
  pointer-events: all;
}
.y-axis-layer text:hover{
  
}
div.popover{
  pointer-events: none;
}
div[name="kodama"]{
  pointer-events: none;   
}

CoffeeScript

d3k = d3k || {}
d3k.panel = ->
  defaults = 
    panels: ["title", "stage", "notes"]
    title: ""
    stage: ""
    notes: ""

  opts = extend(arguments[0], defaults)
  exports = (selection) ->
    selection.each (data) ->
      panel = d3.select(@)
        .selectAll("div.chart-wrapper")
        .data(data)
      panelEnter = panel.enter()
        .append("div.chart-wrapper")
      opts.panels.forEach (d) ->
         panelEnter
           .append("div.chart-#{d}")
           .html opts[d]

  exports.opts = opts; createAccessors(exports)
  exports

addIcon = (sel, data, name, opts) ->
    pspan = sel.selectAll(name).data(data)
    pspan.enter().append(name)
    cl = name.split("\.")[1]
    pspan.attr
      "class": cl + " " + opts.class
      "data-toggle": "tooltip"
      "data-html": true
      "data-title": opts.title || cl
      "data-placement": opts.placement || "left"
        
addIcon(d3.select(".chart-title"), 
  [{}], 'span.glyphicon-edit', {class: 'glyphicon', title: 'edit'}
)

addIcon(d3.select(".chart-title .pull-right"), 
  [{}], 'span.glyphicon-play', {class: 'glyphicon', title: 'animate'}
)

$("[data-toggle='tooltip']").tooltip()

d3.select(".glyphicon-play").on "click", ->
  line = d3.selectAll(".line")
  line.call(animateChart)

d3.select("body")
  .classed("application", true)
palette = ["#013ADF", "#0099FF", "#B80000", "red", "midnightblue",
    "red",  "#B80000", "black", "crimson", "darkmagenta",
    "blue", "maroon", "navy", "blue", "black",
    "#F80000", "maroon", "orange", "maroon", "dodgerblue"
]

d3.uniq = (data, fun) ->
  if typeof fun is 'function'
    v = data.map(fun)
  else
    v = data.map (d) -> d[fun]
  d3.set(v).values()
    
animateChart = ->
  this.each (d) ->
    p = d3.select(this);
    totalLength = p.node().getTotalLength();
    p
     .attr('stroke-dasharray', totalLength + ' ' + totalLength)
     .attr('stroke-dashoffset', totalLength)
     .transition()
     .duration(2000)
     .ease('linear')
    ...