block by vicapow 9904319

Sparklines with Angular and D3

Full Screen

An example of how to create your own sparkline dirctive in AngularJS using replace and transclude

This is a code excerpt from the book D3 on Angular. http://leanpub.com/d3angularjs

index.html

<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
  <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <style>
  html, body{
    width: 100%;
    height: 100%;
    font-size: 1em;
  }
  .sl {
    display: inline-block;
    width: 10em;
    vertical-align: middle;
    stroke: black;
    stroke-width: 1;
  }
  .sl path{
    fill: none;
  }
  .sl circle{
    fill: red;
  }
  .large{
    margin: 0;
    font-size: 3em;
  }
  </style>
</head>
<body ng-app="app">
  <p>so this is a spark line <sl style="stroke: red; width: 2em">[10,40,20,50,80]</sl>. Pretty cool, right?</p>
  <p>here's another <sl r="1" style="stroke:blue; width: 2em">[10,20,30]</sl></p>
  <p>here's a longer example <sl r="1" style="stroke:blue; width:3em">[20,24,20,27,29,50,90]</sl></p>
  <p>an even longer example <sl r="1" style="stroke:green;">[20,24,20,500,29,50,90, 20, 10, 40]</sl></p>
  <p> lets look at a few in a row. </p>
  <p>
    <sl r="1" style="stroke:green">[20,24,20,500,29,50,90, 20, 10, 40]</sl><br>
    <sl r="1" style="stroke:green">[20,24,30,400,29,50,90, 20, 10, 40]</sl><br>
    <sl r="1" style="stroke:green">[20,24,25,300,29,50,90, 20, 10, 40]</sl><br>
    <sl r="1" style="stroke:green">[20,24,21,200,29,50,90, 20, 10, 40]</sl><br>
    <sl r="1" style="stroke:green">[20,24,23,100,29,50,90, 20, 10, 40]</sl>
  </p>
  <p> here's the same data but with consistent scales. </p>
  <p>
    <sl r="1" style="stroke:green" min="0" max="500">[20,24,20,500,29,50,90, 20, 10, 40]</sl><br>
    <sl r="1" style="stroke:green" min="0" max="500">[20,24,30,400,29,50,90, 20, 10, 40]</sl><br>
    <sl r="1" style="stroke:green" min="0" max="500">[20,24,25,300,29,50,90, 20, 10, 40]</sl><br>
    <sl r="1" style="stroke:green" min="0" max="500">[20,24,21,200,29,50,90, 20, 10, 40]</sl><br>
    <sl r="1" style="stroke:green" min="0" max="500">[20,24,23,100,29,50,90, 20, 10, 40]</sl>
  </p>
  <p class="large">
    "But what if my font is big?"<sl style="stroke-width:2px; width:2em">[1, 2, 3, 5, 6, 9, 20, 30, 40, 20, 10]</sl> you ask?
  </p>
</body>
<script>
var app = angular.module('app', []);

app.directive('sl', function(){
  function link(scope, el, attr){
    el = d3.select(el[0]);
    var svg = el;
    var data = JSON.parse(el.text());
    var min = attr.min !== undefined ? +attr.min : d3.min(data);
    var max = attr.max !== undefined ? +attr.max : d3.max(data);
    el.text(''); // remove the original data text
    var r = attr.r || 0;
    var m = r;
    var w = svg.node().clientWidth;
    var h = +getComputedStyle(el.node())['font-size'].replace('px','');
    svg.attr({width: w, height: h});
    var x = d3.scale.linear().domain([0, data.length - 1]).range([m, w - m]);
    var y = d3.scale.linear().domain([min, max]).range([h - m, m]);
    var lines = svg.append('path').data(data)
      .attr('d', 'M' + data.map(function(d, i){ return [x(i),y(d)] }).join('L'));
    var circles = svg.selectAll('circle').data(data).enter().append('circle')
      .attr('r', r)
      .attr('cx', function(d, i){ return x(i) })
      .attr('cy', function(d){ return y(d) });
  }
  return {
      link: link
    , restrict: 'E'
    , replace: true
    , template: '<svg ng-transclude class="sl"></svg>'
    , transclude: true
  };
});
</script>
</html>