线形比赛积分增长或竞赛图|Highcharts企业图表代码示列

线形竞赛图(Line Chart)是一种常用的图表类型,用于显示数据随时间或其他连续变量的变化趋势。它通过将数据点连接成一条线,直观地展示数据的走势和模式。

特点:

  • 时间序列分析:线形竞赛图非常适合展示时间序列数据,例如股票价格、气温变化等。
  • 趋势识别:通过观察线条的上升或下降,可以快速识别数据的趋势。
  • 多系列比较:可以在同一图表中绘制多条线,以便比较不同数据集之间的关系。

竞赛图表

示例代码:

javascript 复制代码
const btn = document.getElementById('play-pause-button'),
    input = document.getElementById('play-range'),
    startRound = 0,
    endRound = 20,
    animationDuration = 1000;

// General helper functions
const arrToAssociative = arr => {
    const tmp = {};
    arr.forEach(item => {
        tmp[item[0]] = item[1];
    });

    return tmp;
};

const formatPoints = [];

const chart = Highcharts.chart('container', {
    chart: {
        type: 'line',
        marginRight: 110,
        animation: {
            duration: animationDuration,
            easing: t => t
        }
    },
    title: {
        text: 'F1 2012 Top Ten Drivers',
        floating: true,
        align: 'left',
        x: 70,
        y: 50
    },
    data: {
        csv: document.getElementById('csv').innerText,
        itemDelimiter: '\t',
        complete: function (options) {
            // Store the data for later use, and remove it from the series
            for (let i = 0; i < options.series.length; i++) {
                formatPoints[i] = arrToAssociative(options.series[i].data);
                options.series[i].data = null;
            }
        }
    },
    xAxis: {
        allowDecimals: false,
        min: startRound,
        max: endRound,
        title: {
            text: 'Round #',
            align: 'high',
            textAlign: 'left',
            x: 20,
            y: -20
        }
    },
    yAxis: {
        reversedStacks: false,
        max: 300,
        title: {
            text: 'Points'
        }
    },
    tooltip: {
        split: true,
        headerFormat: '<span style="font-size: 1.2em">{point.x}</span>',
        pointFormat: '{series.name}: {point.y} Points',
        crosshairs: true
    },
    plotOptions: {
        line: {
            animation: false,
            pointStart: startRound,
            marker: {
                enabled: false
            }
        }
    },
    annotations: [
        {
            crop: false,
            labelOptions: {
                borderWidth: 0,
                backgroundColor: undefined,
                align: 'left',
                verticalAlign: 'middle',
                overflow: 'allow',
                style: {
                    pointerEvents: 'none',
                    transition: 'opacity 0.5s'
                },
                x: -8,
                y: -1
            },
            labels: new Array(10).fill({
                text: 0,
                point: {
                    x: 0,
                    xAxis: 0,
                    y: 0,
                    yAxis: 0
                }
            })
        }
    ],

    responsive: {
        rules: [
            {
                condition: {
                    maxWidth: 500
                },
                chartOptions: {
                    chart: {
                        marginTop: 80
                    },
                    title: {
                        floating: false,
                        x: 0,
                        y: 20
                    },
                    yAxis: {
                        labels: {
                            align: 'left',
                            x: 0,
                            y: -3
                        },
                        tickLength: 0,
                        title: {
                            align: 'high',
                            reserveSpace: false,
                            rotation: 0,
                            textAlign: 'left',
                            y: -20
                        }
                    }
                }
            }
        ]
    }
});

function pause(button) {
    button.title = 'play';
    button.className = 'fa fa-play';
    clearTimeout(chart.sequenceTimer);
    chart.sequenceTimer = undefined;
}

function update(sliderClicked) {

    const series = chart.series,
        labels = chart.annotations[0].labels,
        yearIndex = input.value - startRound,
        dataLength = series[0].options.data.length;

    // If slider moved back in time
    if (yearIndex < dataLength - 1) {
        for (let i = 0; i < series.length; i++) {
            const seriesData = series[i].options.data.slice(0, yearIndex);
            series[i].setData(seriesData, false);
        }
    }

    // If slider moved forward in time
    if (yearIndex > dataLength - 1) {
        const remainingYears = yearIndex - dataLength;
        for (let i = 0; i < series.length; i++) {
            for (let j = input.value - remainingYears; j < input.value; j++) {
                series[i].addPoint([formatPoints[i][j]], false);
            }
        }
    }

    const nextnums = [];
    // Add current year if applicable, and update labels
    for (let i = 0; i < series.length; i++) {
        const newY = formatPoints[i][input.value];
        labels[i].options.point.x = yearIndex;
        labels[i].options.point.y = newY;

        if (yearIndex === 0) {
            labels[i].options.text =
                `<span style="color:${series[i].color}">●</span>
                ${series[i].name}</span>`;
        }
        nextnums.push(newY);
        if (series[i].options.data.length <= yearIndex) {
            series[i].addPoint(newY, false);
        }
    }

    if (sliderClicked) {
        chart.redraw(false);
    } else {
        chart.redraw();
    }

    input.value = parseInt(input.value, 10) + 1;

    if (input.value > endRound) {
        // Auto-pause
        pause(btn);
    }
}

function play(button) {
    // Reset slider at the end
    if (input.value > endRound) {
        input.value = startRound;
    }
    button.title = 'pause';
    button.className = 'fa fa-pause';
    chart.sequenceTimer = setInterval(function () {
        update(false);
    }, animationDuration);
}

btn.addEventListener('click', function () {
    if (chart.sequenceTimer) {
        pause(this);
    } else {
        play(this);
    }
});

update(true); // Move to initial position
update(false); // Animate to the first point immediately
play(btn); // Start the animation

// Trigger the update on the range bar click.
input.addEventListener('click', function () {
    update(true);
});
// Stop animation when clicking and dragging range bar
input.addEventListener('input', function () {
    pause(btn);
    update(true);
});
相关推荐
程序员爱钓鱼3 小时前
Rust Vec 动态数组详解:创建、增删、遍历与排序
前端·后端·rust
超人不会飞_Jay3 小时前
Go课程2
开发语言·后端·golang
LaughingZhu4 小时前
Product Hunt 每日热榜 | 2026-07-23
前端·神经网络·react.js·搜索引擎·前端框架
To_OC4 小时前
拼路径读文件总踩坑?我把 Node 的 path 和 fs 彻彻底底捋了一遍
javascript·后端·node.js
Tirzano4 小时前
java 精简使用ffmpeg
java·开发语言·ffmpeg
自然 醒4 小时前
记录We码开发者工具的一个bug
前端·javascript·bug
葡萄城技术团队4 小时前
HTML元素单元格:用自定义 CellType 扩展 SpreadJS 的显示能力
前端·javascript·html
不好听6134 小时前
Fragment:React 的 `<></>` 和原生的 DocumentFragment,同名不同命
前端·react.js·dom
农村小镇哥4 小时前
python操作配置文件ini
开发语言·python
不好听6134 小时前
useState 完全解析:初始化、异步更新、以及为什么传函数能解决闭包问题
前端·react.js