tutorial pie horizontal chart bar charts chart.js

charts - pie - Chart.js ¿cómo obtener gráficos combinados de barras y líneas?



horizontal bar chart js (6)

Se necesita una pequeña adición de código. En la sección "buildScale", también debe incluir los datos de cadaPoints. Esto es así porque calculaY solo usa los datos de la barra para determinar la altura; la línea que usa datos es ignorada. Si los datos que usan la línea son más altos que los datos que utilizan la barra, el gráfico de líneas se cortará en la parte superior.

buildScale : function(labels){ var self = this; var dataTotal = function(){ var values = []; self.eachBars(function(bar){ values.push(bar.value); }); // missing code ↓↓↓ self.eachPoints(function(point){ values.push(point.value); }); // missing code ↑↑↑ return values; };

Me gustaría preguntar si es posible utilizar Chart.js http://www.chartjs.org/ para obtener barras combinados y gráficos de líneas.

Gracias por cualquier consejo.


pero queremos mostrar las líneas de la cuadrícula

var scaleOptions = { lineColor : this.options.scaleLineColor, // missing code ↓↓↓ showHorizontalLines: this.options.scaleShowHorizontalLines, showVerticalLines: this.options.scaleShowVerticalLines, //missing code ↑↑↑ }


Esto funcionó para mí para cambiar el índice Z de líneas y barras. Cambia los siguientes dos bloques de código:

helpers.each(this.barDatasets, function (dataset, datasetIndex) ... , this); helpers.each(this.lineDatasets, function (dataset, datasetIndex) ... , this);

Me gusta esto:

helpers.each(this.lineDatasets, function (dataset, datasetIndex) ... , this); helpers.each(this.barDatasets, function (dataset, datasetIndex) ... , this);

Buena suerte.


La nueva versión de Charts.js (v2.0) admite barras y gráficos de líneas combinados.

v2.0 se encuentra actualmente en Beta

Enlace a Plunker


Con Chart.js 2.0 lo haces así:

var chartInstance = new Chart(ctx, { type: ''bar'', // set the default type data: { datasets: [{ // default type will be used data: [] }, { type: ''line'', // override the default type data: [] }] } });


La siguiente respuesta se refiere a chart.js 1.x. Chart.js 2.x admite este Chart.js cómo obtener barras combinadas y gráficos de líneas?

EDIT 2 Ahora he agregado esta característica a mi compilación personalizada de chartjs si quieres usar esa https://github.com/leighquince/Chart.js, la única diferencia es que la llamé Superposición no LineBar, así que para usarla simplemente crea una gráfico usando var myOverlayChart = new Chart(lineBar).Overlay(data); todo lo demás es lo mismo sin embargo.

De acuerdo, me apresuré a ver si esto era posible y la respuesta corta es sí, pero necesitaría más trabajo para integrar esto en la compilación de gráficos js. Aquí hay un violín que lo muestra en acción con una línea y un gráfico de barras para comparar: http://fiddle.jshell.net/leighking2/898kzyp7/

Así que mi solución fue crear un nuevo tipo de gráfico llamado LineBar (podría haber ido para la opción de ampliación, pero antes de comenzar sentí que esto iba a necesitar una gran cantidad de métodos anulando así que fui por un nuevo gráfico, también significa que no lo hice tiene que volver a declarar ayudantes como Chart.helpers no es una gran cosa, pero fue razón suficiente en el momento).

En esencia, es el gráfico de barras, pero mantiene un seguimiento de los conjuntos de datos en las variables lineDataSets y barDataSets . Luego, cuando necesite dibujar / verificar eventos / use-the-data, bucles otros dos conjuntos de datos por separado.

Siempre que se esté lineDataSets encima de la variable lineDataSets , se está ejecutando el código del gráfico de líneas actual y viceversa para el gráfico de barras

Así que pegaré el nuevo gráfico en la parte inferior de esta respuesta ya que es bastante grande, para usarlo copie y péguelo en su propio archivo chart.js en la parte inferior o péguelo después de incluir chart.js en su página.

Para hacer uso de él, ahora puede declarar sus datos con una opción adicional llamada type

var data = { labels: ["January", "February", "March", "April", "May", "June", "July"], datasets: [{ label: "My First dataset", //new option, type will default to bar as that what is used to create the scale type: "line", fillColor: "rgba(220,220,220,0.2)", strokeColor: "rgba(220,220,220,1)", pointColor: "rgba(220,220,220,1)", pointStrokeColor: "#fff", pointHighlightFill: "#fff", pointHighlightStroke: "rgba(220,220,220,1)", data: [65, 59, 4, 81, 56, 55, 40] }, { label: "My First dataset", //new option, type will default to bar as that what is used to create the scale type: "bar", fillColor: "rgba(220,20,220,0.2)", strokeColor: "rgba(220,20,220,1)", pointColor: "rgba(220,20,220,1)", pointStrokeColor: "#fff", pointHighlightFill: "#fff", pointHighlightStroke: "rgba(220,220,220,1)", data: [32, 25, 33, 88, 12, 92, 33] }] };

entonces solo crea un nuevo cuadro de tipo LineBar

var lineBar = document.getElementById("line-bar").getContext("2d"); var myLineBarChart = new Chart(lineBar).LineBar(data);

resultado

EDITAR: Se actualizó, por lo que ahora funciona la información sobre herramientas y la funcionalidad removeData / addData. Vea el violín para ver ejemplos de estos. También puede agregar tantos conjuntos de datos como desee, tanto en línea como en barra, y los mostrará en el mismo gráfico.

Limitación: si la barra y la línea se actualizan, sus respectivas piezas también deben actualizarse aquí, lo cual no es bueno, no se romperán si la barra y la línea se actualizan, puede significar que no se ven iguales, lo que sea que se actualice

y aquí está el nuevo gráfico real

//new chart type LineBar - its a bit like bar and line //were slammed together at high speed, not pretty, //but they are part of each other now (function(){ "use strict"; var root = this, Chart = root.Chart, helpers = Chart.helpers; var defaultConfig = { //Function - Whether the current x-axis label should be filtered out, takes in current label and //index, return true to filter out the label return false to keep the label labelsFilter : function(label,index){return false;}, //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value scaleBeginAtZero : true, //Boolean - Whether grid lines are shown across the chart scaleShowGridLines : true, //String - Colour of the grid lines scaleGridLineColor : "rgba(0,0,0,.05)", //Number - Width of the grid lines scaleGridLineWidth : 1, //Boolean - If there is a stroke on each bar barShowStroke : true, //Number - Pixel width of the bar stroke barStrokeWidth : 2, //Number - Spacing between each of the X value sets barValueSpacing : 5, //Number - Spacing between data sets within X values barDatasetSpacing : 1, //Boolean - Whether the line is curved between points bezierCurve : true, //Number - Tension of the bezier curve between points bezierCurveTension : 0.4, //Boolean - Whether to show a dot for each point pointDot : true, //Number - Radius of each point dot in pixels pointDotRadius : 4, //Number - Pixel width of point dot stroke pointDotStrokeWidth : 1, //Number - amount extra to add to the radius to cater for hit detection outside the drawn point pointHitDetectionRadius : 20, //Boolean - Whether to show a stroke for datasets datasetStroke : true, //Number - Pixel width of dataset stroke datasetStrokeWidth : 2, //Boolean - Whether to fill the dataset with a colour datasetFill : true, //String - A legend template legendTemplate : "<ul class=/"<%=name.toLowerCase()%>-legend/"><% for (var i=0; i<datasets.length; i++){%><li><span style=/"background-color:<%=datasets[i].fillColor%>/"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>" }; Chart.Type.extend({ name: "LineBar", defaults : defaultConfig, initialize: function(data){ //Expose options as a scope variable here so we can access it in the ScaleClass var options = this.options; //two new varibale to hold the different graph types this.barDatasets = []; this.lineDatasets = []; //generate the scale, let bar take control here as he needs the width. this.ScaleClass = Chart.Scale.extend({ offsetGridLines : true, calculateBarX : function(datasetCount, datasetIndex, barIndex){ //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar var xWidth = this.calculateBaseWidth(), xAbsolute = this.calculateX(barIndex) - (xWidth/2), barWidth = this.calculateBarWidth(datasetCount); return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2; }, calculateBaseWidth : function(){ return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing); }, calculateBarWidth : function(datasetCount){ //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing); return (baseWidth / datasetCount); } }); //Declare the extension of the default point, to cater for the options passed in to the constructor this.PointClass = Chart.Point.extend({ strokeWidth : this.options.pointDotStrokeWidth, radius : this.options.pointDotRadius, display: this.options.pointDot, hitDetectionRadius : this.options.pointHitDetectionRadius, ctx : this.chart.ctx, inRange : function(mouseX){ return (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2)); } }); this.datasets = []; //Set up tooltip events on the chart if (this.options.showTooltips){ helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ var activeData = (evt.type !== ''mouseout'') ? this.getDataAtEvent(evt) : []; this.eachBars(function(bar){ bar.restore([''fillColor'', ''strokeColor'']); }); this.eachPoints(function(point){ point.restore([''fillColor'', ''strokeColor'']); }); helpers.each(activeData, function(active){ active.fillColor = active.highlightFill; active.strokeColor = active.highlightStroke; }); this.showTooltip(activeData); }); } //Declare the extension of the default point, to cater for the options passed in to the constructor this.BarClass = Chart.Rectangle.extend({ strokeWidth : this.options.barStrokeWidth, showStroke : this.options.barShowStroke, ctx : this.chart.ctx }); //Iterate through each of the datasets, and build this into a property of the chart helpers.each(data.datasets,function(dataset,datasetIndex){ var datasetObject = { label : dataset.label || null, fillColor : dataset.fillColor, strokeColor : dataset.strokeColor, type: dataset.type, bars : [], pointColor : dataset.pointColor, pointStrokeColor : dataset.pointStrokeColor, points : [] }; this.datasets.push(datasetObject); switch(dataset.type) { case "line": this.lineDatasets.push(datasetObject); helpers.each(dataset.data,function(dataPoint,index){ //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 })); },this); break; default: this.barDatasets.push(datasetObject); helpers.each(dataset.data,function(dataPoint,index){ //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); break; } },this); this.buildScale(data.labels); helpers.each(this.lineDatasets,function(dataset,datasetIndex){ //Iterate through each of the datasets, and build this into a property of the chart this.eachPoints(function(point, index){ helpers.extend(point, { x: this.scale.calculateX(index), y: this.scale.endPoint }); point.save(); }, this); },this); this.BarClass.prototype.base = this.scale.endPoint; this.eachBars(function(bar, index, datasetIndex){ helpers.extend(bar, { width : this.scale.calculateBarWidth(this.barDatasets.length), x: this.scale.calculateBarX(this.barDatasets.length, datasetIndex, index), y: this.scale.endPoint }); bar.save(); }, this); this.render(); }, update : function(){ this.scale.update(); // Reset any highlight colours before updating. helpers.each(this.activeElements, function(activeElement){ activeElement.restore([''fillColor'', ''strokeColor'']); }); this.eachBars(function(bar){ bar.save(); }); this.eachPoints(function(point){ point.save(); }); this.render(); }, eachPoints : function(callback){ //use the lineDataSets helpers.each(this.lineDatasets,function(dataset){ helpers.each(dataset.points,callback,this); },this); }, eachBars : function(callback){ //user the barDataSets helpers.each(this.barDatasets,function(dataset, datasetIndex){ helpers.each(dataset.bars, callback, this, datasetIndex); },this); }, getDataAtEvent : function(e) { return this.getPointsAtEvent(e).concat(this.getBarsAtEvent(e)); }, getPointsAtEvent : function(e){ var pointsArray = [], eventPosition = helpers.getRelativePosition(e); helpers.each(this.lineDatasets,function(dataset){ helpers.each(dataset.points,function(point){ if (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point); }); },this); return pointsArray; }, getBarsAtEvent : function(e){ var barsArray = [], eventPosition = helpers.getRelativePosition(e), datasetIterator = function(dataset){ barsArray.push(dataset.bars[barIndex]); }, barIndex; for (var datasetIndex = 0; datasetIndex < this.barDatasets.length; datasetIndex++) { for (barIndex = 0; barIndex < this.barDatasets[datasetIndex].bars.length; barIndex++) { if (this.barDatasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){ helpers.each(this.barDatasets, datasetIterator); return barsArray; } } } return barsArray; }, buildScale : function(labels){ var self = this; var dataTotal = function(){ var values = []; self.eachBars(function(bar){ values.push(bar.value); }); return values; }; var scaleOptions = { labelsFilter: this.options.labelsFilter, templateString : this.options.scaleLabel, height : this.chart.height, width : this.chart.width, ctx : this.chart.ctx, textColor : this.options.scaleFontColor, fontSize : this.options.scaleFontSize, fontStyle : this.options.scaleFontStyle, fontFamily : this.options.scaleFontFamily, valuesCount : labels.length, beginAtZero : this.options.scaleBeginAtZero, integersOnly : this.options.scaleIntegersOnly, calculateYRange: function(currentHeight){ var updatedRanges = helpers.calculateScaleRange( dataTotal(), currentHeight, this.fontSize, this.beginAtZero, this.integersOnly ); helpers.extend(this, updatedRanges); }, xLabels : labels, font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily), lineWidth : this.options.scaleLineWidth, lineColor : this.options.scaleLineColor, gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0, gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)", padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0, showLabels : this.options.scaleShowLabels, display : this.options.showScale }; if (this.options.scaleOverride){ helpers.extend(scaleOptions, { calculateYRange: helpers.noop, steps: this.options.scaleSteps, stepValue: this.options.scaleStepWidth, min: this.options.scaleStartValue, max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) }); } this.scale = new this.ScaleClass(scaleOptions); }, addData : function(valuesArray,label){ //Map the values array for each of the datasets var lineDataSetIndex = 0; var barDataSetIndex = 0; helpers.each(valuesArray,function(value,datasetIndex){ switch(this.datasets[datasetIndex].type) { case "line": //Add a new point for each piece of data, passing any required data to draw. this.lineDatasets[lineDataSetIndex].points.push(new this.PointClass({ value : value, label : label, x: this.scale.calculateX(this.scale.valuesCount+1), y: this.scale.endPoint, strokeColor : this.lineDatasets[lineDataSetIndex].pointStrokeColor, fillColor : this.lineDatasets[lineDataSetIndex].pointColor })); lineDataSetIndex++; break; default: //Add a new point for each piece of data, passing any required data to draw. this.barDatasets[barDataSetIndex].bars.push(new this.BarClass({ value : value, label : label, x: this.scale.calculateBarX(this.barDatasets.length, barDataSetIndex, this.scale.valuesCount+1), y: this.scale.endPoint, width : this.scale.calculateBarWidth(this.barDatasets.length), base : this.scale.endPoint, strokeColor : this.barDatasets[barDataSetIndex].strokeColor, fillColor : this.barDatasets[barDataSetIndex].fillColor })); barDataSetIndex++; break; } },this); this.scale.addXLabel(label); //Then re-render the chart. this.update(); }, removeData : function(){ this.scale.removeXLabel(); //Then re-render the chart. helpers.each(this.barDatasets,function(dataset){ dataset.bars.shift(); },this); helpers.each(this.lineDatasets,function(dataset){ dataset.points.shift(); },this); this.update(); }, reflow : function(){ helpers.extend(this.BarClass.prototype,{ y: this.scale.endPoint, base : this.scale.endPoint }); var newScaleProps = helpers.extend({ height : this.chart.height, width : this.chart.width }); this.scale.update(newScaleProps); }, draw : function(ease){ var easingDecimal = ease || 1; this.clear(); 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); //Draw all the bars for each dataset helpers.each(this.lineDatasets,function(dataset,datasetIndex){ 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){ 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(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 (point.controlPoints.outer.y < this.scale.startPoint){ point.controlPoints.outer.y = this.scale.startPoint; } // 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); } //Draw the line between all the points ctx.lineWidth = this.options.datasetStrokeWidth; ctx.strokeStyle = dataset.strokeColor; ctx.beginPath(); 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( previous.controlPoints.outer.x, previous.controlPoints.outer.y, point.controlPoints.inner.x, point.controlPoints.inner.y, point.x, point.y ); } else{ ctx.lineTo(point.x,point.y); } } }, this); ctx.stroke(); 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(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint); ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint); ctx.fillStyle = dataset.fillColor; ctx.closePath(); ctx.fill(); } //Now draw the points over the line //A little inefficient double looping, but better than the line //lagging behind the point positions helpers.each(pointsWithValues,function(point){ point.draw(); }); },this); helpers.each(this.barDatasets,function(dataset,datasetIndex){ helpers.each(dataset.bars,function(bar,index){ if (bar.hasValue()){ bar.base = this.scale.endPoint; //Transition then draw bar.transition({ x : this.scale.calculateBarX(this.barDatasets.length, datasetIndex, index), y : this.scale.calculateY(bar.value), width : this.scale.calculateBarWidth(this.barDatasets.length) }, easingDecimal).draw(); } },this); },this); }, showTooltip : function(ChartElements, forceRedraw){ // Only redraw the chart if we''ve actually changed what we''re hovering on. if (typeof this.activeElements === ''undefined'') this.activeElements = []; var isChanged = (function(Elements){ var changed = false; if (Elements.length !== this.activeElements.length){ changed = true; return changed; } helpers.each(Elements, function(element, index){ if (element !== this.activeElements[index]){ changed = true; } }, this); return changed; }).call(this, ChartElements); if (!isChanged && !forceRedraw){ return; } else{ this.activeElements = ChartElements; } this.draw(); if (ChartElements.length > 0){ // If we have multiple datasets, show a MultiTooltip for all of the data points at that index if (this.datasets && this.datasets.length > 1) { var dataArray, dataIndex; for (var i = this.lineDatasets.length - 1; i >= 0; i--) { dataArray = this.datasets[i].points; dataIndex = helpers.indexOf(dataArray, ChartElements[0]); if (dataIndex !== -1){ break; } } if(dataIndex === -1) { for (i = this.barDatasets.length - 1; i >= 0; i--) { dataArray = this.datasets[i].bars; dataIndex = helpers.indexOf(dataArray, ChartElements[0]); if (dataIndex !== -1){ break; } } } var tooltipLabels = [], tooltipColors = [], medianPosition = (function(index) { // Get all the points at that particular index var Elements = [], dataCollection, xPositions = [], yPositions = [], xMax, yMax, xMin, yMin; helpers.each(this.lineDatasets, function(dataset){ dataCollection = dataset.points; if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){ Elements.push(dataCollection[dataIndex]); } }); helpers.each(this.barDatasets, function(dataset){ dataCollection = dataset.bars; if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){ Elements.push(dataCollection[dataIndex]); } }); helpers.each(Elements, function(element) { xPositions.push(element.x); yPositions.push(element.y); //Include any colour information about the element tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element)); tooltipColors.push({ fill: element._saved.fillColor || element.fillColor, stroke: element._saved.strokeColor || element.strokeColor }); }, this); yMin = helpers.min(yPositions); yMax = helpers.max(yPositions); xMin = helpers.min(xPositions); xMax = helpers.max(xPositions); return { x: (xMin > this.chart.width/2) ? xMin : xMax, y: (yMin + yMax)/2 }; }).call(this, dataIndex); new Chart.MultiTooltip({ x: medianPosition.x, y: medianPosition.y, xPadding: this.options.tooltipXPadding, yPadding: this.options.tooltipYPadding, xOffset: this.options.tooltipXOffset, fillColor: this.options.tooltipFillColor, textColor: this.options.tooltipFontColor, fontFamily: this.options.tooltipFontFamily, fontStyle: this.options.tooltipFontStyle, fontSize: this.options.tooltipFontSize, titleTextColor: this.options.tooltipTitleFontColor, titleFontFamily: this.options.tooltipTitleFontFamily, titleFontStyle: this.options.tooltipTitleFontStyle, titleFontSize: this.options.tooltipTitleFontSize, cornerRadius: this.options.tooltipCornerRadius, labels: tooltipLabels, legendColors: tooltipColors, legendColorBackground : this.options.multiTooltipKeyBackground, title: ChartElements[0].label, chart: this.chart, ctx: this.chart.ctx }).draw(); } else { each(ChartElements, function(Element) { var tooltipPosition = Element.tooltipPosition(); new Chart.Tooltip({ x: Math.round(tooltipPosition.x), y: Math.round(tooltipPosition.y), xPadding: this.options.tooltipXPadding, yPadding: this.options.tooltipYPadding, fillColor: this.options.tooltipFillColor, textColor: this.options.tooltipFontColor, fontFamily: this.options.tooltipFontFamily, fontStyle: this.options.tooltipFontStyle, fontSize: this.options.tooltipFontSize, caretHeight: this.options.tooltipCaretSize, cornerRadius: this.options.tooltipCornerRadius, text: template(this.options.tooltipTemplate, Element), chart: this.chart }).draw(); }, this); } } return this; }, }); }).call(this); //here ends the LineBar