diff --git a/Chart.js b/Chart.js index ad238c9b9..7336276ae 100644 --- a/Chart.js +++ b/Chart.js @@ -889,7 +889,7 @@ yMin; helpers.each(this.datasets, function(dataset){ dataCollection = dataset.points || dataset.bars || dataset.segments; - if (dataCollection[dataIndex]){ + if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){ Elements.push(dataCollection[dataIndex]); } }); @@ -1053,6 +1053,9 @@ x : this.x, y : this.y }; + }, + hasValue: function(){ + return isNumber(this.value); } }); @@ -2010,18 +2013,16 @@ this.datasets.push(datasetObject); helpers.each(dataset.data,function(dataPoint,index){ - if (helpers.isNumber(dataPoint)){ - //Add a new point for each piece of data, passing any required data to draw. - datasetObject.bars.push(new this.BarClass({ - value : dataPoint, - label : data.labels[index], - datasetLabel: dataset.label, - strokeColor : dataset.strokeColor, - fillColor : dataset.fillColor, - highlightFill : dataset.highlightFill || dataset.fillColor, - highlightStroke : dataset.highlightStroke || dataset.strokeColor - })); - } + //Add a new point for each piece of data, passing any required data to draw. + datasetObject.bars.push(new this.BarClass({ + value : dataPoint, + label : data.labels[index], + datasetLabel: dataset.label, + strokeColor : dataset.strokeColor, + fillColor : dataset.fillColor, + highlightFill : dataset.highlightFill || dataset.fillColor, + highlightStroke : dataset.highlightStroke || dataset.strokeColor + })); },this); },this); @@ -2136,19 +2137,17 @@ addData : function(valuesArray,label){ //Map the values array for each of the datasets helpers.each(valuesArray,function(value,datasetIndex){ - if (helpers.isNumber(value)){ - //Add a new point for each piece of data, passing any required data to draw. - this.datasets[datasetIndex].bars.push(new this.BarClass({ - value : value, - label : label, - x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1), - y: this.scale.endPoint, - width : this.scale.calculateBarWidth(this.datasets.length), - base : this.scale.endPoint, - strokeColor : this.datasets[datasetIndex].strokeColor, - fillColor : this.datasets[datasetIndex].fillColor - })); - } + //Add a new point for each piece of data, passing any required data to draw. + this.datasets[datasetIndex].bars.push(new this.BarClass({ + value : value, + label : label, + x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1), + y: this.scale.endPoint, + width : this.scale.calculateBarWidth(this.datasets.length), + base : this.scale.endPoint, + strokeColor : this.datasets[datasetIndex].strokeColor, + fillColor : this.datasets[datasetIndex].fillColor + })); },this); this.scale.addXLabel(label); @@ -2185,13 +2184,15 @@ //Draw all the bars for each dataset helpers.each(this.datasets,function(dataset,datasetIndex){ helpers.each(dataset.bars,function(bar,index){ - bar.base = this.scale.endPoint; - //Transition then draw - bar.transition({ - x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index), - y : this.scale.calculateY(bar.value), - width : this.scale.calculateBarWidth(this.datasets.length) - }, easingDecimal).draw(); + if (bar.hasValue()){ + bar.base = this.scale.endPoint; + //Transition then draw + bar.transition({ + x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index), + y : this.scale.calculateY(bar.value), + width : this.scale.calculateBarWidth(this.datasets.length) + }, easingDecimal).draw(); + } },this); },this); @@ -2484,19 +2485,16 @@ helpers.each(dataset.data,function(dataPoint,index){ - //Best way to do this? or in draw sequence...? - if (helpers.isNumber(dataPoint)){ //Add a new point for each piece of data, passing any required data to draw. - datasetObject.points.push(new this.PointClass({ - value : dataPoint, - label : data.labels[index], - datasetLabel: dataset.label, - strokeColor : dataset.pointStrokeColor, - fillColor : dataset.pointColor, - highlightFill : dataset.pointHighlightFill || dataset.pointColor, - highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor - })); - } + datasetObject.points.push(new this.PointClass({ + value : dataPoint, + label : data.labels[index], + datasetLabel: dataset.label, + strokeColor : dataset.pointStrokeColor, + fillColor : dataset.pointColor, + highlightFill : dataset.pointHighlightFill || dataset.pointColor, + highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor + })); },this); this.buildScale(data.labels); @@ -2603,17 +2601,15 @@ //Map the values array for each of the datasets helpers.each(valuesArray,function(value,datasetIndex){ - if (helpers.isNumber(value)){ - //Add a new point for each piece of data, passing any required data to draw. - this.datasets[datasetIndex].points.push(new this.PointClass({ - value : value, - label : label, - x: this.scale.calculateX(this.scale.valuesCount+1), - y: this.scale.endPoint, - strokeColor : this.datasets[datasetIndex].pointStrokeColor, - fillColor : this.datasets[datasetIndex].pointColor - })); - } + //Add a new point for each piece of data, passing any required data to draw. + this.datasets[datasetIndex].points.push(new this.PointClass({ + value : value, + label : label, + x: this.scale.calculateX(this.scale.valuesCount+1), + y: this.scale.endPoint, + strokeColor : this.datasets[datasetIndex].pointStrokeColor, + fillColor : this.datasets[datasetIndex].pointColor + })); },this); this.scale.addXLabel(label); @@ -2650,10 +2646,12 @@ //We can use this extra loop to calculate the control points of this dataset also in this loop helpers.each(dataset.points,function(point,index){ - point.transition({ - y : this.scale.calculateY(point.value), - x : this.scale.calculateX(index) - }, easingDecimal); + if (point.hasValue()){ + point.transition({ + y : this.scale.calculateY(point.value), + x : this.scale.calculateX(index) + }, easingDecimal); + } },this); @@ -2682,24 +2680,26 @@ ctx.strokeStyle = dataset.strokeColor; ctx.beginPath(); helpers.each(dataset.points,function(point,index){ - if (index>0){ - if(this.options.bezierCurve){ - ctx.bezierCurveTo( - dataset.points[index-1].controlPoints.outer.x, - dataset.points[index-1].controlPoints.outer.y, - point.controlPoints.inner.x, - point.controlPoints.inner.y, - point.x, - point.y - ); + if (point.hasValue()){ + if (index>0){ + if(this.options.bezierCurve){ + ctx.bezierCurveTo( + dataset.points[index-1].controlPoints.outer.x, + dataset.points[index-1].controlPoints.outer.y, + point.controlPoints.inner.x, + point.controlPoints.inner.y, + point.x, + point.y + ); + } + else{ + ctx.lineTo(point.x,point.y); + } + } else{ - ctx.lineTo(point.x,point.y); + ctx.moveTo(point.x,point.y); } - - } - else{ - ctx.moveTo(point.x,point.y); } },this); ctx.stroke(); @@ -2718,7 +2718,9 @@ //A little inefficient double looping, but better than the line //lagging behind the point positions helpers.each(dataset.points,function(point){ - point.draw(); + if (point.hasValue()){ + point.draw(); + } }); },this); @@ -3088,25 +3090,22 @@ this.datasets.push(datasetObject); helpers.each(dataset.data,function(dataPoint,index){ - //Best way to do this? or in draw sequence...? - if (helpers.isNumber(dataPoint)){ //Add a new point for each piece of data, passing any required data to draw. - var pointPosition; - if (!this.scale.animation){ - pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint)); - } - datasetObject.points.push(new this.PointClass({ - value : dataPoint, - label : data.labels[index], - datasetLabel: dataset.label, - x: (this.options.animation) ? this.scale.xCenter : pointPosition.x, - y: (this.options.animation) ? this.scale.yCenter : pointPosition.y, - strokeColor : dataset.pointStrokeColor, - fillColor : dataset.pointColor, - highlightFill : dataset.pointHighlightFill || dataset.pointColor, - highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor - })); + var pointPosition; + if (!this.scale.animation){ + pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint)); } + datasetObject.points.push(new this.PointClass({ + value : dataPoint, + label : data.labels[index], + datasetLabel: dataset.label, + x: (this.options.animation) ? this.scale.xCenter : pointPosition.x, + y: (this.options.animation) ? this.scale.yCenter : pointPosition.y, + strokeColor : dataset.pointStrokeColor, + fillColor : dataset.pointColor, + highlightFill : dataset.pointHighlightFill || dataset.pointColor, + highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor + })); },this); },this); @@ -3221,17 +3220,15 @@ //Map the values array for each of the datasets this.scale.valuesCount++; helpers.each(valuesArray,function(value,datasetIndex){ - if (helpers.isNumber(value)){ - var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value)); - this.datasets[datasetIndex].points.push(new this.PointClass({ - value : value, - label : label, - x: pointPosition.x, - y: pointPosition.y, - strokeColor : this.datasets[datasetIndex].pointStrokeColor, - fillColor : this.datasets[datasetIndex].pointColor - })); - } + var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value)); + this.datasets[datasetIndex].points.push(new this.PointClass({ + value : value, + label : label, + x: pointPosition.x, + y: pointPosition.y, + strokeColor : this.datasets[datasetIndex].pointStrokeColor, + fillColor : this.datasets[datasetIndex].pointColor + })); },this); this.scale.labels.push(label); @@ -3278,7 +3275,9 @@ //Transition each point first so that the line and point drawing isn't out of sync helpers.each(dataset.points,function(point,index){ - point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal); + if (point.hasValue()){ + point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal); + } },this); @@ -3305,7 +3304,9 @@ //A little inefficient double looping, but better than the line //lagging behind the point positions helpers.each(dataset.points,function(point){ - point.draw(); + if (point.hasValue()){ + point.draw(); + } }); },this); diff --git a/src/Chart.Bar.js b/src/Chart.Bar.js index aca50d82f..fafe74a49 100644 --- a/src/Chart.Bar.js +++ b/src/Chart.Bar.js @@ -104,18 +104,16 @@ this.datasets.push(datasetObject); helpers.each(dataset.data,function(dataPoint,index){ - if (helpers.isNumber(dataPoint)){ - //Add a new point for each piece of data, passing any required data to draw. - datasetObject.bars.push(new this.BarClass({ - value : dataPoint, - label : data.labels[index], - datasetLabel: dataset.label, - strokeColor : dataset.strokeColor, - fillColor : dataset.fillColor, - highlightFill : dataset.highlightFill || dataset.fillColor, - highlightStroke : dataset.highlightStroke || dataset.strokeColor - })); - } + //Add a new point for each piece of data, passing any required data to draw. + datasetObject.bars.push(new this.BarClass({ + value : dataPoint, + label : data.labels[index], + datasetLabel: dataset.label, + strokeColor : dataset.strokeColor, + fillColor : dataset.fillColor, + highlightFill : dataset.highlightFill || dataset.fillColor, + highlightStroke : dataset.highlightStroke || dataset.strokeColor + })); },this); },this); @@ -230,19 +228,17 @@ addData : function(valuesArray,label){ //Map the values array for each of the datasets helpers.each(valuesArray,function(value,datasetIndex){ - if (helpers.isNumber(value)){ - //Add a new point for each piece of data, passing any required data to draw. - this.datasets[datasetIndex].bars.push(new this.BarClass({ - value : value, - label : label, - x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1), - y: this.scale.endPoint, - width : this.scale.calculateBarWidth(this.datasets.length), - base : this.scale.endPoint, - strokeColor : this.datasets[datasetIndex].strokeColor, - fillColor : this.datasets[datasetIndex].fillColor - })); - } + //Add a new point for each piece of data, passing any required data to draw. + this.datasets[datasetIndex].bars.push(new this.BarClass({ + value : value, + label : label, + x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1), + y: this.scale.endPoint, + width : this.scale.calculateBarWidth(this.datasets.length), + base : this.scale.endPoint, + strokeColor : this.datasets[datasetIndex].strokeColor, + fillColor : this.datasets[datasetIndex].fillColor + })); },this); this.scale.addXLabel(label); @@ -279,13 +275,15 @@ //Draw all the bars for each dataset helpers.each(this.datasets,function(dataset,datasetIndex){ helpers.each(dataset.bars,function(bar,index){ - bar.base = this.scale.endPoint; - //Transition then draw - bar.transition({ - x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index), - y : this.scale.calculateY(bar.value), - width : this.scale.calculateBarWidth(this.datasets.length) - }, easingDecimal).draw(); + if (bar.hasValue()){ + bar.base = this.scale.endPoint; + //Transition then draw + bar.transition({ + x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index), + y : this.scale.calculateY(bar.value), + width : this.scale.calculateBarWidth(this.datasets.length) + }, easingDecimal).draw(); + } },this); },this); diff --git a/src/Chart.Core.js b/src/Chart.Core.js index 7023b0b6b..0bfb4c057 100755 --- a/src/Chart.Core.js +++ b/src/Chart.Core.js @@ -217,6 +217,41 @@ return -1; } }, + where = helpers.where = function(collection, filterCallback){ + var filtered = []; + + helpers.each(collection, function(item){ + if (filterCallback(item)){ + filtered.push(item); + } + }); + + return filtered; + }, + findNextWhere = helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex){ + // Default to start of the array + if (!startIndex){ + startIndex = -1; + } + for (var i = startIndex + 1; i < arrayToSearch.length; i++) { + var currentItem = arrayToSearch[i]; + if (filterCallback(currentItem)){ + return currentItem; + } + }; + }, + findPreviousWhere = helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex){ + // Default to end of the array + if (!startIndex){ + startIndex = arrayToSearch.length; + } + for (var i = startIndex - 1; i >= 0; i--) { + var currentItem = arrayToSearch[i]; + if (filterCallback(currentItem)){ + return currentItem; + } + }; + }, inherits = helpers.inherits = function(extensions){ //Basic javascript inheritance based on the model created in Backbone.js var parent = this; @@ -407,11 +442,10 @@ //Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/ template = helpers.template = function(templateString, valuesObject){ // If templateString is function rather than string-template - call the function for valuesObject - if(templateString instanceof Function) - { + if(templateString instanceof Function){ return templateString(valuesObject); - } - + } + var cache = {}; function tmpl(str, data){ // Figure out if we're getting a template, or if we need to @@ -718,7 +752,7 @@ var ctx = chart.ctx, width = chart.canvas.width, height = chart.canvas.height; - //console.log(width + " x " + height); + if (window.devicePixelRatio) { ctx.canvas.style.width = width + "px"; ctx.canvas.style.height = height + "px"; @@ -889,7 +923,7 @@ yMin; helpers.each(this.datasets, function(dataset){ dataCollection = dataset.points || dataset.bars || dataset.segments; - if (dataCollection[dataIndex]){ + if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){ Elements.push(dataCollection[dataIndex]); } }); @@ -1053,6 +1087,9 @@ x : this.x, y : this.y }; + }, + hasValue: function(){ + return isNumber(this.value); } }); @@ -1099,6 +1136,7 @@ // ctx.fill(); // ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y); + // ctx.lineTo(this.x, this.y); // ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y); // ctx.stroke(); diff --git a/src/Chart.Line.js b/src/Chart.Line.js index ff99d5e55..0b3079ffe 100644 --- a/src/Chart.Line.js +++ b/src/Chart.Line.js @@ -98,19 +98,16 @@ helpers.each(dataset.data,function(dataPoint,index){ - //Best way to do this? or in draw sequence...? - if (helpers.isNumber(dataPoint)){ //Add a new point for each piece of data, passing any required data to draw. - datasetObject.points.push(new this.PointClass({ - value : dataPoint, - label : data.labels[index], - datasetLabel: dataset.label, - strokeColor : dataset.pointStrokeColor, - fillColor : dataset.pointColor, - highlightFill : dataset.pointHighlightFill || dataset.pointColor, - highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor - })); - } + datasetObject.points.push(new this.PointClass({ + value : dataPoint, + label : data.labels[index], + datasetLabel: dataset.label, + strokeColor : dataset.pointStrokeColor, + fillColor : dataset.pointColor, + highlightFill : dataset.pointHighlightFill || dataset.pointColor, + highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor + })); },this); this.buildScale(data.labels); @@ -217,17 +214,15 @@ //Map the values array for each of the datasets helpers.each(valuesArray,function(value,datasetIndex){ - if (helpers.isNumber(value)){ - //Add a new point for each piece of data, passing any required data to draw. - this.datasets[datasetIndex].points.push(new this.PointClass({ - value : value, - label : label, - x: this.scale.calculateX(this.scale.valuesCount+1), - y: this.scale.endPoint, - strokeColor : this.datasets[datasetIndex].pointStrokeColor, - fillColor : this.datasets[datasetIndex].pointColor - })); - } + //Add a new point for each piece of data, passing any required data to draw. + this.datasets[datasetIndex].points.push(new this.PointClass({ + value : value, + label : label, + x: this.scale.calculateX(this.scale.valuesCount+1), + y: this.scale.endPoint, + strokeColor : this.datasets[datasetIndex].pointStrokeColor, + fillColor : this.datasets[datasetIndex].pointColor + })); },this); this.scale.addXLabel(label); @@ -255,37 +250,64 @@ var ctx = this.chart.ctx; + // Some helper methods for getting the next/prev points + var hasValue = function(item){ + return item.value !== null; + }, + nextPoint = function(point, collection, index){ + return helpers.findNextWhere(collection, hasValue, index) || point; + }, + previousPoint = function(point, collection, index){ + return helpers.findPreviousWhere(collection, hasValue, index) || point; + }; + this.scale.draw(easingDecimal); helpers.each(this.datasets,function(dataset){ + var pointsWithValues = helpers.where(dataset.points, hasValue); //Transition each point first so that the line and point drawing isn't out of sync //We can use this extra loop to calculate the control points of this dataset also in this loop - helpers.each(dataset.points,function(point,index){ - point.transition({ - y : this.scale.calculateY(point.value), - x : this.scale.calculateX(index) - }, easingDecimal); - + helpers.each(dataset.points, function(point, index){ + if (point.hasValue()){ + point.transition({ + y : this.scale.calculateY(point.value), + x : this.scale.calculateX(index) + }, easingDecimal); + } },this); // Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point // This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed if (this.options.bezierCurve){ - helpers.each(dataset.points,function(point,index){ - //If we're at the start or end, we don't have a previous/next point - //By setting the tension to 0 here, the curve will transition to straight at the end - if (index === 0){ - point.controlPoints = helpers.splineCurve(point,point,dataset.points[index+1],0); + helpers.each(pointsWithValues, function(point, index){ + var tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0; + point.controlPoints = helpers.splineCurve( + previousPoint(point, pointsWithValues, index), + point, + nextPoint(point, pointsWithValues, index), + tension + ); + + // Prevent the bezier going outside of the bounds of the graph + + // Cap puter bezier handles to the upper/lower scale bounds + if (point.controlPoints.outer.y > this.scale.endPoint){ + point.controlPoints.outer.y = this.scale.endPoint; } - else if (index >= dataset.points.length-1){ - point.controlPoints = helpers.splineCurve(dataset.points[index-1],point,point,0); + else if (point.controlPoints.outer.y < this.scale.startPoint){ + point.controlPoints.outer.y = this.scale.startPoint; } - else{ - point.controlPoints = helpers.splineCurve(dataset.points[index-1],point,dataset.points[index+1],this.options.bezierCurveTension); + + // Cap inner bezier handles to the upper/lower scale bounds + if (point.controlPoints.inner.y > this.scale.endPoint){ + point.controlPoints.inner.y = this.scale.endPoint; + } + else if (point.controlPoints.inner.y < this.scale.startPoint){ + point.controlPoints.inner.y = this.scale.startPoint; } },this); } @@ -295,12 +317,18 @@ ctx.lineWidth = this.options.datasetStrokeWidth; ctx.strokeStyle = dataset.strokeColor; ctx.beginPath(); - helpers.each(dataset.points,function(point,index){ - if (index>0){ + + helpers.each(pointsWithValues, function(point, index){ + if (index === 0){ + ctx.moveTo(point.x, point.y); + } + else{ if(this.options.bezierCurve){ + var previous = previousPoint(point, pointsWithValues, index); + ctx.bezierCurveTo( - dataset.points[index-1].controlPoints.outer.x, - dataset.points[index-1].controlPoints.outer.y, + previous.controlPoints.outer.x, + previous.controlPoints.outer.y, point.controlPoints.inner.x, point.controlPoints.inner.y, point.x, @@ -310,19 +338,15 @@ else{ ctx.lineTo(point.x,point.y); } + } + }, this); - } - else{ - ctx.moveTo(point.x,point.y); - } - },this); ctx.stroke(); - - if (this.options.datasetFill){ + if (this.options.datasetFill && pointsWithValues.length > 0){ //Round off the line by going to the base of the chart, back to the start, then fill. - ctx.lineTo(dataset.points[dataset.points.length-1].x, this.scale.endPoint); - ctx.lineTo(this.scale.calculateX(0), this.scale.endPoint); + ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint); + ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint); ctx.fillStyle = dataset.fillColor; ctx.closePath(); ctx.fill(); @@ -331,10 +355,9 @@ //Now draw the points over the line //A little inefficient double looping, but better than the line //lagging behind the point positions - helpers.each(dataset.points,function(point){ + helpers.each(pointsWithValues,function(point){ point.draw(); }); - },this); } }); diff --git a/src/Chart.Radar.js b/src/Chart.Radar.js index 0d0e608bf..134fd2d02 100644 --- a/src/Chart.Radar.js +++ b/src/Chart.Radar.js @@ -111,25 +111,22 @@ this.datasets.push(datasetObject); helpers.each(dataset.data,function(dataPoint,index){ - //Best way to do this? or in draw sequence...? - if (helpers.isNumber(dataPoint)){ //Add a new point for each piece of data, passing any required data to draw. - var pointPosition; - if (!this.scale.animation){ - pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint)); - } - datasetObject.points.push(new this.PointClass({ - value : dataPoint, - label : data.labels[index], - datasetLabel: dataset.label, - x: (this.options.animation) ? this.scale.xCenter : pointPosition.x, - y: (this.options.animation) ? this.scale.yCenter : pointPosition.y, - strokeColor : dataset.pointStrokeColor, - fillColor : dataset.pointColor, - highlightFill : dataset.pointHighlightFill || dataset.pointColor, - highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor - })); + var pointPosition; + if (!this.scale.animation){ + pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint)); } + datasetObject.points.push(new this.PointClass({ + value : dataPoint, + label : data.labels[index], + datasetLabel: dataset.label, + x: (this.options.animation) ? this.scale.xCenter : pointPosition.x, + y: (this.options.animation) ? this.scale.yCenter : pointPosition.y, + strokeColor : dataset.pointStrokeColor, + fillColor : dataset.pointColor, + highlightFill : dataset.pointHighlightFill || dataset.pointColor, + highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor + })); },this); },this); @@ -244,17 +241,15 @@ //Map the values array for each of the datasets this.scale.valuesCount++; helpers.each(valuesArray,function(value,datasetIndex){ - if (helpers.isNumber(value)){ - var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value)); - this.datasets[datasetIndex].points.push(new this.PointClass({ - value : value, - label : label, - x: pointPosition.x, - y: pointPosition.y, - strokeColor : this.datasets[datasetIndex].pointStrokeColor, - fillColor : this.datasets[datasetIndex].pointColor - })); - } + var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value)); + this.datasets[datasetIndex].points.push(new this.PointClass({ + value : value, + label : label, + x: pointPosition.x, + y: pointPosition.y, + strokeColor : this.datasets[datasetIndex].pointStrokeColor, + fillColor : this.datasets[datasetIndex].pointColor + })); },this); this.scale.labels.push(label); @@ -301,7 +296,9 @@ //Transition each point first so that the line and point drawing isn't out of sync helpers.each(dataset.points,function(point,index){ - point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal); + if (point.hasValue()){ + point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal); + } },this); @@ -328,7 +325,9 @@ //A little inefficient double looping, but better than the line //lagging behind the point positions helpers.each(dataset.points,function(point){ - point.draw(); + if (point.hasValue()){ + point.draw(); + } }); },this);