Javascript 多个图表相互叠加渲染

Javascript 多个图表相互叠加渲染,javascript,knockout.js,knockout-validation,durandal-2.0,chart.js,Javascript,Knockout.js,Knockout Validation,Durandal 2.0,Chart.js,我通过AJAX调用加载了一些图表数据,并使用一个支持工具提示的修改过的图标显示这些数据。它在第一次调用时运行良好,但当我通过更改日期范围进行后续调用时,它会在旧图表数据的基础上绘制新的图表数据。我已将图表刷新代码放入“调整窗口大小”事件中,以便它能够响应。然而,这实际上可能是导致问题的原因。这是我的密码: var BreakDowns = [ 'Daily', 'Weekly', 'Monthly', 'Quarterly', 'Yearly' ]; v

我通过AJAX调用加载了一些图表数据,并使用一个支持工具提示的修改过的图标显示这些数据。它在第一次调用时运行良好,但当我通过更改日期范围进行后续调用时,它会在旧图表数据的基础上绘制新的图表数据。我已将图表刷新代码放入“调整窗口大小”事件中,以便它能够响应。然而,这实际上可能是导致问题的原因。这是我的密码:

var BreakDowns = [
    'Daily',
    'Weekly',
    'Monthly',
    'Quarterly',
    'Yearly'
];

var BreakDown = ko.observable(BreakDowns[0]);
BreakDown.subscribe(function (newValue) {
    switch (newValue) {
        case 'Daily':
            EndDate(StartDate());
            break;
        case 'Weekly':
            EndDate(moment(StartDate()).add('d', 7).format('MM/DD/YYYY'));
            break;
        case 'Monthly':
            EndDate(moment(StartDate()).add('M', 1).format('MM/DD/YYYY'));
            break;
        case 'Quarterly':
            EndDate(moment(StartDate()).add('M', 3).format('MM/DD/YYYY'));
            break;
        case 'Yearly':
            EndDate(moment(StartDate()).add('y', 1).format('MM/DD/YYYY'));
            break;
    }
    GetChartData();
});

var date = new Date();

var StartDate = ko.observable(moment(date).format('MM/DD/YYYY'));
var EndDate = ko.observable(moment(date).format('MM/DD/YYYY'));

var Form = ko.validatedObservable({
    StartDate: StartDate.extend({ isDate: true }),
    EndDate: EndDate.extend({ isDate: true })
});      

StartDate.subscribe(function (newValue) {
    GetChartData();
});

EndDate.subscribe(function (newValue) {
    GetChartData();
});


var chart = {};

var GetChartData = function () {
    if (Form.isValid()) {
        $.ajax({
            url: serviceUri + 'api/Document/ChartData/?breakdown=' + BreakDown().toLowerCase() + '&startDate=' + StartDate() + '&endDate=' + EndDate(),
            method: 'GET',
            dataType: 'json',
            success: function (d) {   
                var chartData = {
                    labels: d.AxisLabels,
                    datasets: [
                        {
                            fillColor: "rgba(220,220,220,0.5)",
                            strokeColor: "rgba(220,220,220,1)",
                            pointColor: "rgba(220,220,220,1)",
                            pointStrokeColor: "#fff",
                            data: d.DataSets[0]
                        }
                    ]
                };

                var max = Math.max.apply(Math, d.DataSets[0]);
                var steps = 10;

                var c = $('#summary');
                var ctx = c.get(0).getContext("2d");
                var container = c.parent();

                $(window).resize(respondCanvas);

                function respondCanvas() {
                    var $container = $(container);
                    if ($container.width() >= 900)
                        c.attr('width', $container.width());
                    else
                        c.attr('width', 900);

                    if ($container.height() >= 400)
                        c.attr('height', $container.height());                
                    else
                        c.attr('height', 400);

                    ctx.width = ctx.width;

                    //Call a function to redraw other content (texts, images etc)
                    chart = new Chart(ctx).Bar(chartData, {
                        scaleOverride: true,
                        scaleSteps: steps,
                        scaleStepWidth: Math.ceil(max / steps),
                        scaleStartValue: 0,
                        annotateDisplay: true
                    });
                }

                respondCanvas();
            }
        });
    }
}
下面是生成的图表的图像:

如何使Chart.js不绘制以前的数据并绘制新图表?

在移动
$(窗口)后。从我的AJAX成功回调中调整大小(respondCanvas)
,下面是一个简化版本的我所拥有的正在工作的功能:

var chartData = {};
var max = 0;
var steps = 10;

function respondCanvas() {
    var c = $('#summary');
    var ctx = c.get(0).getContext("2d");
    var container = c.parent();

    var $container = $(container);

    c.attr('width', $container.width()); //max width

    c.attr('height', $container.height()); //max height                   

    //Call a function to redraw other content (texts, images etc)
    var chart = new Chart(ctx).Bar(chartData, {
        scaleOverride: true,
        scaleSteps: steps,
        scaleStepWidth: Math.ceil(max / steps),
        scaleStartValue: 0,
        annotateDisplay: true
    });
}

var GetChartData = function () {
    $.ajax({
        url: serviceUri,
        method: 'GET',
        dataType: 'json',
        success: function (d) {
           chartData = {
                labels: d.AxisLabels,
                datasets: [
                    {
                        fillColor: "rgba(220,220,220,0.5)",
                        strokeColor: "rgba(220,220,220,1)",
                        pointColor: "rgba(220,220,220,1)",
                        pointStrokeColor: "#fff",
                        data: d.DataSets[0]
                    }
                ]
            };

            max = Math.max.apply(Math, d.DataSets[0]);
            steps = 10;

            respondCanvas();
        }
    });
};

$(document).ready(function() {
    $(window).resize(respondCanvas);

    GetChartData();
});
注意,如果要在更新之间插入一个小延迟,可以使用超时:

$(document).ready(function() {
    $(window).resize(setTimeout(respondCanvas, 500));

    GetChartData();
});

您需要移动
$(窗口)。调整大小(respondCanvas)在ajax成功回调之外。使用当前方法,您将多次对resize事件进行细分,这可能会导致多重图表呈现…
ctx.width=ctx.width
在清除画布时似乎不是100%可靠(请参阅上的注释)。尝试使用
ctx.clearRect(0,0,ctx.width,ctx.height)
代替。更正,最后一条注释应该是:尝试使用
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height)
代替。没有一个答案对我有效,所以我删除了元素,并使用
document.createElement('canvas')动态地重新创建它们
并重新创建上下文和图形实例,然后在新画布上重新绘制图表并修复我的问题-清除逻辑从未起作用(chart.js api的版本为1,因此这可能是我的问题)