You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Highcharts中按系列相对位置用双色高亮两条线间区域?

实现Highcharts中两系列间区域的差异化高亮

需求是在Highcharts里高亮两个系列之间的区域,根据系列的相对位置使用不同颜色:

  • 当绿色系列(London)在蓝色系列(Tokyo)上方时,用绿色填充该区域(正区间)
  • 当绿色系列在蓝色系列下方时,用红色填充该区域(负区间)

你当前手动拆分arearange数据的方式无法在两条线的交点处精准停止填充,导致效果不符合预期。正确的做法是自动计算两个系列数据的交点,动态生成对应颜色的填充区间,具体实现如下:

完整实现代码

$(function () {
    // 原始数据
    const tokyoData = [7.0, 6.9, 9.5, 10, 11, 10, 10, 10, 10, 10, 10, 9.6];
    const londonData = [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 11.3, 6.6, 4.8];
    
    // 生成填充区域数据的函数
    function generateFillData(seriesA, seriesB) {
        const redData = []; // 绿色在蓝色下方的区间
        const greenData = []; // 绿色在蓝色上方的区间
        
        // 遍历每个相邻数据点对
        for (let i = 0; i < seriesA.length - 1; i++) {
            const y1A = seriesA[i];
            const y2A = seriesA[i + 1];
            const y1B = seriesB[i];
            const y2B = seriesB[i + 1];
            
            // 情况1:当前区间内绿色始终在蓝色下方
            if (y1B <= y1A && y2B <= y2A) {
                redData.push([y1B, y1A]);
                redData.push([y2B, y2A]);
            }
            // 情况2:当前区间内绿色始终在蓝色上方
            else if (y1B >= y1A && y2B >= y2A) {
                greenData.push([y1A, y1B]);
                greenData.push([y2A, y2B]);
            }
            // 情况3:区间内存在交点,拆分两个子区间
            else {
                // 计算交点的x轴位置(0-1之间的比例)
                const t = (y1A - y1B) / ((y2B - y1B) - (y2A - y1A));
                // 计算交点的y值
                const intersectY = y1A + t * (y2A - y1A);
                
                // 第一个子区间(从i到交点)
                if (y1B < y1A) {
                    redData.push([y1B, y1A]);
                    redData.push([intersectY, intersectY]);
                    greenData.push([intersectY, intersectY]);
                    greenData.push([y2A, y2B]);
                } else {
                    greenData.push([y1A, y1B]);
                    greenData.push([intersectY, intersectY]);
                    redData.push([intersectY, intersectY]);
                    redData.push([y2B, y2A]);
                }
            }
        }
        
        // 处理数据格式,转换为Highcharts arearange需要的点数组
        const formatData = (data) => {
            const formatted = [];
            for (let j = 0; j < data.length; j += 2) {
                formatted.push(data[j]);
            }
            return formatted;
        };
        
        return {
            redFill: formatData(redData),
            greenFill: formatData(greenData)
        };
    }
    
    // 生成填充数据
    const fillData = generateFillData(tokyoData, londonData);
    
    // 初始化图表
    $('#container').highcharts({
        title: {
            text: 'Monthly Average Temperature',
            x: -20 // 居中
        },
        subtitle: {
            text: 'Source: WorldClimate.com',
            x: -20
        },
        xAxis: {
            categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        },
        yAxis: {
            title: {
                text: 'Temperature (°C)'
            },
            plotLines: [{
                value: 0,
                width: 1,
                color: '#808080'
            }]
        },
        tooltip: {
            valueSuffix: '°C'
        },
        legend: {
            layout: 'vertical',
            align: 'right',
            verticalAlign: 'middle',
            borderWidth: 0
        },
        series: [
            {
                name: 'Tokyo',
                data: tokyoData
            },
            {
                type: 'arearange',
                data: fillData.redFill,
                showInLegend: false,
                color: 'red',
                fillOpacity: 0.3 // 调整填充透明度,避免遮挡线条
            },
            {
                type: 'arearange',
                data: fillData.greenFill,
                showInLegend: false,
                color: 'green',
                fillOpacity: 0.3
            },
            {
                name: 'London',
                data: londonData
            }
        ]
    });
});

代码关键点说明

  1. 动态计算填充区间:通过遍历两个系列的相邻数据点,判断位置关系,自动拆分区间或计算交点,确保填充在交点处精准停止。
  2. 交点计算逻辑:使用线性插值计算两条线段的交点坐标,将跨交点的区间拆分为两个子区间,分别对应不同的填充颜色。
  3. 数据格式适配:将计算后的点转换为Highcharts arearange系列所需的[低数值, 高数值]格式,保证填充区域正确渲染。
  4. 透明度优化:给arearange添加fillOpacity属性,避免填充区域遮挡原本的线条,提升视觉效果。

内容的提问来源于stack exchange,提问作者pti_jul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 04:53:09