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

如何修改ECharts ThemeRiver以实现堆叠流面积图效果?

将ECharts ThemeRiver图表修改为堆叠流面积图的方案

要把现有ThemeRiver图表改成堆叠流面积图,核心是切换到直角坐标系、重构数据结构、使用带堆叠配置的折线面积图。以下是具体修改步骤和完整代码:

关键修改点

  • 替换单轴(singleAxis)为直角坐标系的xAxis和yAxis
  • 按电影分组重构数据,每个电影对应一个独立的折线面积系列
  • 给所有系列设置相同的stack属性实现堆叠效果
  • 开启areaStyle配置实现面积填充

修改后的完整代码

async function loadData() {
  try {
    const response = await fetch("h");

    const csvText = await response.text();

    const rows = csvText.split("\n").filter(row => row.trim() !== "");
    const userArray = [];
    const headers = rows[0].split(",");

    for (let i = 1; i < rows.length; i++) {
      const regex = /(".*?"|[^",\s]+)(?=\s*,|\s*$)/g;
      const values = rows[i].match(regex).map(value => value.replace(/^"|"$/g, "").trim());

      const releaseDate = new Date(values[1]);
      const releaseYear = releaseDate.getFullYear();

      if (releaseYear !== 2004) continue;

      const dailySales = values.slice(2).map(value => {
        if (!value || value === "") return 0;
        return parseInt(value.replace(/,/g, ""), 10);
      });

      const extendedDates = Array.from({ length: dailySales.length }, (_, index) => {
        const date = new Date(releaseDate);
        date.setDate(date.getDate() + index);

        const year = date.getFullYear();
        const month = String(date.getMonth() + 1).padStart(2, "0");
        const day = String(date.getDate()).padStart(2, "0");
        return `${year}/${month}/${day}`;
      });

      const dataObject = {
        영화: values[0],
        개봉일: releaseDate,
        개봉일차: extendedDates,
        일수_매출액: dailySales
      };

      userArray.push(dataObject);
    }
    return userArray;
  } catch (error) {
    console.error("데이터 로드 중 오류 발생:", error);
  }
}

function getISOWeek(date) {
  const tempDate = new Date(date);
  tempDate.setHours(0, 0, 0, 0);
  tempDate.setDate(tempDate.getDate() + 3 - ((tempDate.getDay() + 6) % 7));
  const week1 = new Date(tempDate.getFullYear(), 0, 4);
  return Math.round(((tempDate - week1) / (7 * 24 * 60 * 60 * 1000)) + 1);
}

async function createChart() {
  try {
    const userArray = await loadData();

    const chartDom = document.getElementById("root1");
    const myChart = echarts.init(chartDom);

    // 按电影分组重构数据:每个电影对应一组[周数, 周销售额]数据
    const seriesDataMap = new Map();
    const allWeeks = new Set();

    userArray.forEach(obj => {
      const movieName = obj.영화;
      const releaseWeek = getISOWeek(obj.개봉일);
      const dailySales = obj.일수_매출액;

      // 计算周销售额
      const weeklySales = [];
      for (let j = 0; j < dailySales.length; j += 7) {
        const weeklyTotal = dailySales
          .slice(j, j + 7)
          .reduce((sum, value) => sum + value, 0);
        weeklySales.push(weeklyTotal);
      }

      // 生成当前电影的系列数据
      const movieSeriesData = [];
      weeklySales.forEach((sales, k) => {
        const weekNumber = releaseWeek + k;
        movieSeriesData.push([weekNumber, sales]);
        allWeeks.add(weekNumber);
      });

      seriesDataMap.set(movieName, movieSeriesData);
    });

    // 转换为ECharts系列配置数组
    const series = Array.from(seriesDataMap.entries()).map(([name, data]) => ({
      name: name,
      type: 'line',
      stack: 'sales', // 相同stack值实现堆叠
      data: data,
      areaStyle: {}, // 开启面积填充
      label: {
        show: false
      },
      emphasis: {
        itemStyle: {
          shadowBlur: 20,
          shadowColor: 'rgba(0, 0, 0, 0.8)'
        }
      }
    }));

    option = {
      xAxis: {
        type: 'value',
        name: '주차',
        min: Math.min(...allWeeks),
        max: Math.max(...allWeeks)
      },
      yAxis: {
        type: 'value',
        name: '주간 매출액'
      },
      dataZoom: [
        {
          type: 'slider',
          show: true,
          start: 0,
          end: 100,
          handleSize: 8,
          xAxisIndex: 0
        },
        {
          type: 'inside',
          start: 94,
          end: 100,
          xAxisIndex: 0
        }
      ],
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'cross'
        }
      },
      legend: {
        data: Array.from(seriesDataMap.keys())
      },
      series: series
    };

    myChart.setOption(option);
    // 监听窗口变化,自适应图表
    window.addEventListener('resize', () => {
      myChart.resize();
    });
  } catch (error) {
    console.error("Error creating chart:", error);
  }
}

createChart();

代码说明

  1. 数据重构:使用Map按电影名称分组,将每个电影的周销售额转换为[周数, 销售额]的格式,同时收集所有周数用于坐标轴范围设置。
  2. 坐标系切换:移除singleAxis,添加xAxis(周数)和yAxis(销售额),设置合适的轴类型和名称。
  3. 堆叠配置:所有系列设置相同的stack: 'sales',ECharts会自动处理堆叠计算。
  4. 面积效果:通过areaStyle: {}开启面积填充,实现流面积图的视觉效果。
  5. 交互优化:添加legend显示电影名称,tooltip优化轴提示,同时添加窗口 resize 监听保证图表自适应。

内容的提问来源于stack exchange,提问作者홍준표

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:58:12