echarts实现实线与虚线相连接的折线图

6 篇文章 0 订阅
2 篇文章 0 订阅

**

一:UI效果图

**
在这里插入图片描述
**

二:后台返回的数据格式

**

[
 {measureTime:'2021-5-1',value:36,level:1},
 {measureTime:'2021-5-2',value:37.9,level:2},
 {measureTime:'2021-5-3',value:39,level:3},
 ...
]

**

三:代码实现

**


const weekDict2 = ["周一", "周二", "周三", "周四", "周五", "周六", "周日",]
const itemStyleList = [
    { color: '#50D3A1' },
    { color: '#FAAD14' },
    { color: '#FF5858' },
]
getLenRatio = () => {
        const DESIGN_WIDTH = 750; // 设计稿宽度
        return document.documentElement.clientWidth / DESIGN_WIDTH;
    }

getFristDay = (date) => {
        const frist = moment(date).startOf('month');
        switch (frist.day()) {
            case 6:
                return frist.add(2, 'days');
            case 0:
                return frist.add(1, 'days');
            default:
                return frist;
        }
    }

initChart = (tempList = [], reportType) => {
        tempList = tempList || [];
        const { id, chartType } = chartIdList[reportType - 1];
        const dom = document.getElementById(id);
        if (!dom) return;
        this[chartType] = echarts.init(dom);
        const ratio = this.getLenRatio(); //获取比例
        const xAxisData = [];   //x轴数据
        const seriesData1 = []; //实线折线图数据
        const trueSeriesData1 = []; //实线折线图series数据
        const trueTempData = [];  //剔除不存在的体温数据
        const tempNullData = []; //temp为null的数据
        const fristDay = tempList && tempList.length && this.getFristDay(tempList[0].measureTime);
        tempList.forEach((items, index) => {
            const { measureTime, value, level } = items;
            // level 1:正常 2:低热,3高热
            xAxisData.push(measureTime);
            seriesData1.push(value);
            trueSeriesData1.push({ value, symbol: 'circle', itemStyle: level ? itemStyleList[level - 1] : {} })
            if (level) trueTempData.push(value);
            if (typeof level === 'object') tempNullData.push(index);
        });
        //有体温≥37.3°显示高热线
        const maxTemp = Math.max.apply(null, trueTempData);
        const minTemp = Math.min.apply(null, trueTempData);
        const flag = maxTemp && maxTemp >= 37.3;
        const markLineData = [
            { yAxis: 37.3, lineStyle: { color: '#FAAD14', type: 'dashed' } },
        ];
        let yAxisMax = 38;
        let yAxisMin = 34;
        if (minTemp && minTemp < 34) {
            yAxisMin = Math.floor(minTemp);
        }
        if (flag) {
            markLineData.push({
                yAxis: 38.5,
                lineStyle: {
                    color: '#FF6B53',
                    type: 'dashed'
                }
            });
            if (maxTemp > 39) {
                yAxisMax = Math.ceil(maxTemp);
            } else {
                yAxisMax = 39;
            }
        }
        console.log(markLineData);
        //1.如果一个点为空,则其左右两个点得在第二数组,且此点是左右两值的平均点
        //2.如果连续点为空,则取到其后不为null的那个点,
        // 用此点减去上一个点的值的绝对值除以连续空白数量+1,
        // 安插到null值处
        let seriesData2 = [];  //虚线折线图数据
        const tempNullLength = tempNullData.length;
        console.log(tempNullLength, seriesData1.length);
        // 如果有null数据且不全为null数据则进入此判断
        if (!!tempNullLength && tempNullLength !== seriesData1.length) {
            const dataForSeries2 = []; //得出seriesData2的数组
            seriesData1.forEach((items, index) => {
                // 如果value为null 则isReal为false,表示为假数据,
                // 如果为null情况下前后的temp有null,则isContinuous为true 表示连续
                // 如果isReal为true,同时前后没有isReal为false的数据 isNull为true
                const obj = {};
                obj.index = index;
                obj.value = items;
                const preTempType = typeof seriesData1[index - 1] === 'object';
                const nextTempType = typeof seriesData1[index + 1] === 'object';
                if (typeof items === 'object') {
                    obj.isReal = false;
                    obj.isNull = false;
                    if (preTempType || nextTempType) {
                        obj.isContinuous = true;
                    } else {
                        obj.isContinuous = false;
                    }
                } else {
                    obj.isReal = true;
                    if (preTempType || nextTempType) {
                        obj.isNull = false;
                    } else {
                        obj.isNull = true;
                    }
                    obj.isContinuous = false;
                }
                dataForSeries2.push(obj);
            })
            
            //得到dataForSeries2循环获取seriesData2
            for (let i = 0; i < dataForSeries2.length;) {
                const { isReal, isNull, isContinuous, value } = dataForSeries2[i];
                if (isNull) { //如果是null值,就说明该数据前后都是真实数据,继续下一次循环
                    seriesData2[i] = null;
                    i++;
                    continue;
                }
                if (isReal) {//如果不是null值,且是真实数据,继续下一次循环
                    seriesData2[i] = value;
                    i++;
                    continue;
                }
                if (isContinuous) {//如果不是null值也不是真实数据,就判断是否连续,
                    //计算连续段数
                    let continuousNo = 1;
                    for (let continuousIndex = i + 1; continuousIndex < dataForSeries2.length; continuousIndex++) {
                        if (dataForSeries2[continuousIndex].isContinuous) {
                            continuousNo += 1;
                        } else {
                            break;
                        }
                    }

                    if (continuousNo + i === dataForSeries2.length) { // 如果连续到末尾,则所有数据都与之前数据相同
                        for (let continuousNo2 = i; continuousNo2 < dataForSeries2.length; continuousNo2++) {
                            seriesData2[continuousNo2] = dataForSeries2[i - 1].value
                        }
                        i += continuousNo;
                    } else {
                        // 如果连续就看连续段数,将连续结束后的真实数据-连续开始时的数据/(连续段数+1)设置好所有数据后i+上连续段数
                        let preTemp = dataForSeries2[i - 1] && dataForSeries2[i - 1].value;
                        const nextTemp = dataForSeries2[i + continuousNo] && dataForSeries2[i + continuousNo].value;
                        let diffValue = 0;
                        if (preTemp) {
                            diffValue = (nextTemp - preTemp) / (continuousNo + 1);
                        } else {
                            preTemp = nextTemp;
                        }
                        preTemp = preTemp - 0; //转化为数字
                        for (let continuousNo2 = i; continuousNo2 <= i + continuousNo; continuousNo2++) {
                            seriesData2[continuousNo2] = preTemp + diffValue;
                            preTemp += diffValue;
                        }
                        i += continuousNo;
                    }
                } else {
                    //如果不连续,看前后是否都有值,有值就取平均值,没有就取有值的 主要是防止开头和结尾
                    const preTemp = dataForSeries2[i - 1] && dataForSeries2[i - 1].value;
                    const nextTemp = dataForSeries2[i + 1] && dataForSeries2[i + 1].value;
                    console.log(preTemp, nextTemp);
                    if (preTemp && nextTemp) {
                        seriesData2[i] = (preTemp - 0 + (nextTemp - 0)) / 2;
                    } else {
                        seriesData2[i] = preTemp || nextTemp;
                    }
                    i++;
                }
            }
        }
        
        const options = {
            grid: {
                left: 10 * ratio,
                right: 24 * ratio,
                top: 60,
                bottom: 40,
                containLabel: true,
            },
            xAxis: {
                type: 'category',
                data: reportType === 1 ? weekDict2 : xAxisData,
                axisLine: {
                    lineStyle: {
                        color: '#968CAC',
                        opacity: .2
                    }
                },
                axisTick: {
                    show: false,
                },
                axisLabel: {
                    show: true,
                    margin: 24 * ratio,
                    align: 'center',
                    interval: 0,
                    color: '#666',
                    formatter: (value, index) => {
                        if (reportType === 1) {
                            return value;
                        }
                        //第一个日期显示为本月第一个工作日 后面为每周周一
                        let date = moment(value);
                        let weekDay = date.day();
                        if (date.isSame(fristDay)) return date.format('MM.DD');
                        if (weekDay === 1) return date.format('MM.DD');
                    }
                },
                splitLine: {
                    show: false
                },
            },
            yAxis: {
                type: 'value',
                name: '(℃)',
                nameGap: 16,
                max: yAxisMax,
                min: yAxisMin,
                minInterval: 1,
                nameTextStyle: {
                    color: '#666',
                    align: 'right',
                    padding: [0, 24 * ratio, 0, 0]
                },
                axisLine: {
                    show: true,
                    lineStyle: {
                        color: '#968CAC',
                        opacity: .2
                    }
                },
                axisTick: {
                    show: false
                },
                axisLabel: {
                    color: '#666',
                    verticalAlign: 'middle',
                    formatter: (value, index) => {
                        return `${value}.0`;
                    },
                    margin: 28 * ratio,
                    padding: [3, 0, 0, 0],
                },
                splitLine: {
                    lineStyle: {
                        color: '#968CAC',
                        opacity: .2
                    }
                },

            },
            series: [
                {
                    name: '体温',
                    symbolSize: 12 * ratio,
                    data: trueSeriesData1,
                    type: 'line',
                    lineStyle: {
                        color: 'rgba(0,0,0,.2)',
                        width: 2
                    },
                    markLine: {
                        symbol: 'none',
                        label: { show: false },
                        data: markLineData

                    }
                },
                {
                    name: '体温',
                    data: seriesData2,
                    type: 'line',
                    showSymbol: false,
                    lineStyle: {
                        color: 'rgba(0,0,0,.2)',
                        width: 1,
                        type: 'dashed'
                    },
                }
            ]
        };

        this[chartType].setOption(options);
    }

**

四:结尾

**
1.欢迎转载,请备明转载及链接
2.欢迎给出意见和建议,有问题可以在评论区指出

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值