#
whycq
2022-11-17 bb9e8871b4b1ebad935968ae32f3c747fac7c3a2
#
11个文件已修改
27702 ■■■■ 已修改文件
Monitor-APP/pages/home/home.vue 222 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/pages/index/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/uni_modules/qiun-data-charts/changelog.md 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js 1399 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/uni_modules/qiun-data-charts/package.json 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/uni_modules/qiun-data-charts/readme.md 501 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/unpackage/dist/dev/app-plus/app-service.js 3998 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/unpackage/dist/dev/app-plus/app-view.js 21238 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor-APP/pages/home/home.vue
@@ -18,37 +18,86 @@
                                <view class="box-item">
                                    <text class="item-title">自动化立体仓库</text>
                                    <text class="item-subTitle">Automatic Storageand Retrieval System</text>
                                    <text class="item-text">利用立体仓库设备可实现仓库高层合理化、存取自动化、操作简便化;自动化立体仓库是当前技术水平较高的形式。自动化立体仓库的主体由货架、巷道式堆垛起重机、入(出)库工作台和自动运进(出)及操作控制系统组成。货架是钢结构或钢筋混凝土结构的建筑物或结构体,货架内是标准尺寸的货位空间,巷道堆垛起重机穿行于货架之间的巷道中,完成存、取货的工作。管理上采用计算机及条形码技术。</text>
                                    <text class="item-text" style="text-align: left;">利用立体仓库设备可实现仓库高层合理化、存取自动化、操作简便化;自动化立体仓库是当前技术水平较高的形式。自动化立体仓库的主体由货架、巷道式堆垛起重机、入(出)库工作台和自动运进(出)及操作控制系统组成。货架是钢结构或钢筋混凝土结构的建筑物或结构体,货架内是标准尺寸的货位空间,巷道堆垛起重机穿行于货架之间的巷道中,完成存、取货的工作。管理上采用计算机及条形码技术。</text>
                                </view>
                                <view class="box-item">
                                    <text class="item-title">仓库数据</text>
                                    <text class="item-subTitle">warehouse data</text>
                                    <view class="img-box">
                                        <view class="item-img">
                                            <image src="../../static/a1.png" mode="aspectFit"></image>
                                            <view>累计走行距离(米)</view>
                                            <view class="flex-col" style="width: calc(100% - 5vw);">
                                                <view class="flex-row" style="position: relative;" >
                                                    <view style="width: 2vw;padding-left: 5vw;;font-size: 2vw;">{{baseInfo.xDistance}}</view>
                                                    <view style="position: absolute;bottom: 0;left: 7vw;">m</view>
                                                </view>
                                                <view style="height: 100%;text-align: left;text-indent: 2em;">累计走行距离(米)</view>
                                            </view>
                                        </view>
                                        <view class="item-img">
                                            <image src="../../static/a1.png" mode="aspectFit"></image>
                                            <view>累计走行距离(米)</view>
                                            <image src="../../static/b1.png" mode="aspectFit"></image>
                                            <view class="flex-col" style="width: calc(100% - 5vw);">
                                                <view class="flex-row" style="position: relative;" >
                                                    <view style="width: 2vw;padding-left: 5vw;;font-size: 2vw;">{{baseInfo.yDistance}}</view>
                                                    <view style="position: absolute;bottom: 0;left: 7vw;">m</view>
                                                </view>
                                                <view style="height: 100%;text-align: left;text-indent: 2em;">累计升降距离(米)</view>
                                            </view>
                                        </view>
                                        <view class="item-img">
                                            <image src="../../static/a1.png" mode="aspectFit"></image>
                                            <view>累计走行距离(米)</view>
                                            <image src="../../static/c1.png" mode="aspectFit"></image>
                                            <view class="flex-col" style="width: calc(100% - 5vw);">
                                                <view class="flex-row" style="position: relative;" >
                                                    <view style="width: 2vw;padding-left: 5vw;;font-size: 2vw;">{{baseInfo.xDuration}}</view>
                                                    <view style="position: absolute;bottom: 0;left: 7vw;">s</view>
                                                </view>
                                                <view style="height: 100%;text-align: left;text-indent: 2em;">累计走行时长(秒)</view>
                                            </view>
                                        </view>
                                        <view class="item-img">
                                            <image src="../../static/a1.png" mode="aspectFit"></image>
                                            <view>累计走行距离(米)</view>
                                            <image src="../../static/d1.png" mode="aspectFit"></image>
                                            <view class="flex-col" style="width: calc(100% - 5vw);">
                                                <view class="flex-row" style="position: relative;" >
                                                    <view style="width: 2vw;padding-left: 5vw;;font-size: 2vw;">{{baseInfo.yDuration}}</view>
                                                    <view style="position: absolute;bottom: 0;left: 7vw;">s</view>
                                                </view>
                                                <view style="height: 100%;text-align: left;text-indent: 2em;">累计升降时长(秒)</view>
                                            </view>
                                        </view>
                                    </view>
                                </view>
                                <view class="box-item">
                                    <text class="item-title">库位使用率</text>
                                    <text class="item-subTitle">EQUIPMENT USAGE THIS MONTH</text>
                                    <view class="flex-row" style="width: 100%;">
                                        <!-- 左侧 -->
                                        <view class="flex-col" style="align-items: flex-start;justify-content: flex-start;">
                                            <text class="item-title">库位使用率</text>
                                            <text class="item-subTitle">EQUIPMENT USAGE THIS MONTH</text>
                                        </view>
                                        <!-- 右侧 -->
                                        <view style="margin-left: auto;">
                                            <!-- 百分比 -->
                                            <view class="flex-col" style="align-items: flex-end;justify-content: flex-end;" >
                                                <!-- style="justify-content: flex-end;position: absolute;top: 0;right: 1vw;text-align: right;" -->
                                                <text class="item-title">{{baseInfo.usedPr}}%</text>
                                                <text class="item-subTitle">同比上月 + 5%</text>
                                            </view>
                                        </view>
                                    </view>
                                    <view class="flex-col" style="width: 100%;align-items: flex-start;position: relative;font-size: 1vw">
                                        <!-- 进度条 -->
                                        <view class="flex-row" style="width: 100%;position: relative;margin-top: 5%;">
                                            <view class="progressBar" style="width: 80%;height: 2vw;">
                                                <view class="progress" :style="'width:'+ baseInfo.usedPr + '%'"></view>
                                            </view>
                                            <view style="position: absolute;bottom: 0;right: 0;font-size: 2.5vw;color: #FF5722;;">{{baseInfo.used}}</view>
                                        </view>
                                    </view>
                                </view>
                            </y-box>
                        </view>
@@ -56,15 +105,61 @@
                    <view class="mian-item">
                        <view class="mian-item-box">
                            <view style="width: 100%;height: 100%;">
                                <view style="height: 40%;">
                                    <!-- 折线图 -->
                                    <y-box>
                                        <view class="box-item">
                                            <view class="flex-row" style="width: 100%;">
                                                <!-- 左侧 -->
                                                <view class="flex-col" style="align-items: flex-start;justify-content: flex-start;">
                                                    <text class="item-title">入出库统计</text>
                                                    <text class="item-subTitle">ORDER STATISTICS</text>
                                                </view>
                                                <!-- 右侧 -->
                                                <view style="margin-left: auto;">
                                                    <!-- 百分比 -->
                                                    <view class="flex-col" style="align-items: flex-end;justify-content: flex-end;" >
                                                        <!-- style="justify-content: flex-end;position: absolute;top: 0;right: 1vw;text-align: right;" -->
                                                        <text class="item-title">31</text>
                                                        <text class="item-subTitle">今日订单数</text>
                                                    </view>
                                                </view>
                                            </view>
                                            <view class="charts-box" v-if="!showCharts">
                                                <qiun-data-charts type="line" :chartData="chartsDataLine1" :echartsH5="true" :echartsApp="true"/>
                                            </view>
                                        </view>
                                    </y-box>
                                </view>
                                <!-- null -->
                                <view style="height: 2%;"></view>
                                <view style="height: 38%;">
                                    <y-box></y-box>
                                    <y-box>
                                        <view class="box-item">
                                            <view class="flex-row" style="width: 100%;">
                                                <!-- 左侧 -->
                                                <view class="flex-col" style="align-items: flex-start;justify-content: flex-start;">
                                                    <text class="item-title">库存类型</text>
                                                    <text class="item-subTitle">INCOME DATE</text>
                                                </view>
                                                <!-- 右侧 -->
                                                <view style="margin-left: auto;">
                                                    <!-- 百分比 -->
                                                    <view class="flex-col" style="align-items: flex-end;justify-content: flex-end;" >
                                                        <text class="item-title">今天</text>
                                                        <text class="item-subTitle">Today</text>
                                                    </view>
                                                </view>
                                            </view>
                                        </view>
                                    </y-box>
                                </view>
                                <view style="height: 2%;"></view>
                                <view style="height: 38%;">
                                    <y-box></y-box>
                                </view>
                                <view style="height: 2%;"></view>
                                <view style="height: 20%;">
                                <view style="height: 18%;">
                                    <y-box></y-box>
                                </view>
                            </view>
@@ -83,9 +178,11 @@
</template>
<script>
    import demodata from '@/mockdata/demodata.json';
    export default {
        data() {
            return {
                series: [],
                homeViewShow: true,
                modeClass: ['fade', 'slide-top'],
                homeView: {
@@ -98,14 +195,33 @@
                    backgroundColor: '#4cd964',
                    boxShadow: '0 0 5px 1px rgba(0,0,0,0.2)'
                },
                baseInfo: {
                    xDistance: 1,
                    yDistance: 2,
                    xDuration: 3,
                    yDuration: 4,
                    usedPr: 50,
                    used: 3537
                },
                chartsData: {
                    "Line": {
                        "categories": [],
                        "series": []
                    },
                    "Pie": {
                        "series": [{
                            "data": []
                        }]
                    },
                },
                duration: 1000,
                calendar: '',
                xDistance: '',
                yDistance: '',
                xDuration: '',
                yDuration: '',
                ringOpts:{},
                chartsDataLine1: {},
                chartsDataPie2: {},
                fontSize: '',
                height: ''
                height: '',
                showCharts: false
            }
        },
        onShow() {
@@ -115,17 +231,26 @@
            // #endif
        },
        onLoad() {
            this.getServerData()
            this.getDate()
            setInterval(()=>{
                this.getDate()
            },1000)
            setInterval(()=>{
                // this.handle(['fade', 'slide-top'])
                this.handle(['fade', 'slide-top'])
            },4000)
        },
        methods: {
            getServerData() {
                this.chartsDataLine1=JSON.parse(JSON.stringify(demodata.Line))
            },
            handle(type) {
                this.homeViewShow = !this.homeViewShow
                setTimeout(()=>{
                    this.showCharts = !this.showCharts
                },1000)
                this.modeClass = type
            },
            // 日历
@@ -157,6 +282,17 @@
<style>
    @import url("../../static/css/common.css");
    /* 列 */
    .flex-col {
        display: flex;
        flex-direction: column;
    }
    /* 行 */
    .flex-row {
        display: flex;
        flex-direction: row;
    }
    .container{
        width: 100vw;
        min-height: 100vh;
@@ -219,6 +355,25 @@
        width: 13.5%;
        height: 8.5%;
    }
    .progressBar {
        margin-top: 9%;
        /* width: 100%; */
        height: 20%;
        background-color: #233751;
        border-radius: 5vw;
    }
    .progress {
        /* width: 90%; */
        height: 100%;
        background-color: #FF5722;
        border-radius: 5vw;
    }
    .charts-box {
      width: 80%;
      height: 24vh;
      margin-left: 10%;
    }
    
    
    
@@ -244,7 +399,7 @@
    }
    .box-item {
        width: 100%;
        margin-top: 2%;
        margin-top: 4%;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
@@ -256,30 +411,35 @@
    }
    .item-subTitle {
        font-size:0.5vw;
        text-indent: 1em;
        text-indent: 0em;
    }
    .item-text {
        font-size: 1vw;
        text-indent: 2em;
        letter-spacing: 1px;
        line-height: 3vh;
    }
    .img-box {
        width: 100%;
        background-color: #666666;
        /* background-color: #666666; */
        display: flex;
        flex-direction: row;
        justify-content: flex-start;
        flex-wrap: wrap;
        font-size: 1vw;
    }
    .item-img {
        width: 50%;
        margin-top: 3%;
        background-color: #00ffff;
        margin-top: 5%;
        display: flex;
        flex-direction: row;
        /* background-color: #00ffff; */
        justify-content: flex-start;
        align-items: flex-start;
    }
    .distance {
    }
    .item-img image {
        height: 5vw;
        width: 5vw;
Monitor-APP/pages/index/index.vue
@@ -187,7 +187,6 @@
                                <p class="english">Today</p>
                            </view>
                            <view class="sub-main">
                                <!-- 折线图 -->
                                <view class="charts-box ring">
                                    <qiun-data-charts type="ring" :opts="{legend:{position:'bottom'}}" :eopts="ringOpts" :chartData="chartsDataPie2" :echartsH5="true" :echartsApp="true"/>
                                </view>
Monitor-APP/uni_modules/qiun-data-charts/changelog.md
@@ -1,3 +1,90 @@
## 2.4.4-20221102(2022-11-02)
- 秋云图表组件 修复使用echarts时reload、reshow无法调用重新渲染的bug,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/40)
- 秋云图表组件 修复使用echarts时,初始化时宽高不正确的bug,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/42)
- 秋云图表组件 修复uniapp的h5使用history模式时,无法加载echarts的bug
- 秋云图表组件 小程序端@complete、@scrollLeft、@scrollRight、@getTouchStart、@getTouchMove、@getTouchEnd事件增加opts参数传出,方便一些特殊需求的交互获取数据。
- uCharts.js 修复calTooltipYAxisData方法内formatter格式化方法未与y轴方法同步的问题,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/43)
- uCharts.js 地图新增参数opts.series[i].fillOpacity,以透明度方式来设置颜色过度效果,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/38)
- uCharts.js 地图新增参数opts.extra.map.active,是否启用点击激活变色
- uCharts.js 地图新增参数opts.extra.map.activeTextColor,是否启用点击激活变色
- uCharts.js 地图新增渲染完成事件renderComplete
- uCharts.js 漏斗图修复当部分数据相同时tooltip提示窗点击错误的bug
- uCharts.js 漏斗图新增参数series.data[i].centerText 居中标签文案
- uCharts.js 漏斗图新增参数series.data[i].centerTextSize 居中标签文案字体大小,默认opts.fontSize
- uCharts.js 漏斗图新增参数series.data[i].centerTextColor 居中标签文案字体颜色,默认#FFFFFF
- uCharts.js 漏斗图新增参数opts.extra.funnel.minSize 最小值的最小宽度,默认0
- uCharts.js 进度条新增参数opts.extra.arcbar.direction,动画方向,可选值为cw顺时针、ccw逆时针
- uCharts.js 混合图新增参数opts.extra.mix.line.width,折线的宽度,默认2
- uCharts.js 修复tooltip开启horizentalLine水平横线标注时,图表显示错位的bug
- uCharts.js 优化tooltip当文字很多变为左侧显示时,如果画布仍显显示不下,提示框错位置变为以左侧0位置起画
- uCharts.js 修复开启滚动条后X轴文字超出绘图区域后的隐藏逻辑
- uCharts.js 柱状图、条状图修复堆叠模式不能通过{value,color}赋值单个柱子颜色的问题
- uCharts.js 气泡图修复不识别series.textSize和series.textColor的bug
## 报错TypeError: Cannot read properties of undefined (reading 'length')
1. 如果是uni-modules版本组件,请先登录HBuilderX账号;
2. 在HBuilderX中的manifest.json,点击重新获取uniapp的appid,或者删除appid重新粘贴,重新运行;
3. 如果是cli项目请使用码云上的非uniCloud版本组件;
4. 或者添加uniCloud的依赖;
5. 或者使用原生uCharts;
## 2.4.3-20220505(2022-05-05)
- 秋云图表组件 修复开启canvas2d后将series赋值为空数组显示加载图标时,再次赋值后画布闪动的bug
- 秋云图表组件 修复升级hbx最新版后ECharts的highlight方法报错的bug
- uCharts.js 雷达图新增参数opts.extra.radar.gridEval,数据点位网格抽希,默认1
- uCharts.js 雷达图新增参数opts.extra.radar.axisLabel,    是否显示刻度点值,默认false
- uCharts.js 雷达图新增参数opts.extra.radar.axisLabelTofix,刻度点值小数位数,默认0
- uCharts.js 雷达图新增参数opts.extra.radar.labelPointShow,是否显示末端刻度圆点,默认false
- uCharts.js 雷达图新增参数opts.extra.radar.labelPointRadius,刻度圆点的半径,默认3
- uCharts.js 雷达图新增参数opts.extra.radar.labelPointColor,刻度圆点的颜色,默认#cccccc
- uCharts.js 雷达图新增参数opts.extra.radar.linearType,渐变色类型,可选值"none"关闭渐变,"custom"开启渐变
- uCharts.js 雷达图新增参数opts.extra.radar.customColor,自定义渐变颜色,数组类型对应series的数组长度以匹配不同series颜色的不同配色方案,例如["#FA7D8D", "#EB88E2"]
- uCharts.js 雷达图优化支持series.textColor、series.textSize属性
- uCharts.js 柱状图中温度计式图标,优化支持全圆角类型,修复边框有缝隙的bug,详见官网【演示】中的温度计图表
- uCharts.js 柱状图新增参数opts.extra.column.activeWidth,当前点击柱状图的背景宽度,默认一个单元格单位
- uCharts.js 混合图增加opts.extra.mix.area.gradient 区域图是否开启渐变色
- uCharts.js 混合图增加opts.extra.mix.area.opacity 区域图透明度,默认0.2
- uCharts.js 饼图、圆环图、玫瑰图、漏斗图,增加opts.series[0].data[i].labelText,自定义标签文字,避免formatter格式化的繁琐,详见官网【演示】中的饼图
- uCharts.js 饼图、圆环图、玫瑰图、漏斗图,增加opts.series[0].data[i].labelShow,自定义是否显示某一个指示标签,避免因饼图类别太多导致标签重复或者居多导致图形变形的问题,详见官网【演示】中的饼图
- uCharts.js 增加opts.series[i].legendText/opts.series[0].data[i].legendText(与series.name同级)自定义图例显示文字的方法
- uCharts.js 优化X轴、Y轴formatter格式化方法增加形参,统一为fromatter:function(value,index,opts){}
- uCharts.js 修复横屏模式下无法使用双指缩放方法的bug
- uCharts.js 修复当只有一条数据或者多条数据值相等的时候Y轴自动计算的最大值错误的bug
- 【官网模板】增加外部自定义图例与图表交互的例子,[点击跳转](https://www.ucharts.cn/v2/#/layout/info?id=2)
## 注意:非unimodules 版本如因更新 hbx 至 3.4.7 导致报错如下,请到码云更新非 unimodules 版本组件,[点击跳转](https://gitee.com/uCharts/uCharts/tree/master/uni-app/uCharts-%E7%BB%84%E4%BB%B6)
> Error in callback for immediate watcher "uchartsOpts": "SyntaxError: Unexpected token u in JSON at position 0"
## 2.4.2-20220421(2022-04-21)
- 秋云图表组件 修复HBX升级3.4.6.20220420版本后echarts报错的问题
## 2.4.2-20220420(2022-04-20)
## 重要!此版本uCharts新增了很多功能,修复了诸多已知问题
- 秋云图表组件 新增onzoom开启双指缩放功能(仅uCharts),前提需要直角坐标系类图表类型,并且ontouch为true、opts.enableScroll为true,详见实例项目K线图
- 秋云图表组件 新增optsWatch是否监听opts变化,关闭optsWatch后,动态修改opts不会触发图表重绘
- 秋云图表组件 修复开启canvas2d功能后,动态更新数据后画布闪动的bug
- 秋云图表组件 去除directory属性,改为自动获取echarts.min.js路径(升级不受影响)
- 秋云图表组件 增加getImage()方法及@getImage事件,通过ref调用getImage()方法获,触发@getImage事件获取当前画布的base64图片文件流。
- 秋云图表组件 支付宝、字节跳动、飞书、快手小程序支持开启canvas2d同层渲染设置。
- 秋云图表组件 新增加【非uniCloud】版本组件,避免有些不需要uniCloud的使用组件发布至小程序需要提交隐私声明问题,请到码云[【非uniCloud版本】](https://gitee.com/uCharts/uCharts/tree/master/uni-app/uCharts-%E7%BB%84%E4%BB%B6),或npm[【非uniCloud版本】](https://www.npmjs.com/package/@qiun/uni-ucharts)下载使用。
- uCharts.js 新增dobuleZoom双指缩放功能
- uCharts.js 新增山峰图type="mount",数据格式为饼图类格式,不需要传入categories,具体详见新版官网在线演示
- uCharts.js 修复折线图当数据中存在null时tooltip报错的bug
- uCharts.js 修复饼图类当画布比较小时自动计算的半径是负数报错的bug
- uCharts.js 统一各图表类型的series.formatter格式化方法的形参为(val, index, series, opts),方便格式化时有更多参数可用
- uCharts.js 标记线功能增加labelText自定义显示文字,增加labelAlign标签显示位置(左侧或右侧),增加标签显示位置微调labelOffsetX、labelOffsetY
- uCharts.js 修复条状图当数值很小时开启圆角后样式错误的bug
- uCharts.js 修复X轴开启disabled后,X轴仍占用空间的bug
- uCharts.js 修复X轴开启滚动条并且开启rotateLabel后,X轴文字与滚动条重叠的bug
- uCharts.js 增加X轴rotateAngle文字旋转自定义角度,取值范围(-90至90)
- uCharts.js 修复地图文字标签层级显示不正确的bug
- uCharts.js 修复饼图、圆环图、玫瑰图当数据全部为0的时候不显示数据标签的bug
- uCharts.js 修复当opts.padding上边距为0时,Y轴顶部刻度标签位置不正确的bug
## 另外我们还开发了各大原生小程序组件,已发布至码云和npm
[https://gitee.com/uCharts/uCharts](https://gitee.com/uCharts/uCharts)
[https://www.npmjs.com/~qiun](https://www.npmjs.com/~qiun)
## 对于原生uCharts文档我们已上线新版官方网站,详情点击下面链接进入官网
[https://www.uCharts.cn/v2/](https://www.ucharts.cn/v2/)
## 2.3.7-20220122(2022-01-22)
## 重要!使用vue3编译,请使用cli模式并升级至最新依赖,HbuilderX编译需要使用3.3.8以上版本
- uCharts.js 修复uni-app平台组件模式使用vue3编译到小程序报错的bug。
Monitor-APP/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue
@@ -1,5 +1,5 @@
<!-- 
 * qiun-data-charts 秋云高性能跨全端图表组件 v2.3.7-20220118
 * qiun-data-charts 秋云高性能跨全端图表组件
 * Copyright (c) 2021 QIUN® 秋云 https://www.ucharts.cn All rights reserved.
 * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 * 复制使用请保留本段注释,感谢支持开源!
@@ -97,7 +97,7 @@
    </block>
    <!-- #endif -->
    <!-- 其他小程序通过vue渲染图表 -->
    <!-- #ifdef MP-360 || MP-BAIDU || MP-QQ || MP-TOUTIAO || MP-WEIXIN -->
    <!-- #ifdef MP-360 || MP-BAIDU || MP-QQ || MP-TOUTIAO || MP-WEIXIN || MP-KUAISHOU || MP-LARK || MP-JD -->
    <block v-if="type2d">
      <view v-if="ontouch" @tap="_tap">
        <canvas
@@ -175,7 +175,7 @@
function formatterAssign(args,formatter) {
  for (let key in args) {
    if(args[key] !== null && typeof args[key] === 'object'){
    if(args.hasOwnProperty(key) && args[key] !== null && typeof args[key] === 'object'){
      formatterAssign(args[key],formatter)
    }else if(key === 'format' && typeof args[key] === 'string'){
      args['formatter'] = formatter[args[key]] ? formatter[args[key]] : undefined;
@@ -306,6 +306,14 @@
      type: Boolean,
      default: false
    },
    optsWatch: {
      type: Boolean,
      default: true
    },
    onzoom: {
      type: Boolean,
      default: false
    },
    ontap: {
      type: Boolean,
      default: true
@@ -399,7 +407,9 @@
      cHeight: 250,
      showchart: false,
      echarts: false,
      echartsResize:false,
      echartsResize:{
        state:false
      },
      uchartsOpts: {},
      echartsOpts: {},
      drawData:{},
@@ -426,15 +436,16 @@
    if (this.canvas2d === false || systemInfo.platform === 'windows' || systemInfo.platform === 'mac') {
      this.type2d = false;
    }else{
      this.type2d = true;
      this.pixel = systemInfo.pixelRatio;
      if (this.canvasId === 'uchartsid' || this.canvasId == '') {
        console.log('[uCharts]:开启canvas2d模式,必须指定canvasId,否则会出现偶尔获取不到dom节点的问题!');
      }
    }
    // #endif
    //非微信小程序端强制关闭canvas2d模式
    // #ifndef MP-WEIXIN
    this.type2d = false;
    // #endif
    // #ifdef  MP-TOUTIAO || MP-LARK || MP-ALIPAY
    this.type2d = this.canvas2d;
    // #endif
    // #ifdef MP-ALIPAY
    this.inAli = true;
@@ -486,7 +497,7 @@
          return;
        }
        if (_this.echarts) {
          _this.echartsResize = !_this.echartsResize;
          _this.echartsResize.state = !_this.echartsResize.state;
        } else {
          _this.resizeHandler();
        }
@@ -511,11 +522,11 @@
      handler(val, oldval) {
        if (typeof val === 'object') {
          if (JSON.stringify(val) !== JSON.stringify(oldval)) {
            this._clearChart();
            if (val.series && val.series.length > 0) {
              this.beforeInit();
            }else{
              this.mixinDatacomLoading = true;
              this._clearChart();
              this.showchart = false;
              this.mixinDatacomErrorMessage = null;
            }
@@ -549,7 +560,7 @@
    optsProps: {
      handler(val, oldval) {
        if (typeof val === 'object') {
          if (JSON.stringify(val) !== JSON.stringify(oldval) && this.echarts === false) {
          if (JSON.stringify(val) !== JSON.stringify(oldval) && this.echarts === false && this.optsWatch == true) {
            this.checkData(this.drawData);
          }
        } else {
@@ -581,7 +592,7 @@
      if (val === true && this.mixinDatacomLoading === false) {
        setTimeout(() => {
          this.mixinDatacomErrorMessage = null;
          this.echartsResize = !this.echartsResize;
          this.echartsResize.state = !this.echartsResize.state;
          this.checkData(this.drawData);
        }, 200);
      }
@@ -854,10 +865,12 @@
    },
    _clearChart() {
      let cid = this.cid
      if (this.echrts !== true) {
        const ctx = uni.createCanvasContext(cid, this);
        ctx.clearRect(0, 0, this.cWidth, this.cHeight);
        ctx.draw();
      if (this.echarts !== true && cfu.option[cid] && cfu.option[cid].context) {
        const ctx = cfu.option[cid].context;
        if(typeof ctx === "object" && !!!cfu.option[cid].update){
          ctx.clearRect(0, 0, this.cWidth*this.pixel, this.cHeight*this.pixel);
          ctx.draw();
        }
      }
    },
    init() {
@@ -882,6 +895,7 @@
              cfu.option[cid].animation = this.animation;
              cfu.option[cid].width = data.width * this.pixel;
              cfu.option[cid].height = data.height * this.pixel;
              cfu.option[cid].onzoom = this.onzoom;
              cfu.option[cid].ontap = this.ontap;
              cfu.option[cid].ontouch = this.ontouch;
              cfu.option[cid].onmouse = this.openmouse;
@@ -924,14 +938,14 @@
                        const canvas = res[0].node;
                        const ctx = canvas.getContext('2d');
                        cfu.option[cid].context = ctx;
                        canvas.width = data.width * this.pixel;
                        canvas.height = data.height * this.pixel;
                        canvas._width = data.width * this.pixel;
                        canvas._height = data.height * this.pixel;
                        cfu.option[cid].rotateLock = cfu.option[cid].rotate;
                        if(cfu.instance[cid] && cfu.option[cid] && cfu.option[cid].update === true){
                          this._updataUChart(cid)
                        }else{
                          canvas.width = data.width * this.pixel;
                          canvas.height = data.height * this.pixel;
                          canvas._width = data.width * this.pixel;
                          canvas._height = data.height * this.pixel;
                          setTimeout(()=>{
                            cfu.option[cid].context.restore();
                            cfu.option[cid].context.save();
@@ -983,17 +997,38 @@
            //#endif
            //#ifndef H5
              uni.saveImageToPhotosAlbum({
                  filePath: res.tempFilePath,
                  success: function () {
                      uni.showToast({
                          title: '保存成功',
                          duration: 2000
                      });
                  }
              filePath: res.tempFilePath,
              success: function () {
                uni.showToast({
                  title: '保存成功',
                  duration: 2000
                });
              }
              });
            //#endif
          } 
        },this);
    },
    getImage(){
      if(this.type2d == false){
        uni.canvasToTempFilePath({
          canvasId: this.cid,
          success: res=>{
            this.emitMsg({name: 'getImage', params: {type:"getImage", base64: res.tempFilePath}});
          }
        },this);
      }else{
        const query = uni.createSelectorQuery().in(this)
        query
          .select('#' + this.cid)
          .fields({ node: true, size: true })
          .exec(res => {
            if (res[0]) {
              const canvas = res[0].node;
              this.emitMsg({name: 'getImage', params: {type:"getImage", base64: canvas.toDataURL('image/png')}});
            }
          });
      }
    },
    // #ifndef APP-VUE || H5
    _newChart(cid) {
@@ -1003,14 +1038,14 @@
      this.showchart = true;
      cfu.instance[cid] = new uCharts(cfu.option[cid]);
      cfu.instance[cid].addEventListener('renderComplete', () => {
        this.emitMsg({name: 'complete', params: {type:"complete", complete: true, id: cid}});
        this.emitMsg({name: 'complete', params: {type:"complete", complete: true, id: cid, opts: cfu.instance[cid].opts}});
        cfu.instance[cid].delEventListener('renderComplete')
      });
      cfu.instance[cid].addEventListener('scrollLeft', () => {
        this.emitMsg({name: 'scrollLeft', params: {type:"scrollLeft", scrollLeft: true, id: cid}});
        this.emitMsg({name: 'scrollLeft', params: {type:"scrollLeft", scrollLeft: true, id: cid, opts: cfu.instance[cid].opts}});
      });
      cfu.instance[cid].addEventListener('scrollRight', () => {
        this.emitMsg({name: 'scrollRight', params: {type:"scrollRight", scrollRight: true, id: cid}});
        this.emitMsg({name: 'scrollRight', params: {type:"scrollRight", scrollRight: true, id: cid, opts: cfu.instance[cid].opts}});
      });
    },
    _updataUChart(cid) {
@@ -1124,31 +1159,35 @@
    _touchStart(e) {
      let cid = this.cid
      lastMoveTime=Date.now();
      if(cfu.option[cid].enableScroll === true){
      if(cfu.option[cid].enableScroll === true && e.touches.length == 1){
        cfu.instance[cid].scrollStart(e);
      }
      this.emitMsg({name:'getTouchStart', params:{type:"touchStart", event:e.changedTouches[0], id:cid}});
      this.emitMsg({name:'getTouchStart', params:{type:"touchStart", event:e.changedTouches[0], id:cid, opts: cfu.instance[cid].opts}});
    },
    _touchMove(e) {
      let cid = this.cid
      let currMoveTime = Date.now();
      let duration = currMoveTime - lastMoveTime;
      if (duration < Math.floor(1000 / 60)) return;//每秒60帧
      let touchMoveLimit = cfu.option[cid].touchMoveLimit || 24;
      if (duration < Math.floor(1000 / touchMoveLimit)) return;//每秒60帧
      lastMoveTime = currMoveTime;
      if(cfu.option[cid].enableScroll === true){
      if(cfu.option[cid].enableScroll === true && e.changedTouches.length == 1){
        cfu.instance[cid].scroll(e);
      }
      this.emitMsg({name: 'getTouchMove', params: {type:"touchMove", event:e.changedTouches[0], id: cid}});
      if(this.ontap === true && cfu.option[cid].enableScroll === false && this.onmovetip === true){
        this._tap(e,true)
      }
      if(this.ontouch === true && cfu.option[cid].enableScroll === true && this.onzoom === true && e.changedTouches.length == 2){
        cfu.instance[cid].dobuleZoom(e);
      }
      this.emitMsg({name: 'getTouchMove', params: {type:"touchMove", event:e.changedTouches[0], id: cid, opts: cfu.instance[cid].opts}});
    },
    _touchEnd(e) {
      let cid = this.cid
      if(cfu.option[cid].enableScroll === true){
      if(cfu.option[cid].enableScroll === true && e.touches.length == 0){
        cfu.instance[cid].scrollEnd(e);
      }
      this.emitMsg({name:'getTouchEnd', params:{type:"touchEnd", event:e.changedTouches[0], id:cid}});
      this.emitMsg({name:'getTouchEnd', params:{type:"touchEnd", event:e.changedTouches[0], id:cid, opts: cfu.instance[cid].opts}});
      if(this.ontap === true && cfu.option[cid].enableScroll === false && this.onmovetip === true){
        this._tap(e,true)
      }
@@ -1195,7 +1234,7 @@
function rdformatterAssign(args,formatter) {
  for (let key in args) {
    if(args[key] !== null && typeof args[key] === 'object'){
    if(args.hasOwnProperty(key) && args[key] !== null && typeof args[key] === 'object'){
      rdformatterAssign(args[key],formatter)
    }else if(key === 'format' && typeof args[key] === 'string'){
      args['formatter'] = formatter[args[key]] ? formatter[args[key]] : undefined;
@@ -1246,19 +1285,22 @@
        cfe.option[cid] = rddeepCloneAssign({}, eopts);
      }
      let newData = eopts.chartData;
      //挂载categories和series
      if(cfe.option[cid].xAxis && cfe.option[cid].xAxis.type && cfe.option[cid].xAxis.type === 'category'){
        cfe.option[cid].xAxis.data = newData.categories
      if(newData){
        //挂载categories和series
        if(cfe.option[cid].xAxis && cfe.option[cid].xAxis.type && cfe.option[cid].xAxis.type === 'category'){
          cfe.option[cid].xAxis.data = newData.categories
        }
        if(cfe.option[cid].yAxis && cfe.option[cid].yAxis.type && cfe.option[cid].yAxis.type === 'category'){
          cfe.option[cid].yAxis.data = newData.categories
        }
        cfe.option[cid].series = []
        for (var i = 0; i < newData.series.length; i++) {
          cfe.option[cid].seriesTemplate = cfe.option[cid].seriesTemplate ? cfe.option[cid].seriesTemplate : {}
          let Template = rddeepCloneAssign({},cfe.option[cid].seriesTemplate,newData.series[i])
          cfe.option[cid].series.push(Template)
        }
      }
      if(cfe.option[cid].yAxis && cfe.option[cid].yAxis.type && cfe.option[cid].yAxis.type === 'category'){
        cfe.option[cid].yAxis.data = newData.categories
      }
      cfe.option[cid].series = []
      for (var i = 0; i < newData.series.length; i++) {
        cfe.option[cid].seriesTemplate = cfe.option[cid].seriesTemplate ? cfe.option[cid].seriesTemplate : {}
        let Template = rddeepCloneAssign({},cfe.option[cid].seriesTemplate,newData.series[i])
        cfe.option[cid].series.push(Template)
      }
      if (typeof window.echarts === 'object') {
          this.newEChart()
      }else{
@@ -1267,9 +1309,9 @@
        script.src = './uni_modules/qiun-data-charts/static/app-plus/echarts.min.js'
        // #endif
        // #ifdef H5
        const rooturl = window.location.origin
        const directory = instance.getDataset().directory
        script.src = rooturl + directory + 'uni_modules/qiun-data-charts/static/h5/echarts.min.js'
        const { origin } = window.location
        const rooturl = origin + process.env.BASE_URL
        script.src = rooturl + 'uni_modules/qiun-data-charts/static/h5/echarts.min.js'
        // #endif
        script.onload = this.newEChart
        document.head.appendChild(script)
@@ -1294,7 +1336,7 @@
          })
          // 增加ECharts的highlight消息,实现按下移动返回索引功能。add by onefish 创建于 2021-12-11 09:50
          cfe.instance[cid].on('highlight', resdata => {
            that[cid].callMethod('emitMsg',{name:"getHighlight", params:{type:"highlight", dataIndex:resdata.batch[0].dataIndex, id:cid}})
            that[cid].callMethod('emitMsg',{name:"getHighlight", params:{type:"highlight", res:resdata, id:cid}})
          })
        }
        this.updataEChart(cid,cfe.option[cid])
@@ -1328,7 +1370,16 @@
        if(cfe.instance[cid]){
          cfe.instance[cid].off('finished')
        }
      })
      });
      //修复init初始化实例获取宽高不正确问题
      if(
        typeof that[cid].$el.children[0].clientWidth != 'undefined' &&
          (
            Math.abs( that[cid].$el.children[0].clientWidth - cfe.instance[cid].getWidth() )>3 ||
            Math.abs( that[cid].$el.children[0].clientHeight - cfe.instance[cid].getHeight() )>3
          )
      ){this.ecresize();}
    },
    tooltipPosition(){
      return (point, params, dom, rect, size) => {
@@ -1380,14 +1431,14 @@
      let cid = this.rid
      cfu.instance[cid] = new uChartsRD(cfu.option[cid])
      cfu.instance[cid].addEventListener('renderComplete', () => {
        that[cid].callMethod('emitMsg',{name:"complete",params:{type:"complete",complete:true,id:cid}})
        that[cid].callMethod('emitMsg',{name:"complete",params:{type:"complete",complete:true,id:cid, opts: cfu.instance[cid].opts}})
        cfu.instance[cid].delEventListener('renderComplete')
      });
      cfu.instance[cid].addEventListener('scrollLeft', () => {
        that[cid].callMethod('emitMsg',{name:"scrollLeft",params:{type:"scrollLeft",scrollLeft:true,id:cid}})
        that[cid].callMethod('emitMsg',{name:"scrollLeft",params:{type:"scrollLeft",scrollLeft:true,id:cid, opts: cfu.instance[cid].opts}})
      });
      cfu.instance[cid].addEventListener('scrollRight', () => {
        that[cid].callMethod('emitMsg',{name:"scrollRight",params:{type:"scrollRight",scrollRight:true,id:cid}})
        that[cid].callMethod('emitMsg',{name:"scrollRight",params:{type:"scrollRight",scrollRight:true,id:cid, opts: cfu.instance[cid].opts}})
      });
    },
    updataUChart() {
@@ -1471,31 +1522,39 @@
      let cid = this.rid
      let ontouch = cfu.option[cid].ontouch
      if(ontouch == false) return;
      cfu.instance[cid].scrollStart(e)
      that[cid].callMethod('emitMsg',{name:"getTouchStart",params:{type:"touchStart",event:e.changedTouches[0],id:cid}})
      if(cfu.option[cid].enableScroll === true && e.touches.length == 1){
        cfu.instance[cid].scrollStart(e);
      }
      that[cid].callMethod('emitMsg',{name:"getTouchStart",params:{type:"touchStart",event:e.changedTouches[0],id:cid, opts: cfu.instance[cid].opts}})
    },
    touchMove(e) {
      let cid = this.rid
      let ontouch = cfu.option[cid].ontouch
      if(ontouch == false) return;
      cfu.instance[cid].scroll(e)
      that[cid].callMethod('emitMsg',{name:"getTouchMove",params:{type:"touchMove",event:e.changedTouches[0],id:cid}})
      if(cfu.option[cid].enableScroll === true && e.changedTouches.length == 1){
        cfu.instance[cid].scroll(e);
      }
      if(cfu.option[cid].ontap === true && cfu.option[cid].enableScroll === false && cfu.option[cid].onmovetip === true){
        let rchartdom = document.getElementById('UC'+cid).getBoundingClientRect()
        let tmpe = { x: e.changedTouches[0].clientX - rchartdom.left, y:e.changedTouches[0].clientY - rchartdom.top + rootdom.top}
        e.changedTouches = [];
        e.changedTouches.unshift(tmpe)
        if(cfu.option[cid].tooltipShow === true){
          this.showTooltip(e,cid)
        }
      }
      if(ontouch === true && cfu.option[cid].enableScroll === true && cfu.option[cid].onzoom === true && e.changedTouches.length == 2){
        cfu.instance[cid].dobuleZoom(e);
      }
      that[cid].callMethod('emitMsg',{name:"getTouchMove",params:{type:"touchMove",event:e.changedTouches[0],id:cid, opts: cfu.instance[cid].opts}})
    },
    touchEnd(e) {
      let cid = this.rid
      let ontouch = cfu.option[cid].ontouch
      if(ontouch == false) return;
      cfu.instance[cid].scrollEnd(e)
      that[cid].callMethod('emitMsg',{name:"getTouchEnd",params:{type:"touchEnd",event:e.changedTouches[0],id:cid}})
      if(cfu.option[cid].enableScroll === true && e.touches.length == 0){
        cfu.instance[cid].scrollEnd(e);
      }
      that[cid].callMethod('emitMsg',{name:"getTouchEnd",params:{type:"touchEnd",event:e.changedTouches[0],id:cid, opts: cfu.instance[cid].opts}})
    },
    mouseDown(e) {
      let cid = this.rid
@@ -1508,7 +1567,7 @@
      e.changedTouches.unshift(tmpe)
      cfu.instance[cid].scrollStart(e)
      cfu.option[cid].mousedown=true;
      that[cid].callMethod('emitMsg',{name:"getTouchStart",params:{type:"mouseDown",event:tmpe,id:cid}})
      that[cid].callMethod('emitMsg',{name:"getTouchStart",params:{type:"mouseDown",event:tmpe,id:cid, opts: cfu.instance[cid].opts}})
    },
    mouseMove(e) {
      let cid = this.rid
@@ -1522,7 +1581,7 @@
      e.changedTouches.unshift(tmpe)
      if(cfu.option[cid].mousedown){
        cfu.instance[cid].scroll(e)
        that[cid].callMethod('emitMsg',{name:"getTouchMove",params:{type:"mouseMove",event:tmpe,id:cid}})
        that[cid].callMethod('emitMsg',{name:"getTouchMove",params:{type:"mouseMove",event:tmpe,id:cid, opts: cfu.instance[cid].opts}})
      }else if(cfu.instance[cid]){
        if(tooltipShow==true){
          this.showTooltip(e,cid)
@@ -1540,7 +1599,7 @@
      e.changedTouches.unshift(tmpe)
      cfu.instance[cid].scrollEnd(e)
      cfu.option[cid].mousedown=false;
      that[cid].callMethod('emitMsg',{name:"getTouchEnd",params:{type:"mouseUp",event:tmpe,id:cid}})
      that[cid].callMethod('emitMsg',{name:"getTouchEnd",params:{type:"mouseUp",event:tmpe,id:cid, opts: cfu.instance[cid].opts}})
    },
  }
}
Monitor-APP/uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js
@@ -43,22 +43,22 @@
const cfu = {
  //demotype为自定义图表类型,一般不需要自定义图表类型,只需要改根节点上对应的类型即可
    "type":["pie","ring","rose","word","funnel","map","arcbar","line","column","bar","area","radar","gauge","candle","mix","tline","tarea","scatter","bubble","demotype"],
    "range":["饼状图","圆环图","玫瑰图","词云图","漏斗图","地图","圆弧进度条","折线图","柱状图","条状图","区域图","雷达图","仪表盘","K线图","混合图","时间轴折线","时间轴区域","散点图","气泡图","自定义类型"],
    "type":["pie","ring","rose","word","funnel","map","arcbar","line","column","mount","bar","area","radar","gauge","candle","mix","tline","tarea","scatter","bubble","demotype"],
    "range":["饼状图","圆环图","玫瑰图","词云图","漏斗图","地图","圆弧进度条","折线图","柱状图","山峰图","条状图","区域图","雷达图","仪表盘","K线图","混合图","时间轴折线","时间轴区域","散点图","气泡图","自定义类型"],
  //增加自定义图表类型,如果需要categories,请在这里加入您的图表类型,例如最后的"demotype"
  //自定义类型时需要注意"tline","tarea","scatter","bubble"等时间轴(矢量x轴)类图表,没有categories,不需要加入categories
    "categories":["line","column","bar","area","radar","gauge","candle","mix","demotype"],
    "categories":["line","column","mount","bar","area","radar","gauge","candle","mix","demotype"],
  //instance为实例变量承载属性,不要删除
  "instance":{},
  //option为opts及eopts承载属性,不要删除
  "option":{},
  //下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换
  "formatter":{
    "yAxisDemo1":function(val){return val+'元'},
    "yAxisDemo2":function(val){return val.toFixed(2)},
    "xAxisDemo1":function(val){return val+'年'},
    "xAxisDemo2":function(val){return formatDateTime(val,'h:m')},
    "seriesDemo1":function(val){return val+'元'},
    "yAxisDemo1":function(val, index, opts){return val+'元'},
    "yAxisDemo2":function(val, index, opts){return val.toFixed(2)},
    "xAxisDemo1":function(val, index, opts){return val+'年';},
    "xAxisDemo2":function(val, index, opts){return formatDateTime(val,'h:m')},
    "seriesDemo1":function(val, index, series, opts){return val+'元'},
    "tooltipDemo1":function(item, category, index, opts){
      if(index==0){
          return '随便用'+item.data+'年'
@@ -66,7 +66,7 @@
          return '其他我没改'+item.data+'天'
      }
    },
    "pieDemo":function(val, index, series){
    "pieDemo":function(val, index, series, opts){
      if(index !== undefined){
        return series[index].name+':'+series[index].data+'元'
      }
@@ -333,6 +333,25 @@
            },
        }
    },
  "mount":{
      "type": "mount",
    "color": color,
      "padding": [15,15,0,5],
      "xAxis": {
      "disableGrid": true,
      },
      "yAxis": {
      "data":[{"min":0}]
      },
      "legend": {
      },
      "extra": {
          "mount": {
              "type": "mount",
              "widthRatio": 1.5,
          },
      }
  },
  "bar":{
      "type": "bar",
    "color": color,
Monitor-APP/uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md
@@ -1,12 +1,5 @@
# uCharts JSSDK说明
1、如不使用uCharts组件,可直接引用u-charts.js,打包编译后会`自动压缩`,压缩后体积约为`98kb`。
2、如果100kb的体积仍需压缩,请手动删除u-charts.js内您不需要的图表类型,如k线图candle。
1、如不使用uCharts组件,可直接引用u-charts.js,打包编译后会`自动压缩`,压缩后体积约为`120kb`。
2、如果120kb的体积仍需压缩,请手到uCharts官网通过在线定制选择您需要的图表。
3、config-ucharts.js为uCharts组件的用户配置文件,升级前请`自行备份config-ucharts.js`文件,以免被强制覆盖。
3、config-echarts.js为ECharts组件的用户配置文件,升级前请`自行备份config-echarts.js`文件,以免被强制覆盖。
# v1.0转v2.0注意事项
1、opts.colors变更为opts.color
2、ring圆环图的扩展配置由extra.pie变更为extra.ring
3、混合图借用的扩展配置由extra.column变更为extra.mix.column
4、全部涉及到format的格式化属性变更为formatter
5、不需要再传canvasId及$this参数,如果通过uChats获取context,可能会导致this实例混乱,导致小程序开发者工具报错。如果不使用qiun-data-charts官方组件,需要在new uCharts()实例化之前,自行获取canvas的上下文context(ctx),并传入new中的context(opts.context)。为了能跨更多的端,给您带来的不便敬请谅解。
4、config-echarts.js为ECharts组件的用户配置文件,升级前请`自行备份config-echarts.js`文件,以免被强制覆盖。
Monitor-APP/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js
@@ -1,11 +1,11 @@
/*
 * uCharts®
 * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台
 * Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
 * uCharts (R)
 * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360/快手)、Vue、Taro等支持canvas的框架平台
 * Copyright (C) 2018-2022 QIUN (R) 秋云 https://www.ucharts.cn All rights reserved.
 * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 * 复制使用请保留本段注释,感谢支持开源!
 * 
 * uCharts®官方网站
 * uCharts (R) 官方网站
 * https://www.uCharts.cn
 * 
 * 开源地址:
@@ -19,17 +19,13 @@
'use strict';
var config = {
  version: 'v2.3.7-20220122',
  version: 'v2.4.4-20221102',
  yAxisWidth: 15,
  yAxisSplit: 5,
  xAxisHeight: 22,
  xAxisLineHeight: 22,
  legendHeight: 15,
  yAxisTitleWidth: 15,
  xAxisTextPadding: 3,
  padding: [10, 10, 10, 10],
  pixelRatio: 1,
  rotate: false,
  columePadding: 3,
  fontSize: 13,
  fontColor: '#666666',
  dataPointShape: ['circle', 'circle', 'circle', 'circle'],
@@ -37,17 +33,13 @@
  linearColor: ['#0EE2F8', '#2BDCA8', '#FA7D8D', '#EB88E2', '#2AE3A0', '#0EE2F8', '#EB88E2', '#6773E3', '#F78A85'],
  pieChartLinePadding: 15,
  pieChartTextPadding: 5,
  xAxisTextPadding: 3,
  titleColor: '#333333',
  titleFontSize: 20,
  subtitleColor: '#999999',
  subtitleFontSize: 15,
  toolTipPadding: 3,
  toolTipBackground: '#000000',
  toolTipOpacity: 0.7,
  toolTipLineHeight: 20,
  radarLabelTextMargin: 13,
  gaugeLabelTextMargin: 13
};
var assign = function(target, ...varArgs) {
@@ -115,28 +107,6 @@
  return e;
}
// 经纬度转墨卡托
function lonlat2mercator(longitude, latitude) {
  var mercator = Array(2);
  var x = longitude * 20037508.34 / 180;
  var y = Math.log(Math.tan((90 + latitude) * Math.PI / 360)) / (Math.PI / 180);
  y = y * 20037508.34 / 180;
  mercator[0] = x;
  mercator[1] = y;
  return mercator;
}
// 墨卡托转经纬度
function mercator2lonlat(longitude, latitude) {
  var lonlat = Array(2)
  var x = longitude / 20037508.34 * 180;
  var y = latitude / 20037508.34 * 180;
  y = 180 / Math.PI * (2 * Math.atan(Math.exp(y * Math.PI / 180)) - Math.PI / 2);
  lonlat[0] = x;
  lonlat[1] = y;
  return lonlat;
}
// hex 转 rgba
function hexToRgb(hexValue, opc) {
  var rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
@@ -168,6 +138,9 @@
  }
  while (num % limit !== 0) {
    if (type === 'upper') {
      if (num == num + 1) { //修复数据值过大num++无效的bug by 向日葵 @xrk_jy
        break;
      }
      num++;
    } else {
      num--;
@@ -203,6 +176,10 @@
function calValidDistance(self, distance, chartData, config, opts) {
  var dataChartAreaWidth = opts.width - opts.area[1] - opts.area[3];
  var dataChartWidth = chartData.eachSpacing * (opts.chartData.xAxisData.xAxisPoints.length - 1);
  if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1){
    if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2
    dataChartWidth += (opts.extra.mount.widthRatio - 1)*chartData.eachSpacing;
  }
  var validDistance = distance;
  if (distance >= 0) {
    validDistance = 0;
@@ -241,18 +218,6 @@
    }
  }
  return angle >= startAngle && angle <= endAngle;
}
function calRotateTranslate(x, y, h) {
  var xv = x;
  var yv = h - y;
  var transX = xv + (h - yv - xv) / Math.sqrt(2);
  transX *= -1;
  var transY = (h - yv) * (Math.sqrt(2) - 1) - (h - yv - xv) / Math.sqrt(2);
  return {
    transX: transX,
    transY: transY
  };
}
function createCurveControlPoints(points, i) {
@@ -330,6 +295,7 @@
  };
}
function convertCoordinateOrigin(x, y, center) {
  return {
    x: center.x + x,
@@ -406,13 +372,12 @@
          item.legendShape = "line";
          break;
        case 'column':
        case 'bar':
          item.legendShape = "rect";
          break;
        case 'area':
        case 'mount':
          item.legendShape = "triangle";
          break;
        case 'bar':
          item.legendShape = "rect";
          break;
        default:
          item.legendShape = "circle";
@@ -435,7 +400,7 @@
  }
  return newcolor;
}
function getDataRange(minData, maxData) {
  var limit = 0;
  var range = maxData - minData;
@@ -618,7 +583,12 @@
    }
    points = filterPoints[0][index[0]];
  }else{
    points = calPoints[0][index];
    for (let i = 0; i < calPoints.length; i++) {
      if(calPoints[i][index]){
        points = calPoints[i][index];
        break;
      }
    }
  };
  var textList = seriesData.map(function(item) {
    let titleText = null;
@@ -959,6 +929,7 @@
  return Math.pow(currentPoints.x - center.x, 2) + Math.pow(currentPoints.y - center.y, 2) <= Math.pow(radius, 2);
}
function splitPoints(points,eachSeries) {
  var newPoints = [];
  var items = [];
@@ -984,6 +955,7 @@
  }
  return newPoints;
}
function calLegendData(series, opts, config, chartData, context) {
  let legendData = {
@@ -1022,7 +994,8 @@
    let currentRow = [];
    for (let i = 0; i < series.length; i++) {
      let item = series[i];
      let itemWidth = shapeWidth + shapeRight + measureText(item.name || 'undefined', fontSize, context) + opts.legend.itemGap * opts.pix;
      const legendText = item.legendText ? item.legendText : item.name;
      let itemWidth = shapeWidth + shapeRight + measureText(legendText || 'undefined', fontSize, context) + opts.legend.itemGap * opts.pix;
      if (widthCount + itemWidth > opts.width - opts.area[1] - opts.area[3]) {
        legendList.push(currentRow);
        widthCountArr.push(widthCount - opts.legend.itemGap * opts.pix);
@@ -1131,14 +1104,24 @@
    angle: 0,
    xAxisHeight: config.xAxisHeight
  };
  var categoriesTextLenth = categories.map(function(item) {
    return measureText(item, opts.xAxis.fontSize * opts.pix || config.fontSize, context);
  var fontSize = opts.xAxis.fontSize * opts.pix || config.fontSize;
  var categoriesTextLenth = categories.map(function(item,index) {
    var xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item,index,opts) : item;
    return measureText(String(xitem), fontSize, context);
  });
  var maxTextLength = Math.max.apply(this, categoriesTextLenth);
  if (opts.xAxis.rotateLabel == true && maxTextLength + 2 * config.xAxisTextPadding > eachSpacing) {
    result.angle = 45 * Math.PI / 180;
    result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle);
  if (opts.xAxis.rotateLabel == true) {
    result.angle = opts.xAxis.rotateAngle * Math.PI / 180;
    let tempHeight = 2 * config.xAxisTextPadding +  Math.abs(maxTextLength * Math.sin(result.angle))
    tempHeight = tempHeight < fontSize + 2 * config.xAxisTextPadding ? tempHeight + 2 * config.xAxisTextPadding : tempHeight;
    if(opts.enableScroll == true && opts.xAxis.scrollShow == true){
      tempHeight += 12 * opts.pix;
    }
    result.xAxisHeight = tempHeight;
  }
  if (opts.xAxis.disabled){
    result.xAxisHeight = 0;
  }
  return result;
}
@@ -1314,22 +1297,19 @@
  return series;
}
function getFunnelDataPoints(series, radius, type, eachSpacing) {
function getFunnelDataPoints(series, radius, option, eachSpacing) {
  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
  series = series.sort(function(a, b) {
    return parseInt(b.data) - parseInt(a.data);
  });
  for (let i = 0; i < series.length; i++) {
    if(type == 'funnel'){
    if(option.type == 'funnel'){
      series[i].radius = series[i].data / series[0].data * radius * process;
    }else{
      series[i].radius =  (eachSpacing * (series.length - i)) / (eachSpacing * series.length) * radius * process;
    }
    series[i]._proportion_ = series[i].data / series[0].data;
  }
  if(type !== 'pyramid'){
    series.reverse();
  }
  // if(option.type !== 'pyramid'){
  //   series.reverse();
  // }
  return series;
}
@@ -1372,6 +1352,43 @@
}
function getArcbarDataPoints(series, arcbarOption) {
  var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
  if (process == 1) {
    process = 0.999999;
  }
  for (let i = 0; i < series.length; i++) {
    let item = series[i];
    item.data = item.data === null ? 0 : item.data;
    let totalAngle;
    if (arcbarOption.type == 'circle') {
      totalAngle = 2;
    } else {
      if(arcbarOption.direction == 'ccw'){
        if (arcbarOption.startAngle < arcbarOption.endAngle) {
          totalAngle = 2 + arcbarOption.startAngle - arcbarOption.endAngle;
        } else {
          totalAngle = arcbarOption.startAngle - arcbarOption.endAngle;
        }
      }else{
        if (arcbarOption.endAngle < arcbarOption.startAngle) {
          totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle;
        } else {
          totalAngle = arcbarOption.startAngle - arcbarOption.endAngle;
        }
      }
    }
    item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle;
    if(arcbarOption.direction == 'ccw'){
      item._proportion_ = arcbarOption.startAngle - totalAngle * item.data * process ;
    }
    if (item._proportion_ >= 2) {
      item._proportion_ = item._proportion_ % 2;
    }
  }
  return series;
}
function getGaugeArcbarDataPoints(series, arcbarOption) {
  var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
  if (process == 1) {
    process = 0.999999;
@@ -1516,12 +1533,12 @@
    if (item === null) {
      return null;
    }
    item.width = Math.ceil(eachSpacing - 2 * categoryGap);
    item.width = eachSpacing - 2 * categoryGap;
    if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
      item.width = Math.min(item.width, +opts.extra.column.width * opts.pix);
    }
    if (index > 0) {
      item.width -= 2 * border;
      item.width -= border;
    }
    return item;
  });
@@ -1567,16 +1584,22 @@
  if ((opts.type == 'line' || opts.type == 'area' || opts.type == 'scatter' || opts.type == 'bubble' || opts.type == 'bar') && dataCount > 1 && opts.xAxis.boundaryGap == 'justify') {
    dataCount -= 1;
  }
  var widthRatio = 0;
  if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1){
    if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2
    widthRatio = opts.extra.mount.widthRatio - 1;
    dataCount += widthRatio;
  }
  var eachSpacing = spacingValid / dataCount;
  var xAxisPoints = [];
  var startX = opts.area[3];
  var endX = opts.width - opts.area[1];
  categories.forEach(function(item, index) {
    xAxisPoints.push(startX + index * eachSpacing);
    xAxisPoints.push(startX + widthRatio / 2 * eachSpacing + index * eachSpacing);
  });
  if (opts.xAxis.boundaryGap !== 'justify') {
    if (opts.enableScroll === true) {
      xAxisPoints.push(startX + categories.length * eachSpacing);
      xAxisPoints.push(startX + widthRatio * eachSpacing + categories.length * eachSpacing);
    } else {
      xAxisPoints.push(endX);
    }
@@ -1658,6 +1681,32 @@
  return points;
}
function getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption) {
  var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
  var points = [];
  var validHeight = opts.height - opts.area[0] - opts.area[2];
  var validWidth = opts.width - opts.area[1] - opts.area[3];
  var mountWidth = eachSpacing * mountOption.widthRatio;
  series.forEach(function(item, index) {
    if (item === null) {
      points.push(null);
    } else {
      var point = {};
      point.color = item.color;
      point.x = xAxisPoints[index];
      point.x += eachSpacing / 2;
      var value = item.data;
      var height = validHeight * (value - minRange) / (maxRange - minRange);
      height *= process;
      point.y = opts.height - height - opts.area[2];
      point.value = value;
      point.width = mountWidth;
      points.push(point);
    }
  });
  return points;
}
function getBarDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config) {
  var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
  var points = [];
@@ -1707,6 +1756,9 @@
        var height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
      } else {
        var value = item;
        if (typeof item === 'object' && item !== null) {
          value = item.value;
        }
        var height = validHeight * (value - minRange) / (maxRange - minRange);
        var height0 = 0;
      }
@@ -1742,6 +1794,9 @@
        var height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
      } else {
        var value = item;
        if (typeof item === 'object' && item !== null) {
          value = item.value;
        }
        var height = validHeight * (value - minRange) / (maxRange - minRange);
        var height0 = 0;
      }
@@ -1802,31 +1857,18 @@
    minData = Math.min.apply(this, sorted);
    maxData = Math.max.apply(this, sorted);
  }
  //为了兼容v1.9.0之前的项目
  // if (index > -1) {
  //   if (typeof opts.yAxis.data[index].min === 'number') {
  //     minData = Math.min(opts.yAxis.data[index].min, minData);
  //   }
  //   if (typeof opts.yAxis.data[index].max === 'number') {
  //     maxData = Math.max(opts.yAxis.data[index].max, maxData);
  //   }
  // } else {
  //   if (typeof opts.yAxis.min === 'number') {
  //     minData = Math.min(opts.yAxis.min, minData);
  //   }
  //   if (typeof opts.yAxis.max === 'number') {
  //     maxData = Math.max(opts.yAxis.max, maxData);
  //   }
  // }
  if (minData === maxData) {
    var rangeSpan = maxData || 10;
    maxData += rangeSpan;
    if(maxData == 0){
      maxData = 10;
    }else{
      minData = 0;
    }
  }
  var dataRange = getDataRange(minData, maxData);
  var minRange = yData.min === undefined || yData.min === null ? dataRange.minRange : yData.min;
  var maxRange = yData.max === undefined || yData.min === null ? dataRange.maxRange : yData.max;
  var range = [];
  var minRange = (yData.min === undefined || yData.min === null) ? dataRange.minRange : yData.min;
  var maxRange = (yData.max === undefined || yData.max === null) ? dataRange.maxRange : yData.max;
  var eachRange = (maxRange - minRange) / opts.yAxis.splitNumber;
  var range = [];
  for (var i = 0; i <= opts.yAxis.splitNumber; i++) {
    range.push(minRange + eachRange * i);
  }
@@ -1862,13 +1904,13 @@
      }
      if(yData.type === 'categories'){
        if(!yData.formatter){
          yData.formatter = (val) => {return val + (yData.unit || '')};
          yData.formatter = (val,index,opts) => {return val + (yData.unit || '')};
        }
        yData.categories = yData.categories || opts.categories;
        rangesArr[i] = yData.categories;
      }else{
        if(!yData.formatter){
          yData.formatter = (val) => {return val.toFixed(yData.tofix) + (yData.unit || '')};
          yData.formatter = (val,index,opts) => {return util.toFixed(val, yData.tofix || 0) + (yData.unit || '')};
        }
        rangesArr[i] = getYAxisTextList(newSeries[i], opts, config, columnstyle.type, yData, i);
      }
@@ -1877,8 +1919,8 @@
        position: yData.position ? yData.position : 'left',
        width: 0
      };
      rangesFormatArr[i] = rangesArr[i].map(function(items) {
        items = yData.formatter(items);
      rangesFormatArr[i] = rangesArr[i].map(function(items,index) {
        items = yData.formatter(items,index,opts);
        yAxisWidthArr[i].width = Math.max(yAxisWidthArr[i].width, measureText(items, yAxisFontSizes, context) + 5);
        return items;
      });
@@ -1894,26 +1936,14 @@
    var yAxisWidthArr = new Array(1);
    if(opts.type === 'bar'){
      rangesArr[0] = opts.categories;
      if(!opts.yAxis.formatter){
        opts.yAxis.formatter = (val) => {return val + (opts.yAxis.unit || '')}
      }
    }else{
      if(!opts.yAxis.formatter){
        opts.yAxis.formatter = (val) => {return val.toFixed(opts.yAxis.tofix ) + (opts.yAxis.unit || '')}
      }
      rangesArr[0] = getYAxisTextList(series, opts, config, columnstyle.type, {});
    }
    yAxisWidthArr[0] = {
      position: 'left',
      width: 0
    };
    var yAxisFontSize = opts.yAxis.fontSize * opts.pix || config.fontSize;
    rangesFormatArr[0] = rangesArr[0].map(function(item) {
      item = opts.yAxis.formatter(item);
      yAxisWidthArr[0].width = Math.max(yAxisWidthArr[0].width, measureText(item, yAxisFontSize, context) + 5);
      return item;
    });
    yAxisWidthArr[0].width += 3 * opts.pix;
    if (opts.yAxis.disabled === true) {
      yAxisWidthArr[0] = {
        position: 'left',
@@ -1928,13 +1958,20 @@
        position: 'left',
        max: opts.yAxis.max,
        min: opts.yAxis.min,
        formatter: opts.yAxis.formatter
        formatter: (val,index,opts) => {return val}
      };
      if(opts.type === 'bar'){
        opts.yAxis.data[0].categories = opts.categories;
        opts.yAxis.data[0].type = 'categories';
      }
    }
    var yAxisFontSize = opts.yAxis.fontSize * opts.pix || config.fontSize;
    rangesFormatArr[0] = rangesArr[0].map(function(item,index) {
      item = opts.yAxis.data[0].formatter(item,index,opts);
      yAxisWidthArr[0].width = Math.max(yAxisWidthArr[0].width, measureText(item, yAxisFontSize, context) + 5);
      return item;
    });
    yAxisWidthArr[0].width += 3 * opts.pix;
  }
  return {
    rangesFormat: rangesFormatArr,
@@ -1949,10 +1986,10 @@
  let minAxis = opts.area[0];
  let items = [];
  for (let i = 0; i < ranges.length; i++) {
    let maxVal = ranges[i].shift();
    let minVal = ranges[i].pop();
    let maxVal = Math.max.apply(this, ranges[i]);
    let minVal = Math.min.apply(this, ranges[i]);
    let item = maxVal - (maxVal - minVal) * (point - minAxis) / spacingValid;
    item = opts.yAxis.data[i].formatter ? opts.yAxis.data[i].formatter(item) : item.toFixed(0);
    item = opts.yAxis.data && opts.yAxis.data[i].formatter ? opts.yAxis.data[i].formatter(item, i, opts) : item.toFixed(0);
    items.push(String(item))
  }
  return items;
@@ -2027,7 +2064,7 @@
        context.lineTo(item.x, item.y - 4.5);
      }
    });
  } else if (shape === 'triangle') {
  } else if (shape === 'none') {
    return;
  }
  context.closePath();
@@ -2093,7 +2130,28 @@
          value = data[index].value
        }
      }
      var formatVal = series.formatter ? series.formatter(value,index) : value;
      var formatVal = series.formatter ? series.formatter(value,index,series,opts) : value;
      context.setTextAlign('center');
      context.fillText(String(formatVal), item.x, item.y - 4 + textOffset * opts.pix);
      context.closePath();
      context.stroke();
      context.setTextAlign('left');
    }
  });
}
function drawMountPointText(points, series, config, context, opts) {
  // 绘制数据文案
  var data = series.data;
  var textOffset = series.textOffset ? series.textOffset : 0;
  points.forEach(function(item, index) {
    if (item !== null) {
      context.beginPath();
      var fontSize = series[index].textSize ? series[index].textSize * opts.pix : config.fontSize;
      context.setFontSize(fontSize);
      context.setFillStyle(series[index].textColor || opts.fontColor);
      var value = item.value
      var formatVal = series[index].formatter ? series[index].formatter(value,index,series,opts) : value;
      context.setTextAlign('center');
      context.fillText(String(formatVal), item.x, item.y - 4 + textOffset * opts.pix);
      context.closePath();
@@ -2117,7 +2175,7 @@
      if (typeof data[index] === 'object' && data[index] !== null) {
        value = data[index].value ;
      }
      var formatVal = series.formatter ? series.formatter(value,index) : value;
      var formatVal = series.formatter ? series.formatter(value,index,series,opts) : value;
      context.setTextAlign('left');
      context.fillText(String(formatVal), item.x + 4 * opts.pix , item.y + fontSize / 2 - 3 );
      context.closePath();
@@ -2128,6 +2186,7 @@
function drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context) {
  radius -= gaugeOption.width / 2 + gaugeOption.labelOffset * opts.pix;
  radius = radius < 10 ? 10 : radius;
  let totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
  let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
  let totalNumber = gaugeOption.endNumber - gaugeOption.startNumber;
@@ -2139,7 +2198,7 @@
      x: radius * Math.cos(nowAngle * Math.PI),
      y: radius * Math.sin(nowAngle * Math.PI)
    };
    var labelText = gaugeOption.formatter ? gaugeOption.formatter(nowNumber) : nowNumber;
    var labelText = gaugeOption.formatter ? gaugeOption.formatter(nowNumber,i,opts) : nowNumber;
    pos.x += centerPosition.x - measureText(labelText, config.fontSize, context) / 2;
    pos.y += centerPosition.y;
    var startX = pos.x;
@@ -2156,16 +2215,26 @@
    }
    nowNumber += splitNumber;
  }
}
function drawRadarLabel(angleList, radius, centerPosition, opts, config, context) {
  var radarOption = opts.extra.radar || {};
  radius += config.radarLabelTextMargin * opts.pix;
  angleList.forEach(function(angle, index) {
    if(radarOption.labelPointShow === true && opts.categories[index] !== ''){
      var posPoint = {
        x: radius * Math.cos(angle),
        y: radius * Math.sin(angle)
      };
      var posPointAxis = convertCoordinateOrigin(posPoint.x, posPoint.y, centerPosition);
      context.setFillStyle(radarOption.labelPointColor);
      context.beginPath();
      context.arc(posPointAxis.x, posPointAxis.y, radarOption.labelPointRadius * opts.pix, 0, 2 * Math.PI, false);
      context.closePath();
      context.fill();
    }
    var pos = {
      x: radius * Math.cos(angle),
      y: radius * Math.sin(angle)
      x: (radius + config.radarLabelTextMargin * opts.pix) * Math.cos(angle),
      y: (radius + config.radarLabelTextMargin * opts.pix) * Math.sin(angle)
    };
    var posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition);
    var startX = posRelativeCanvas.x;
@@ -2189,8 +2258,9 @@
  var lineRadius = config.pieChartLinePadding;
  var textObjectCollection = [];
  var lastTextObject = null;
  var seriesConvert = series.map(function(item,index,series) {
    var text = item.formatter ? item.formatter(item,index,series) : util.toFixed(item._proportion_.toFixed(4) * 100) + '%';
  var seriesConvert = series.map(function(item,index) {
    var text = item.formatter ? item.formatter(item,index,series,opts) : util.toFixed(item._proportion_.toFixed(4) * 100) + '%';
    text = item.labelText ? item.labelText : text;
    var arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._proportion_ / 2);
    if (item._rose_proportion_) {
      arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._rose_proportion_ / 2);
@@ -2204,6 +2274,7 @@
      radius: radius,
      textColor: item.textColor,
      textSize: item.textSize,
      labelShow: item.labelShow
    };
  });
  for (let i = 0; i < seriesConvert.length; i++) {
@@ -2261,6 +2332,9 @@
    textObjectCollection.push(lastTextObject);
  }
  for (let i = 0; i < textObjectCollection.length; i++) {
    if(seriesConvert[i].labelShow === false){
      continue;
    }
    let item = textObjectCollection[i];
    let lineStartPoistion = convertCoordinateOrigin(item.lineStart.x, item.lineStart.y, center);
    let lineEndPoistion = convertCoordinateOrigin(item.lineEnd.x, item.lineEnd.y, center);
@@ -2279,7 +2353,7 @@
    context.closePath();
    context.beginPath();
    context.moveTo(textPosition.x + item.width, textPosition.y);
    context.arc(curveStartX, textPosition.y, 2, 0, 2 * Math.PI);
    context.arc(curveStartX, textPosition.y, 2 * opts.pix, 0, 2 * Math.PI);
    context.closePath();
    context.fill();
    context.beginPath();
@@ -2313,7 +2387,7 @@
    context.setFontSize(config.fontSize);
    let textWidth = measureText(labelText, config.fontSize, context);
    let textX = offsetX - 0.5 * textWidth;
    let textY = endY;
    let textY = endY + 2 * opts.pix;
    context.beginPath();
    context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity));
    context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground);
@@ -2347,7 +2421,9 @@
      labelFontColor: '#666666',
      labelBgColor: '#DFE8FF',
      labelBgOpacity: 0.8,
      yAxisIndex: 0
      labelAlign: 'left',
      labelOffsetX: 0,
      labelOffsetY: 0,
    }, points[i]);
    if (markLineOption.type == 'dash') {
      context.setLineDash([markLineOption.dashLength, markLineOption.dashLength]);
@@ -2360,27 +2436,28 @@
    context.stroke();
    context.setLineDash([]);
    if (item.showLabel) {
      let labelText = opts.yAxis.formatter ? opts.yAxis.formatter(item.value) : item.value;
      let labelText = item.labelText ? item.labelText : item.value;
      context.setFontSize(config.fontSize);
      let textWidth = measureText(labelText, config.fontSize, context);
      let yAxisWidth = opts.chartData.yAxisData.yAxisWidth[0].width;
      let bgStartX = opts.area[3] - textWidth - config.toolTipPadding * 2;
      let bgEndX = opts.area[3];
      let bgWidth = bgEndX - bgStartX;
      let textX = bgEndX - config.toolTipPadding;
      let bgWidth = textWidth + config.toolTipPadding * 2;
      let bgStartX = item.labelAlign == 'left' ? opts.area[3] - bgWidth : opts.width - opts.area[1];
      bgStartX += item.labelOffsetX;
      let bgStartY = item.y - 0.5 * config.fontSize - config.toolTipPadding;
      bgStartY += item.labelOffsetY;
      let textX = bgStartX + config.toolTipPadding;
      let textY = item.y;
      context.setFillStyle(hexToRgb(item.labelBgColor, item.labelBgOpacity));
      context.setStrokeStyle(item.labelBgColor);
      context.setLineWidth(1 * opts.pix);
      context.beginPath();
      context.rect(bgStartX, textY - 0.5 * config.fontSize - config.toolTipPadding, bgWidth, config.fontSize + 2 * config.toolTipPadding);
      context.rect(bgStartX, bgStartY, bgWidth, config.fontSize + 2 * config.toolTipPadding);
      context.closePath();
      context.stroke();
      context.fill();
      context.setFontSize(config.fontSize);
      context.setTextAlign('right');
      context.setTextAlign('left');
      context.setFillStyle(item.labelFontColor);
      context.fillText(String(labelText), textX, textY + 0.5 * config.fontSize);
      context.fillText(String(labelText), textX, bgStartY + config.fontSize + config.toolTipPadding/2);
      context.stroke();
      context.setTextAlign('left');
    }
@@ -2414,10 +2491,10 @@
      let textWidth = measureText(labelText[i], config.fontSize, context);
      let bgStartX, bgEndX, bgWidth;
      if (widthArr[i].position == 'left') {
        bgStartX = tStartLeft - widthArr[i].width;
        bgStartX = tStartLeft - (textWidth + config.toolTipPadding * 2) - 2 * opts.pix;
        bgEndX = Math.max(bgStartX, bgStartX + textWidth + config.toolTipPadding * 2);
      } else {
        bgStartX = tStartRight;
        bgStartX = tStartRight + 2 * opts.pix;
        bgEndX = Math.max(bgStartX + widthArr[i].width, bgStartX + textWidth + config.toolTipPadding * 2);
      }
      bgWidth = bgEndX - bgStartX;
@@ -2427,8 +2504,7 @@
      context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity));
      context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground);
      context.setLineWidth(1 * opts.pix);
      context.rect(bgStartX, textY - 0.5 * config.fontSize - config.toolTipPadding, bgWidth, config.fontSize + 2 *
        config.toolTipPadding);
      context.rect(bgStartX, textY - 0.5 * config.fontSize - config.toolTipPadding, bgWidth, config.fontSize + 2 * config.toolTipPadding);
      context.closePath();
      context.stroke();
      context.fill();
@@ -2450,13 +2526,15 @@
function drawToolTipSplitArea(offsetX, opts, config, context, eachSpacing) {
  var toolTipOption = assign({}, {
    activeBgColor: '#000000',
    activeBgOpacity: 0.08
    activeBgOpacity: 0.08,
    activeWidth: eachSpacing
  }, opts.extra.column);
  toolTipOption.activeWidth = toolTipOption.activeWidth > eachSpacing ? eachSpacing : toolTipOption.activeWidth;
  var startY = opts.area[0];
  var endY = opts.height - opts.area[2];
  context.beginPath();
  context.setFillStyle(hexToRgb(toolTipOption.activeBgColor, toolTipOption.activeBgOpacity));
  context.rect(offsetX - eachSpacing / 2, startY, eachSpacing, endY - startY);
  context.rect(offsetX - toolTipOption.activeWidth / 2, startY, toolTipOption.activeWidth, endY - startY);
  context.closePath();
  context.fill();
  context.setFillStyle("#FFFFFF");
@@ -2476,6 +2554,7 @@
  context.fill();
  context.setFillStyle("#FFFFFF");
}
function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxisPoints) {
  var toolTipOption = assign({}, {
@@ -2498,7 +2577,7 @@
  var legendMarginRight = 5 * opts.pix;
  var arrowWidth = toolTipOption.showArrow ? 8 * opts.pix : 0;
  var isOverRightBorder = false;
  if (opts.type == 'line' || opts.type == 'area' || opts.type == 'candle' || opts.type == 'mix') {
  if (opts.type == 'line' || opts.type == 'mount' || opts.type == 'area' || opts.type == 'candle' || opts.type == 'mix') {
    if (toolTipOption.splitLine == true) {
      drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context);
    }
@@ -2530,6 +2609,10 @@
  context.setStrokeStyle(hexToRgb(toolTipOption.borderColor, toolTipOption.borderOpacity));
  var radius = toolTipOption.borderRadius;
  if (isOverRightBorder) {
    // 增加左侧仍然超出的判断
    if(toolTipWidth + arrowWidth > opts.width){
      offset.x = opts.width + Math.abs(opts._scrollDistance_ || 0) + arrowWidth + (toolTipWidth - opts.width)
    }
    if (toolTipOption.showArrow) {
      context.moveTo(offset.x, offset.y + 10 * opts.pix);
      context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pix + 5 * opts.pix);
@@ -2575,7 +2658,10 @@
        startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding;
      }
      context.fillRect(startX, startY, legendWidth, config.fontSize);
      // 圆形图例请注释上行,并把下行取消注释
      // context.arc(startX + legendWidth / 2 , startY + opts.fontSize / 2, 4 * opts.pix, 0, 2 * Math.PI);
      context.closePath();
      context.fill();
    }
  });
  // draw text list
@@ -2684,8 +2770,8 @@
              context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI);
            } else {
              context.moveTo(startX, item.y);
              context.lineTo(startX + item.width - 2, item.y);
              context.lineTo(startX + item.width - 2, opts.height - opts.area[2]);
              context.lineTo(startX + item.width, item.y);
              context.lineTo(startX + item.width, opts.height - opts.area[2]);
              context.lineTo(startX, opts.height - opts.area[2]);
              context.lineTo(startX, item.y);
              context.setLineWidth(1)
@@ -2716,7 +2802,7 @@
            }
            context.setFillStyle(fillColor);
            context.moveTo(startX, item.y);
            context.fillRect(startX, item.y, item.width - 2, height);
            context.fillRect(startX, item.y, item.width, height);
            context.closePath();
            context.fill();
          }
@@ -2727,84 +2813,59 @@
        var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
        calPoints.push(points);
        points = fixColumeMeterData(points, eachSpacing, series.length, seriesIndex, config, opts, columnOption.meterBorder);
        if (seriesIndex == 0) {
          for (let i = 0; i < points.length; i++) {
            let item = points[i];
            if (item !== null && i > leftNum && i < rightNum) {
              //画背景颜色
              context.beginPath();
              context.setFillStyle(columnOption.meterFillColor);
              if (seriesIndex == 0 && columnOption.meterBorder > 0) {
                context.setStrokeStyle(eachSeries.color);
                context.setLineWidth(columnOption.meterBorder * opts.pix);
              }
              if(seriesIndex == 0){
                context.setFillStyle(columnOption.meterFillColor);
              }else{
                context.setFillStyle(item.color || eachSeries.color);
              }
              var startX = item.x - item.width / 2;
              var height = opts.height - item.y - opts.area[2];
              if (columnOption.barBorderCircle) {
                var barBorderRadius = (item.width - columnOption.meterBorder*2) / 2;
                if(barBorderRadius>height){
                  barBorderRadius = height;
              if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) {
                const left = startX;
                const top = item.y;
                const width = item.width;
                const height = opts.height - opts.area[2] - item.y;
                if (columnOption.barBorderCircle) {
                  columnOption.barBorderRadius = [width / 2, width / 2, 0, 0];
                }
                context.moveTo(startX + columnOption.meterBorder, opts.height - opts.area[2]);
                context.lineTo(startX + columnOption.meterBorder, item.y + barBorderRadius);
                context.arc(startX + item.width/2, item.y + barBorderRadius, barBorderRadius, -Math.PI, 0);
                context.lineTo(startX + item.width - columnOption.meterBorder , opts.height - opts.area[2]);
                context.lineTo(startX, opts.height - opts.area[2]);
                let [r0, r1, r2, r3] = columnOption.barBorderRadius;
                let minRadius = Math.min(width/2,height/2);
                r0 = r0 > minRadius ? minRadius : r0;
                r1 = r1 > minRadius ? minRadius : r1;
                r2 = r2 > minRadius ? minRadius : r2;
                r3 = r3 > minRadius ? minRadius : r3;
                r0 = r0 < 0 ? 0 : r0;
                r1 = r1 < 0 ? 0 : r1;
                r2 = r2 < 0 ? 0 : r2;
                r3 = r3 < 0 ? 0 : r3;
                context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2);
                context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0);
                context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2);
                context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI);
                context.fill();
              }else{
                context.moveTo(startX, item.y);
                context.fillRect(startX, item.y, item.width, height);
                context.closePath();
                context.lineTo(startX + item.width, item.y);
                context.lineTo(startX + item.width, opts.height - opts.area[2]);
                context.lineTo(startX, opts.height - opts.area[2]);
                context.lineTo(startX, item.y);
                context.fill();
              }
              //画边框线
              if (columnOption.meterBorder > 0) {
                context.beginPath();
                context.setStrokeStyle(eachSeries.color);
                context.setLineWidth(columnOption.meterBorder * opts.pix);
                if (columnOption.barBorderCircle) {
                  var barBorderRadius = (item.width - columnOption.meterBorder)/ 2;
                  if(barBorderRadius>height){
                    barBorderRadius = height;
                  }
                  context.moveTo(startX  + columnOption.meterBorder * 0.5, opts.height - opts.area[2]);
                  context.lineTo(startX + columnOption.meterBorder * 0.5, item.y + barBorderRadius);
                  context.arc(startX + item.width/2, item.y + barBorderRadius - columnOption.meterBorder * 0.5, barBorderRadius, -Math.PI, 0);
                  context.lineTo(startX + item.width - columnOption.meterBorder * 0.5, opts.height - opts.area[2]);
                }else{
                  context.moveTo(startX + columnOption.meterBorder * 0.5, item.y + height);
                  context.lineTo(startX + columnOption.meterBorder * 0.5, item.y + columnOption.meterBorder * 0.5);
                  context.lineTo(startX + item.width - columnOption.meterBorder * 0.5, item.y + columnOption.meterBorder * 0.5);
                  context.lineTo(startX + item.width - columnOption.meterBorder * 0.5, item.y + height);
                }
              if (seriesIndex == 0 && columnOption.meterBorder > 0) {
                context.closePath();
                context.stroke();
              }
            }
          };
        } else {
          for (let i = 0; i < points.length; i++) {
            let item = points[i];
            if (item !== null && i > leftNum && i < rightNum) {
              context.beginPath();
              context.setFillStyle(item.color || eachSeries.color);
              var startX = item.x - item.width / 2;
              var height = opts.height - item.y - opts.area[2];
              if (columnOption.barBorderCircle) {
                var barBorderRadius = item.width / 2;
                if(barBorderRadius>height){
                  barBorderRadius = height;
                }
                context.moveTo(startX, opts.height - opts.area[2]);
                context.arc(startX + barBorderRadius, item.y + barBorderRadius, barBorderRadius, -Math.PI, -Math.PI / 2);
                context.arc(startX + item.width - barBorderRadius, item.y + barBorderRadius, barBorderRadius, -Math.PI / 2, 0);
                context.lineTo(startX + item.width, opts.height - opts.area[2]);
                context.lineTo(startX, opts.height - opts.area[2]);
                context.fill();
              }else{
                context.moveTo(startX, item.y);
                context.fillRect(startX, item.y, item.width, height);
                context.closePath();
                context.fill();
              }
            }
          };
        }
          }
        break;
    }
  });
@@ -2837,6 +2898,226 @@
  return {
    xAxisPoints: xAxisPoints,
    calPoints: calPoints,
    eachSpacing: eachSpacing
  };
}
function drawMountDataPoints(series, opts, config, context) {
  let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
  let xAxisData = opts.chartData.xAxisData,
    xAxisPoints = xAxisData.xAxisPoints,
    eachSpacing = xAxisData.eachSpacing;
  let mountOption = assign({}, {
    type: 'mount',
    widthRatio: 1,
    borderWidth: 1,
    barBorderCircle: false,
    barBorderRadius: [],
    linearType: 'none',
    linearOpacity: 1,
    customColor: [],
    colorStop: 0,
  }, opts.extra.mount);
  mountOption.widthRatio = mountOption.widthRatio <= 0 ? 0 : mountOption.widthRatio;
  mountOption.widthRatio = mountOption.widthRatio >= 2 ? 2 : mountOption.widthRatio;
  let calPoints = [];
  context.save();
  let leftNum = -2;
  let rightNum = xAxisPoints.length + 2;
  if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
    context.translate(opts._scrollDistance_, 0);
    leftNum = Math.floor(-opts._scrollDistance_ / eachSpacing) - 2;
    rightNum = leftNum + opts.xAxis.itemCount + 4;
  }
  mountOption.customColor = fillCustomColor(mountOption.linearType, mountOption.customColor, series, config);
    let ranges, minRange, maxRange;
    ranges = [].concat(opts.chartData.yAxisData.ranges[0]);
    minRange = ranges.pop();
    maxRange = ranges.shift();
    var points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, process);
    switch (mountOption.type) {
      case 'bar':
        for (let i = 0; i < points.length; i++) {
          let item = points[i];
          if (item !== null && i > leftNum && i < rightNum) {
            var startX = item.x - eachSpacing*mountOption.widthRatio/2;
            var height = opts.height - item.y - opts.area[2];
            context.beginPath();
            var fillColor = item.color || series[i].color
            var strokeColor = item.color || series[i].color
            if (mountOption.linearType !== 'none') {
              var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]);
              //透明渐变
              if (mountOption.linearType == 'opacity') {
                grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity));
                grd.addColorStop(1, hexToRgb(fillColor, 1));
              } else {
                grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity));
                grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity));
                grd.addColorStop(1, hexToRgb(fillColor, 1));
              }
              fillColor = grd
            }
            // 圆角边框
            if ((mountOption.barBorderRadius && mountOption.barBorderRadius.length === 4) || mountOption.barBorderCircle === true) {
              const left = startX;
              const top = item.y;
              const width = item.width;
              const height = opts.height - opts.area[2] - item.y - mountOption.borderWidth * opts.pix / 2;
              if (mountOption.barBorderCircle) {
                mountOption.barBorderRadius = [width / 2, width / 2, 0, 0];
              }
              let [r0, r1, r2, r3] = mountOption.barBorderRadius;
              let minRadius = Math.min(width/2,height/2);
              r0 = r0 > minRadius ? minRadius : r0;
              r1 = r1 > minRadius ? minRadius : r1;
              r2 = r2 > minRadius ? minRadius : r2;
              r3 = r3 > minRadius ? minRadius : r3;
              r0 = r0 < 0 ? 0 : r0;
              r1 = r1 < 0 ? 0 : r1;
              r2 = r2 < 0 ? 0 : r2;
              r3 = r3 < 0 ? 0 : r3;
              context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2);
              context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0);
              context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2);
              context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI);
            } else {
              context.moveTo(startX, item.y);
              context.lineTo(startX + item.width, item.y);
              context.lineTo(startX + item.width, opts.height - opts.area[2]);
              context.lineTo(startX, opts.height - opts.area[2]);
              context.lineTo(startX, item.y);
            }
            context.setStrokeStyle(strokeColor);
            context.setFillStyle(fillColor);
            if(mountOption.borderWidth > 0){
              context.setLineWidth(mountOption.borderWidth * opts.pix);
              context.closePath();
              context.stroke();
            }
            context.fill();
          }
        };
        break;
      case 'triangle':
        for (let i = 0; i < points.length; i++) {
          let item = points[i];
          if (item !== null && i > leftNum && i < rightNum) {
            var startX = item.x - eachSpacing*mountOption.widthRatio/2;
            var height = opts.height - item.y - opts.area[2];
            context.beginPath();
            var fillColor = item.color || series[i].color
            var strokeColor = item.color || series[i].color
            if (mountOption.linearType !== 'none') {
              var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]);
              //透明渐变
              if (mountOption.linearType == 'opacity') {
                grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity));
                grd.addColorStop(1, hexToRgb(fillColor, 1));
              } else {
                grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity));
                grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity));
                grd.addColorStop(1, hexToRgb(fillColor, 1));
              }
              fillColor = grd
            }
            context.moveTo(startX, opts.height - opts.area[2]);
            context.lineTo(item.x, item.y);
            context.lineTo(startX + item.width, opts.height - opts.area[2]);
            context.setStrokeStyle(strokeColor);
            context.setFillStyle(fillColor);
            if(mountOption.borderWidth > 0){
              context.setLineWidth(mountOption.borderWidth * opts.pix);
              context.stroke();
            }
            context.fill();
          }
        };
        break;
      case 'mount':
        for (let i = 0; i < points.length; i++) {
          let item = points[i];
          if (item !== null && i > leftNum && i < rightNum) {
            var startX = item.x - eachSpacing*mountOption.widthRatio/2;
            var height = opts.height - item.y - opts.area[2];
            context.beginPath();
            var fillColor = item.color || series[i].color
            var strokeColor = item.color || series[i].color
            if (mountOption.linearType !== 'none') {
              var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]);
              //透明渐变
              if (mountOption.linearType == 'opacity') {
                grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity));
                grd.addColorStop(1, hexToRgb(fillColor, 1));
              } else {
                grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity));
                grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity));
                grd.addColorStop(1, hexToRgb(fillColor, 1));
              }
              fillColor = grd
            }
            context.moveTo(startX, opts.height - opts.area[2]);
            context.bezierCurveTo(item.x - item.width/4, opts.height - opts.area[2], item.x - item.width/4, item.y, item.x, item.y);
            context.bezierCurveTo(item.x + item.width/4, item.y, item.x + item.width/4, opts.height - opts.area[2], startX + item.width, opts.height - opts.area[2]);
            context.setStrokeStyle(strokeColor);
            context.setFillStyle(fillColor);
            if(mountOption.borderWidth > 0){
              context.setLineWidth(mountOption.borderWidth * opts.pix);
              context.stroke();
            }
            context.fill();
          }
        };
        break;
      case 'sharp':
        for (let i = 0; i < points.length; i++) {
          let item = points[i];
          if (item !== null && i > leftNum && i < rightNum) {
            var startX = item.x - eachSpacing*mountOption.widthRatio/2;
            var height = opts.height - item.y - opts.area[2];
            context.beginPath();
            var fillColor = item.color || series[i].color
            var strokeColor = item.color || series[i].color
            if (mountOption.linearType !== 'none') {
              var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]);
              //透明渐变
              if (mountOption.linearType == 'opacity') {
                grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity));
                grd.addColorStop(1, hexToRgb(fillColor, 1));
              } else {
                grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity));
                grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity));
                grd.addColorStop(1, hexToRgb(fillColor, 1));
              }
              fillColor = grd
            }
            context.moveTo(startX, opts.height - opts.area[2]);
            context.quadraticCurveTo(item.x - 0, opts.height - opts.area[2] - height/4, item.x, item.y);
            context.quadraticCurveTo(item.x + 0, opts.height - opts.area[2] - height/4, startX + item.width, opts.height - opts.area[2])
            context.setStrokeStyle(strokeColor);
            context.setFillStyle(fillColor);
            if(mountOption.borderWidth > 0){
              context.setLineWidth(mountOption.borderWidth * opts.pix);
              context.stroke();
            }
            context.fill();
          }
        };
        break;
    }
  if (opts.dataLabel !== false && process === 1) {
    let ranges, minRange, maxRange;
    ranges = [].concat(opts.chartData.yAxisData.ranges[0]);
    minRange = ranges.pop();
    maxRange = ranges.shift();
    var points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, process);
    drawMountPointText(points, series, config, context, opts);
  }
  context.restore();
  return {
    xAxisPoints: xAxisPoints,
    calPoints: points,
    eachSpacing: eachSpacing
  };
}
@@ -2910,7 +3191,7 @@
              const left = startX;
              const width = item.width;
              const top = item.y - item.width / 2;
              const height = item.heigh;
              const height = item.height;
              if (columnOption.barBorderCircle) {
                columnOption.barBorderRadius = [width / 2, width / 2, 0, 0];
              }
@@ -2932,8 +3213,8 @@
            } else {
              context.moveTo(startX, startY);
              context.lineTo(item.x, startY);
              context.lineTo(item.x, startY + item.width - 2);
              context.lineTo(startX, startY + item.width - 2);
              context.lineTo(item.x, startY + item.width);
              context.lineTo(startX, startY + item.width);
              context.lineTo(startX, startY);
              context.setLineWidth(1)
              context.setStrokeStyle(strokeColor);
@@ -2958,7 +3239,7 @@
            var startX = item.x0;
            context.setFillStyle(fillColor);
            context.moveTo(startX, item.y - item.width/2);
            context.fillRect(startX, item.y - item.width/2, item.height , item.width - 2);
            context.fillRect(startX, item.y - item.width/2, item.height , item.width);
            context.closePath();
            context.fill();
          }
@@ -3443,9 +3724,9 @@
    if (opts.dataLabel !== false && process === 1) {
      points.forEach(function(item, index) {
        context.beginPath();
        var fontSize = series.textSize * opts.pix || config.fontSize;
        var fontSize = eachSeries.textSize * opts.pix || config.fontSize;
        context.setFontSize(fontSize);
        context.setFillStyle(series.textColor || "#FFFFFF");
        context.setFillStyle(eachSeries.textColor || "#FFFFFF");
        context.setTextAlign('center');
        context.fillText(String(item.t), item.x, item.y + fontSize/2);
        context.closePath();
@@ -3461,7 +3742,6 @@
    eachSpacing: eachSpacing
  };
}
function drawLineDataPoints(series, opts, config, context) {
  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
@@ -3574,6 +3854,9 @@
function drawMixDataPoints(series, opts, config, context) {
  let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
  let xAxisData = opts.chartData.xAxisData,
    xAxisPoints = xAxisData.xAxisPoints,
    eachSpacing = xAxisData.eachSpacing;
  let columnOption = assign({}, {
    width: eachSpacing / 2,
    barBorderCircle: false,
@@ -3584,9 +3867,13 @@
    customColor: [],
    colorStop: 0,
  }, opts.extra.mix.column);
  let xAxisData = opts.chartData.xAxisData,
    xAxisPoints = xAxisData.xAxisPoints,
    eachSpacing = xAxisData.eachSpacing;
  let areaOption = assign({}, {
    opacity: 0.2,
    gradient: false
  }, opts.extra.mix.area);
  let lineOption = assign({}, {
    width: 2
  }, opts.extra.mix.line);
  let endY = opts.height - opts.area[2];
  let calPoints = [];
  var columnIndex = 0;
@@ -3666,8 +3953,8 @@
            context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI);
          } else {
            context.moveTo(startX, item.y);
            context.lineTo(startX + item.width - 2, item.y);
            context.lineTo(startX + item.width - 2, opts.height - opts.area[2]);
            context.lineTo(startX + item.width, item.y);
            context.lineTo(startX + item.width, opts.height - opts.area[2]);
            context.lineTo(startX, opts.height - opts.area[2]);
            context.lineTo(startX, item.y);
            context.setLineWidth(1)
@@ -3688,7 +3975,15 @@
        // 绘制区域数据
        context.beginPath();
        context.setStrokeStyle(eachSeries.color);
        context.setFillStyle(hexToRgb(eachSeries.color, 0.2));
        context.setStrokeStyle(hexToRgb(eachSeries.color, areaOption.opacity));
        if (areaOption.gradient) {
          let gradient = context.createLinearGradient(0, opts.area[0], 0, opts.height - opts.area[2]);
          gradient.addColorStop('0', hexToRgb(eachSeries.color, areaOption.opacity));
          gradient.addColorStop('1.0', hexToRgb("#FFFFFF", 0.1));
          context.setFillStyle(gradient);
        } else {
          context.setFillStyle(hexToRgb(eachSeries.color, areaOption.opacity));
        }
        context.setLineWidth(2 * opts.pix);
        if (points.length > 1) {
          var firstPoint = points[0];
@@ -3745,7 +4040,7 @@
        }
        context.beginPath();
        context.setStrokeStyle(eachSeries.color);
        context.setLineWidth(2 * opts.pix);
        context.setLineWidth(lineOption.width * opts.pix);
        if (points.length === 1) {
          context.moveTo(points[0].x, points[0].y);
          context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
@@ -3817,9 +4112,10 @@
  }
}
function drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints) {
  var toolTipOption = opts.extra.tooltip || {};
  if (toolTipOption.horizentalLine && opts.tooltip && process === 1 && (opts.type == 'line' || opts.type == 'area' || opts.type == 'column' || opts.type == 'candle' || opts.type == 'mix')) {
  if (toolTipOption.horizentalLine && opts.tooltip && process === 1 && (opts.type == 'line' || opts.type == 'area' || opts.type == 'column' || opts.type == 'mount' || opts.type == 'candle' || opts.type == 'mix')) {
    drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints)
  }
  context.save();
@@ -3852,6 +4148,10 @@
    var scrollY = opts.height - opts.area[2] + config.xAxisHeight;
    var scrollScreenWidth = endX - startX;
    var scrollTotalWidth = eachSpacing * (xAxisPoints.length - 1);
    if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1){
      if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2
      scrollTotalWidth += (opts.extra.mount.widthRatio - 1)*eachSpacing;
    }
    var scrollWidth = scrollScreenWidth * scrollScreenWidth / scrollTotalWidth;
    var scrollLeft = 0;
    if (opts._scrollDistance_) {
@@ -3944,7 +4244,7 @@
    var xAxisFontSize = opts.xAxis.fontSize * opts.pix || config.fontSize;
    if (config._xAxisTextAngle_ === 0) {
      newCategories.forEach(function(item, index) {
        var xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item) : item;
        var xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item,index,opts) : item;
        var offset = -measureText(String(xitem), xAxisFontSize, context) / 2;
        if (boundaryGap == 'center') {
          offset += eachSpacing / 2;
@@ -3953,35 +4253,53 @@
        if (opts.xAxis.scrollShow) {
          scrollHeight = 6 * opts.pix;
        }
        context.beginPath();
        context.setFontSize(xAxisFontSize);
        context.setFillStyle(opts.xAxis.fontColor || opts.fontColor);
        context.fillText(String(xitem), xAxisPoints[index] + offset, startY + xAxisFontSize + (config.xAxisHeight - scrollHeight - xAxisFontSize) / 2);
        context.closePath();
        context.stroke();
        // 如果在主视图区域内
        var _scrollDistance_ = opts._scrollDistance_ || 0;
        var truePoints = boundaryGap == 'center' ? xAxisPoints[index] + eachSpacing / 2 : xAxisPoints[index];
        if((truePoints - Math.abs(_scrollDistance_)) >= opts.area[3] && (truePoints - Math.abs(_scrollDistance_)) <= (opts.width - opts.area[1])){
          context.beginPath();
          context.setFontSize(xAxisFontSize);
          context.setFillStyle(opts.xAxis.fontColor || opts.fontColor);
          context.fillText(String(xitem), xAxisPoints[index] + offset, startY + xAxisFontSize + (config.xAxisHeight - scrollHeight - xAxisFontSize) / 2);
          context.closePath();
          context.stroke();
        }
      });
    } else {
      newCategories.forEach(function(item, index) {
        var xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item) : item;
        context.save();
        context.beginPath();
        context.setFontSize(xAxisFontSize);
        context.setFillStyle(opts.xAxis.fontColor || opts.fontColor);
        var textWidth = measureText(String(xitem), xAxisFontSize, context);
        var offset = -textWidth;
        if (boundaryGap == 'center') {
          offset += eachSpacing / 2;
        // 如果在主视图区域内
        var _scrollDistance_ = opts._scrollDistance_ || 0;
        var truePoints = boundaryGap == 'center' ? xAxisPoints[index] + eachSpacing / 2 : xAxisPoints[index];
        if((truePoints - Math.abs(_scrollDistance_)) >= opts.area[3] && (truePoints - Math.abs(_scrollDistance_)) <= (opts.width - opts.area[1])){
          context.save();
          context.beginPath();
          context.setFontSize(xAxisFontSize);
          context.setFillStyle(opts.xAxis.fontColor || opts.fontColor);
          var textWidth = measureText(String(xitem), xAxisFontSize, context);
          var offsetX = xAxisPoints[index];
          if (boundaryGap == 'center') {
            offsetX = xAxisPoints[index] + eachSpacing / 2;
          }
          var scrollHeight = 0;
          if (opts.xAxis.scrollShow) {
            scrollHeight = 6 * opts.pix;
          }
          var offsetY = startY + 6 * opts.pix + xAxisFontSize - xAxisFontSize * Math.abs(Math.sin(config._xAxisTextAngle_));
          if(opts.xAxis.rotateAngle < 0){
            offsetX -= xAxisFontSize / 2;
            textWidth = 0;
          }else{
            offsetX += xAxisFontSize / 2;
            textWidth = -textWidth;
          }
          context.translate(offsetX, offsetY);
          context.rotate(-1 * config._xAxisTextAngle_);
          context.fillText(String(xitem), textWidth , 0 );
          context.closePath();
          context.stroke();
          context.restore();
        }
        var _calRotateTranslate = calRotateTranslate(xAxisPoints[index] + eachSpacing / 2, startY + xAxisFontSize / 2 + 5, opts.height),
          transX = _calRotateTranslate.transX,
          transY = _calRotateTranslate.transY;
        context.rotate(-1 * config._xAxisTextAngle_);
        context.translate(transX, transY);
        context.fillText(String(xitem), xAxisPoints[index] + offset, startY + xAxisFontSize + 5);
        context.closePath();
        context.stroke();
        context.restore();
      });
    }
  }
@@ -4007,6 +4325,10 @@
  let xAxisPoints = opts.chartData.xAxisData.xAxisPoints,
    xAxiseachSpacing = opts.chartData.xAxisData.eachSpacing;
  let TotalWidth = xAxiseachSpacing * (xAxisPoints.length - 1);
  if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1 ){
    if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2
    TotalWidth += (opts.extra.mount.widthRatio - 1)*xAxiseachSpacing;
  }
  let endX = startX + TotalWidth;
  let points = [];
  let startY = 1
@@ -4044,21 +4366,14 @@
  var startX = opts.area[3];
  var endX = opts.width - opts.area[1];
  var endY = opts.height - opts.area[2];
  var fillEndY = endY + config.xAxisHeight;
  if (opts.xAxis.scrollShow) {
    fillEndY -= 3 * opts.pix;
  }
  if (opts.xAxis.rotateLabel) {
    fillEndY = opts.height - opts.area[2] + opts.fontSize * opts.pix / 2;
  }
  // set YAxis background
  context.beginPath();
  context.setFillStyle(opts.background);
  if (opts.enableScroll == true && opts.xAxis.scrollPosition && opts.xAxis.scrollPosition !== 'left') {
    context.fillRect(0, 0, startX, fillEndY);
    context.fillRect(0, 0, startX, endY + 2 * opts.pix);
  }
  if (opts.enableScroll == true && opts.xAxis.scrollPosition && opts.xAxis.scrollPosition !== 'right') {
    context.fillRect(endX, 0, opts.width, fillEndY);
    context.fillRect(endX, 0, opts.width, endY + 2 * opts.pix);
  }
  context.closePath();
  context.stroke();
@@ -4086,7 +4401,7 @@
        let textAlign = yData.textAlign || "right";
        //画Y轴刻度及文案
        rangesFormat.forEach(function(item, index) {
          var pos = points[index] ? points[index] : endY;
          var pos = points[index];
          context.beginPath();
          context.setFontSize(yAxisFontSize);
          context.setLineWidth(1 * opts.pix);
@@ -4313,17 +4628,18 @@
      context.stroke();
      startX += shapeWidth + shapeRight;
      let fontTrans = 0.5 * lineHeight + 0.5 * fontSize - 2;
      const legendText = item.legendText ? item.legendText : item.name;
      context.beginPath();
      context.setFontSize(fontSize);
      context.setFillStyle(item.show ? opts.legend.fontColor : opts.legend.hiddenColor);
      context.fillText(item.name, startX, startY + fontTrans);
      context.fillText(legendText, startX, startY + fontTrans);
      context.closePath();
      context.stroke();
      if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
        startX += measureText(item.name, fontSize, context) + itemGap;
        startX += measureText(legendText, fontSize, context) + itemGap;
        item.area[2] = startX;
      } else {
        item.area[2] = startX + measureText(item.name, fontSize, context) + itemGap;;
        item.area[2] = startX + measureText(legendText, fontSize, context) + itemGap;;
        startX -= shapeWidth + shapeRight;
        startY += lineHeight;
      }
@@ -4356,6 +4672,7 @@
  }
  var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding);
  radius = radius < 10 ? 10 : radius;
  if (pieOption.customRadius > 0) {
    radius = pieOption.customRadius * opts.pix;
  }
@@ -4415,16 +4732,7 @@
    context.fill();
  }
  if (opts.dataLabel !== false && process === 1) {
    var valid = false;
    for (var i = 0, len = series.length; i < len; i++) {
      if (series[i].data > 0) {
        valid = true;
        break;
      }
    }
    if (valid) {
      drawPieText(series, opts, config, context, radius, centerPosition);
    }
    drawPieText(series, opts, config, context, radius, centerPosition);
  }
  if (process === 1 && opts.type === 'ring') {
    drawRingTitle(opts, config, context, centerPosition);
@@ -4458,6 +4766,7 @@
    y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
  };
  var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding);
  radius = radius < 10 ? 10 : radius;
  var minRadius = roseOption.minRadius || radius * 0.5;
  series = getRoseDataPoints(series, roseOption.type, minRadius, radius, process);
  var activeRadius = roseOption.activeRadius * opts.pix;
@@ -4504,16 +4813,7 @@
  });
  if (opts.dataLabel !== false && process === 1) {
    var valid = false;
    for (var i = 0, len = series.length; i < len; i++) {
      if (series[i].data > 0) {
        valid = true;
        break;
      }
    }
    if (valid) {
      drawPieText(series, opts, config, context, radius, centerPosition);
    }
    drawPieText(series, opts, config, context, radius, centerPosition);
  }
  return {
    center: centerPosition,
@@ -4528,6 +4828,8 @@
    startAngle: 0.75,
    endAngle: 0.25,
    type: 'default',
    direction: 'cw',
    lineCap: 'round',
    width: 12 ,
    gap: 2 ,
    linearType: 'none',
@@ -4554,6 +4856,7 @@
    radius -= 5 * opts.pix;
    radius -= arcbarOption.width / 2;
  }
  radius = radius < 10 ? 10 : radius;
  arcbarOption.customColor = fillCustomColor(arcbarOption.linearType, arcbarOption.customColor, series, config);
  
  for (let i = 0; i < series.length; i++) {
@@ -4561,12 +4864,12 @@
    //背景颜色
    context.setLineWidth(arcbarOption.width * opts.pix);
    context.setStrokeStyle(arcbarOption.backgroundColor || '#E9E9E9');
    context.setLineCap('round');
    context.setLineCap(arcbarOption.lineCap);
    context.beginPath();
    if (arcbarOption.type == 'default') {
      context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, arcbarOption.endAngle * Math.PI, false);
      context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, arcbarOption.endAngle * Math.PI, arcbarOption.direction == 'ccw');
    } else {
      context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, 0, 2 * Math.PI, false);
      context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, 0, 2 * Math.PI, arcbarOption.direction == 'ccw');
    }
    context.stroke();
    //进度条
@@ -4579,9 +4882,9 @@
    }
    context.setLineWidth(arcbarOption.width * opts.pix);
    context.setStrokeStyle(fillColor);
    context.setLineCap('round');
    context.setLineCap(arcbarOption.lineCap);
    context.beginPath();
    context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, eachSeries._proportion_ * Math.PI, false);
    context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, eachSeries._proportion_ * Math.PI, arcbarOption.direction == 'ccw');
    context.stroke();
  }
  drawRingTitle(opts, config, context, centerPosition);
@@ -4627,6 +4930,7 @@
  var radius = Math.min(centerPosition.x, centerPosition.y);
  radius -= 5 * opts.pix;
  radius -= gaugeOption.width / 2;
  radius = radius < 10 ? 10 : radius;
  var innerRadius = radius - gaugeOption.width;
  var totalAngle = 0;
  //判断仪表盘的样式:default百度样式,progress新样式
@@ -4676,7 +4980,7 @@
    }
    context.restore();
    //## 第三步画进度条
    series = getArcbarDataPoints(series, gaugeOption, process);
    series = getGaugeArcbarDataPoints(series, gaugeOption, process);
    context.setLineWidth(gaugeOption.width);
    context.setStrokeStyle(series[0].color);
    context.setLineCap('round');
@@ -4799,10 +5103,19 @@
  var radarOption = assign({}, {
    gridColor: '#cccccc',
    gridType: 'radar',
    gridEval:1,
    axisLabel:false,
    axisLabelTofix:0,
    labelColor:'#666666',
    labelPointShow:false,
    labelPointRadius:3,
    labelPointColor:'#cccccc',
    opacity: 0.2,
    gridCount: 3,
    border:false,
    borderWidth:2
    borderWidth:2,
    linearType: 'none',
    customColor: [],
  }, opts.extra.radar);
  var coordinateAngle = getRadarCoordinateSeries(opts.categories.length);
  var centerPosition = {
@@ -4813,14 +5126,17 @@
  var yr = (opts.height - opts.area[0] - opts.area[2]) / 2
  var radius = Math.min(xr - (getMaxTextListLength(opts.categories, config.fontSize, context) + config.radarLabelTextMargin), yr - config.radarLabelTextMargin);
  radius -= config.radarLabelTextMargin * opts.pix;
  radius = radius < 10 ? 10 : radius;
  // 画分割线
  context.beginPath();
  context.setLineWidth(1 * opts.pix);
  context.setStrokeStyle(radarOption.gridColor);
  coordinateAngle.forEach(function(angle) {
  coordinateAngle.forEach(function(angle,index) {
    var pos = convertCoordinateOrigin(radius * Math.cos(angle), radius * Math.sin(angle), centerPosition);
    context.moveTo(centerPosition.x, centerPosition.y);
    context.lineTo(pos.x, pos.y);
    if (index % radarOption.gridEval == 0) {
      context.lineTo(pos.x, pos.y);
    }
  });
  context.stroke();
  context.closePath();
@@ -4853,13 +5169,28 @@
  for (var i = 1; i <= radarOption.gridCount; i++) {
    _loop(i);
  }
  radarOption.customColor = fillCustomColor(radarOption.linearType, radarOption.customColor, series, config);
  var radarDataPoints = getRadarDataPoints(coordinateAngle, centerPosition, radius, series, opts, process);
  radarDataPoints.forEach(function(eachSeries, seriesIndex) {
    // 绘制区域数据
    context.beginPath();
    context.setLineWidth(radarOption.borderWidth * opts.pix);
    context.setStrokeStyle(eachSeries.color);
    context.setFillStyle(hexToRgb(eachSeries.color, radarOption.opacity));
    var fillcolor = hexToRgb(eachSeries.color, radarOption.opacity);
    if (radarOption.linearType == 'custom') {
      var grd;
      if(context.createCircularGradient){
        grd = context.createCircularGradient(centerPosition.x, centerPosition.y, radius)
      }else{
        grd = context.createRadialGradient(centerPosition.x, centerPosition.y, 0,centerPosition.x, centerPosition.y, radius)
      }
      grd.addColorStop(0, hexToRgb(radarOption.customColor[series[seriesIndex].linearIndex], radarOption.opacity))
      grd.addColorStop(1, hexToRgb(eachSeries.color, radarOption.opacity))
      fillcolor = grd
    }
    context.setFillStyle(fillcolor);
    eachSeries.data.forEach(function(item, index) {
      if (index === 0) {
        context.moveTo(item.position.x, item.position.y);
@@ -4880,6 +5211,21 @@
      drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
    }
  });
  // 画刻度值
  if(radarOption.axisLabel === true){
    const maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series)));
    const stepLength = radius / radarOption.gridCount;
    const fontSize = opts.fontSize * opts.pix;
    context.setFontSize(fontSize);
    context.setFillStyle(opts.fontColor);
    context.setTextAlign('left');
    for (var i = 0; i < radarOption.gridCount + 1; i++) {
      let label = i * maxData / radarOption.gridCount;
      label = label.toFixed(radarOption.axisLabelTofix);
      context.fillText(String(label), centerPosition.x + 3 * opts.pix, centerPosition.y - i * stepLength + fontSize / 2);
    }
  }
  // draw label text
  drawRadarLabel(coordinateAngle, radius, centerPosition, opts, config, context);
  
@@ -4925,36 +5271,27 @@
  };
}
function normalInt(min, max, iter) {
  iter = iter == 0 ? 1 : iter;
  var arr = [];
  for (var i = 0; i < iter; i++) {
    arr[i] = Math.random();
  };
  return Math.floor(arr.reduce(function(i, j) {
    return i + j
  }) / iter * (max - min)) + min;
};
// 经纬度转墨卡托
function lonlat2mercator(longitude, latitude) {
  var mercator = Array(2);
  var x = longitude * 20037508.34 / 180;
  var y = Math.log(Math.tan((90 + latitude) * Math.PI / 360)) / (Math.PI / 180);
  y = y * 20037508.34 / 180;
  mercator[0] = x;
  mercator[1] = y;
  return mercator;
}
function collisionNew(area, points, width, height) {
  var isIn = false;
  for (let i = 0; i < points.length; i++) {
    if (points[i].area) {
      if (area[3] < points[i].area[1] || area[0] > points[i].area[2] || area[1] > points[i].area[3] || area[2] < points[i].area[0]) {
        if (area[0] < 0 || area[1] < 0 || area[2] > width || area[3] > height) {
          isIn = true;
          break;
        } else {
          isIn = false;
        }
      } else {
        isIn = true;
        break;
      }
    }
  }
  return isIn;
};
// 墨卡托转经纬度
function mercator2lonlat(longitude, latitude) {
  var lonlat = Array(2)
  var x = longitude / 20037508.34 * 180;
  var y = latitude / 20037508.34 * 180;
  y = 180 / Math.PI * (2 * Math.atan(Math.exp(y * Math.PI / 180)) - Math.PI / 2);
  lonlat[0] = x;
  lonlat[1] = y;
  return lonlat;
}
function getBoundingBox(data) {
  var bounds = {},coords;
@@ -5053,12 +5390,12 @@
  }
}
function drawMapDataPoints(series, opts, config, context) {
  var mapOption = assign({}, {
    border: true,
    mercator: false,
    borderWidth: 1,
    active:true,
    borderColor: '#666666',
    fillOpacity: 0.6,
    activeBorderColor: '#f04864',
@@ -5085,8 +5422,8 @@
    context.beginPath();
    context.setLineWidth(mapOption.borderWidth * opts.pix);
    context.setStrokeStyle(mapOption.borderColor);
    context.setFillStyle(hexToRgb(series[i].color, mapOption.fillOpacity));
    if (opts.tooltip) {
    context.setFillStyle(hexToRgb(series[i].color, series[i].fillOpacity||mapOption.fillOpacity));
    if (mapOption.active == true && opts.tooltip) {
      if (opts.tooltip.index == i) {
        context.setStrokeStyle(mapOption.activeBorderColor);
        context.setFillStyle(hexToRgb(mapOption.activeFillColor, mapOption.activeFillOpacity));
@@ -5118,7 +5455,9 @@
        context.stroke();
      }
    }
    if (opts.dataLabel == true) {
  }
  if (opts.dataLabel == true) {
    for (var i = 0; i < data.length; i++) {
      var centerPoint = data[i].properties.centroid;
      if (centerPoint) {
        if (mapOption.mercator) {
@@ -5126,10 +5465,14 @@
        }
        point = coordinateToPoint(centerPoint[1], centerPoint[0], bounds, scale, xoffset, yoffset);
        let fontSize = data[i].textSize * opts.pix || config.fontSize;
        let fontColor = data[i].textColor || opts.fontColor;
        if(mapOption.active && mapOption.activeTextColor && opts.tooltip && opts.tooltip.index == i){
          fontColor = mapOption.activeTextColor;
        }
        let text = data[i].properties.name;
        context.beginPath();
        context.setFontSize(fontSize)
        context.setFillStyle(data[i].textColor || opts.fontColor)
        context.setFillStyle(fontColor)
        context.fillText(text, point.x - measureText(text, fontSize, context) / 2, point.y + fontSize / 2);
        context.closePath();
        context.stroke();
@@ -5146,6 +5489,37 @@
  drawToolTipBridge(opts, config, context, 1);
  context.draw();
}
function normalInt(min, max, iter) {
  iter = iter == 0 ? 1 : iter;
  var arr = [];
  for (var i = 0; i < iter; i++) {
    arr[i] = Math.random();
  };
  return Math.floor(arr.reduce(function(i, j) {
    return i + j
  }) / iter * (max - min)) + min;
};
function collisionNew(area, points, width, height) {
  var isIn = false;
  for (let i = 0; i < points.length; i++) {
    if (points[i].area) {
      if (area[3] < points[i].area[1] || area[0] > points[i].area[2] || area[1] > points[i].area[3] || area[2] < points[i].area[0]) {
        if (area[0] < 0 || area[1] < 0 || area[2] > width || area[3] > height) {
          isIn = true;
          break;
        } else {
          isIn = false;
        }
      } else {
        isIn = true;
        break;
      }
    }
  }
  return isIn;
};
function getWordCloudPoint(opts, type, context) {
  let points = opts.series;
@@ -5225,7 +5599,6 @@
  return points;
}
function drawWordCloudDataPoints(series, opts, config, context) {
  let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
  let wordOption = assign({}, {
@@ -5295,6 +5668,7 @@
    borderWidth: 2,
    borderColor: '#FFFFFF',
    fillOpacity: 1,
    minSize: 0,
    labelAlign: 'right',
    linearType: 'none',
    customColor: [],
@@ -5306,42 +5680,42 @@
  };
  let activeWidth = funnelOption.activeWidth * opts.pix;
  let radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - activeWidth, (opts.height - opts.area[0] - opts.area[2]) / 2 - activeWidth);
  series = getFunnelDataPoints(series, radius, funnelOption.type, eachSpacing, process);
  let seriesNew = getFunnelDataPoints(series, radius, funnelOption, eachSpacing, process);
  context.save();
  context.translate(centerPosition.x, centerPosition.y);
  funnelOption.customColor = fillCustomColor(funnelOption.linearType, funnelOption.customColor, series, config);
  if(funnelOption.type == 'pyramid'){
    for (let i = 0; i < series.length; i++) {
      if (i == series.length -1) {
    for (let i = 0; i < seriesNew.length; i++) {
      if (i == seriesNew.length -1) {
        if (opts.tooltip) {
          if (opts.tooltip.index == i) {
            context.beginPath();
            context.setFillStyle(hexToRgb(series[i].color, funnelOption.activeOpacity));
            context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
            context.moveTo(-activeWidth, -eachSpacing);
            context.lineTo(-series[i].radius - activeWidth, 0);
            context.lineTo(series[i].radius + activeWidth, 0);
            context.lineTo(-seriesNew[i].radius - activeWidth, 0);
            context.lineTo(seriesNew[i].radius + activeWidth, 0);
            context.lineTo(activeWidth, -eachSpacing);
            context.lineTo(-activeWidth, -eachSpacing);
            context.closePath();
            context.fill();
          }
        }
        series[i].funnelArea = [centerPosition.x - series[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + series[i].radius, centerPosition.y - eachSpacing * i];
        seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * i];
        context.beginPath();
        context.setLineWidth(funnelOption.borderWidth * opts.pix);
        context.setStrokeStyle(funnelOption.borderColor);
        var fillColor = hexToRgb(series[i].color, funnelOption.fillOpacity);
        var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity);
        if (funnelOption.linearType == 'custom') {
          var grd = context.createLinearGradient(series[i].radius, -eachSpacing, -series[i].radius, -eachSpacing);
          grd.addColorStop(0, hexToRgb(series[i].color, funnelOption.fillOpacity));
          grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[series[i].linearIndex], funnelOption.fillOpacity));
          grd.addColorStop(1, hexToRgb(series[i].color, funnelOption.fillOpacity));
          var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing);
          grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
          grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity));
          grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
          fillColor = grd
        }
        context.setFillStyle(fillColor);
        context.moveTo(0, -eachSpacing);
        context.lineTo(-series[i].radius, 0);
        context.lineTo(series[i].radius, 0);
        context.lineTo(-seriesNew[i].radius, 0);
        context.lineTo(seriesNew[i].radius, 0);
        context.lineTo(0, -eachSpacing);
        context.closePath();
        context.fill();
@@ -5352,35 +5726,35 @@
        if (opts.tooltip) {
          if (opts.tooltip.index == i) {
            context.beginPath();
            context.setFillStyle(hexToRgb(series[i].color, funnelOption.activeOpacity));
            context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
            context.moveTo(0, 0);
            context.lineTo(-series[i].radius - activeWidth, 0);
            context.lineTo(-series[i + 1].radius - activeWidth, -eachSpacing);
            context.lineTo(series[i + 1].radius + activeWidth, -eachSpacing);
            context.lineTo(series[i].radius + activeWidth, 0);
            context.lineTo(-seriesNew[i].radius - activeWidth, 0);
            context.lineTo(-seriesNew[i + 1].radius - activeWidth, -eachSpacing);
            context.lineTo(seriesNew[i + 1].radius + activeWidth, -eachSpacing);
            context.lineTo(seriesNew[i].radius + activeWidth, 0);
            context.lineTo(0, 0);
            context.closePath();
            context.fill();
          }
        }
        series[i].funnelArea = [centerPosition.x - series[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + series[i].radius, centerPosition.y - eachSpacing * i];
        seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * i];
        context.beginPath();
        context.setLineWidth(funnelOption.borderWidth * opts.pix);
        context.setStrokeStyle(funnelOption.borderColor);
        var fillColor = hexToRgb(series[i].color, funnelOption.fillOpacity);
        var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity);
        if (funnelOption.linearType == 'custom') {
          var grd = context.createLinearGradient(series[i].radius, -eachSpacing, -series[i].radius, -eachSpacing);
          grd.addColorStop(0, hexToRgb(series[i].color, funnelOption.fillOpacity));
          grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[series[i].linearIndex], funnelOption.fillOpacity));
          grd.addColorStop(1, hexToRgb(series[i].color, funnelOption.fillOpacity));
          var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing);
          grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
          grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity));
          grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
          fillColor = grd
        }
        context.setFillStyle(fillColor);
        context.moveTo(0, 0);
        context.lineTo(-series[i].radius, 0);
        context.lineTo(-series[i + 1].radius, -eachSpacing);
        context.lineTo(series[i + 1].radius, -eachSpacing);
        context.lineTo(series[i].radius, 0);
        context.lineTo(-seriesNew[i].radius, 0);
        context.lineTo(-seriesNew[i + 1].radius, -eachSpacing);
        context.lineTo(seriesNew[i + 1].radius, -eachSpacing);
        context.lineTo(seriesNew[i].radius, 0);
        context.lineTo(0, 0);
        context.closePath();
        context.fill();
@@ -5391,37 +5765,40 @@
      context.translate(0, -eachSpacing)
    }
  }else{
    for (let i = 0; i < series.length; i++) {
      if (i == 0) {
    context.translate(0, - (seriesNew.length - 1) * eachSpacing);
    for (let i = 0; i < seriesNew.length; i++) {
      if (i == seriesNew.length - 1) {
        if (opts.tooltip) {
          if (opts.tooltip.index == i) {
            context.beginPath();
            context.setFillStyle(hexToRgb(series[i].color, funnelOption.activeOpacity));
            context.moveTo(-activeWidth, 0);
            context.lineTo(-series[i].radius - activeWidth, -eachSpacing);
            context.lineTo(series[i].radius + activeWidth, -eachSpacing);
            context.lineTo(activeWidth, 0);
            context.lineTo(-activeWidth, 0);
            context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
            context.moveTo(-activeWidth - funnelOption.minSize/2, 0);
            context.lineTo(-seriesNew[i].radius - activeWidth, -eachSpacing);
            context.lineTo(seriesNew[i].radius + activeWidth, -eachSpacing);
            context.lineTo(activeWidth + funnelOption.minSize/2, 0);
            context.lineTo(-activeWidth - funnelOption.minSize/2, 0);
            context.closePath();
            context.fill();
          }
        }
        series[i].funnelArea = [centerPosition.x - series[i].radius, centerPosition.y - eachSpacing, centerPosition.x + series[i].radius, centerPosition.y];
        seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing, centerPosition.x + seriesNew[i].radius, centerPosition.y ];
        context.beginPath();
        context.setLineWidth(funnelOption.borderWidth * opts.pix);
        context.setStrokeStyle(funnelOption.borderColor);
        var fillColor = hexToRgb(series[i].color, funnelOption.fillOpacity);
        var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity);
        if (funnelOption.linearType == 'custom') {
          var grd = context.createLinearGradient(series[i].radius, -eachSpacing, -series[i].radius, -eachSpacing);
          grd.addColorStop(0, hexToRgb(series[i].color, funnelOption.fillOpacity));
          grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[series[i].linearIndex], funnelOption.fillOpacity));
          grd.addColorStop(1, hexToRgb(series[i].color, funnelOption.fillOpacity));
          var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing);
          grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
          grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity));
          grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
          fillColor = grd
        }
        context.setFillStyle(fillColor);
        context.moveTo(0, 0);
        context.lineTo(-series[i].radius, -eachSpacing);
        context.lineTo(series[i].radius, -eachSpacing);
        context.lineTo(-funnelOption.minSize/2, 0);
        context.lineTo(-seriesNew[i].radius, -eachSpacing);
        context.lineTo(seriesNew[i].radius, -eachSpacing);
        context.lineTo(funnelOption.minSize/2, 0);
        context.lineTo(0, 0);
        context.closePath();
        context.fill();
@@ -5432,35 +5809,35 @@
        if (opts.tooltip) {
          if (opts.tooltip.index == i) {
            context.beginPath();
            context.setFillStyle(hexToRgb(series[i].color, funnelOption.activeOpacity));
            context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
            context.moveTo(0, 0);
            context.lineTo(-series[i - 1].radius - activeWidth, 0);
            context.lineTo(-series[i].radius - activeWidth, -eachSpacing);
            context.lineTo(series[i].radius + activeWidth, -eachSpacing);
            context.lineTo(series[i - 1].radius + activeWidth, 0);
            context.lineTo(-seriesNew[i + 1].radius - activeWidth, 0);
            context.lineTo(-seriesNew[i].radius - activeWidth, -eachSpacing);
            context.lineTo(seriesNew[i].radius + activeWidth, -eachSpacing);
            context.lineTo(seriesNew[i + 1].radius + activeWidth, 0);
            context.lineTo(0, 0);
            context.closePath();
            context.fill();
          }
        }
        series[i].funnelArea = [centerPosition.x - series[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + series[i].radius, centerPosition.y - eachSpacing * i];
        seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (seriesNew.length - i), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * (seriesNew.length - i - 1)];
        context.beginPath();
        context.setLineWidth(funnelOption.borderWidth * opts.pix);
        context.setStrokeStyle(funnelOption.borderColor);
        var fillColor = hexToRgb(series[i].color, funnelOption.fillOpacity);
        var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity);
        if (funnelOption.linearType == 'custom') {
          var grd = context.createLinearGradient(series[i].radius, -eachSpacing, -series[i].radius, -eachSpacing);
          grd.addColorStop(0, hexToRgb(series[i].color, funnelOption.fillOpacity));
          grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[series[i].linearIndex], funnelOption.fillOpacity));
          grd.addColorStop(1, hexToRgb(series[i].color, funnelOption.fillOpacity));
          var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing);
          grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
          grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity));
          grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
          fillColor = grd
        }
        context.setFillStyle(fillColor);
        context.moveTo(0, 0);
        context.lineTo(-series[i - 1].radius, 0);
        context.lineTo(-series[i].radius, -eachSpacing);
        context.lineTo(series[i].radius, -eachSpacing);
        context.lineTo(series[i - 1].radius, 0);
        context.lineTo(-seriesNew[i + 1].radius, 0);
        context.lineTo(-seriesNew[i].radius, -eachSpacing);
        context.lineTo(seriesNew[i].radius, -eachSpacing);
        context.lineTo(seriesNew[i + 1].radius, 0);
        context.lineTo(0, 0);
        context.closePath();
        context.fill();
@@ -5468,39 +5845,38 @@
          context.stroke();
        }
      }
      context.translate(0, -eachSpacing)
      context.translate(0, eachSpacing)
    }
  }
  
  context.restore();
  if (opts.dataLabel !== false && process === 1) {
    drawFunnelText(series, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition);
    drawFunnelText(seriesNew, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition);
  }
  if (process === 1) {
    drawFunnelCenterText(seriesNew, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition);
  }
  return {
    center: centerPosition,
    radius: radius,
    series: series
    series: seriesNew
  };
}
function drawFunnelText(series, opts, context, eachSpacing, labelAlign, activeWidth, centerPosition) {
  for (let i = 0; i < series.length; i++) {
    let item = series[i];
    if(item.labelShow === false){
      continue;
    }
    let startX, endX, startY, fontSize;
    let text = item.formatter ? item.formatter(item,i,series) : util.toFixed(item._proportion_ * 100) + '%';
    let text = item.formatter ? item.formatter(item,i,series,opts) : util.toFixed(item._proportion_ * 100) + '%';
    text = item.labelText ? item.labelText : text;
    if (labelAlign == 'right') {
      if(opts.extra.funnel.type === 'pyramid'){
        if (i == series.length -1) {
          startX = (item.funnelArea[2] + centerPosition.x) / 2;
        } else {
          startX = (item.funnelArea[2] + series[i + 1].funnelArea[2]) / 2;
        }
      }else{
        if (i == 0) {
          startX = (item.funnelArea[2] + centerPosition.x) / 2;
        } else {
          startX = (item.funnelArea[2] + series[i - 1].funnelArea[2]) / 2;
        }
      if (i == series.length -1) {
        startX = (item.funnelArea[2] + centerPosition.x) / 2;
      } else {
        startX = (item.funnelArea[2] + series[i + 1].funnelArea[2]) / 2;
      }
      endX = startX + activeWidth * 2;
      startY = item.funnelArea[1] + eachSpacing / 2;
@@ -5515,7 +5891,7 @@
      context.closePath();
      context.beginPath();
      context.moveTo(endX, startY);
      context.arc(endX, startY, 2, 0, 2 * Math.PI);
      context.arc(endX, startY, 2 * opts.pix, 0, 2 * Math.PI);
      context.closePath();
      context.fill();
      context.beginPath();
@@ -5525,19 +5901,12 @@
      context.closePath();
      context.stroke();
      context.closePath();
    } else {
      if(opts.extra.funnel.type === 'pyramid'){
        if (i == series.length -1) {
          startX = (item.funnelArea[0] + centerPosition.x) / 2;
        } else {
          startX = (item.funnelArea[0] + series[i + 1].funnelArea[0]) / 2;
        }
      }else{
        if (i == 0) {
          startX = (item.funnelArea[0] + centerPosition.x) / 2;
        } else {
          startX = (item.funnelArea[0] + series[i - 1].funnelArea[0]) / 2;
        }
    }
    if (labelAlign == 'left') {
      if (i == series.length -1) {
        startX = (item.funnelArea[0] + centerPosition.x) / 2;
      } else {
        startX = (item.funnelArea[0] + series[i + 1].funnelArea[0]) / 2;
      }
      endX = startX - activeWidth * 2;
      startY = item.funnelArea[1] + eachSpacing / 2;
@@ -5563,9 +5932,27 @@
      context.stroke();
      context.closePath();
    }
  }
}
function drawFunnelCenterText(series, opts, context, eachSpacing, labelAlign, activeWidth, centerPosition) {
  for (let i = 0; i < series.length; i++) {
    let item = series[i];
    let startY, fontSize;
    if (item.centerText) {
      startY = item.funnelArea[1] + eachSpacing / 2;
      fontSize = item.centerTextSize * opts.pix || opts.fontSize * opts.pix;
      context.beginPath();
      context.setFontSize(fontSize);
      context.setFillStyle(item.centerTextColor || "#FFFFFF");
      context.fillText(item.centerText, centerPosition.x - measureText(item.centerText, fontSize, context) / 2, startY + fontSize / 2 - 2);
      context.closePath();
      context.stroke();
      context.closePath();
    }
  }
}
function drawCanvas(opts, context) {
  context.draw();
@@ -5645,10 +6032,17 @@
  var _this = this;
  var series = opts.series;
  //兼容ECharts饼图类数据格式
  if (type === 'pie' || type === 'ring' || type === 'rose' || type === 'funnel') {
  if (type === 'pie' || type === 'ring' || type === 'mount' || type === 'rose' || type === 'funnel') {
    series = fixPieSeries(series, opts, config);
  }
  var categories = opts.categories;
  if (type === 'mount') {
    categories = [];
    for (let j = 0; j < series.length; j++) {
      if(series[j].show !== false) categories.push(series[j].name)
    }
    opts.categories = categories;
  }
  series = fillSeries(series, opts, config);
  var duration = opts.animation ? opts.duration : 0;
  _this.animationInstance && _this.animationInstance.stop();
@@ -5697,7 +6091,7 @@
  let _calYAxisData = {},
    yAxisWidth = 0;
  if (opts.type === 'line' || opts.type === 'column' || opts.type === 'area' || opts.type === 'mix' || opts.type === 'candle' || opts.type === 'scatter'  || opts.type === 'bubble' || opts.type === 'bar') {
  if (opts.type === 'line' || opts.type === 'column'|| opts.type === 'mount' || opts.type === 'area' || opts.type === 'mix' || opts.type === 'candle' || opts.type === 'scatter'  || opts.type === 'bubble' || opts.type === 'bar') {
      _calYAxisData = calYAxisData(series, opts, config, context);
      yAxisWidth = _calYAxisData.yAxisWidth;
    //如果显示Y轴标题
@@ -5759,6 +6153,7 @@
      };
    }
  }
  //计算右对齐偏移距离
  if (opts.enableScroll && opts.xAxis.scrollAlign == 'right' && opts._scrollDistance_ === undefined) {
    let offsetLeft = 0,
@@ -5769,18 +6164,17 @@
    let totalWidth = eachSpacing * (xAxisPoints.length - 1);
    let screenWidth = endX - startX;
    offsetLeft = screenWidth - totalWidth;
    _this.scrollOption = {
      currentOffset: offsetLeft,
      startTouchX: offsetLeft,
      distance: 0,
      lastMoveTime: 0
    };
    _this.scrollOption.currentOffset = offsetLeft;
    _this.scrollOption.startTouchX = offsetLeft;
    _this.scrollOption.distance = 0;
    _this.scrollOption.lastMoveTime = 0;
    opts._scrollDistance_ = offsetLeft;
  }
  if (type === 'pie' || type === 'ring' || type === 'rose') {
    config._pieTextMaxLength_ = opts.dataLabel === false ? 0 : getPieTextMaxLength(seriesMA, config, context, opts);
  }
  switch (type) {
    case 'word':
      this.animationInstance = new Animation({
@@ -5802,6 +6196,9 @@
    case 'map':
      context.clearRect(0, 0, opts.width, opts.height);
      drawMapDataPoints(series, opts, config, context);
      setTimeout(()=>{
        this.uevent.trigger('renderComplete');
      },50)
      break;
    case 'funnel':
      this.animationInstance = new Animation({
@@ -5977,6 +6374,37 @@
        }
      });
      break;
    case 'mount':
      this.animationInstance = new Animation({
        timing: opts.timing,
        duration: duration,
        onProcess: function onProcess(process) {
          context.clearRect(0, 0, opts.width, opts.height);
          if (opts.rotate) {
            contextRotate(context, opts);
          }
          drawYAxisGrid(categories, opts, config, context);
          drawXAxis(categories, opts, config, context);
          var _drawMountDataPoints = drawMountDataPoints(series, opts, config, context, process),
            xAxisPoints = _drawMountDataPoints.xAxisPoints,
            calPoints = _drawMountDataPoints.calPoints,
            eachSpacing = _drawMountDataPoints.eachSpacing;
          opts.chartData.xAxisPoints = xAxisPoints;
          opts.chartData.calPoints = calPoints;
          opts.chartData.eachSpacing = eachSpacing;
          drawYAxis(series, opts, config, context);
          if (opts.enableMarkLine !== false && process === 1) {
            drawMarkLine(opts, config, context);
          }
          drawLegend(opts.series, opts, config, context, opts.chartData);
          drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
          drawCanvas(opts, context);
        },
        onAnimationFinish: function onAnimationFinish() {
          _this.uevent.trigger('renderComplete');
        }
      });
      break;
    case 'bar':
      this.animationInstance = new Animation({
        timing: opts.timing,
@@ -6040,6 +6468,24 @@
      });
      break;
    case 'ring':
      this.animationInstance = new Animation({
        timing: opts.timing,
        duration: duration,
        onProcess: function onProcess(process) {
          context.clearRect(0, 0, opts.width, opts.height);
          if (opts.rotate) {
            contextRotate(context, opts);
          }
          opts.chartData.pieData = drawPieDataPoints(series, opts, config, context, process);
          drawLegend(opts.series, opts, config, context, opts.chartData);
          drawToolTipBridge(opts, config, context, process);
          drawCanvas(opts, context);
        },
        onAnimationFinish: function onAnimationFinish() {
          _this.uevent.trigger('renderComplete');
        }
      });
      break;
    case 'pie':
      this.animationInstance = new Animation({
        timing: opts.timing,
@@ -6214,6 +6660,7 @@
    showTitle: false,
    disabled: false,
    disableGrid: false,
    gridSet: 'number',
    splitNumber: 5,
    gridType: 'solid',
    dashLength: 4 * opts.pix,
@@ -6223,6 +6670,7 @@
  }, opts.yAxis);
  opts.xAxis = assign({}, {
    rotateLabel: false,
    rotateAngle:45,
    disabled: false,
    disableGrid: false,
    splitNumber: 5,
@@ -6257,9 +6705,8 @@
  opts.rotate = opts.rotate ? true : false;
  opts.canvas2d = opts.canvas2d ? true : false;
  
  let config$$1 = JSON.parse(JSON.stringify(config));
  let config$$1 = assign({}, config);
  config$$1.color = opts.color ? opts.color : config$$1.color;
  config$$1.yAxisTitleWidth = opts.yAxis.disabled !== true && opts.yAxis.title ? config$$1.yAxisTitleWidth : 0;
  if (opts.type == 'pie') {
    config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.pie.labelWidth * opts.pix || config$$1.pieChartLinePadding * opts.pix;
  }
@@ -6270,7 +6717,6 @@
    config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.rose.labelWidth * opts.pix || config$$1.pieChartLinePadding * opts.pix;
  }
  config$$1.pieChartTextPadding = opts.dataLabel === false ? 0 : config$$1.pieChartTextPadding * opts.pix;
  config$$1.yAxisSplit = opts.yAxis.splitNumber ? opts.yAxis.splitNumber : config.yAxisSplit;
  //屏幕旋转
  config$$1.rotate = opts.rotate;
@@ -6288,15 +6734,11 @@
  if (opts.enableScroll && opts.xAxis.scrollShow) {
    config$$1.xAxisHeight += 6 * opts.pix;
  }
  config$$1.xAxisLineHeight = config.xAxisLineHeight * opts.pix;
  config$$1.fontSize = opts.fontSize * opts.pix;
  config$$1.titleFontSize = config.titleFontSize * opts.pix;
  config$$1.subtitleFontSize = config.subtitleFontSize * opts.pix;
  config$$1.toolTipPadding = config.toolTipPadding * opts.pix;
  config$$1.toolTipLineHeight = config.toolTipLineHeight * opts.pix;
  config$$1.columePadding = config.columePadding * opts.pix;
  //this.context = opts.context ? opts.context : uni.createCanvasContext(opts.canvasId, opts.$this);
  //v2.0版本后需要自行获取context并传入opts进行初始化,这么做是为了确保uCharts可以跨更多端使用,并保证了自定义组件this实例不被循环嵌套。如果您觉得不便请取消上面注释,采用v1.0版本的方式使用,对此给您带来的不便敬请谅解!
  if(!opts.context){
    throw new Error('[uCharts] 未获取到context!注意:v2.0版本后,需要自行获取canvas的绘图上下文并传入opts.context!');
  }
@@ -6346,7 +6788,7 @@
  let scrollPosition = data.scrollPosition || 'current';
  switch (scrollPosition) {
    case 'current':
      //this.opts._scrollDistance_ = this.scrollOption.currentOffset;
      this.opts._scrollDistance_ = this.scrollOption.currentOffset;
      break;
    case 'left':
      this.opts._scrollDistance_ = 0;
@@ -6412,13 +6854,77 @@
  }
  this.scrollOption = {
    currentOffset: offsetLeft,
    startTouchX: offsetLeft,
    startTouchX: 0,
    distance: 0,
    lastMoveTime: 0
  };
  calValidDistance(this, offsetLeft, this.opts.chartData, this.config, this.opts);
  this.opts._scrollDistance_ = offsetLeft;
  drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
};
uCharts.prototype.dobuleZoom = function(e) {
  if (this.opts.enableScroll !== true) {
    console.log('[uCharts] 请启用滚动条后使用')
    return;
  }
  const tcs = e.changedTouches;
  if (tcs.length < 2) {
    return;
  }
  for (var i = 0; i < tcs.length; i++) {
    tcs[i].x = tcs[i].x ? tcs[i].x : tcs[i].clientX;
    tcs[i].y = tcs[i].y ? tcs[i].y : tcs[i].clientY;
  }
  const ntcs = [getTouches(tcs[0], this.opts, e),getTouches(tcs[1], this.opts, e)];
  const xlength = Math.abs(ntcs[0].x - ntcs[1].x);
  // 记录初始的两指之间的数据
  if(!this.scrollOption.moveCount){
    let cts0 = {changedTouches:[{x:tcs[0].x,y:this.opts.area[0] / this.opts.pix + 2}]};
    let cts1 = {changedTouches:[{x:tcs[1].x,y:this.opts.area[0] / this.opts.pix + 2}]};
    if(this.opts.rotate){
      cts0 = {changedTouches:[{x:this.opts.height / this.opts.pix - this.opts.area[0] / this.opts.pix - 2,y:tcs[0].y}]};
      cts1 = {changedTouches:[{x:this.opts.height / this.opts.pix - this.opts.area[0] / this.opts.pix - 2,y:tcs[1].y}]};
    }
    const moveCurrent1 = this.getCurrentDataIndex(cts0).index;
    const moveCurrent2 = this.getCurrentDataIndex(cts1).index;
    const moveCount = Math.abs(moveCurrent1 - moveCurrent2);
    this.scrollOption.moveCount = moveCount;
    this.scrollOption.moveCurrent1 = Math.min(moveCurrent1, moveCurrent2);
    this.scrollOption.moveCurrent2 = Math.max(moveCurrent1, moveCurrent2);
    return;
  }
  let currentEachSpacing = xlength / this.scrollOption.moveCount;
  let itemCount = (this.opts.width - this.opts.area[1] - this.opts.area[3]) / currentEachSpacing;
  itemCount = itemCount <= 2 ? 2 : itemCount;
  itemCount = itemCount >= this.opts.categories.length ? this.opts.categories.length : itemCount;
  this.opts.animation = false;
  this.opts.xAxis.itemCount = itemCount;
  // 重新计算滚动条偏移距离
  let offsetLeft = 0;
  let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config),
    xAxisPoints = _getXAxisPoints0.xAxisPoints,
    startX = _getXAxisPoints0.startX,
    endX = _getXAxisPoints0.endX,
    eachSpacing = _getXAxisPoints0.eachSpacing;
  let currentLeft = eachSpacing * this.scrollOption.moveCurrent1;
  let screenWidth = endX - startX;
  let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1);
  offsetLeft = -currentLeft+Math.min(ntcs[0].x,ntcs[1].x)-this.opts.area[3]-eachSpacing;
  if (offsetLeft > 0) {
    offsetLeft = 0;
  }
  if (offsetLeft < MaxLeft) {
    offsetLeft = MaxLeft;
  }
  this.scrollOption.currentOffset= offsetLeft;
  this.scrollOption.startTouchX= 0;
  this.scrollOption.distance=0;
  calValidDistance(this, offsetLeft, this.opts.chartData, this.config, this.opts);
  this.opts._scrollDistance_ = offsetLeft;
  drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
}
uCharts.prototype.stopAnimation = function() {
  this.animationInstance && this.animationInstance.stop();
@@ -6563,6 +7069,29 @@
        };
      }
    }
    drawCharts.call(this, opts.type, opts, this.config, this.context);
  }
  if (this.opts.type === 'mount') {
    var index = option.index == undefined ? this.getCurrentDataIndex(e).index : option.index;
    if (index > -1) {
      var opts = assign({}, this.opts, {animation: false});
      var seriesData = assign({}, opts._series_[index]);
      var textList = [{
        text: option.formatter ? option.formatter(seriesData, undefined, index, opts) : seriesData.name + ': ' + seriesData.data,
        color: seriesData.color
      }];
      var offset = {
        x: opts.chartData.calPoints[index].x,
        y: _touches$.y
      };
      opts.tooltip = {
        textList: option.textList ? option.textList : textList,
        offset: option.offset !== undefined ? option.offset : offset,
        option: option,
        index: index
      };
    }
    drawCharts.call(this, opts.type, opts, this.config, this.context);
  }
  if (this.opts.type === 'bar') {
@@ -6767,6 +7296,7 @@
  let currMoveTime = Date.now();
  let duration = currMoveTime - this.scrollOption.lastMoveTime;
  if (duration < Math.floor(1000 / Limit)) return;
  if (this.scrollOption.startTouchX == 0) return;
  this.scrollOption.lastMoveTime = currMoveTime;
  var touches = null;
  if (e.changedTouches) {
@@ -6798,6 +7328,7 @@
      distance = _scrollOption.distance;
    this.scrollOption.currentOffset = currentOffset + distance;
    this.scrollOption.distance = 0;
    this.scrollOption.moveCount = 0;
  }
};
Monitor-APP/uni_modules/qiun-data-charts/package.json
@@ -1,8 +1,8 @@
{
  "id": "qiun-data-charts",
  "displayName": "秋云 ucharts echarts 高性能跨全端图表组件",
  "version": "2.3.7-20220122",
  "description": "uCharts v2.3.7支持Vue3!全新官方图表组件,支持H5及APP用ECharts渲染图表,uniapp可视化首选组件",
  "version": "2.4.4-20221102",
  "description": "uCharts 新增双指缩放、新增山峰图!支持H5及APP用 ucharts echarts 渲染图表,uniapp可视化首选组件",
  "keywords": [
    "ucharts",
    "echarts",
@@ -14,11 +14,7 @@
  "engines": {
    "HBuilderX": "^3.3.8"
  },
  "dcloudext": {
    "category": [
        "前端组件",
        "通用组件"
    ],
"dcloudext": {
    "sale": {
      "regular": {
        "price": "0.00"
@@ -35,7 +31,8 @@
      "data": "插件不采集任何数据",
      "permissions": "无"
    },
    "npmurl": ""
    "npmurl": "https://www.npmjs.com/~qiun",
    "type": "component-vue"
  },
  "uni_modules": {
    "dependencies": [],
Monitor-APP/uni_modules/qiun-data-charts/readme.md
@@ -1,453 +1,102 @@
## [uCharts官方网站](https://www.ucharts.cn)
## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
## [优秀的nvue全端组件与模版库nPro](https://ext.dcloud.net.cn/plugin?id=5169)
## [图表组件在项目中的应用 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651)
## [如何安装、更新 uni_modules 插件点这里,必看,必看,必看](https://uniapp.dcloud.io/uni_modules?id=%e4%bd%bf%e7%94%a8-uni_modules-%e6%8f%92%e4%bb%b6)
## 点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
## 初次使用不显示问题详见[常见问题选项卡](https://demo.ucharts.cn)
## <font color=#FF0000> 新手请先完整阅读【帮助文档】及【常见问题】3遍,右侧蓝色按钮【示例项目】请看2遍! </font>
## <font color=#FF0000> 关于NVUE兼容的说明: </font> uCharts.js从2.3.0开始支持nuve(暂时只能通过原生canvas写法调用uCharts,nuve版本组件请见码云示例项目[uCharts-demo-nvue](https://gitee.com/uCharts/uCharts)),因其渲染方式是通过nvue的gcanvas组件来渲染,理论上性能不及renderjs的qiun-data-charts组件性能。官方仍然建议NVUE使用图表的页面改为vue页面,在App端,从性能来讲,由于通讯阻塞的问题,nvue的canvas性能不可能达到使用renderjs的vue页面的canvas。在App端,仍然推荐使用qiun-data-charts组件。[详见uni-app官方说明](https://uniapp.dcloud.io/component/canvas?id=canvas)
[![uCharts/uCharts](https://gitee.com/uCharts/uCharts/widgets/widget_card.svg?colors=393222,ebdfc1,fffae5,d8ca9f,393222,a28b40)](https://gitee.com/uCharts/uCharts)
## 秋云图表组件使用帮助
全新图表组件,全端全平台支持,开箱即用,可选择uCharts引擎全端渲染,也可指定PC端或APP端`单独使用ECharts`引擎渲染图表。支持极简单的调用方式,只需指定图表类型及传入符合标准的图表数据即可,使开发者只需专注业务及数据。同时也支持datacom组件读取uniClinetDB,无需关心如何拼接数据等不必要的重复工作,大大缩短开发时间。
## 为何使用官方封装的组件?
封装组件并不难,谁都会,但组件调试却是一件令人掉头发的事,尤其是canvas封装成组件会带来一系列问题:例如封装后不显示,图表多次初始化导致抖动问题,单页面多个图表点击事件错乱,组件放在scroll-view中无法点击,在图表上滑动时页面无法滚动等等一系列问题。为解决开发者使用可视化组件的困扰,uCharts官方特推出可视化通用组件,本组件具备以下特点:
- 极简单的调用方式,默认配置下只需要传入`图表类型`及`图表数据`即可全端显示。
- 提供强大的`在线配置生成工具`,可视化中的可视化,鼠标点一点就可以生成图表,可视化从此不再难配。
- 兼容ECharts,可选择`PC端或APP端单独使用ECharts`引擎渲染图表。
- H5及App采用`renderjs`渲染图表,动画流畅、性能翻倍。
- 根据父容器尺寸`弹性显示图表`,再也不必为宽高匹配及多端适配问题发愁。
- 支持`加载状态loading及error展示`,避免数据读取显示空白的尴尬。
- chartData`配置与数据解耦`,即便使用ECharts引擎也不必担心拼接option的困扰。
- localdata`后端数据直接渲染`,无需自行拼接chartData的categories及series,从后端拿回的数据简单处理即可生成图表。
- 小程序端不必担心包体积过大问题,ECharts引擎将不会编译到各小程序端,u-charts.js编译后`仅为93kb`。
- 未来将支持通过HbuilderX的[schema2code自动生成全端全平台图表](https://ext.dcloud.net.cn/plugin?id=4684),敬请期待!!!
- uCharts官方拥有4个2000人的QQ群支持,庞大的用户量证明我们一直在努力,本组件将持续更新,请各位放心使用,您的宝贵建议是我们努力的动力!!
## 致开发者
## <font color='red'>写给uCharts使用者的一封信</font>
<font color='red'>
亲爱的用户:
感谢各位开发者`三年`来对秋云及uCharts的支持,uCharts的进步离不开各位开发者的鼓励与贡献,为更好的帮助各位开发者在uni-app生态系统更好的应用图表,uCharts始终坚持开源,并提供社群帮助开发者解决问题。 为确保您能更好的应用图表组件,建议您先`仔细阅读本页文档`以及uCharts官方文档,而不是下载下来`直接使用`。 如遇到问题请先阅读文档,如仍然不能解决,请加入QQ群咨询,如群友均不能解决或者您有特殊需求,请在群内私聊我,因工作原因,回复不一定很及时,您可直接说问题,有时间一定会回复您。
- 由于最近上线的官网中实行了部分收费体验,收到了许多用户的使用反馈,大致反馈的问题都指向同一矛头:为何新官网的在线工具也要收费?对于这件事,我们深表歉意。由于新官网本身未提供技术文档,使得用户误以为我们对文档实行了收费。经我们连夜整改,新官网目前已经将技术文档开放出来供大家阅读使用,并免费对外开放了【演示】中的查看全端全平台的代码的功能,为此再次向所受影响的用户们致以诚恳的歉意。
uCharts的开源图表组件的开发,付出了大量的个人时间与精力,经过两年来的考验,不会有比较明显的bug,请各位放心使用。不求您5星评价,也不求您赞赏,`只求您对开源贡献的支持态度`,所以,当您想给`1星评价`的时候,秋云真的会`含泪希望您绕路而行……`。如果您有更好的想法,可以在`码云提交Pull Requests`以帮助更多开发者完成需求,再次感谢各位对uCharts的鼓励与支持!
- 其次,我们须澄清几点,如下:
1. uCharts的插件本身遵循开源原则,并不收费,用户可自行到DCloud市场与Gitee码云上获取源码
2. uCharts的技术文档永久对用户开放
3. 收费内容仅针对原生工具、组件工具、定制功能以及模板市场的部分收费模板
- uCharts为什么实行收费原则?
1. 服务器的费用支撑
2. 团队的运营支出;正如你所见,我们的群里有大量的用户在请教图表配置与反馈问题,群里的每一位管理员都在花费不少精力在积极解决用户的问题,然而遇到巨大的咨询量时,我们无法及时、精准解答回复,因此,我们推出了会员优先服务
3. 与其说模板市场是收费,倒不如说给野生用户提供了创造价值的机会,用户既可以在上面发布模板赚取费用,遇到心动的模板也能免费/付费使用
- 收费不是目的,正如你们所见,用户可以申请成为[【开发者】](https://www.ucharts.cn/v2/#/agreement/developer),开发者不限制任何官网功能,并享有官方指导、开发、改造uCharts的权力,并且活动期间【返还超级会员费用】!我们想说的是,我们新版官网上线旨在希望更多的用户加入到开发者的队伍,我们共同去维护uCharts!
我们相信:星星之火可以燎原!
uCharts技术团队
2022.4.23
</font>
## 友情推荐([https://ext.dcloud.net.cn/plugin?id=7088](https://ext.dcloud.net.cn/plugin?id=7088))
![在这里插入图片描述](https://img-blog.csdnimg.cn/b2782da0ab6d415c98c4de28b0279bd5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAVHVfTmlhbw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
**图鸟UI**,是基于uni-app进行开发的UI框架,提供丰富的组件进行快速开发,已经支持**APP**、**H5**、**微信小程序**,包含全面的UI元素、60+功能组件、酷炫自定义tabbar,并提供丰富好看的免费前端模板。
![logo](https://img-blog.csdnimg.cn/4a276226973841468c1be356f8d9438b.png)
[![star](https://gitee.com/uCharts/uCharts/badge/star.svg?theme=gvp)](https://gitee.com/uCharts/uCharts/stargazers)
[![fork](https://gitee.com/uCharts/uCharts/badge/fork.svg?theme=gvp)](https://gitee.com/uCharts/uCharts/members)
[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[![npm package](https://img.shields.io/npm/v/@qiun/ucharts.svg?style=flat-square)](https://www.npmjs.com/~qiun)
## uCharts简介
`uCharts`是一款基于`canvas API`开发的适用于所有前端应用的图表库,开发者编写一套代码,可运行到 Web、iOS、Android(基于 uni-app / taro )、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等更多支持 canvas API 的平台。
## 官方网站
## [https://www.ucharts.cn](https://www.ucharts.cn)
## 快速体验
一套代码编到7个平台,依次扫描二维码,亲自体验uCharts图表跨平台效果!IOS因demo比较简单无法上架,请自行编译。
![](https://box.kancloud.cn/58092090f2bccc6871ca54dbec268811_654x479.png)
一套代码编到多个平台,依次扫描二维码,亲自体验uCharts图表跨平台效果!其他平台请自行编译。
## 快速上手
### <font color=#FF0000> 注意前提条件【版本要求:HBuilderX 3.1.0+】 </font>
- 1、插件市场点击右侧绿色按钮【使用HBuilderX导入插件】,或者【使用HBuilderX导入示例项目】查看完整示例工程
- 2、依赖uniapp的vue-cli项目:请将uni-modules目录复制到src目录,即src/uni_modules。(请升级uniapp依赖为最新版本)
- 3、页面中直接按下面用法直接调用即可,无需在页面中注册组件qiun-data-charts
- 4、注意父元素class='charts-box'这个样式需要有宽高
![](https://www.ucharts.cn/images/web/guide/qrcode20220224.png)
## 基本用法
## 致开发者
- template代码:([建议使用在线工具生成](https://demo.ucharts.cn))
感谢各位开发者`四年`来对秋云及uCharts的支持,uCharts的进步离不开各位开发者的鼓励与贡献。为更好的帮助各位开发者使用图表工具,我们推出了新版官网,增加了在线定制、问答社区、在线配置等一些增值服务,为确保您能更好的应用图表组件,建议您先`仔细阅读本页指南`以及`常见问题`,而不是下载下来`直接使用`。如仍然不能解决,请到`官网社区`或开通会员后加入`专属VIP会员群`提问将会很快得到回答。
```
<view class="charts-box">
    <qiun-data-charts type="column" :chartData="chartData" />
</view>
```
## 社群支持
- 标准数据格式1:(折线图、柱状图、区域图等需要categories的直角坐标系图表类型)
uCharts官方拥有4个2000人的QQ群及专属VIP会员群支持,庞大的用户量证明我们一直在努力,请各位放心使用!uCharts的开源图表组件的开发,团队付出了大量的时间与精力,经过四来的考验,不会有比较明显的bug,请各位放心使用。如果您有更好的想法,可以在`码云提交Pull Requests`以帮助更多开发者完成需求,再次感谢各位对uCharts的鼓励与支持!
```
chartData:{
  categories: ["2016", "2017", "2018", "2019", "2020", "2021"],
  series: [{
    name: "目标值",
    data: [35, 36, 31, 33, 13, 34]
  }, {
    name: "完成量",
    data: [18, 27, 21, 24, 6, 28]
  }]
}
```
- 标准数据格式2:(饼图、圆环图、漏斗图等不需要categories的图表类型)
```
chartData:{
  series: [{
    data: [
      {
        name: "一班",
        value: 50
      }, {
        name: "二班",
        value: 30
      }, {
        name: "三班",
        value: 20
      }, {
        name: "四班",
        value: 18
      }, {
        name: "五班",
        value: 8
      }
    ]
  }]
}
```
注:其他特殊图表类型,请参考mockdata文件夹下的数据格式,v2.0版本的uCharts已兼容ECharts的数据格式,v2.0版本仍然支持v1.0版本的数据格式。
## localdata数据渲染用法
- 使用localdata数据格式渲染图表的优势:数据结构简单,无需自行拼接chartData的categories及series,从后端拿回的数据简单处理即可生成图表。
- localdata数据的缺点:并不是所有的图表类型均可通过localdata渲染图表,例如混合图,组件并不能识别哪个series分组需要渲染成折线还是柱状图,涉及到复杂的图表,仍需要由chartData传入。
- template代码:([建议使用在线工具生成](https://demo.ucharts.cn))
```
<view class="charts-box">
    <qiun-data-charts type="column" :localdata="localdata" />
</view>
```
- 标准数据格式1:(折线图、柱状图、区域图等需要categories的直角坐标系图表类型)
其中value代表数据的数值,text代表X轴的categories数据点,group代表series分组的类型名称即series[i].name。
```
localdata:[
  {value:35, text:"2016", group:"目标值"},
  {value:18, text:"2016", group:"完成量"},
  {value:36, text:"2017", group:"目标值"},
  {value:27, text:"2017", group:"完成量"},
  {value:31, text:"2018", group:"目标值"},
  {value:21, text:"2018", group:"完成量"},
  {value:33, text:"2019", group:"目标值"},
  {value:24, text:"2019", group:"完成量"},
  {value:13, text:"2020", group:"目标值"},
  {value:6, text:"2020", group:"完成量"},
  {value:34, text:"2021", group:"目标值"},
  {value:28, text:"2021", group:"完成量"}
]
```
- 标准数据格式2:(饼图、圆环图、漏斗图等不需要categories的图表类型)
其中value代表数据的数值,text代表value数值对应的描述。
```
localdata:[
  {value:50, text:"一班"},
  {value:30, text:"二班"},
  {value:20, text:"三班"},
  {value:18, text:"四班"},
  {value:8, text:"五班"},
]
```
- 注意,localdata的数据格式必需要符合datacom组件规范[【详见datacom组件】](https://uniapp.dcloud.io/component/datacom?id=mixindatacom)。
## 进阶用法读取uniCloud数据库并渲染图表
- 组件基于uniCloud的[clientDB](https://uniapp.dcloud.net.cn/uniCloud/clientdb)技术,无需云函数,在前端对数据库通过where查询条件及group和count统计即可渲染图表。
- 具体可参考/pages/unicloud/unicloud.vue中的demo例子,使用前,请先关联云服务空间,然后在uniCloud/database/db_init.json文件上点右键,初始化云数据库,当控制台显示“初始化云数据库完成”即完成示例数据的导入,之后方可运行uniCloud的demo。
- template代码:
```
<qiun-data-charts
  type="line"
  :chartData="demoData"
  collection="uni-id-users"
  field="register_date,status"
  :where="'publish_date >= ' + new Date(startDate).getTime() + ' && publish_date <= ' + new Date(endDate).getTime()"
  groupby="dateToString(add(new Date(0),register_date),'%Y-%m-%d','+0800') as text,status as group"
  group-field="count(*) as value"
/>
```
- 注意,从uniCloud读取出的数据,需要符合localdata的标准结果数据格式(参考上部分localdata),并需要把输出的字段as成规定的别名(value、text、group)。
## 示例文件地址:
### <font color=#FF0000> 强烈建议先看本页帮助,再看下面示例文件源码!</font>
```
/pages/ucharts/ucharts.vue(展示用uCharts全端运行的例子)
/pages/echarts/echarts.vue(展示H5和App用ECharts,小程序端用uCharts的例子)
/pages/unicloud/unicloud.vue(展示读取uniCloud数据库后直接渲染图表的例子)
/pages/updata/updata.vue(展示动态更新图表数据的例子)
/pages/other/other.vue(展示图表交互的例子:动态更新图表数据,渲染完成事件,获取点击索引,自定义tooltip,图表保存为图片,强制展示错误信息等)
/pages/format-u/format-u.vue(展示uCharts的formatter用法的例子)
/pages/format-e/format-e.vue(展示ECharts的formatter用法的例子)
/pages/tab/tab.vue(展示再tab选项卡中用法的例子,即父容器采用v-show或v-if时需要注意的问题)
/pages/layout/layout.vue(展示特殊布局用法的例子:swiper、scroll-view、绝对定位等布局)
/pages/canvas/canvas.vue(展示uCharts v2.0版本原生js用法的例子)
```
## 组件基本API参数
|属性名|类型|默认值|必填|说明|
| -- | -- | -- | -- | -- |
|type|String|null|`是`|图表类型,如全端用uCharts,可选值为pie、ring、rose、word、funnel、map、arcbar、line、column、bar、area、radar、gauge、candle、mix、tline、tarea、scatter、bubble <font color=#FF0000>(您也可以根据需求自定义新图表类型,需要在config-ucharts.js或config-echarts.js内添加,可参考config-ucharts.js内的"demotype"类型)</font>|
|chartData|Object|见说明|`是`|图表数据,常用的标准数据格式为{categories: [],series: []},请按不同图表类型传入对应的标准数据。|
|localdata|Array|[]|`是`|图表数据,如果您觉得拼接上面chartData比较繁琐,可以通过使用localdata渲染,组件会根据传入的type类型,自动拼接categories或series数据(使用localdata就不必再传入chartData,详见 /pages/other/other.vue 中使用localdata渲染图表的例子)。【localdata和collection(uniCloud数据库)同时存在,优先使用localdata;如果localdata和chartData同时存在,优先使用chartData。<font color=#FF0000> 即chartData>localdata>collection的优先级</font>渲染图表】。|
|opts|Object|{}|否|uCharts图表配置参数(option),请参考[【在线生成工具】](https://demo.ucharts.cn)<font color=#FF0000>注:传入的opts会覆盖默认config-ucharts.js中的配置,只需传入与config-ucharts.js中属性不一致的opts即可实现【同类型的图表显示不同的样式】。</font>|
|eopts|Object|{}|否|ECharts图表配置参数(option),请参考[【ECharts配置手册】](https://echarts.apache.org/zh/option.html)传入eopts。<font color=#FF0000>注:1、传入的eopts会覆盖默认config-echarts.js中的配置,以实现同类型的图表显示不同的样式。2、eopts不能传递function,如果option配置参数需要function,请将option写在config-echarts.js中即可实现。</font>|
|loadingType|Number|2|否|加载动画样式,0为不显示加载动画,1-5为不同的样式,见下面示例。|
|errorShow|Boolean|true|否|是否在页面上显示错误提示,true为显示错误提示图片,false时会显示空白区域|
|errorReload|Boolean|true|否|是否启用点击错误提示图表重新加载,true为允许点击重新加载,false为禁用点击重新加载事件|
|errorMessage|String|null|否|自定义错误信息,强制显示错误图片及错误信息,当上面errorShow为true时可用。(组件会监听该属性的变化,只要有变化,就会强制显示错误信息!)。说明:1、一般用于页面网络不好或其他情况导致图表loading动画一直显示,可以传任意(不为null或者"null"或者空"")字符串强制显示错误图片及说明。2、如果组件使用了data-come属性读取uniCloud数据,组件会自动判断错误状态并展示错误图标,不必使用此功能。3、当状态从非null改变为null或者空时,会强制调用reload重新加载并渲染图表数据。|
|echartsH5|Boolean|false|否|是否在H5端使用ECharts引擎渲染图表|
|directory|String|'/'|否|二级目录名称,如果开启上面echartsH5即H5端用ECharts引擎渲染图表,并且项目未发布在website根目录,需要填写此项配置。例如二级目录是h5,则需要填写`/h5/`,左右两侧需要带`/`,发布到三级或更多层目录示例`/web/v2/h5/`|
|echartsApp|Boolean|false|否|是否在APP端使用ECharts引擎渲染图表|
|canvasId|String|见说明|否|默认生成32位随机字符串。如果指定canvasId,可方便后面调用指定图表实例,否则需要通过渲染完成事件获取自动生成随机的canvasId|
|canvas2d|Boolean|false|否|是否开启canvas2d模式,用于解决微信小程序层级过高问题,仅微信小程序端可用,其他端会强制关闭canvas2d模式。<font color=#FF0000>注:开启canvas2d模式,必须要传入上面的canvasId(随机字符串,不能是动态绑定的值,不能是数字),否则微信小程序可能会获取不到dom导致无法渲染图表!**开启后,开发者工具显示不正常,预览正常(不能“真机调试”,不能“真机调试”,不能“真机调试”)**</font>|
|background|String|none|否|背景颜色,默认透明none,可选css的16进制color值,如#FFFFFF|
|animation|Boolean|true|否|是否开启图表动画效果|
|inScrollView|Boolean|false|否|图表组件是否在scroll-view中,如果在请传true,否则会出现点击事件坐标不准确的现象|
|pageScrollTop|Number|0|否|如果图表组件是在scroll-view中,并且整个页面还存在滚动条,这个值应为绑定为页面滚动条滚动的距离,否则会出现点击事件坐标不准确的现象|
|reshow|Boolean|false|否|强制重新渲染属性,如果图表组件父级用v-show包裹,初始化的时候会获取不到元素的宽高值,导致渲染失败,此时需要把父元素的v-show方法复制到reshow中,组件检测到reshow值变化并且为true的时候会强制重新渲染|
|reload|Boolean|false|否|强制重新加载属性,与上面的reshow区别在于:1、reload会重新显示loading动画;2、如果组件绑定了uniCloud数据查询,通过reload会重新执行SQL语句查询,重新请求网络。而reshow则不会显示loading动画,只是应用现有的chartData数据进行重新渲染|
|disableScroll|Boolean|false|否|当在canvas中移动时,且有绑定手势事件时,禁止屏幕滚动以及下拉刷新(赋值为true时,在图表区域内无法拖动页面滚动)|
|tooltipShow|Boolean|true|否|点击或者鼠标经过图表时,是否显示tooltip提示窗,默认显示|
|tooltipFormat|String|undefined|否|自定义格式化Tooltip显示内容,详见下面【tooltipFormat格式化】|
|tooltipCustom|Object|undefined|否|(仅uCharts)如果以上系统自带的Tooltip格式化方案仍然不满足您,您可以用此属性实现更多需求,详见下面【tooltipCustom自定义】|
|startDate|String|undefined|否|需为标准时间格式,例如"2021-02-14"。用于配合uniClinetDB自动生成categories使用|
|endDate|String|undefined|否|需为标准时间格式,例如"2021-03-31"。用于配合uniClinetDB自动生成categories使用|
|groupEnum|Array|[]|否|当使用到uniCloud数据库时,group字段属性如果遇到统计枚举属性的字段,需要通过将DB Schema中的enum的描述定义指派给该属性,具体格式为[{value: 1,text: "男"},{value: 2,text: "女"}]|
|textEnum|Array|[]|否|当使用到uniCloud数据库时,text字段属性如果遇到统计枚举属性的字段,需要通过将DB Schema中的enum的描述定义指派给该属性,具体格式为[{value: 1,text: "男"},{value: 2,text: "女"}]|
|ontap|Boolean|true|否|是否监听@tap@cilck事件,禁用后不会触发组件点击事件|
|ontouch|Boolean|false|否|(仅uCharts)是否监听@touchstart@touchmove@touchend事件(赋值为true时,非PC端在图表区域内无法拖动页面滚动)|
|onmouse|Boolean|true|否|是否监听@mousedown@mousemove@mouseup事件,禁用后鼠标经过图表上方不会显示tooltip|
|on movetip|Boolean|false|否|(仅uCharts)是否开启跟手显示tooltip功能(前提条件,1、需要开启touch功能,即:ontouch="true";2、并且opts.enableScroll=false即关闭图表的滚动条功能)(建议微信小程序开启canvas2d功能,否则原生canvas组件会很卡)|
|tapLegend|Boolean|true|否|(仅uCharts)是否开启图例点击交互事件 |
## 组件事件及方法
|事件名|说明|
| --| --|
|@complete|图表渲染完成事件,渲染完成会返回图表实例{complete: true, id:"xxxxx"(canvasId), type:"complete"}。可以引入config-ucharts.js/config-echarts.js来根据返回的id,调用uCharts或者ECharts实例的相关方法,详见other.vue其他图表高级应用。|
|@getIndex|获取点击数据索引,点击后返回图表索引currentIndex,图例索引(仅uCharts)legendIndex,等信息。返回数据:{type: "getIndex", currentIndex: 3, legendIndex: -1, id:"xxxxx"(canvasId), event: {x: 100, y: 100}(点击坐标值)}|
|@error|当组件发生错误时会触发该事件。返回数据:返回数据:{type:"error",errorShow:true/false(组件props中的errorShow状态值) , msg:"错误消息xxxx", id: "xxxxx"(canvasId)}|
|@getTouchStart|(仅uCharts)拖动开始监听事件。返回数据:{type:"touchStart",event:{x: 100, y: 100}(点击坐标值),id:"xxxxx"(canvasId)}|
|@getTouchMove|(仅uCharts)拖动中监听事件。返回数据:{type:"touchMove",event:{x: 100, y: 100}(点击坐标值),id:"xxxxx"(canvasId)}|
|@getTouchEnd|(仅uCharts)拖动结束监听事件。返回数据:{type:"touchEnd",event:{x: 100, y: 100}(点击坐标值),id:"xxxxx"(canvasId)}|
|@scrollLeft|(仅uCharts)开启滚动条后,滚动条到最左侧触发的事件,用于动态打点,需要自行编写防抖方法。返回数据:{type:"scrollLeft", scrollLeft: true, id: "xxxxx"(canvasId)}|
|@scrollRight|(仅uCharts)开启滚动条后,滚动条到最右侧触发的事件,用于动态打点,需要自行编写防抖方法。返回数据:返回数据:{type:"scrollRight", scrollRight: true, id: "xxxxx"(canvasId)}|
## tooltipFormat格式化(uCharts和ECharts)
tooltipFormat类型为string字符串类型,需要指定config-ucharts.js/config-echarts.js中formatter下的属性值。因各小程序及app端通过组件均不能传递function类型参数,因此请先在config-ucharts.js/config-echarts.js内定义您想格式化的数据,然后在这里传入formatter下的key值,组件会自动匹配与其对应的function。如不定义该属性,组件会调用默认的tooltip方案,标准的tooltipFormat使用姿势如下:
```
<qiun-data-charts
  type="column"
  :chartData="chartData"
  tooltipFormat="tooltipDemo1"
⁄>
==================
config-ucharts.js
formatter:{
  tooltipDemo1:function(item, category, index, opts){return item.data+'天'}
}
==================
config-echarts.js
formatter:{
  tooltipDemo1:function(){
  }
}
```
注意,config-ucharts.js内的formatter下的function需要携带(item, category, index, opts)参数,这4个参数都是uCharts实例内传递过来的数据,具体定义如下:
|属性名|说明|
| -- | -- |
|item|组件内计算好的当前点位的series[index]数据,其属性有data(继承series[index].format属性),color,type,style,pointShape,disableLegend,name,show|
|category|当前点位的X轴categories[index]分类名称(如果图表类型没有category,其值则为undefined)|
|index|当前点位的索引值|
|opts|全部uCharts的opts配置,包含categories、series等一切你需要的都在里面,可以根据index索引值获取其他相关数据。您可以在渲染完成后打印一下opts,看看里面都有什么,也可以自定义一些你需要的挂载到opts上,这样就可以根据需求更方便的显示自定义内容了。|
## tooltipCustom自定义(仅uCharts)
上面仅仅展示了Tooltip的自定义格式化,如果仍然仍然还不能还不能满足您的需求,只能看这里的方法了。tooltipCustom可以自定义在任何位置显示任何内容的文本,当然tooltipCustom可以和tooltipFormat格式化同时使用以达到更多不同的需求,下面展示了tooltip固定位置显示的方法:
```
<qiun-data-charts
    type="column"
    :chartData="chartData"
    :tooltipCustom="{x:10,y:10}"
/>
```
tooltipCustom属性如下:
|属性名|类型|默认值|说明|
| -- | -- | -- | -- |
|x|Number|undefined|tooltip左上角相对于画布的X坐标|
|y|Number|undefined|tooltip左上角相对于画布的Y坐标|
|index|Number|undefined|相对于series或者categories中的索引值。当没有定义index或者index定义为undefined的时候,组件会自动获取当前点击的索引,并根据上面的xy位置绘制tooltip提示框。如果为0及以上的数字时,会根据您传的索引自动计算x轴方向的偏移量(仅直角坐标系有效)|
|textList|Array.Object|undefined|多对象数组,tooltip的文字组。当没有定义textList或者textList定义为undefined的时候,会调自动获取点击索引并拼接相应的textList。如传递[{text:'默认显示的tooltip',color:null},{text:'类别1:某个值xxx',color:'#2fc25b'},{text:'类别2:某个值xxx',color:'#facc14'},{text:'类别3:某个值xxx',color:'#f04864'}]这样定义好的数组,则会只显示该数组。|
|textList[i].text|String| |显示的文字|
|textList[i].color|Color| |左侧图表颜色|
## datacome属性及说明
- 通过配置datacome属性,可直接获取uniCloud云数据,并快速自动生成图表,使开发者只需专注业务及数据,无需关心如何拼接数据等不必要的重复工作,大大缩短开发时间。datacome属性及说明,详见[datacom组件规范](https://uniapp.dcloud.io/component/datacom?id=mixindatacom)
|属性名|类型|默认值|说明|
| -- | -- | -- | -- |
|collection|String| |表名。支持输入多个表名,用 , 分割|
|field|String| |查询字段,多个字段用 , 分割|
|where|String| |查询条件,内容较多,另见jql文档:[详情](https://uniapp.dcloud.net.cn/uniCloud/uni-clientDB?id=jsquery)|
|orderby|String| |排序字段及正序倒叙设置|
|groupby|String| |对数据进行分组|
|group-field|String| |对数据进行分组统计|
|distinct|Boolean|false|是否对数据查询结果中重复的记录进行去重|
|action|string| |云端执行数据库查询的前或后,触发某个action函数操作,进行预处理或后处理,详情。场景:前端无权操作的数据,比如阅读数+1|
|page-data|string|add|分页策略选择。值为 add 代表下一页的数据追加到之前的数据中,常用于滚动到底加载下一页;值为 replace 时则替换当前data数据,常用于PC式交互,列表底部有页码分页按钮|
|page-current|Number|0|当前页|
|page-size|Number|0|每页数据数量|
|getcount|Boolean|false|是否查询总数据条数,默认 false,需要分页模式时指定为 true|
|getone|Boolean|false|指定查询结果是否仅返回数组第一条数据,默认 false。在false情况下返回的是数组,即便只有一条结果,也需要[0]的方式获取。在值为 true 时,直接返回结果数据,少一层数组。一般用于非列表页,比如详情页|
|gettree|Boolean|false|是否查询树状数据,默认 false|
|startwith|String|''|gettree的第一层级条件,此初始条件可以省略,不传startWith时默认从最顶级开始查询|
|limitlevel|Number|10|gettree查询返回的树的最大层级。超过设定层级的节点不会返回。默认10级,最大15,最小1|
## uni_modules目录说明
```
├── components
│ └── qiun-data-chatrs──────────# 组件主入口模块
│ └── qiun-error────────────────# 加载动画组件文件目录(可以修改错误提示图标以减少包体积)
│ └── qiun-loading──────────────# 加载动画组件文件目录(可以删除您不需要的动画效果以减少包体积)
├── js_skd
│ └── u-charts
│ ── └──config-echarts.js ──────# ECharts默认配置文件(非APP端内可作为实例公用中转)
│ ── └──config-ucharts.js ──────# uCharts默认配置文件(非APP端内可作为实例公用中转)
│ ── └──u-charts-v2.0.0.js──────# uCharts基础库v2.0.0版本,部分API与之前版本不同
├── static
│ └── app-plus──────────────────# 条件编译目录,仅编译到APP端
│ ── └──echarts.min.js──────────# Echarts基础库v4.2.1
│ └── h5────────────────────────# 条件编译目录,仅编译到H5端
│ ── └──echarts.min.js──────────# Echarts基础库v4.2.1
```
## 加载动画及错误提示
- 为保证编译后的包体积,加载动画引用作者wkiwi提供的[w-loading](https://ext.dcloud.net.cn/plugin?id=504)中选取5种,如需其他样式请看下面说明。
- loading的展示逻辑:
    * 1、如果是uniCloud数据,从发送网络请求到返回数据期间展示。
    * 2、如果是自行传入的chartData,当chartData.series=[]空数组的时候展示loading,也就是说初始化图表的时候,如果您没有数据,可以通过先传个空数组来展示loading效果,当chartData.series有数据后会自动隐藏loading图标。
- <font color=#FF0000>如您修改了qiun-data-charts.vue组件文件,请务必在升级前备份您的文件,以免被覆盖!!!建议将加载状态显示做成组件,避免下次升级时丢失后无法找到。</font>
## 配置文件说明
- <font color=#FF0000>注意,config-echarts.js和config-ucharts.js内只需要配置符合您项目整体UI的整体默认配置,根据需求,先用[【在线工具】](http://demo.ucharts.cn)调试好默认配置,并粘贴到配置文件中。</font>
- <font color=#FF0000>如果需要与configjs中不同的配置,只需要在组件上绑定:opts或者:eopts传入与默认配置不同的某个属性及值即可覆盖默认配置,极大降低了代码量。</font>
- ECharts默认配置文件:config-echarts.js
    i、<font color=#FF0000>如您修改了默认配置文件,请务必在升级前备份您的配置文件,以免被覆盖!!!</font>
    ii、ECharts配置手册:[https://echarts.apache.org/zh/option.html](https://echarts.apache.org/zh/option.html)
    iii、"type"及"categories"属性为支持的图表属性,您可参照ECharts配置手册,配置您更多的图表类型,并将对应的图表配置添加至下面
    iv、"formatter"属性,因各小程序及app端通过组件均不能传递function类型参数,因此请先在此属性下定义您想格式化的数据,组件会自动匹配与其对应的function
    v、"seriesTemplate"属性,因ECharts的大部分配置均在series内,seriesTemplate作为series的模板,这样只需要在这里做好模板配置,组件的数组层chartData(或者localdata或者collection)的series会自动挂载模板配置。如需临时或动态改变seriesTemplate,可在:eopts中传递seriesTemplate,详见pages/echarts/echarts.vue中的曲线图。
    vi、ECharts配置仅可用于H5或者APP端,并且配置`echartsH5`或`echartsApp`为`true`时可用
- uCharts默认配置文件:config-ucharts.js
    i、<font color=#FF0000>如您修改了默认配置文件,请务必在升级前备份您的配置文件,以免被覆盖!!!</font>
    ii、v2版本后的uCharts基础库不提供配置手册,您可以使用在线配置生成工具来快速生成配置:[http://demo.ucharts.cn](http://demo.ucharts.cn)
    iii、"type"及"categories"属性为支持的图表属性,不支持添加uCharts基础库没有的图表类型
    iv、"formatter"属性因各小程序及app端通过组件均不能传递function类型参数,因此请先在此属性下定义您想格式化的数据,组件会自动匹配与其对应的function
    v、uCharts配置可跨全端使用
## 常见问题及注意事项
- `图表无法显示问题`:
    * 请先检查您的HBuilderX版本,要求高于3.1.0+。
    * 1、如果是首次导入插件不显示,或者报以下未注册`qiun-data-charts`的错误:
    > Unknown custom element: &lt; qiun-data-charts &gt; - did you register the component correctly? For recursive components, make sure to provide the "name" option.
    * 2、<font color=#FF0000>请【重启HBuilderX】或者【重启项目】或者【重启开发者工具】或者【删除APP基座】重新运行,避免缓存问题导致不能显示。</font>
  * 3、如果是基于uniapp的vue-cli项目,1、请 npm update 升级uniapp依赖为最新版本;2、请尝试清理node-modules,重新install,还不行就删除项目,再重新install。如果仍然不行,请检查uniapp依赖是否为最新版本,再重试以上步骤。如果仍然不行,请使用<font color=#FF0000>【非uni_modules版本】</font>组件,最新非uni_modules版本在码云发布,[点击此处获取](https://gitee.com/uCharts/uCharts/tree/master/qiun-data-charts%EF%BC%88%E9%9D%9Euni-modules%EF%BC%89)。。
    * 4、请检查控制台是否有报错或提示信息,如果没有报错,也没有提示信息,并且检查视图中class="charts-box"这个元素的宽高均为0,请修改父元素的css样式或进行下面第4步检查。
    * 5、检查父级是否使用了v-show来控制显示。如果页面初始化时组件处于隐藏状态,组件则无法正确获取宽高尺寸,此时<font color=#FF0000>需要组件内绑定reshow属性(逻辑应与父级的v-show的逻辑相同)</font>,强制重新渲染图表,例如:reshow="父级v-show绑定的事件"。
    * 6、如果在微信小程序端开启了canvas2d模式<font color=#FF0000>(不能使用真机调试,请直接预览)</font>不显示图表:
        * a、请务必在组件上定义canvasId,不能为纯数字、不能为变量、不能重复、尽量长一些。
        * b、请检查微信小程序的基础库,修改至2.16.0或者最新版本的基础库。
        * c、请检查父元素或父组件是否用v-if来控制显示,如有请改为v-show,并将v-show的逻辑绑定至组件。
- `formatter格式化问题`:无论是uCharts还是ECharts,因为组件不能传递function,所有的formatter均需要变成别名format来定义,并在config-ucharts.js或config-echarts.js配置对应的formatter方法,组件会根据format的值自动替换配置文件中的formatter方法。(参考示例项目pages/format/format.vue)
- `图表抖动问题`:如果开启了animation动画效果,由于组件内开启了chartData和opts的监听,当数据变化时会重新渲染图表,<font color=#FF0000>建议整体改变chartData及opts的属性值</font>,而不要通过循环或遍历来改变this实例下的chartData及opts,例如先定义一个临时变量,拼接好数据后再整体赋值。(参考示例项目pages/updata/updata.vue)
- `微信小程序报错Maximum call stack size exceeded问题`:由于组件内开启了chartData和opts的监听,当数据变化时会重新渲染图表,<font color=#FF0000>建议整体改变chartData及opts的属性值</font>,而不要通过循环或遍历来改变this实例下的chartData及opts,例如先定义一个临时变量,拼接好数据后再整体赋值。(参考示例项目pages/updata/updata.vue)
- `Loading状态问题`:如不使用uniClinetDB获取数据源,并且需要展示Loading状态,请先清空series,使组件变更为Loading状态,即this.chartData.series=[]即可展示,然后再从服务端获取数据,拼接完成后再传入this.chartData。如果不需要展示Loading状态,则不需要以上步骤,获取到数据,拼接好标准格式后,直接赋值即可。
- `微信小程序图表层级过高问题`:因canvas在微信小程序是原生组件,如果使用自定义tabbar或者自定义导航栏,图表则会超出预期,此时需要给组件的canvas2d传值true来使用type='2d'的功能,开启此模式后,<font color=#FF0000>一定要在组件上自定义canvasId,不能为数字,不能动态绑定,要为随机字符串!不能“真机调试”,不能“真机调试”,不能“真机调试”</font>开发者工具显示不正常,图表层级会变高,而正常预览或者发布上线则是正常状态,开发者不必担心,一切以真机预览为准(因微信开发者工具显示不正确,canvas2d这种模式下给调试带来了困难,开发时,可以先用:canvas2d="false"来调试,预览无误后再改成true)。
- `开启canvas2d后图表不显示问题`:开启canvas2d后,需要手动指定canvasId,并且父元素不能含有v-if,否则会导致获取不到dom节点问题,请将v-if改成v-show,更多开启canvas2d不显示问题,请参考示例项目pages/layout/layout.vue文件,对照示例项目修改您的项目。
- `MiniPorgramError U.createEvent is ot a function`:此问题一般是微信小程序开启了canvas2d,并点击了“真机调试导致”,参考上面【微信小程序图表层级过高问题】解决办法,开启2d后,不可以真机调试,只能开发者工具调试或者扫二维码“预览”。
- `在图表上滑动无法使页面滚动问题`:此问题是因为监听了touchstart、touchmove和touchend三个事件,或者开启了disableScroll属性,如果您的图表不需要开启图表内的滚动条功能,请禁用这三个方法的监听,即:ontouch="false"或者:disableScroll="false"即可(此时图表组件默认通过@tap事件来监听点击,可正常显示Tooltip提示窗)。
- `开启滚动条无法拖动图表问题`:此问题正与以上问题相反,是因为禁用了监听touchstart、touchmove和touchend三个事件,请启用这三个方法的监听,即在组件上加入 :ontouch="true" 即可。注意,不要忘记在opts里需要配置enableScroll:true,另外如果需要显示滚动条,需要在xAxis中配置scrollShow:ture,及itemCount(单屏数据密度)数量的配置。
- `开启滚动条后图表两侧有白边问题`:此问题是因为组件上的background为none或者没有指定,请在组件上加入background="#000000"(您的背景色)。如果父元素为图片,尽量不要开启滚动条,此时图表是透明色,可以显示父元素背景图片。
- `开启滚动条后动态打点更新数据滚动条位置问题`:开启滚动条后动态打点,需要把opts中update需要赋值为true,来启用uCharts的updateData方法来更新视图,详见示例项目pages/updata/updata.vue。
- `地图变形问题`:此问题是因为您引用的geojson地图数据的坐标系可能是地球坐标(WGS84)导致,需要开启【是否进行WGS84转墨卡托投影】功能。开启后因大量的数据运算tooltip可能会不跟手,建议自行转换为墨卡托坐标系,可参照源码内function lonlat2mercator()。其他地图数据下载地址:[http://datav.aliyun.com/tools/atlas/](http://datav.aliyun.com/tools/atlas/)
- `支付宝(钉钉)小程序无法点击问题`:请检查支付宝小程序开发者工具中,点击【详情】,在弹出的【项目详情】中【取消】启用小程序基础库 2.0 构建,一定不要勾选此项。
- `uni-simple-router中使用问题`:如果使用uni-simple-router路由插件,H5开启完全路由模式(即h5:{vueRouterDev:true})时,会导致组件内uni.xxx部分方法失效,引发节点获取不正常报错,请使用普通模式即可。
- `Y轴刻度标签数字重复问题`:此问题一般是series数据内数值较小,而Y轴网格数量较多,并且Y轴刻度点显示整数导致。解决方法1,Y轴刻度值保留两位小数,组件上传值 :opts="{yAxis:{data:[{tofix:2}]}}";解决方法2,修改Y轴网格数量为series中的最大值的数量,例如series中最大值为3,那么修改yAxis.splitNumber=3即可;解决方法3,根据Y轴网格数量修改Y轴最大值 :opts="{yAxis:{data:[{max:5}]}}"。
- `柱状图柱子高度不符合预期问题`:此问题是Y轴最小值未默认为0的问题导致,组件上传值 :opts="{yAxis:{data:[{min:0}]}}"即可解决。
- `饼图类百分比改其他文案的问题`:参考示例项目pages/format-u/format-u.vue,在chartData的series中使用format。
## [更多常见问题以官方网站【常见问题】为准](http://demo.ucharts.cn)
## QQ群号码
## <font color=#FF0000> 请先完整阅读【帮助文档】及【常见问题】3遍,右侧蓝色按钮【示例项目】请看2遍!不看文档不看常见问题进群就问的拒绝回答问题!咨询量太大请理解作者! </font>
#### 官方交流群
- 交流群1:371774600(已满)
- 交流群2:619841586
- 交流群2:619841586(已满)
- 交流群3:955340127(已满)
- 交流群4:641669795
- 口令`uniapp`
#### 专属VIP会员群
- 开通会员后详见【账号详情】页面中顶部的滚动通知
- 口令`您的用户ID`
## 版权信息
uCharts始终坚持开源,遵循 [Apache Licence 2.0](https://www.apache.org/licenses/LICENSE-2.0.html) 开源协议,意味着您无需支付任何费用,即可将uCharts应用到您的产品中。
注意:这并不意味着您可以将uCharts应用到非法的领域,比如涉及赌博,暴力等方面。如因此产生纠纷或法律问题,uCharts相关方及秋云科技不承担任何责任。
## 合作伙伴
[![DIY官网](https://www.ucharts.cn/images/web/guide/links/diy-gw.png)](https://www.diygw.com/)
[![HasChat](https://www.ucharts.cn/images/web/guide/links/haschat.png)](https://gitee.com/howcode/has-chat)
[![uViewUI](https://www.ucharts.cn/images/web/guide/links/uView.png)](https://www.uviewui.com/)
[![图鸟UI](https://www.ucharts.cn/images/web/guide/links/tuniao.png)](https://ext.dcloud.net.cn/plugin?id=7088)
[![thorui](https://www.ucharts.cn/images/web/guide/links/thorui.png)](https://ext.dcloud.net.cn/publisher?id=202)
[![FirstUI](https://www.ucharts.cn/images/web/guide/links/first.png)](https://www.firstui.cn/)
[![nProUI](https://www.ucharts.cn/images/web/guide/links/nPro.png)](https://ext.dcloud.net.cn/plugin?id=5169)
[![GraceUI](https://www.ucharts.cn/images/web/guide/links/grace.png)](https://www.graceui.com/)
## 更新记录
详见官网指南中说明,[点击此处查看](https://www.ucharts.cn/v2/#/guide/index?id=100)
## 相关链接
- [DCloud插件市场地址](https://ext.dcloud.net.cn/plugin?id=271)
- [uCharts官网](https://www.ucharts.cn)
- [DCloud插件市场地址](https://ext.dcloud.net.cn/plugin?id=271)
- [uCharts码云开源托管地址](https://gitee.com/uCharts/uCharts) [![star](https://gitee.com/uCharts/uCharts/badge/star.svg?theme=gvp)](https://gitee.com/uCharts/uCharts/stargazers)
- [图表组件在项目中的应用 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651)
- [uCharts npm开源地址](https://www.ucharts.cn)
- [ECharts官网](https://echarts.apache.org/zh/index.html)
- [ECharts配置手册](https://echarts.apache.org/zh/option.html)
- [`wkiwi`提供的w-loading组件地址](https://ext.dcloud.net.cn/plugin?id=504)
- [图表组件在项目中的应用 ReportPlus数据报表](https://www.ucharts.cn/v2/#/layout/info?id=1)
Monitor-APP/unpackage/dist/dev/app-plus/app-service.js
Diff too large
Monitor-APP/unpackage/dist/dev/app-plus/app-view.js
Diff too large