您现在的位置是:网站首页 > 平行坐标系(Parallel)实现文章详情

平行坐标系(Parallel)实现

平行坐标系(Parallel)实现

平行坐标系是ECharts中用于展示高维数据的强大工具。它通过多个平行轴将多维数据映射到二维平面,每个轴代表一个维度,数据点在各轴上对应位置用折线连接,形成直观可视化效果。

基本配置

平行坐标系的核心配置项是parallelparallelAxis。以下是最简配置示例:

option = {
  parallelAxis: [
    { dim: 0, name: 'Price' },
    { dim: 1, name: 'Weight' },
    { dim: 2, name: 'Rating' }
  ],
  series: {
    type: 'parallel',
    data: [
      [12, 56, 3.6],
      [23, 89, 4.2],
      [31, 47, 5.0]
    ]
  }
};

坐标轴配置

平行坐标系的每个轴都可以单独配置:

parallelAxis: [
  {
    dim: 0,
    name: '温度(℃)',
    type: 'value',
    min: -10,
    max: 40,
    axisLine: { lineStyle: { color: '#FF4500' } }
  },
  {
    dim: 1,
    name: '湿度(%)',
    inverse: true,
    nameLocation: 'end',
    nameTextStyle: { fontWeight: 'bold' }
  }
]

数据映射与样式

数据系列支持丰富的样式配置:

series: {
  type: 'parallel',
  lineStyle: {
    width: 2,
    opacity: 0.7,
    color: function(params) {
      const colorList = ['#c23531','#2f4554','#61a0a8'];
      return colorList[params.dataIndex % 3];
    }
  },
  emphasis: {
    lineStyle: {
      width: 4,
      opacity: 1
    }
  },
  data: [
    { value: [12, 5.4, 32], name: '产品A' },
    { value: [18, 6.2, 45], name: '产品B' }
  ]
}

交互功能

平行坐标系支持多种交互:

parallel: {
  parallelAxisDefault: {
    axisLabel: { interval: 'auto' },
    tooltip: { show: true },
    realtime: true  // 拖动轴时实时更新
  },
  axisExpandable: true,
  axisExpandCenter: 2,
  axisExpandCount: 5,
  axisExpandWidth: 50
}

大数据量优化

处理大量数据时的性能优化方案:

series: {
  type: 'parallel',
  progressive: 500,  // 增量渲染阈值
  smooth: true,     // 平滑曲线
  dimensions: ['date', 'value1', 'value2'],
  data: largeDataSet,
  itemStyle: {
    opacity: 0.05  // 半透明处理重叠线
  }
}

与其它图表联动

实现平行坐标系与散点图的联动:

option = {
  grid: [
    { left: '5%', width: '45%', bottom: '55%' },
    { left: '55%', width: '45%', bottom: '55%' }
  ],
  xAxis: [{ gridIndex: 0 }, { gridIndex: 1 }],
  yAxis: [{ gridIndex: 0 }, { gridIndex: 1 }],
  parallel: {
    top: '60%',
    height: '35%'
  },
  series: [
    {
      type: 'scatter',
      xAxisIndex: 0,
      yAxisIndex: 0,
      data: scatterData1
    },
    {
      type: 'parallel',
      data: parallelData,
      selectedMode: 'multiple',
      brushSelect: true
    }
  ]
};

自定义视觉映射

通过visualMap实现数据到视觉通道的映射:

visualMap: {
  type: 'continuous',
  dimension: 2,  // 基于第三个维度映射
  seriesIndex: 0,
  min: 0,
  max: 100,
  inRange: {
    color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
  }
}

真实案例:汽车数据可视化

完整的多维汽车数据可视化示例:

option = {
  dataset: {
    source: [
      ['Model', 'MPG', 'Cylinders', 'Displacement', 'Horsepower', 'Weight', 'Acceleration', 'Year'],
      ['Chevrolet', 18, 8, 307, 130, 3504, 12, 70],
      ['Buick', 15, 8, 350, 165, 3693, 11.5, 70]
    ]
  },
  parallelAxis: [
    { dim: 1, name: 'MPG' },
    { dim: 2, name: 'Cylinders', type: 'category' },
    { dim: 3, name: 'Displacement' },
    { dim: 4, name: 'Horsepower' },
    { dim: 5, name: 'Weight' },
    { dim: 6, name: 'Acceleration' },
    { dim: 7, name: 'Year', type: 'category' }
  ],
  series: {
    type: 'parallel',
    datasetIndex: 0,
    lineStyle: {
      width: 1
    },
    emphasis: {
      lineStyle: {
        width: 3
      }
    },
    tooltip: {
      formatter: function(params) {
        return params.seriesName + '<br>' +
          params.marker + params.data[0] + '<br>' +
          params.value.map((val, idx) => {
            return option.parallelAxis[idx].name + ': ' + val;
          }).join('<br>');
      }
    }
  }
};

高级交互:轴缩放与过滤

实现基于轴范围的动态数据过滤:

option = {
  parallel: {
    axisExpandable: true,
    axisExpandCenter: 3,
    axisExpandCount: 6,
    axisExpandWidth: 30,
    parallelAxisDefault: {
      tooltip: { show: true },
      type: 'value',
      nameLocation: 'end',
      nameGap: 20,
      nameTextStyle: { fontSize: 12 }
    }
  },
  brush: {
    parallelIndex: 0,
    inBrush: { opacity: 1 },
    outOfBrush: { opacity: 0.2 },
    throttleType: 'debounce',
    throttleDelay: 300
  }
};

性能优化技巧

处理超大规模数据集时的实用技巧:

// 数据采样策略
function downSample(data, factor) {
  return data.filter((_, index) => index % factor === 0);
}

// Web Worker处理
const worker = new Worker('parallelWorker.js');
worker.postMessage({ action: 'process', data: rawData });
worker.onmessage = function(e) {
  myChart.setOption({
    series: [{ type: 'parallel', data: e.data }]
  });
};

// 分块渲染
function chunkRender(data, chunkSize = 1000) {
  let rendered = 0;
  const timer = setInterval(() => {
    const chunk = data.slice(rendered, rendered + chunkSize);
    myChart.appendData({ seriesIndex: 0, data: chunk });
    rendered += chunkSize;
    if (rendered >= data.length) clearInterval(timer);
  }, 200);
}

动态更新与动画

实现数据的动态更新效果:

let currentData = initialData;
setInterval(() => {
  currentData = currentData.map(item => {
    return item.map(val => val * (0.9 + Math.random() * 0.2));
  });
  
  myChart.setOption({
    series: [{
      type: 'parallel',
      data: currentData,
      animationDurationUpdate: 1000,
      animationEasingUpdate: 'cubicInOut'
    }]
  });
}, 2000);

多系列对比

在同一坐标系中展示多个数据系列:

series: [
  {
    type: 'parallel',
    name: '2022年',
    data: data2022,
    lineStyle: { color: '#FFA500' }
  },
  {
    type: 'parallel',
    name: '2023年',
    data: data2023,
    lineStyle: { color: '#1E90FF' }
  }
],
legend: {
  data: ['2022年', '2023年'],
  selected: {
    '2022年': true,
    '2023年': false
  }
}

坐标轴个性化

为不同坐标轴应用不同样式:

parallelAxis: [
  {
    dim: 0,
    name: '温度',
    axisLine: {
      lineStyle: {
        color: '#FF6347',
        width: 3
      }
    },
    axisLabel: {
      formatter: '{value} °C'
    }
  },
  {
    dim: 1,
    name: '压力',
    axisTick: {
      inside: true
    },
    splitArea: {
      show: true,
      areaStyle: {
        color: ['rgba(255,255,255,0.3)','rgba(200,200,200,0.3)']
      }
    }
  }
]

响应式设计

适应不同屏幕尺寸的配置方案:

function resizeParallel() {
  const width = window.innerWidth;
  const option = {
    parallel: {
      left: width < 768 ? '5%' : '15%',
      right: width < 768 ? '5%' : '15%',
      top: width < 768 ? '20%' : '15%',
      bottom: width < 768 ? '15%' : '10%',
      parallelAxisDefault: {
        nameTextStyle: {
          fontSize: width < 768 ? 10 : 12
        }
      }
    }
  };
  myChart.setOption(option);
}

window.addEventListener('resize', resizeParallel);

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步