2 nv.models.line = function() {
4 //============================================================
5 // Public Variables with Default Settings
6 //------------------------------------------------------------
8 var scatter = nv.models.scatter()
11 var margin = {top: 0, right: 0, bottom: 0, left: 0}
14 , color = nv.utils.defaultColor() // a function that returns a color
15 , getX = function(d) { return d.x } // accessor to get the x value from a data point
16 , getY = function(d) { return d.y } // accessor to get the y value from a data point
17 , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined
18 , isArea = function(d) { return d.area } // decides if a line is an area or just a line
19 , clipEdge = false // if true, masks lines within x and y scale
20 , x //can be accessed via chart.xScale()
21 , y //can be accessed via chart.yScale()
22 , interpolate = "linear" // controls the line interpolation
26 .size(16) // default size
27 .sizeDomain([16,256]) //set to speed up calculation, needs to be unset if there is a custom size accessor
30 //============================================================
33 //============================================================
35 //------------------------------------------------------------
37 var x0, y0 //used to store previous scales
40 //============================================================
43 function chart(selection) {
44 selection.each(function(data) {
45 var availableWidth = width - margin.left - margin.right,
46 availableHeight = height - margin.top - margin.bottom,
47 container = d3.select(this);
49 //------------------------------------------------------------
58 //------------------------------------------------------------
61 //------------------------------------------------------------
62 // Setup containers and skeleton of chart
64 var wrap = container.selectAll('g.nv-wrap.nv-line').data([data]);
65 var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-line');
66 var defsEnter = wrapEnter.append('defs');
67 var gEnter = wrapEnter.append('g');
68 var g = wrap.select('g')
70 gEnter.append('g').attr('class', 'nv-groups');
71 gEnter.append('g').attr('class', 'nv-scatterWrap');
73 wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
75 //------------------------------------------------------------
81 .width(availableWidth)
82 .height(availableHeight)
84 var scatterWrap = wrap.select('.nv-scatterWrap');
85 //.datum(data); // Data automatically trickles down from the wrap
87 scatterWrap.transition().call(scatter);
91 defsEnter.append('clipPath')
92 .attr('id', 'nv-edge-clip-' + scatter.id())
95 wrap.select('#nv-edge-clip-' + scatter.id() + ' rect')
96 .attr('width', availableWidth)
97 .attr('height', availableHeight);
99 g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
101 .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
106 var groups = wrap.select('.nv-groups').selectAll('.nv-group')
107 .data(function(d) { return d }, function(d) { return d.key });
108 groups.enter().append('g')
109 .style('stroke-opacity', 1e-6)
110 .style('fill-opacity', 1e-6);
113 .style('stroke-opacity', 1e-6)
114 .style('fill-opacity', 1e-6)
117 .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
118 .classed('hover', function(d) { return d.hover })
119 .style('fill', function(d,i){ return color(d, i) })
120 .style('stroke', function(d,i){ return color(d, i)});
123 .style('stroke-opacity', 1)
124 .style('fill-opacity', .5);
128 var areaPaths = groups.selectAll('path.nv-area')
129 .data(function(d) { return isArea(d) ? [d] : [] }); // this is done differently than lines because I need to check if series is an area
130 areaPaths.enter().append('path')
131 .attr('class', 'nv-area')
132 .attr('d', function(d) {
134 .interpolate(interpolate)
136 .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })
137 .y0(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })
138 .y1(function(d,i) { return y0( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })
139 //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this
140 .apply(this, [d.values])
142 groups.exit().selectAll('path.nv-area')
147 .attr('d', function(d) {
149 .interpolate(interpolate)
151 .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
152 .y0(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
153 .y1(function(d,i) { return y( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })
154 //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this
155 .apply(this, [d.values])
160 var linePaths = groups.selectAll('path.nv-line')
161 .data(function(d) { return [d.values] });
162 linePaths.enter().append('path')
163 .attr('class', 'nv-line')
166 .interpolate(interpolate)
168 .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })
169 .y(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })
171 groups.exit().selectAll('path.nv-line')
175 .interpolate(interpolate)
177 .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
178 .y(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
184 .interpolate(interpolate)
186 .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
187 .y(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
192 //store old scales for use in transitions on update
202 //============================================================
203 // Expose Public Variables
204 //------------------------------------------------------------
206 chart.dispatch = scatter.dispatch;
207 chart.scatter = scatter;
209 d3.rebind(chart, scatter, 'id', 'interactive', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'xRange', 'yRange',
210 'sizeDomain', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'useVoronoi', 'clipRadius', 'padData','highlightPoint','clearHighlights');
212 chart.options = nv.utils.optionsFunc.bind(chart);
214 chart.margin = function(_) {
215 if (!arguments.length) return margin;
216 margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
217 margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
218 margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
219 margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
223 chart.width = function(_) {
224 if (!arguments.length) return width;
229 chart.height = function(_) {
230 if (!arguments.length) return height;
235 chart.x = function(_) {
236 if (!arguments.length) return getX;
242 chart.y = function(_) {
243 if (!arguments.length) return getY;
249 chart.clipEdge = function(_) {
250 if (!arguments.length) return clipEdge;
255 chart.color = function(_) {
256 if (!arguments.length) return color;
257 color = nv.utils.getColor(_);
258 scatter.color(color);
262 chart.interpolate = function(_) {
263 if (!arguments.length) return interpolate;
268 chart.defined = function(_) {
269 if (!arguments.length) return defined;
274 chart.isArea = function(_) {
275 if (!arguments.length) return isArea;
276 isArea = d3.functor(_);
280 //============================================================