最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Echarts stacked bar chartwaterfall chart unable to create - Stack Overflow

programmeradmin1浏览0评论

I'm trying to make a stacked bar chart / waterfall chart and I am having a lot of difficulties setting it up. I'm using echarts with vue, but the framework doesn't matter that much. Any help regarding setting this up in echarts would be extremely helpful!

It needs to look like this:

The following code is what I ended up with, which just creates randomly generated data as a mock.

import { defineComponent, ref, onMounted } from 'vue';
import { use } from 'echarts/core';
import VChart from 'vue-echarts';
import { BarChart } from 'echarts/charts';
import { GridComponent, TooltipComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';

use([BarChart, GridComponent, TooltipComponent, CanvasRenderer]);

export default defineComponent({
  components: {
    VChart,
  },
  setup() {
    const timeIntervals = ref([]);
    
    const updateTimeIntervals = () => {
      const intervals = [];
      let startTime = new Date();
      startTime.setMinutes(0, 0, 0);
      for (let i = 0; i < 8; i++) { // 8 hours with 1-hour intervals
        intervals.push(
          startTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
        );
        startTime.setHours(startTime.getHours() + 1);
      }
      timeIntervals.value = intervals;
    };
    
    onMounted(updateTimeIntervals);
    
    const chartOptions = ref({
      tooltip: {
        trigger: 'axis',
        axisPointer: { type: 'shadow' },
      },
      xAxis: {
        type: 'category',
        data: timeIntervals,
        axisLabel: { rotate: 45 },
      },
      yAxis: {
        type: 'value',
        min: -100,
        max: 100,
      },
      series: [
        {
          name: 'Category A',
          type: 'bar',
          stack: 'total',
          data: Array.from({ length: 8 }, () => Math.floor(Math.random() * 200 - 100)),
          color: '#5470c6',
        },
        {
          name: 'Category A (Duplicate)',
          type: 'bar',
          stack: 'total',
          data: Array.from({ length: 8 }, () => Math.floor(Math.random() * 200 - 100)),
          color: '#91cc75',
        },
        {
          name: 'Category B',
          type: 'bar',
          stack: 'total',
          data: Array.from({ length: 8 }, () => Math.floor(Math.random() * 200 - 100)),
          color: '#fac858',
        },
        {
          name: 'Category C',
          type: 'bar',
          stack: 'total',
          data: Array.from({ length: 8 }, () => Math.floor(Math.random() * 200 - 100)),
          color: '#ee6666',
        },
        {
          name: 'Category D',
          type: 'bar',
          stack: 'total',
          data: Array.from({ length: 8 }, () => Math.floor(Math.random() * 200 - 100)),
          color: '#73c0de',
        },
      ],
    });
    
    return { chartOptions, timeIntervals };
  },
});

The code above generates something like this which has multiple where htings where items overlap, not centered in 0 (this is because of mock data) and it just generally isn't what I want. But this is the furthest I have come:

I'm trying to make a stacked bar chart / waterfall chart and I am having a lot of difficulties setting it up. I'm using echarts with vue, but the framework doesn't matter that much. Any help regarding setting this up in echarts would be extremely helpful!

It needs to look like this:

The following code is what I ended up with, which just creates randomly generated data as a mock.

import { defineComponent, ref, onMounted } from 'vue';
import { use } from 'echarts/core';
import VChart from 'vue-echarts';
import { BarChart } from 'echarts/charts';
import { GridComponent, TooltipComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';

use([BarChart, GridComponent, TooltipComponent, CanvasRenderer]);

export default defineComponent({
  components: {
    VChart,
  },
  setup() {
    const timeIntervals = ref([]);
    
    const updateTimeIntervals = () => {
      const intervals = [];
      let startTime = new Date();
      startTime.setMinutes(0, 0, 0);
      for (let i = 0; i < 8; i++) { // 8 hours with 1-hour intervals
        intervals.push(
          startTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
        );
        startTime.setHours(startTime.getHours() + 1);
      }
      timeIntervals.value = intervals;
    };
    
    onMounted(updateTimeIntervals);
    
    const chartOptions = ref({
      tooltip: {
        trigger: 'axis',
        axisPointer: { type: 'shadow' },
      },
      xAxis: {
        type: 'category',
        data: timeIntervals,
        axisLabel: { rotate: 45 },
      },
      yAxis: {
        type: 'value',
        min: -100,
        max: 100,
      },
      series: [
        {
          name: 'Category A',
          type: 'bar',
          stack: 'total',
          data: Array.from({ length: 8 }, () => Math.floor(Math.random() * 200 - 100)),
          color: '#5470c6',
        },
        {
          name: 'Category A (Duplicate)',
          type: 'bar',
          stack: 'total',
          data: Array.from({ length: 8 }, () => Math.floor(Math.random() * 200 - 100)),
          color: '#91cc75',
        },
        {
          name: 'Category B',
          type: 'bar',
          stack: 'total',
          data: Array.from({ length: 8 }, () => Math.floor(Math.random() * 200 - 100)),
          color: '#fac858',
        },
        {
          name: 'Category C',
          type: 'bar',
          stack: 'total',
          data: Array.from({ length: 8 }, () => Math.floor(Math.random() * 200 - 100)),
          color: '#ee6666',
        },
        {
          name: 'Category D',
          type: 'bar',
          stack: 'total',
          data: Array.from({ length: 8 }, () => Math.floor(Math.random() * 200 - 100)),
          color: '#73c0de',
        },
      ],
    });
    
    return { chartOptions, timeIntervals };
  },
});

The code above generates something like this which has multiple where htings where items overlap, not centered in 0 (this is because of mock data) and it just generally isn't what I want. But this is the furthest I have come:

Share Improve this question asked Mar 14 at 9:38 dunctdunct 811 silver badge8 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

You can achieve the given look by using two different stacks, one for the positive and one for the negative part. The resulting bars can be overlapped with barGap: "-100%". Note, that the blue bar is cut into two pieces, which might complicate things when using legend or tooltip.

Example:

const data = [{
    time: 1,
    blue: 48,
    green_pos: 0,
    green_neg: 0,
    yellow_pos: 0,
    yellow_neg: 0
  }, ... ];

option = {
  xAxis: {
    type: 'category',
  },
  yAxis: { type: 'value' },
  series: [
    {
      name: 'blue_pos',
      type: 'bar',
      stack: 'pos',
      data: data.map(x => x.blue / 2),
      color: '#5470c6'
    },
    {
      name: 'blue_neg',
      type: 'bar',
      stack: 'neg',
      data: data.map(x => -x.blue / 2),
      color: '#5470c6'
    },
    {
      name: 'green_pos',
      type: 'bar',
      stack: 'pos',
      data: data.map(x => x.green_pos),
      color: '#91cc75'
    },
    {
      name: 'green_neg',
      type: 'bar',
      stack: 'neg',
      data: data.map(x => -x.green_neg),
      color: '#91cc75'
      
    },
    {
      name: 'yellow_pos',
      type: 'bar',
      stack: 'pos',
      data: data.map(x => x.yellow_pos),
      color: '#fac858'
    },
    {
      name: 'yellow_neg',
      type: 'bar',
      stack: 'neg',
      data: data.map(x => -x.yellow_neg),
      color: '#fac858',
      barGap: "-100%"
    },
  ]
};
发布评论

评论列表(0)

  1. 暂无评论