sparkline

by abenrob

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<div ng-app="MyApp">
    <div class="sparkbox" ng-controller="MyController">
         <sparkline series-data="series" chart-height="40"></sparkline>
    </div>
</div>

CSS

.sparkbox {
    width: 300px;
    margin:20px;
}
.line {
    stroke: darkgray;
}
.spark-circle {
    fill: none;
}
.max-circle {
    fill: red;
}
.min-circle {
    fill: steelblue
}
.current-circle {
    fill: orange;
}
.hovergroup {
    pointer-events: all;
}
.hovergroup.hovered .hoverline {
    stroke: black;
}
.hovertext {
    font-size: 10px;
    font-weight: bold;
    fill: none;
}
.hovertext.right {
    text-anchor: end
}
.hovergroup.hovered .hovertext {
    fill: black;
}

JavaScript

var myApp = angular.module('MyApp', []);
myApp.directive('sparkline', function () {
		var link = function (scope, elem, attrs) {
			var elemHeight = scope.chartHeight || 30;
            var elemWidth = scope.chartWidth || 300;
			var margin = {top: 5, right: 5, bottom: 5, left: 5};
			var spark = d3.select(elem[0])
            			.append("svg")
	            			.style('height', elemHeight+'px')
	            			.style('width', '100%')
            			.append('g')
            				.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            // Set the dimensions of the canvas / graph
			var width = elemWidth - margin.left - margin.right,
			    height = elemHeight - margin.top - margin.bottom;
            // Set the ranges
			var x = d3.scale.linear().range([0, width]);
			var y = d3.scale.linear().range([height, 0]);
            
			// Define the line
			var valueline = d3.svg.line()
				.interpolate("monotone") 
			    .x(function(d,i) { return x(i); })
			    .y(function(d) { return y(d.value); });

			// Scale the range of the data
			function setData(){
				var data = scope.seriesData;
				var maxVal = d3.max(data, function(d) { return d.value; });
				var minVal = d3.min(data, function(d) { return d.value; });
				x.domain([0,data.length-1]);
			    y.domain([minVal, maxVal]);
			    // Add the valueline path.
			    spark.append("path")
			        .attr("class", "line")
			        .style("fill", "none")
			        .attr("d", valueline(data));
			    spark.selectAll("circle")
			    	.data(data)
			    	.enter().append('circle')
			    	.attr("cx", function(d,i){ return x(i) })
			    	.attr("cy", function(d){ return y(d.value) })
			    	.attr("r", function(d){ return d.current ? 2.5 : 2 })
			    	.attr("class","spark-circle")
			    	.classed("current-circle", function(d,i){return i+1 == data.length })
			    	.classed("max-circle", function(d){ return d.value == maxVal ? true : false })
			    	.classed("min-circle", function(d){...