Chart.js如何获得组合条形图和折线图?

js81xvg6  于 2022-11-06  发布在  Chart.js
关注(0)|答案(6)|浏览(281)

我想问一下,是否可以使用Chart.js http://www.chartjs.org/来获得组合的条形图和折线图?
谢谢你的建议。

qc6wkl3g

qc6wkl3g1#

下面的答案与chart.js 1.x有关。Chart.js 2.x支持此Chart.js如何获得组合条形图和折线图?

EDIT 2我现在已经将此功能添加到我的chartjs自定义版本中,如果您想使用https://github.com/leighquince/Chart.js,唯一的区别是我将其命名为Overlay而不是LineBar,因此要使用它,只需使用var myOverlayChart = new Chart(lineBar).Overlay(data);创建一个图形,但其他一切都是相同的。

好的,我们来看看这是否可行,简单的答案是肯定的,但是需要更多的工作来真正将其整合到chart js的构建中。下面是一个小提琴,用一个折线图和条形图来比较它的运行情况:http://fiddle.jshell.net/leighking2/898kzyp7/
所以我的解决方案是创建一个新的图表类型称为LineBar(本来可以去扩展选项,但在开始之前,我觉得这将需要很多的方法覆盖,所以去了一个新的图形,这也意味着我不必重新声明助手作为图表。助手不是一个巨大的事情,但在当时是足够的理由)。
它的核心是一个条形图,但是它在单独的lineDataSetsbarDataSets变量中跟踪数据集。然后当它需要绘制/检查事件/使用数据时,它会分别循环其他两个新的数据集。
每当它在lineDataSets变量上循环时,它执行当前折线图中的代码,反之亦然,对于条形图也是如此
所以我会把新的图表粘贴在这个答案的底部,因为它很大,要使用它,可以复制并粘贴到底部的chart.js文件中,或者在你的页面上包含chart.js后粘贴。
要使用它,您现在可以使用一个名为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]
    }]
};

然后创建一个新的LineBar类型的图表

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

结果

**EDIT:**更新了它,现在它有了工具提示和removeData/addData功能。查看这些例子的小提琴。你也可以添加任意多的数据集,无论是直线还是条形,它都将在同一个图表上显示它们。

局限性-如果条和线得到更新,它们各自的部分也必须在这里更新,这不是很好,如果条和线得到更新,它们不会中断,这可能意味着它们看起来不一样,无论得到更新
这是新的图表

//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
wlsrxk51

wlsrxk512#

在Chart.js 2.0中,您可以这样做:

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: []          
    }]
  }
});
1wnzp6jl

1wnzp6jl3#

Charts.js(v2.0)的新版本支持组合条形图和折线图。
v2.0目前处于测试阶段
链接到Plunker

odopli94

odopli944#

需要添加一个小的代码。在“buildScale”部分中,您还需要包括eachPoints的数据。这是因为calculatedY只使用bar的数据来确定高度;使用线的数据被忽略。如果使用线的数据高于使用棒的数据,则折线图将在顶部被截断。

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;
    };
ccrfmcuu

ccrfmcuu5#

但我们希望显示网格线

var scaleOptions = {

lineColor : this.options.scaleLineColor,

// missing code ↓↓↓

showHorizontalLines: this.options.scaleShowHorizontalLines,
showVerticalLines: this.options.scaleShowVerticalLines,

//missing code ↑↑↑

}
inn6fuwd

inn6fuwd6#

这对我更改线条和条形的z索引很有效。交换下面两个代码块:

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

就像这样:

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

祝你好运

相关问题