Vue中使用pyz-charts封装echarts快速插件实现echarts图例

安装pyz-charts稳定版本pyz-charts@1.1.0

image.png
npm install pyz-charts
or
npm install pyz-charts@1.1.0
or
npm install pyz-charts@next
or
npm i pyz-charts@latest

version: 1.1.1+
1、解决了resize冲突问题,加入句柄对象
2、解决了Vue动态绑定渲染层!DOCTYPE标准的高度不能加载的问题
3、释放句柄对象、提升性能
4、依赖echarts所以项目文件不用在npm i echarts这个过程,
防止main.js导入过多依赖影响首次加载性能。
5、兼容TS版本

首先导入main.js文件

// main.js 
import Vue from 'vue';
import PyzCharts from "pyz-charts";

Vue.use(PyzCharts)

Quick Start 快速开始

<!-- a.template -->
<template>
  <pyz-charts @init="callbackEchartsInstance" :option="youEhartsOption"/>
</template>
  • 1、封装了所有的echarts事件,支持所有事件@click等
  • 2、@init事件回调(instance)实例,可以做深度检测,和扩展。
  • 3、option绑定v-bind是echarts的option配置文件,可以写成Option类的实例

例如

<!-- a.template -->
<template>
  <pyz-charts @click="clickMethod" 
  @mousemove="mousemoveMethod" 
  @mouseover="mouseoverMethod" 
  @keydown="keydownMethod" 
  @keyup="keyupMethod" 
  ...
  :option="youEhartsOption"/>
</template>

Option建议写法

 'use strict'
  class CarOption {
      public option: any;
      constructor(props){
         this.option = {};
      }
  }
<script>
// a.vue
  export default {
      ...
     methods: {
         callbackEchartsInstance(ecInstance) {
            ?ecInstance.setOption(option)
            or
            ?ecInstance?....
         }
     }
  }
</script>

为什么建议使用Option写法

option的写法基于面向对象的基础,这样我们可以把同类型的echarts配置作为封装,下次使用的时候就不用那么麻烦的区写配置Option参数,Option中的参数我们可以写算法实现更多的功能及动态参数,下面示例一个动态参数:

'use strict'
import PyzJSON from "./PyzJSON";
import FontDisplayConstraint from "../static/script/FontDisplayConstraint";

class CarRadiusInfoOption {
    constructor(props) {
        this.title = props.title?props.title: {
            text: '默认',
            moduleName: '',
            value_total: 1000,
            diffNum: 50,  // 差异
            allNum: 100, // 总数
            nowLast: false,
        };
        this.contentSize = props.contentSize?props.contentSize:undefined;
        this.toolTipFixed = this.contentSize?(this.contentSize.w/this.contentSize.h>1):false;
        this.keys = props.keys?props.keys:['默认', '默认'];
        this.titleFontSize = this.contentSize?this.contentSize.w/50:10;
        this.titleFontSize = this.titleFontSize<10?10:this.titleFontSize;
        this.titleMargin = this.titleFontSize*3;
        this.titleNumFontSize = this.contentSize?this.contentSize.w/50:10;
        this.titleNumFontSize = this.titleNumFontSize<12?10:this.titleNumFontSize;
        this.targets = props.targets?props.targets:[9, 21];
        this.values = props.values?props.values:[10, 20];
        this.dynamicTargets = props.dynamicTargets?props.dynamicTargets:[0,0];
        // console.log('targets',this.targets)
        // 调整顺序
        // this.keys.reverse(); this.targets.reverse();
        // this.values.reverse(); this.dynamicTargets.reverse()
        // 指针 错乱
        // this.diffNum = props.num?props.num:500;
        // this.allNum = props.allNum?props.allNum:1000;
        this.data = [];
        this.borderWidth = this.contentSize?this.contentSize.w/70:5; // 自适应宽度;
        this.borderWidth = this.borderWidth<5?5:this.borderWidth;
        this.borderColor = 'rgba(0,160,254, 1)';
        // 主要是问题类型
        this.info = props.info;
        this.colorYellowOption = {
            type: 'linear',
            x: 0,
            y: 0,
            x2: 0,
            y2: 1,
            colorStops: [{
                offset: 0, color: 'rgba(0,160,254, 1)' // 0% 处的颜色
            }, {
                offset: 1, color: 'rgba(0,160,254, 0.5)' // 100% 处的颜色
            }],
            global: false // 缺省为 false
        };
        this.colorRedOption = {
            type: 'linear',
            x: 0,
            y: 0,
            x2: 0,
            y2: 1,
            colorStops: [{
                offset: 0, color: 'rgba(252, 2, 33, 1)' // 0% 处的颜色
            }, {
                offset: 1, color: 'rgba(252, 2, 33, 0.5)' // 100% 处的颜色
            }],
            global: false // 缺省为 false
        };
        this.colorGreenOption = {
            type: 'linear',
            x: 0,
            y: 0,
            x2: 0,
            y2: 1,
            colorStops: [{
                offset: 0, color: 'rgba(65, 218, 88, 1)' // 0% 处的颜色
            }, {
                offset: 1, color: 'rgba(65, 218, 88, 0.5)' // 100% 处的颜色
            }],
            global: false // 缺省为 false
        };
        this.init(this.keys, this.targets, this.values);
        this.initGaugeData();
        this.option = {
            title: [
                {
                    text: this.title.text,
                    x: 'center',
                    top: '29%',
                    textStyle: {
                        color: '#fff',
                        fontSize: this.titleFontSize,
                        fontFamily: 'YouSheBiaoTiHei',
                        fontWeight: 100,
                        textShadowColor: '#000',
                        textShadowBlur: 4,
                        textShadowOffsetX: 2,
                        textShadowOffsetY: 2,
                    },
                },
                {
                    text: this.title.value_total, // + '台', // 总数
                    x: 'center',
                    top: '36%',
                    textStyle: {
                        fontSize: this.titleNumFontSize,
                        color: '#fff',
                        fontFamily: 'YouSheBiaoTiHei',
                        fontWeight: 100,
                        textShadowColor: '#000',
                        textShadowBlur: 4,
                        textShadowOffsetX: 2,
                        textShadowOffsetY: 2,
                    },
                },
                //中间大分割线
                {
                    text: '—————',
                    x: 'center',
                    top: '46%',
                    textStyle: {
                        fontSize: this.titleFontSize/1.2,
                        color: this.borderColor,
                        textBorderColor: this.borderColor,
                        textBorderWidth: this.titleFontSize/4,
                        textShadowColor: '#000',
                        textShadowBlur: 4,
                        textShadowOffsetX: 2,
                        textShadowOffsetY: 2,
                    },
                },
                {
                    text: this.title.diffNum, // + '台', // 差异
                    x: 'center',
                    top: '54%',
                    textStyle: {
                        fontSize: this.titleNumFontSize,
                        color: '#fff',
                        fontFamily: 'YouSheBiaoTiHei',
                        fontWeight: 100,
                        textShadowColor: '#000',
                        textShadowBlur: 4,
                        textShadowOffsetX: 2,
                        textShadowOffsetY: 2,
                    },
                },
                {

                    text: ' ',// '差额',
                    x: 'center',
                    top: '62.5%',
                    textStyle: {
                        fontSize: this.titleFontSize,
                        color: '#fff',
                        fontFamily: 'YouSheBiaoTiHei',
                        fontWeight: 100,
                        textShadowColor: '#000',
                        textShadowBlur: 4,
                        textShadowOffsetX: 2,
                        textShadowOffsetY: 2,
                    },
                },
            ],
            tooltip: {
                show: this.toolTipFixed, // 临时
                confine:true,
                enterable: this.toolTipFixed,
                backgroundColor: 'rgba(0,0,0,.8)',
                formatter: (params)=>{
                        let color = params.color.colorStops[0].color;
                        let target = this.getQlalityNumber(this.targets[params.dataIndex]);
                        let value = this.getQlalityNumber(this.values[params.dataIndex]);
                        let etsCss = `background: ${color}; border: 3px solid ${color}`;
                        let barName = this.title.moduleName!=='scale'?'CP8':params.seriesName;
                        let carName = params.name;
                        let data = this.info?.[carName]?.[barName]?this.info?.[carName]?.[barName]?.data:this.info?.[carName]?.data || [];

                        let proText = data.length>0?
                        `${FontDisplayConstraint.toSliceString(data[0][Object.keys(data[0])[3]])}`:'';
                        let dispatchData = {
                            title: `${this.displayName}-${carName}-${barName}-Details:`,
                            data: {
                                title: this.info?.[carName]?.[barName]?.title || this.info?.[carName]?.title,
                                data: data,
                            },
                        }
                        let dispatchJSData = PyzJSON.toOneString(dispatchData);

                        let temple = `
                       <div class="Echarts-Tooltip-typeface">
                        <div style="font-size:20px;">${params.data.name}</div>
                        <div class="Echarts-Tooltip">
                            <div class="Echarts-Tooltips">
                                <div class="Echarts-Tooltip-Style" 
                                style="${etsCss}"></div>
                                <div>Rate:</div>
                            </div> 
                            <div>${params.data.value}%</div>
                        </div>
                        <div class="Echarts-Tooltip">
                            <div class="Echarts-Tooltips">
                                <div class="Echarts-Tooltip-Style"  
                                style="${etsCss}"></div>
                                <div>Target:</div></div> 
                            <div>${target}</div>
                        </div>   
                        <div class="Echarts-Tooltip">
                            <div class="Echarts-Tooltips">
                                <div class="Echarts-Tooltip-Style" 
                                style="${etsCss}"></div>
                                <div>Actual:</div></div> 
                            <div>${value}</div>
                        </div>
                        <div style="display: ${this.title.nowLast?'block':'none'}">
                          <div>Problem:
                            <span>${proText}</span>  
                          </div>
                          <div>
                            <a href="javascript:pyzDialogInfo(${dispatchJSData})">Detail</a>
                          </div>
                        </div>
                       <div>
                     `
                        return temple;
                }
            },
            grid: {
                left: '0%',
                //right: '0%',
                bottom: '0%',
                //top: '30%',
            },
            series: [
                {
                    type: 'gauge',
                    startAngle: 90,
                    endAngle: -270,
                    pointer: {
                        show: false,
                    },
                    emphasis: {
                        itemStyle: {
                           color: '#3DFFFF',
                        },
                    },
                    progress: {
                        show: true,
                        overlap: false,
                        roundCap: true,
                        clip: false,
                        itemStyle: {
                            borderWidth: 1,
                            borderColor: '#464646'
                        }
                    },
                    axisLine: {
                        lineStyle: {
                            width: this.borderWidth,//this.borderWidth,
                            backgroundColor: 'transparent',
                            color:[[1,'rgba(100,100,100, .5)']],
                            // color:[[1,'#484848']],
                            // borderColor:'#484848',
                            // boderWidth:20
                        }
                    },
                    splitLine: {
                        show: false,
                        distance: 0,
                        length: 10
                    },
                    axisTick: {
                        show: false
                    },
                    axisLabel: {
                        show: false,
                        distance: 50
                    },
                    data: this.data,
                    title: {
                        show: false,
                        fontSize: 50,
                    },
                    detail: {
                        show: false,
                        width: 10,
                        height: 14,
                        fontSize: 1,
                        color: 'auto',
                        borderColor: 'auto',
                        borderRadius: 20,
                        formatter: '{value}%',
                    }
                }
            ]
        }
    }

    init(keys, targets, values) {
        this.data = [];
        this.borderWidth = keys.length>2?this.borderWidth*3:this.borderWidth;
        for(let [index, item] of keys.entries()) {
            let tar = targets[index]?targets[index]:1;
            let val = parseFloat(((values[index]/tar)*100).toFixed(1));
            this.data.push({
                    value: val==='Infinity'?0:val,
                    name: item,
                    title: {
                    offsetCenter: ['0%', `${index*10}`]
                },
                detail: {
                    valueAnimation: true,
                    offsetCenter: ['0%', `${index*10}`]
                }
            })
        }
        // 中间颜色
        if(this.title.diffNum>=0) {
            this.borderColor = 'rgba(65, 218, 88, 1)';
        }else{
            this.title.nowLast?
                this.borderColor = 'rgba(252, 2, 33, 1)':
                this.borderColor = 'rgba(0,160,254, 1)';
        }
    }

    initGaugeData() {
        let isSagitar = this.keys.includes('sagitar');
        if (this.values.length > 0) {
            this.data.find((val, index, arr)=>{
                // nowLast 昨天
                if(this.title.nowLast) {
                    if(isSagitar) {
                        // 今天 速腾
                        if(val.value<100) {
                            arr[index] = Object.assign(val,{
                                itemStyle: {
                                    color: this.colorRedOption,
                                }
                            });
                        }else{
                            arr[index] = Object.assign(val,{
                                itemStyle: {
                                    color: this.colorGreenOption,
                                }
                            });
                        }
                    }else{
                        // 今天 捷达
                        if(this.title.diffNum<=0) {
                            arr[index] = Object.assign(val,{
                                itemStyle: {
                                    color: this.colorRedOption,
                                }
                            });
                        }else{
                            arr[index] = Object.assign(val,{
                                itemStyle: {
                                    color: this.colorGreenOption,
                                }
                            });
                        }
                    }
                }else{
                    // 今天
                    if(val.value<100) {
                        arr[index] = Object.assign(val,{
                            itemStyle: {
                               // color: this.title.nowLast?this.colorRedOption:this.colorYellowOption,
                                color: this.colorYellowOption,
                            }
                        });
                    }else{
                        arr[index] = Object.assign(val,{
                            itemStyle: {
                                color: this.colorGreenOption,
                            }
                        });
                    }
                }
            });
        }
    }
    // 求千分数
    // 求千分数
    getQlalityNumber(number) {
        try {
            let nStrs = Math.abs(number).toString();
            let nStr = nStrs;
            let list = [];
            let spits = 3;
            let length = Math.abs(number).toString().length;
            let lg = parseInt( length / spits); // 千分号
            let yus = length % spits;
            lg = yus ? lg + 1 : lg;
            for (let i = 0; i < lg; i++) {
                let index = i * spits;
                let last = nStr.split('').reverse().join('').slice(index, spits + index);
                list.push(last.split('').reverse().join(''))
            }
            let nList = list.reverse().join(',');
            nList = number<0?'-'+nList:nList;
            return nList;
        }catch (e){/*console.log(e)*/}
    }
}

export default CarRadiusInfoOption;
export { CarRadiusInfoOption };

调用:

this.allListDatas.echartsJettaData = new CarBarInfoOption({});
<pyz-charts :option="allListDatas.echartsJettaData.option" />

下面是事件及实例回调:

不建议使用ref来回调实例,其实很容易拿不到

使用pyz-charts很容就把实例对象拿到:

<template>
<pyz-charts @init="getInstance($event)" 
@click="getOnChartsClick($event)"
:option="allListDatas.echartsJettaData.option" />
</template>
<script>
   export default {
      ...
      methods: { 
          init() {},
          getInstance(instance) {
             //  获取实例
              console.log(instance)
          },
         getOnChartsClick(echartsItemData) {
               // 获取点击事件下的 每一个图例 Item 信息
               // 支持所有事件
               console.log(echartsItemData)
          }
     }
   }
</script>

github Dome地址:

PyzCharts-GitHub
觉得好用的朋友们点个Star

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容