forked from Alligator/sparklines
-
Notifications
You must be signed in to change notification settings - Fork 1
/
svg.sparklines.js
136 lines (116 loc) · 4.79 KB
/
svg.sparklines.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Dependency on svg.js library
var sparklines = function sparklines ( el /*, aspectRatio */ ) {
var maxWidth = el.clientWidth,
padding = 0,
values = el
.dataset
.values
.split( ',' )
.map( function ( value ) { return parseFloat( value ); } ),
aspectRatio = arguments.length > 1
? arguments[ 1 ]
: false,
gridSettings = el.dataset.grid,
plot, grid, path,
// filled = el.classList.contains( 'sparkline-filled' ),
// grid = el.classList.contains( 'sparkline-grid' ),
// @TODO check for class inclusion to determine grid inclusion, allow for "x-only" and "y-only"
scale, max, min, xStep, yStep, maxHeight, pathArray;
var buildGrid = function ( ) {
var xGridLine, yGridLine;
pathArray.forEach( function ( segment ) {
if ( gridSettings.indexOf( 'x' ) > - 1 ) {
xGridLine = plot.line(
segment[ 1 ],
padding,
segment[ 1 ],
maxHeight - padding );
xGridLine.addClass( 'grid' );
}
if ( gridSettings.indexOf( 'y' ) > - 1 ) {
yGridLine = plot.line(
padding,
segment[ 2 ],
maxWidth - ( padding * 2 ),
segment[ 2 ] );
yGridLine.addClass( 'grid' );
}
});
};
var calculateY = function ( y ) {
return Math.round( ( maxHeight - ( 2 * padding ) ) * ( ( y - min ) / ( max - min ) ) ) + padding;
};
var buildPathArray = function( ) {
var pathValues = values.map( function ( value, index ) {
var xValue = index * xStep + padding,
yValue = calculateY( value );
return [ ( index == 0 ) ? 'M' : 'L', xValue, yValue ];
});
// @TODO
// if ( filled ) {
// pathString = 'M 0 ' + y1 + ' L ' + maxWidth + ' ' + ( y2 );
// }
return pathValues;
};
// Figure out aspect ratio, if not passed in
if ( ! aspectRatio ) {
// Use the element height
if ( el.clientHeight > 0 ) {
aspectRatio = el.clientWidth / el.clientHeight;
}
// If the element has 0 height, check the parent
else if ( el.parentElement.clientHeight > 0 ) {
aspectRatio = el.clientWidth / el.parentElement.clientHeight;
}
// If we can't get a height, use a sensible default
else {
aspectRatio = 2.5;
}
}
maxHeight = Math.round( maxWidth / aspectRatio );
padding = maxHeight * 0.05;
// Get or calculate max and min Y values
if ( undefined !== el.dataset.scale ) {
scale = el.dataset.scale.split( ',' ).map( function ( value ) { return parseFloat( value ); } );
min = scale[ 0 ];
max = scale[ 1 ];
}
else {
max = Math.max.apply( null, values );
min = Math.min.apply( null, values );
}
// Calculate the how far apart each X and Y point should be
xStep = Math.floor( ( maxWidth - ( 2 * padding ) ) / ( values.length - 1 ) );
yStep = ( maxHeight - 2 * padding - 1 ) / ( max - 1 );
// Build the SVG container
plot = SVG( el );
plot.viewbox( 0, 0, maxWidth, maxHeight )
.attr( 'preserveAspectRatio', 'none' )
.addClass( 'plot' );
// Check if we are building a path or a line
if ( values.length === 2 ) {
var y1 = calculateY( values[ 0 ] ).toFixed( 2 ),
y2 = calculateY( values[ 1 ] ).toFixed( 2 );
pathArray = [ [ 'M', padding, y1 ], [ 'L', maxWidth - ( padding * 2 ), y2 ] ];
}
else if ( values.length > 2 ) {
// Both the grid and plot need the path array
pathArray = buildPathArray( );
}
else {
var y1 = calculateY( values[ 0 ] ).toFixed( 2 );
pathArray = [ [ 'M', padding, y1 ], [ 'L', maxWidth - ( padding * 2 ), y1 ] ];
}
// Build the grid lines first so they render under the plot
if ( gridSettings ) {
buildGrid();
}
path = plot.path( pathArray );
path.fill( 'none' )
.transform( { scaleX: 1, scaleY: -1 } )
.translate( 0, maxHeight )
.attr( 'stroke-linejoin', 'round' );
if ( el.dataset.dashed ) {
path.attr( 'stroke-dasharray', ( strokeWidth * 1.5 ) + '%, ' + ( strokeWidth * .75 ) + '%' );
}
};