echarts实现甘特图思路

1,793 阅读2分钟
  • 首先设置y轴类型为 category
    yAxis: {
        data: [...],
        type: 'category',
        inverse: true,
        axisLine: {
            show: false,
        },
        axisTick: {
            show: false,
        },
        splitLine: { show: false },
    }
  • 设置x轴为 value, 并设置起始值min,结束值max
    xAxis: {
        type: 'value',
        min: 0,
        max: 24,
        scale: true,
        splitLine: {
            show: false,
        },
        axisLine: {
            show: false,
        },
    }
  • 接下来定义一个自定义系列custom
    series: [
        // 矩形
        {
            type: 'custom',
            renderItem: renderItem,
            yAxisIndex: 0,
            itemStyle: {
                opacity: 0.8,
            },
            encode: {
                x: [-1] // 使其不受datazoom控制
            },
            data: data1,
        }
    ]
// 画矩形
function renderItem(params, api) {
    // 数据格式 [2, 3, 4]
    // 2为y轴索引
    const categoryIndex = api.value(0);
    // 3,4为矩形起始 末尾坐标
    const start = api.coord([api.value(1), categoryIndex]);
    const end = api.coord([api.value(2), categoryIndex]);
    const height = api.size([0, 1])[1] * 0.2;

    const rectShape = echarts.graphic.clipRectByRect(
        {
            x: start[0],
            y: start[1] - height / 2,
            width: end[0] - start[0],
            height,
        },
        {
            x: params.coordSys.x,
            y: params.coordSys.y,
            width: params.coordSys.width,
            height: params.coordSys.height,
        }
    );

    return (
        rectShape && {
            type: 'rect',
            transition: ['shape'],
            shape: rectShape,
            style: api.style(),
        }
    );
}
  • 最后传入数据实现
const data1 = [
    {
        value: [0, 1, 8.8],
        itemStyle: { color: '#1abc9c' },
    },
    {
        value: [1, 8.8, 9.2],
        itemStyle: { color: '#f1c40f' },
    },
    {
        value: [2, 9.2, 10],
        itemStyle: { color: '#3498db' },
    },
    {
        value: [3, 9.2, 10],
        itemStyle: { color: '#9b59b6' },
    },
    {
        value: [4, 10, 12.5],
        itemStyle: { color: '#e67e22' },
    },
    {
        value: [2, 12.5, 13],
        itemStyle: { color: '#3498db' },
    },
    {
        value: [0, 13, 14],
        itemStyle: { color: '#1abc9c' },
    },
    {
        value: [4, 14, 19],
        itemStyle: { color: '#e67e22' },
    },
    {
        value: [2, 19, 20],
        itemStyle: { color: '#3498db' },
    },
    {
        value: [5, 20, 21.5],
        itemStyle: { color: '#e74c3c' },
    },
    {
        value: [6, 21.5, 22],
        itemStyle: { color: '#34495e' },
    },
    {
        value: [1, 22, 22.5],
        itemStyle: { color: '#f1c40f' },
    },
    {
        value: [5, 22.5, 24],
        itemStyle: { color: '#e74c3c' },
    },
    {
        value: [5, 0, 1],
        itemStyle: { color: '#e74c3c' },
    }
];

效果如下:

image.png

源代码如下:

const data1 = [
    {
        value: [0, 1, 8.8],
        itemStyle: { color: '#1abc9c' },
    },
    {
        value: [1, 8.8, 9.2],
        itemStyle: { color: '#f1c40f' },
    },
    {
        value: [2, 9.2, 10],
        itemStyle: { color: '#3498db' },
    },
    {
        value: [3, 9.2, 10],
        itemStyle: { color: '#9b59b6' },
    },
    {
        value: [4, 10, 12.5],
        itemStyle: { color: '#e67e22' },
    },
    {
        value: [2, 12.5, 13],
        itemStyle: { color: '#3498db' },
    },
    {
        value: [0, 13, 14],
        itemStyle: { color: '#1abc9c' },
    },
    {
        value: [4, 14, 19],
        itemStyle: { color: '#e67e22' },
    },
    {
        value: [2, 19, 20],
        itemStyle: { color: '#3498db' },
    },
    {
        value: [5, 20, 21.5],
        itemStyle: { color: '#e74c3c' },
    },
    {
        value: [6, 21.5, 22],
        itemStyle: { color: '#34495e' },
    },
    {
        value: [1, 22, 22.5],
        itemStyle: { color: '#f1c40f' },
    },
    {
        value: [5, 22.5, 24],
        itemStyle: { color: '#e74c3c' },
    },
    {
        value: [5, 0, 1],
        itemStyle: { color: '#e74c3c' },
    },
];

// 画矩形
function renderItem(params, api) {
    // 数据格式 [2, 3, 4]
    // 2为y轴索引
    const categoryIndex = api.value(0);
    // 3,4为矩形起始 末尾坐标
    const start = api.coord([api.value(1), categoryIndex]);
    const end = api.coord([api.value(2), categoryIndex]);
    const height = api.size([0, 1])[1] * 0.2;

    const rectShape = echarts.graphic.clipRectByRect(
        {
            x: start[0],
            y: start[1] - height / 2,
            width: end[0] - start[0],
            height,
        },
        {
            x: params.coordSys.x,
            y: params.coordSys.y,
            width: params.coordSys.width,
            height: params.coordSys.height,
        }
    );

    return (
        rectShape && {
            type: 'rect',
            transition: ['shape'],
            shape: rectShape,
            style: api.style(),
        }
    );
}

var option = {
    tooltip: {},
    dataZoom: [
        {
            type: 'slider',
            filterMode: 'weakFilter',
            showDataShadow: false,
            // top: 600,
            labelFormatter: '',
        },
        {
            type: 'inside',
            filterMode: 'weakFilter',
        },
    ],
    grid: {
        // height: 300,
        // bottom: 100
        top: 90,
        right: 20,
    },
    xAxis: {
        type: 'value',
        min: 0,
        max: 24,
        scale: true,
        splitLine: {
            show: false,
        },
        axisLine: {
            show: false,
        },
    },
    yAxis: {
        data: ['睡觉', '洗漱', '吃饭', '在路上', '上班', '娱乐', '运动'],
        type: 'category',
        inverse: true,
        axisLine: {
            show: false,
        },
        axisTick: {
            show: false,
        },
        splitLine: { show: false },
    },
    series: [
        // 矩形
        {
            type: 'custom',
            renderItem: renderItem,
            yAxisIndex: 0,
            itemStyle: {
                opacity: 0.8,
            },
            encode: {
                x: [-1] // 使其不受datazoom控制
            },
            data: data1,
        }
    ]
};

喜欢的点点赞哦~