Преглед на файлове

预警分析模块新增uchart插件,折线图实现

bobo04052021@163.com преди 3 дни
родител
ревизия
b8fc258d30
променени са 32 файла, в които са добавени 14818 реда и са изтрити 3746 реда
  1. 1 1
      .hbuilderx/launch.json
  2. 2 2
      common/service/config.service.js
  3. 4 4
      main.js
  4. 71 0
      pages/component/chart/line.vue
  5. 6 6
      pages/filecenter/filecenter.vue
  6. 935 1322
      pages/gasreport/components/gasImgIdentify.vue
  7. 6 6
      pages/warndata/components/device-detail.vue
  8. 18 236
      pages/warndata/components/dust-detail.vue
  9. 523 770
      pages/warndata/components/fire-detail-ckq.vue
  10. 233 293
      pages/warndata/components/fire-detail-mb.vue
  11. 410 569
      pages/warndata/components/fire-detail-out.vue
  12. 132 344
      pages/warndata/components/vent-detail.vue
  13. 267 193
      pages/warndata/warndata.vue
  14. 320 0
      uni_modules/qiun-data-charts/changelog.md
  15. 1618 0
      uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue
  16. 42 0
      uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue
  17. 162 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue
  18. 170 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue
  19. 173 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue
  20. 222 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue
  21. 229 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue
  22. 36 0
      uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue
  23. 422 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js
  24. 679 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js
  25. 5 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md
  26. 7706 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js
  27. 17 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js
  28. 201 0
      uni_modules/qiun-data-charts/license.md
  29. 80 0
      uni_modules/qiun-data-charts/package.json
  30. 84 0
      uni_modules/qiun-data-charts/readme.md
  31. 22 0
      uni_modules/qiun-data-charts/static/app-plus/echarts.min.js
  32. 22 0
      uni_modules/qiun-data-charts/static/h5/echarts.min.js

+ 1 - 1
.hbuilderx/launch.json

@@ -2,7 +2,7 @@
     "version" : "1.0",
     "configurations" : [
         {
-            "playground" : "custom",
+            "playground" : "standard",
             "type" : "uni-app:app-android"
         },
         {

+ 2 - 2
common/service/config.service.js

@@ -7,13 +7,13 @@ if (process.env.NODE_ENV == "development") {
   // BASE_URL = "http://10.248.135.10:9999"; // 大柳塔进
   // BASE_URL = "http://10.248.135.121:9999"; // 活鸡兔井
   // BASE_URL = "http://10.246.63.125:9999"; // 寸草塔二矿
-  // BASE_URL = "http://10.246.183.35:9999"; // 乌兰木伦
+  BASE_URL = "http://10.246.183.35:9999"; // 乌兰木伦
   // BASE_URL = "http://10.120.120.164:9999"; // 察哈素
   // BASE_URL = "http://182.92.126.35:9999"; // 生产环境
   // BASE_URL = "http://172.16.53.16:9999"; //
   // BASE_URL = "http://10.246.167.205:9999"; //上湾
   // BASE_URL = "http://172.30.157.9:9999"; //元子沟
-  BASE_URL = "http://10.246.167.205:9999"; //上湾
+  // BASE_URL = "http://10.246.167.205:9999"; //上湾
 }
 let staticDomainURL = BASE_URL + "/sys/common/static";
 

+ 4 - 4
main.js

@@ -6,9 +6,8 @@ import tip from "./common/util/tip.js";
 import configService from "./common/service/config.service.js";
 import router from "./common/router";
 import { RouterMount } from "./plugin/uni-simple-router/index.js";
-
-import * as echarts from 'echarts'
-Vue.prototype.$echarts = echarts
+import * as echarts from "echarts";
+Vue.prototype.$echarts = echarts;
 
 // 注册缓存器
 Vue.use(MinCache, { timeout: 6 });
@@ -45,7 +44,8 @@ import filecenter from "./pages/filecenter/filecenter.vue";
 Vue.component("filecenter", filecenter);
 import gasreport from "./pages/gasreport/gasreport.vue";
 Vue.component("gasreport", gasreport);
-
+import LineChart from "./pages/component/chart/line.vue";
+Vue.component("LineChart", LineChart);
 // 自定义组件
 import mySelect from "./components/my-componets/my-select.vue";
 Vue.component("mySelect", mySelect);

+ 71 - 0
pages/component/chart/line.vue

@@ -0,0 +1,71 @@
+<template>
+  <view style="width: 100%; height: 100%">
+    <qiun-data-charts type="line" :opts="opts" :chartData="chartData" />
+  </view>
+</template>
+
+<script>
+import qiunDataCharts from "@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue";
+export default {
+  props: {
+    chartData: { type: Object, default: () => ({}) }, // 图表数据
+    chartOpts: { type: Object, default: () => ({}) }, // 图表配置项
+  },
+  components: { qiunDataCharts },
+  data() {
+    return {
+      opts: {
+        color: [
+          "#1890FF",
+          "#91CB74",
+          "#FAC858",
+          "#EE6666",
+          "#73C0DE",
+          "#3CA272",
+          "#FC8452",
+          "#9A60B4",
+          "#ea7ccc",
+        ],
+        padding: [15, 10, 0, 15],
+        dataLabel: false,
+        enableScroll: false,
+        update: true,
+        duration: 0,
+        animation: false,
+        legend: {},
+        xAxis: {
+          disableGrid: true,
+        },
+        yAxis: {
+          gridType: "dash",
+          dashLength: 2,
+        },
+        extra: {
+          line: {
+            type: "curve",
+            width: 2,
+            activeType: "hollow",
+            linearType: "custom",
+          },
+        },
+      },
+    };
+  },
+  computed: {
+    mergedOpts() {
+      // 合并默认配置与自定义配置
+      return { ...this.opts, ...this.chartOpts };
+    },
+  },
+  onReady() {},
+  methods: {},
+};
+</script>
+
+<style scoped>
+/* 请根据实际需求修改父元素尺寸,组件自动识别宽高 */
+.charts-box {
+  width: 100%;
+  height: 300px;
+}
+</style>

+ 6 - 6
pages/filecenter/filecenter.vue

@@ -5,11 +5,10 @@
       :bgStatusImage="backPic0"
       :bgImage="backPic"
       :safeAreaInsetTop="true"
-      @leftClick="fileTreeShow"
     >
-      <!-- <view class="u-nav-slot" slot="left">
+      <view class="u-nav-slot" slot="left">
         <u-icon name="list" size="20"> </u-icon>
-      </view> -->
+      </view>
     </u-navbar>
     <!-- <view v-if="menushow" class="menupage">
       <FileTreeMenu @menuClick="menuClick"></FileTreeMenu>
@@ -52,6 +51,7 @@
             mode="subsection"
             :current="curNow"
             @change="sectionChange"
+            :active-color="'#4590fe'"
           ></u-subsection>
           <u-list>
             <u-list-item
@@ -325,9 +325,9 @@ export default {
   },
   computed: {},
   methods: {
-    fileTreeShow(e) {
-      this.menushow = !this.menushow;
-    },
+    // fileTreeShow(e) {
+    //   this.menushow = !this.menushow;
+    // },
     menuClick(id) {
       this.menushow = false;
     },

Файловите разлики са ограничени, защото са твърде много
+ 935 - 1322
pages/gasreport/components/gasImgIdentify.vue


+ 6 - 6
pages/warndata/components/device-detail.vue

@@ -345,7 +345,7 @@ export default {
           overflow-y: auto;
 
           .content-tr {
-            height: 32px;
+            height: 80px;
             display: flex;
             justify-content: space-between;
             align-items: center;
@@ -378,11 +378,11 @@ export default {
             }
 
             .td2 {
-              width: 35%;
+              width: 30%;
             }
 
             .td3 {
-              width: 25%;
+              width: 30%;
             }
           }
         }
@@ -392,7 +392,7 @@ export default {
           overflow-y: auto;
 
           .content-tr {
-            height: 32px;
+            height: 80px;
             display: flex;
             justify-content: space-between;
             align-items: center;
@@ -429,11 +429,11 @@ export default {
             }
 
             .td3 {
-              width: 20%;
+              width: 15%;
             }
 
             .td4 {
-              width: 20%;
+              width: 25%;
             }
           }
         }

+ 18 - 236
pages/warndata/components/dust-detail.vue

@@ -38,10 +38,10 @@
           </view>
         </view>
         <view class="top-echart">
-          <canvas
-            :id="`myChart${index}`"
-            :style="{ width: '100%', height: '220px' }"
-          ></canvas>
+          <LineChart
+            :chartData="option"
+            :style="{ width: '100%', height: '180px' }"
+          ></LineChart>
         </view>
       </view>
       <view class="bot-area">
@@ -89,6 +89,7 @@ export default {
   watch: {},
   data() {
     return {
+      option: {},
       timer: "",
       PageCur: "0",
       tabList: [],
@@ -222,7 +223,19 @@ export default {
                   });
                   that.maxY = that.formatRoundNum(max * 1.5);
                   // console.log(that.xData, that.yDataS, that.yDataY, that.yDataN, '000')
-                  that.initChart(index);
+                  this.option = {
+                    categories: this.xData.slice(-3) || [],
+                    series: [
+                      {
+                        name: "预测值",
+                        data: this.yDataY.slice(-3) || [],
+                      },
+                      {
+                        name: "最新值",
+                        data: this.yDataN.slice(-3) || [],
+                      },
+                    ],
+                  };
                 });
               }
             } else {
@@ -313,237 +326,6 @@ export default {
         Math.ceil(interger / Math.pow(10, leng - 1)) * Math.pow(10, leng - 1)
       );
     },
-    //初始化echarts实例
-    initChart(index) {
-      let canvas = document.getElementById(`myChart${index}`);
-      this.myChart = this.$echarts.init(canvas);
-      let option = {
-        grid: {
-          top: "20%",
-          left: "2%",
-          bottom: "4%",
-          right: "2%",
-          containLabel: true,
-        },
-        tooltip: {
-          trigger: "item",
-          backgroundColor: "rgba(0, 0, 0, .6)",
-          textStyle: {
-            color: "#fff",
-            fontSize: 12,
-          },
-        },
-        legend: {
-          // align: 'center',
-          right: "0%",
-          top: "0%",
-          type: "plain",
-          textStyle: {
-            color: "#0eb4fc",
-            fontSize: 12,
-          },
-          // icon:'rect',
-          itemGap: 25,
-          itemWidth: 20,
-          icon: "path://M0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z",
-          data: [
-            {
-              name: "实时值",
-            },
-            {
-              name: "预测值",
-            },
-
-            {
-              name: "最新值",
-            },
-          ],
-        },
-        xAxis: [
-          {
-            type: "category",
-            boundaryGap: false,
-            axisLabel: {
-              // formatter: '{value}',
-              fontSize: 12,
-              margin: 10,
-              textStyle: {
-                color: "#b3b8cc",
-              },
-              formatter: function (params) {
-                let newParamsName = ""; // 最终拼接成的字符串
-                let paramsNameNumber = params.length; // 实际标签的个数
-                let provideNumber = 10; // 每行能显示的字的个数
-                let rowNumber = Math.ceil(paramsNameNumber / provideNumber); // 换行的话,需要显示几行,向上取整
-                /**
-                 * 判断标签的个数是否大于规定的个数, 如果大于,则进行换行处理 如果不大于,即等于或小于,就返回原标签
-                 */
-                // 条件等同于rowNumber>1
-                if (paramsNameNumber > provideNumber) {
-                  /** 循环每一行,p表示行 */
-                  for (var p = 0; p < rowNumber; p++) {
-                    var tempStr = ""; // 表示每一次截取的字符串
-                    var start = p * provideNumber; // 开始截取的位置
-                    var end = start + provideNumber; // 结束截取的位置
-                    // 此处特殊处理最后一行的索引值
-                    if (p == rowNumber - 1) {
-                      // 最后一次不换行
-                      tempStr = params.substring(start, paramsNameNumber);
-                    } else {
-                      // 每一次拼接字符串并换行
-                      tempStr = params.substring(start, end) + "\n";
-                    }
-                    newParamsName += tempStr; // 最终拼成的字符串
-                  }
-                } else {
-                  // 将旧标签的值赋给新标签
-                  newParamsName = params;
-                }
-                //将最终的字符串返回
-                return newParamsName;
-              },
-            },
-            axisLine: {
-              lineStyle: {
-                color: "#f1f5f6",
-              },
-            },
-            axisTick: {
-              show: false,
-            },
-            data: this.xData || [],
-          },
-        ],
-        yAxis: [
-          {
-            boundaryGap: false,
-            type: "value",
-            max: this.maxY,
-            axisLabel: {
-              textStyle: {
-                color: "#b3b8cc",
-              },
-              formatter: "{value}",
-            },
-            name: "(m³/min)",
-            nameTextStyle: {
-              color: "#b3b8cc",
-              fontSize: 12,
-              lineHeight: 0,
-            },
-            splitLine: {
-              lineStyle: {
-                color: "#f1f5f6",
-              },
-            },
-            axisLine: {
-              show: true,
-              lineStyle: {
-                color: "#f1f5f6",
-              },
-            },
-            axisTick: {
-              show: false,
-            },
-          },
-          {
-            boundaryGap: false,
-            type: "value",
-            max: this.maxY,
-            axisLabel: {
-              textStyle: {
-                color: "#b3b8cc",
-              },
-              formatter: "{value}",
-            },
-            name: "(m³/min)",
-            nameTextStyle: {
-              color: "#fff",
-              fontSize: 12,
-              lineHeight: 10,
-            },
-            splitLine: {
-              lineStyle: {
-                color: "#f1f5f6",
-              },
-            },
-            axisLine: {
-              show: true,
-              lineStyle: {
-                color: "#f1f5f6",
-              },
-            },
-            axisTick: {
-              show: false,
-            },
-          },
-        ],
-        series: [
-          {
-            name: "实时值",
-            type: "line",
-            smooth: true,
-            showSymbol: true,
-            symbolSize: 8,
-            zlevel: 3,
-            itemStyle: {
-              color: "#19a3df",
-              borderColor: "#a3c8d8",
-            },
-            lineStyle: {
-              normal: {
-                width: 2,
-                color: "#19a3df",
-              },
-            },
-            data: this.yDataS || [],
-          },
-          {
-            name: "预测值",
-            type: "line",
-            smooth: true,
-            showSymbol: true,
-            symbolSize: 8,
-            zlevel: 3,
-            itemStyle: {
-              color: "#4fffad",
-              borderColor: "#a3c8d8",
-            },
-            lineStyle: {
-              normal: {
-                width: 2,
-                color: "#4fffad",
-              },
-            },
-            data: this.yDataY || [],
-          },
-          {
-            name: "最新值",
-            type: "line",
-            smooth: true,
-            showSymbol: true,
-            symbolSize: 8,
-            zlevel: 3,
-            itemStyle: {
-              color: "#fc8452",
-              borderColor: "#a3c8d8",
-            },
-            lineStyle: {
-              normal: {
-                width: 2,
-                color: "#fc8452",
-              },
-            },
-
-            data: this.yDataN || [],
-          },
-        ],
-      };
-      this.myChart.setOption(option);
-      window.addEventListener("resize", () => {
-        this.myChart.resize();
-      });
-    },
   },
   computed: {},
 };

+ 523 - 770
pages/warndata/components/fire-detail-ckq.vue

@@ -1,811 +1,564 @@
 <template>
-    <view class="fire-detail-ckq">
-        <view class="top-area">
-            <view class="top-card">
-                <view class="card-box" v-for="(item, index) in cardList" :key="index">
-                    <view class="box-item">
-                        <view class="box-val">{{ item.value }}</view>
-                        <view class="box-name">{{ item.name }}</view>
-                    </view>
-                </view>
-            </view>
+  <view class="fire-detail-ckq">
+    <view class="top-area">
+      <view class="top-card">
+        <view class="card-box" v-for="(item, index) in cardList" :key="index">
+          <view class="box-item">
+            <view class="box-val">{{ item.value }}</view>
+            <view class="box-name">{{ item.name }}</view>
+          </view>
         </view>
-        <view class="center-area">
-            <view class="bot-title">
-                <view style="font-weight: bold;">光钎测温系统温度实时监测</view>
+      </view>
+    </view>
+    <view class="center-area">
+      <view class="bot-title">
+        <view style="font-weight: bold">光钎测温系统温度实时监测</view>
+      </view>
+      <view class="echartBox">
+        <LineChart :chartData="option" :style="{ width: '100%' }"></LineChart>
+      </view>
+    </view>
+    <view class="bot-area">
+      <view class="bot-title">
+        <view style="font-weight: bold">束管系统监测</view>
+      </view>
+      <view
+        class="bot-content"
+        v-for="(item, index) in botContentList"
+        :key="index"
+      >
+        <view class="content-title">{{ item.title }}</view>
+        <view class="content-item-box">
+          <view class="content-item">
+            <view class="item-l">
+              <view class="item-value">{{ item.value }}</view>
+              <view class="item-label">浓度</view>
             </view>
-            <view class="echartBox">
-                <canvas id="myChart" :style="{ width: '100%', height: '220px' }"></canvas>
+
+            <view class="item-r">
+              <view class="item-value">{{ item.time }}</view>
+              <view class="item-label">时间</view>
             </view>
+          </view>
         </view>
-        <view class="bot-area">
-            <view class="bot-title">
-                <view style="font-weight: bold;">束管系统监测</view>
-            </view>
-            <view class="bot-content" v-for="(item, index) in botContentList" :key="index">
-                <view class="content-title">{{ item.title }}</view>
-                <view class="content-item-box">
-                    <view class="content-item">
-                        <view class="item-l">
-                            <view class="item-value">{{ item.value }}</view>
-                            <view class="item-label">浓度</view>
-                        </view>
-
-                        <view class="item-r">
-                            <view class="item-value">{{ item.time }}</view>
-                            <view class="item-label">时间</view>
-                        </view>
-                    </view>
-                </view>
-                <view class="echartbox1">
-                    <canvas :id="`myChartH${index}`" :style="{ width: '100%', height: '220px' }"></canvas>
-                </view>
-            </view>
+        <view class="echartbox1">
+          <LineChart
+            v-if="item.title == 'O₂'"
+            :chartData="option1"
+            :style="{
+              width: '100%',
+            }"
+          />
+          <LineChart
+            v-if="item.title == 'C₂H₄'"
+            :chartData="option2"
+            :style="{ width: '100%' }"
+          />
+          <LineChart
+            v-if="item.title == 'CO'"
+            :chartData="option3"
+            :style="{ width: '100%' }"
+          />
+          <LineChart
+            v-if="item.title == 'CH₄'"
+            :chartData="option4"
+            :style="{ width: '100%' }"
+          />
+          <LineChart
+            v-if="item.title == 'CO₂'"
+            :chartData="option5"
+            :style="{ width: '100%' }"
+          />
+          <LineChart
+            v-if="item.title == 'C₂H₂'"
+            :chartData="option6"
+            :style="{ width: '100%' }"
+          />
         </view>
-
+      </view>
     </view>
+  </view>
 </template>
 
 <script>
 import api from "@/api/api";
 export default {
-    name: 'fireDetailCkq',
-    props: {
-        detailCkq: {
-            type: Object,
-            default: () => {
-                return {}
-            }
-        }
+  name: "fireDetailCkq",
+  props: {
+    detailCkq: {
+      type: Object,
+      default: () => {
+        return {};
+      },
     },
-    data() {
-        return {
-            myChart: null,
-            xData: [],
-            yData: [],
-            cardList: [
-                { name: '最高温度()', value: 0 },
-                { name: '最低温度()', value: 0 },
-                { name: '平均温度()', value: 0 },
-                { name: '状态', value: '' },
-                { name: '回风隅角-O2', value: 0 },
-                { name: '回风隅角-CO', value: 0 },
-            ],
-            myChartH: null,
-            legendName: '',
-            axisDw: '',
-            xDataH: [],
-            yDataH: [],
-            botContentList: [
-                { title: 'O₂', value: 0, time: '', address: '' },
-                { title: 'C₂H₄', value: 0, time: '', address: '' },
-                { title: 'CO', value: 0, time: '', address: '' },
-                { title: 'CH₄', value: 0, time: '', address: '' },
-                { title: 'CO₂', value: 0, time: '', address: '' },
-                { title: 'C₂H₂', value: 0, time: '', address: '' },
-            ]
-        };
-    },
-    watch: {
-        detailCkq: {
-            handler(newC, oldC) {
-                console.log(newC, 'newC--------------')
-                let that = this
-                that.xData = []
-                that.yData = []
-                if (JSON.stringify(newC) != '{}') {
-                    if (newC.fiber.length != 0) {
-                        that.cardList[0].value = newC.fiber[0].readData.fmax;
-                        that.cardList[1].value = newC.fiber[0].readData.fmin;
-                        that.cardList[2].value = newC.fiber[0].readData.favg;
-                        that.cardList[3].value = newC.fiber[0].warnFlag ? '报警' : '正常';
-                        JSON.parse(newC.fiber[0].readData.fibreTemperature).forEach((el) => {
-                            that.xData.push(el.pos);
-                            that.yData.push(el.value);
-                        });
-                        that.initChart()
-                    } else {
-                        that.cardList[0].value = '--';
-                        that.cardList[1].value = '--';
-                        that.cardList[2].value = '--';
-                        that.cardList[3].value = '正常';
-                    }
-
-                    if (newC.bundletube.length != 0) {
-                        that.botContentList[0].value = newC.bundletube[0].readData.o2val;
-                        that.botContentList[1].value = newC.bundletube[0].readData.ch2val;
-                        that.botContentList[2].value = newC.bundletube[0].readData.coval;
-                        that.botContentList[3].value = newC.bundletube[0].readData.chval;
-                        that.botContentList[4].value = newC.bundletube[0].readData.co2val;
-                        that.botContentList[5].value = newC.bundletube[0].readData.gasval;
-                        that.botContentList.forEach((el, index) => {
-                            el.time = newC.bundletube[0].readTime;
-                            if (el.title == 'O₂') {
-                                that.xDataH = newC.bundletube[0].history.map(x => x.time)
-                                that.yDataH = newC.bundletube[0].history.map(y => y.o2val)
-                                that.legendName = 'O₂'
-                                that.axisDw = '%'
-                            } else if (el.title == 'C₂H₄') {
-                                that.xDataH = newC.bundletube[0].history.map(x => x.time)
-                                that.yDataH = newC.bundletube[0].history.map(y => y.ch2val)
-                                that.legendName = 'C₂H₄'
-                                that.axisDw = 'ppm'
-                            } else if (el.title == 'CO') {
-                                that.xDataH = newC.bundletube[0].history.map(x => x.time)
-                                that.yDataH = newC.bundletube[0].history.map(y => y.coval)
-                                that.legendName = 'CO'
-                                that.axisDw = 'ppm'
-                            } else if (el.title == 'CH₄') {
-                                that.xDataH = newC.bundletube[0].history.map(x => x.time)
-                                that.yDataH = newC.bundletube[0].history.map(y => y.chval)
-                                that.legendName = 'CH₄'
-                                that.axisDw = 'ppm'
-                            } else if (el.title == 'CO₂') {
-                                that.xDataH = newC.bundletube[0].history.map(x => x.time)
-                                that.yDataH = newC.bundletube[0].history.map(y => y.co2val)
-                                that.legendName = 'CO₂'
-                                that.axisDw = '%'
-                            } else if (el.title == 'C₂H₂') {
-                                that.xDataH = newC.bundletube[0].history.map(x => x.time)
-                                that.yDataH = newC.bundletube[0].history.map(y => y.gasval)
-                                that.legendName = 'C₂H₂'
-                                that.axisDw = 'ppm'
-                            }
-                            that.initChartH(index)
-                        })
-                    } else {
-                        that.botContentList[0].value = '--';
-                        that.botContentList[1].value = '--';
-                        that.botContentList[2].value = '--';
-                        that.botContentList[3].value = '--';
-                        that.botContentList[4].value = '--';
-                        that.botContentList[5].value = '--';
-                        that.botContentList.forEach(el => {
-                            el.time = '--';
-                        })
-                    }
-
-
-                }
-            },
-            immediate: true,
-            deep: true
+  },
+  data() {
+    return {
+      option: {},
+      option1: {},
+      option2: {},
+      option3: {},
+      option4: {},
+      option5: {},
+      option6: {},
+      historyData: [],
+      myChart: null,
+      xData: [],
+      yData: [],
+      cardList: [
+        { name: "最高温度()", value: 0 },
+        { name: "最低温度()", value: 0 },
+        { name: "平均温度()", value: 0 },
+        { name: "状态", value: "" },
+        { name: "回风隅角-O2", value: 0 },
+        { name: "回风隅角-CO", value: 0 },
+      ],
+      myChartH: null,
+      legendName: "",
+      axisDw: "",
+      xDataH: [],
+      yDataH: [],
+      botContentList: [
+        { title: "O₂", value: 0, time: "", address: "" },
+        { title: "C₂H₄", value: 0, time: "", address: "" },
+        { title: "CO", value: 0, time: "", address: "" },
+        { title: "CH₄", value: 0, time: "", address: "" },
+        { title: "CO₂", value: 0, time: "", address: "" },
+        { title: "C₂H₂", value: 0, time: "", address: "" },
+      ],
+    };
+  },
+  watch: {
+    detailCkq: {
+      handler(newC, oldC) {
+        console.log(newC, "newC--------------");
+        let that = this;
+        that.xData = [];
+        that.yData = [];
+        if (JSON.stringify(newC) != "{}") {
+          if (newC.fiber.length != 0) {
+            that.cardList[0].value = newC.fiber[0].readData.fmax;
+            that.cardList[1].value = newC.fiber[0].readData.fmin;
+            that.cardList[2].value = newC.fiber[0].readData.favg;
+            that.cardList[3].value = newC.fiber[0].warnFlag ? "报警" : "正常";
+            JSON.parse(newC.fiber[0].readData.fibreTemperature).forEach(
+              (el) => {
+                that.xData.push(el.pos);
+                that.yData.push(el.value);
+              }
+            );
+            that.initChart();
+          } else {
+            that.cardList[0].value = "--";
+            that.cardList[1].value = "--";
+            that.cardList[2].value = "--";
+            that.cardList[3].value = "正常";
+            that.initChart();
+          }
+          if (newC.bundletube.length != 0) {
+            that.botContentList[0].value = newC.bundletube[0].readData.o2val;
+            that.botContentList[1].value = newC.bundletube[0].readData.ch2val;
+            that.botContentList[2].value = newC.bundletube[0].readData.coval;
+            that.botContentList[3].value = newC.bundletube[0].readData.chval;
+            that.botContentList[4].value = newC.bundletube[0].readData.co2val;
+            that.botContentList[5].value = newC.bundletube[0].readData.gasval;
+            this.historyData = newC.bundletube[0].history || [];
+            that.botContentList.forEach((el, index) => {
+              el.time = newC.bundletube[0].readTime;
+              if (el.title == "O₂") {
+                that.xDataH = newC.bundletube[0].history.map((x) => x.time);
+                that.yDataH = newC.bundletube[0].history.map((y) => y.o2val);
+                that.legendName = "O₂";
+                that.axisDw = "%";
+              } else if (el.title == "C₂H₄") {
+                that.xDataH = newC.bundletube[0].history.map((x) => x.time);
+                that.yDataH = newC.bundletube[0].history.map((y) => y.ch2val);
+                that.legendName = "C₂H₄";
+                that.axisDw = "ppm";
+              } else if (el.title == "CO") {
+                that.xDataH = newC.bundletube[0].history.map((x) => x.time);
+                that.yDataH = newC.bundletube[0].history.map((y) => y.coval);
+                that.legendName = "CO";
+                that.axisDw = "ppm";
+              } else if (el.title == "CH₄") {
+                that.xDataH = newC.bundletube[0].history.map((x) => x.time);
+                that.yDataH = newC.bundletube[0].history.map((y) => y.chval);
+                that.legendName = "CH₄";
+                that.axisDw = "ppm";
+              } else if (el.title == "CO₂") {
+                that.xDataH = newC.bundletube[0].history.map((x) => x.time);
+                that.yDataH = newC.bundletube[0].history.map((y) => y.co2val);
+                that.legendName = "CO₂";
+                that.axisDw = "%";
+              } else if (el.title == "C₂H₂") {
+                that.xDataH = newC.bundletube[0].history.map((x) => x.time);
+                that.yDataH = newC.bundletube[0].history.map((y) => y.gasval);
+                that.legendName = "C₂H₂";
+                that.axisDw = "ppm";
+              }
+              this.initChartH(el);
+            });
+          } else {
+            that.botContentList[0].value = "--";
+            that.botContentList[1].value = "--";
+            that.botContentList[2].value = "--";
+            that.botContentList[3].value = "--";
+            that.botContentList[4].value = "--";
+            that.botContentList[5].value = "--";
+            that.botContentList.forEach((el) => {
+              el.time = "--";
+              that.xData = [];
+              that.yData = [];
+              this.initChartH(el);
+            });
+          }
         }
+      },
+      immediate: true,
+      deep: true,
     },
-    mounted() { },
-    methods: {
-        //初始化echarts实例
-        initChart() {
-            let canvas = document.getElementById('myChart');
-            this.myChart = this.$echarts.init(canvas)
-            let option = {
-                grid: {
-                    top: '20%',
-                    left: '4%',
-                    bottom: '4%',
-                    right: '2%',
-                    containLabel: true,
-                },
-                tooltip: {
-                    trigger: 'item',
-                    backgroundColor: 'rgba(0, 0, 0, .6)',
-                    textStyle: {
-                        color: '#fff',
-                        fontSize: 12,
-                    },
-                },
-                legend: {
-                    // align: 'center',
-                    right: 'center',
-                    top: '0%',
-                    type: 'plain',
-                    textStyle: {
-                        color: '#0eb4fc',
-                        fontSize: 12,
-                    },
-                    // icon:'rect',
-                    itemGap: 25,
-                    itemWidth: 20,
-                    icon: 'path://M0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z',
-                    data: [
-                        {
-                            name: '当前温度',
-                        },
-
-                    ],
-                },
-                xAxis: [
-                    {
-                        type: 'category',
-                        boundaryGap: false,
-                        axisLabel: {
-                            // formatter: '{value}',
-                            fontSize: 12,
-                            margin: 10,
-                            textStyle: {
-                                color: '#b3b8cc',
-                            },
-                            formatter: function (params) {
-                                let newParamsName = ''  // 最终拼接成的字符串
-                                let paramsNameNumber = params.length // 实际标签的个数
-                                let provideNumber = 10  // 每行能显示的字的个数
-                                let rowNumber = Math.ceil(paramsNameNumber / provideNumber) // 换行的话,需要显示几行,向上取整
-                                /**
-                                 * 判断标签的个数是否大于规定的个数, 如果大于,则进行换行处理 如果不大于,即等于或小于,就返回原标签
-                                 */
-                                // 条件等同于rowNumber>1
-                                if (paramsNameNumber > provideNumber) {
-                                    /** 循环每一行,p表示行 */
-                                    for (var p = 0; p < rowNumber; p++) {
-                                        var tempStr = '' // 表示每一次截取的字符串
-                                        var start = p * provideNumber // 开始截取的位置
-                                        var end = start + provideNumber // 结束截取的位置
-                                        // 此处特殊处理最后一行的索引值
-                                        if (p == rowNumber - 1) {
-                                            // 最后一次不换行
-                                            tempStr = params.substring(start, paramsNameNumber)
-                                        } else {
-                                            // 每一次拼接字符串并换行
-                                            tempStr = params.substring(start, end) + '\n'
-                                        }
-                                        newParamsName += tempStr // 最终拼成的字符串
-                                    }
-                                } else {
-                                    // 将旧标签的值赋给新标签
-                                    newParamsName = params
-                                }
-                                //将最终的字符串返回
-                                return newParamsName
-                            }
-                        },
-                        axisLine: {
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                        data: this.xData || [],
-                    },
-                ],
-                yAxis: [
-                    {
-                        boundaryGap: false,
-                        type: 'value',
-                        max: 2000,
-                        axisLabel: {
-                            textStyle: {
-                                color: '#b3b8cc',
-                            },
-                            formatter: '{value}'
-                        },
-                        name: '(­°C)',
-                        nameTextStyle: {
-                            color: '#b3b8cc',
-                            fontSize: 12,
-                            lineHeight: 0,
-                        },
-                        splitLine: {
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisLine: {
-                            show: true,
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                    },
-                    {
-                        boundaryGap: false,
-                        type: 'value',
-                        max: 2000,
-                        axisLabel: {
-                            textStyle: {
-                                color: '#b3b8cc',
-                            },
-                            formatter: '{value}'
-                        },
-                        name: '(­°C)',
-                        nameTextStyle: {
-                            color: '#fff',
-                            fontSize: 12,
-                            lineHeight: 10,
-                        },
-                        splitLine: {
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisLine: {
-                            show: true,
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                    },
-                ],
-                series: [
-                    {
-                        name: '当前温度',
-                        type: 'line',
-                        smooth: true,
-                        showSymbol: true,
-                        symbolSize: 8,
-                        zlevel: 3,
-                        itemStyle: {
-                            color: '#19a3df',
-                            borderColor: '#a3c8d8',
-                        },
-                        lineStyle: {
-                            normal: {
-                                width: 2,
-                                color: '#19a3df',
-                            },
-                        },
-                        data: this.yData || [],
-                    },
-
-                ],
-            };
-            this.myChart.setOption(option)
-            window.addEventListener('resize', () => {
-                this.myChart.resize()
-            })
-
-
-        },
-        initChartH(ind) {
-            let canvas = document.getElementById(`myChartH${ind}`);
-            this.myChartH = this.$echarts.init(canvas)
-            let option = {
-                grid: {
-                    top: '20%',
-                    left: '4%',
-                    bottom: '4%',
-                    right: '2%',
-                    containLabel: true,
-                },
-                tooltip: {
-                    trigger: 'item',
-                    backgroundColor: 'rgba(0, 0, 0, .6)',
-                    textStyle: {
-                        color: '#fff',
-                        fontSize: 12,
-                    },
-                },
-                legend: {
-                    // align: 'center',
-                    right: 'center',
-                    top: '0%',
-                    type: 'plain',
-                    textStyle: {
-                        color: '#0eb4fc',
-                        fontSize: 12,
-                    },
-                    // icon:'rect',
-                    itemGap: 25,
-                    itemWidth: 20,
-                    icon: 'path://M0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z',
-                    data: [
-                        {
-                            name: this.legendName || '',
-                        },
-
-                    ],
-                },
-                xAxis: [
-                    {
-                        type: 'category',
-                        boundaryGap: false,
-                        axisLabel: {
-                            // formatter: '{value}',
-                            fontSize: 12,
-                            margin: 10,
-                            textStyle: {
-                                color: '#b3b8cc',
-                            },
-                            formatter: function (params) {
-                                let newParamsName = ''  // 最终拼接成的字符串
-                                let paramsNameNumber = params.length // 实际标签的个数
-                                let provideNumber = 10  // 每行能显示的字的个数
-                                let rowNumber = Math.ceil(paramsNameNumber / provideNumber) // 换行的话,需要显示几行,向上取整
-                                /**
-                                 * 判断标签的个数是否大于规定的个数, 如果大于,则进行换行处理 如果不大于,即等于或小于,就返回原标签
-                                 */
-                                // 条件等同于rowNumber>1
-                                if (paramsNameNumber > provideNumber) {
-                                    /** 循环每一行,p表示行 */
-                                    for (var p = 0; p < rowNumber; p++) {
-                                        var tempStr = '' // 表示每一次截取的字符串
-                                        var start = p * provideNumber // 开始截取的位置
-                                        var end = start + provideNumber // 结束截取的位置
-                                        // 此处特殊处理最后一行的索引值
-                                        if (p == rowNumber - 1) {
-                                            // 最后一次不换行
-                                            tempStr = params.substring(start, paramsNameNumber)
-                                        } else {
-                                            // 每一次拼接字符串并换行
-                                            tempStr = params.substring(start, end) + '\n'
-                                        }
-                                        newParamsName += tempStr // 最终拼成的字符串
-                                    }
-                                } else {
-                                    // 将旧标签的值赋给新标签
-                                    newParamsName = params
-                                }
-                                //将最终的字符串返回
-                                return newParamsName
-                            }
-                        },
-                        axisLine: {
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                        data: this.xDataH || [],
-                    },
-                ],
-                yAxis: [
-                    {
-                        boundaryGap: false,
-                        type: 'value',
-                        max: 50,
-                        axisLabel: {
-                            textStyle: {
-                                color: '#b3b8cc',
-                            },
-                            formatter: '{value}'
-                        },
-                        name: `(${this.axisDw})`,
-                        nameTextStyle: {
-                            color: '#b3b8cc',
-                            fontSize: 12,
-                            lineHeight: 0,
-                        },
-                        splitLine: {
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisLine: {
-                            show: true,
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                    },
-                    {
-                        boundaryGap: false,
-                        type: 'value',
-                        max: 50,
-                        axisLabel: {
-                            textStyle: {
-                                color: '#b3b8cc',
-                            },
-                            formatter: '{value}'
-                        },
-                        name: `(${this.axisDw})`,
-                        nameTextStyle: {
-                            color: '#fff',
-                            fontSize: 12,
-                            lineHeight: 10,
-                        },
-                        splitLine: {
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisLine: {
-                            show: true,
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                    },
-                ],
-                series: [
-                    {
-                        name: this.legendName || '',
-                        type: 'line',
-                        smooth: true,
-                        showSymbol: true,
-                        symbolSize: 8,
-                        zlevel: 3,
-                        itemStyle: {
-                            color: '#19a3df',
-                            borderColor: '#a3c8d8',
-                        },
-                        lineStyle: {
-                            normal: {
-                                width: 2,
-                                color: '#19a3df',
-                            },
-                        },
-                        data: this.yDataH || [],
-                    },
-
-                ],
-            };
-            this.myChartH.setOption(option)
-            window.addEventListener('resize', () => {
-                this.myChartH.resize()
-            })
-
-
-        },
+  },
+  mounted() {},
+  methods: {
+    //初始化echarts实例
+    initChart() {
+      this.option = {
+        categories: this.xData.slice(-10) || [],
+        series: [
+          {
+            name: "当前温度",
+            data: this.yData.slice(-10) || [],
+          },
+        ],
+      };
     },
-    computed: {
-
+    initChartH(el) {
+      switch (el.title) {
+        case "O₂":
+          return (this.option1 = {
+            categories: this.xDataH.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yDataH.slice(-3) || [],
+              },
+            ],
+          });
+        case "C₂H₄":
+          return (this.option2 = {
+            categories: this.xDataH.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yDataH.slice(-3) || [],
+              },
+            ],
+          });
+        case "CO":
+          return (this.option3 = {
+            categories: this.xDataH.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yDataH.slice(-3) || [],
+              },
+            ],
+          });
+        case "CH₄":
+          return (this.option4 = {
+            categories: this.xDataH.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yDataH.slice(-3) || [],
+              },
+            ],
+          });
+        case "CO₂":
+          return (this.option5 = {
+            categories: this.xDataH.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yDataH.slice(-3) || [],
+              },
+            ],
+          });
+        case "C₂H₂":
+          return (this.option6 = {
+            categories: this.xDataH.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yDataH.slice(-3) || [],
+              },
+            ],
+          });
+      }
     },
+  },
+  computed: {},
 };
 </script>
 
 <style lang="scss" scoped>
 .fire-detail-ckq {
-    width: 100%;
-    height: 100%;
+  width: 100%;
+  height: 100%;
 
-    // box-sizing: border-box;
-    // overflow-y: auto;
-    .top-area {
-        width: 100%;
-        padding: 10px;
-        background-color: #FFF;
-        margin-bottom: 2px;
-        box-sizing: border-box;
+  // box-sizing: border-box;
+  // overflow-y: auto;
+  .top-area {
+    width: 100%;
+    padding: 10px;
+    background-color: #fff;
+    margin-bottom: 2px;
+    box-sizing: border-box;
+
+    .top-card {
+      width: 100%;
+      display: flex;
+      justify-content: flex-start;
+      align-items: flex-start;
+      flex-wrap: wrap;
+
+      .card-box {
+        width: 31.5%;
+        height: 60px;
+        border-radius: 5px;
+        background: linear-gradient(
+          to right,
+          rgba(55, 135, 254, 0.08),
+          rgba(4, 184, 255, 0.08),
+          rgba(60, 161, 237, 0.08)
+        );
+
+        &:nth-child(1) {
+          margin-bottom: 10px;
+        }
 
-        .top-card {
-            width: 100%;
-            display: flex;
-            justify-content: flex-start;
-            align-items: flex-start;
-            flex-wrap: wrap;
-
-            .card-box {
-                width: 31.5%;
-                height: 60px;
-                border-radius: 5px;
-                background: linear-gradient(to right, rgba(55, 135, 254, 0.08), rgba(4, 184, 255, 0.08), rgba(60, 161, 237, 0.08));
-
-                &:nth-child(1) {
-                    margin-bottom: 10px;
-                }
-
-                &:nth-child(2) {
-                    margin-bottom: 10px;
-                    margin-left: 10px;
-                    margin-right: 10px;
-                }
-
-                &:nth-child(3) {
-                    margin-bottom: 10px;
-                }
-
-                &:nth-child(5) {
-                    margin-left: 10px;
-                    margin-right: 10px;
-                }
-            }
-
-            .card-box:nth-child(1) .box-item {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: flex-start;
-                width: 100%;
-                height: 100%;
-                padding: 0px 15px;
-                background: url('/static/zgwd.png') no-repeat right;
-                background-size: 40% 80%;
-            }
-
-            .card-box:nth-child(2) .box-item {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: flex-start;
-                width: 100%;
-                height: 100%;
-                padding: 0px 15px;
-                background: url('/static/zdwd.png') no-repeat right;
-                background-size: 40% 80%;
-            }
-
-            .card-box:nth-child(3) .box-item {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: flex-start;
-                width: 100%;
-                height: 100%;
-                padding: 0px 15px;
-                background: url('/static/pjwd.png') no-repeat right;
-                background-size: 40% 80%;
-            }
-
-            .card-box:nth-child(4) .box-item {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: flex-start;
-                width: 100%;
-                height: 100%;
-                padding: 0px 15px;
-                background: url('/static/zt.png') no-repeat right;
-                background-size: 40% 80%;
-            }
-
-            .card-box:nth-child(5) .box-item {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: flex-start;
-                width: 100%;
-                height: 100%;
-                padding: 0px 15px;
-                background: url('/static/O₂.png') no-repeat right;
-                background-size: 40% 80%;
-            }
-
-            .card-box:nth-child(6) .box-item {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: flex-start;
-                width: 100%;
-                height: 100%;
-                padding: 0px 15px;
-                background: url('/static/CO.png') no-repeat right;
-                background-size: 40% 80%;
-            }
+        &:nth-child(2) {
+          margin-bottom: 10px;
+          margin-left: 10px;
+          margin-right: 10px;
         }
 
-        .box-item .box-val {
-            height: 28px;
-            line-height: 28px;
-            color: #0eb4fc;
-            font-weight: bold;
+        &:nth-child(3) {
+          margin-bottom: 10px;
         }
 
-        .box-item .box-name {
-            font-size: 12px;
+        &:nth-child(5) {
+          margin-left: 10px;
+          margin-right: 10px;
         }
-    }
+      }
 
-    .center-area {
+      .card-box:nth-child(1) .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
         width: 100%;
-        padding: 10px;
-        background-color: #FFF;
-        margin-bottom: 2px;
-        box-sizing: border-box;
-
-        .bot-title {
-            height: 28px;
-            margin-bottom: 5px;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-        }
+        height: 100%;
+        padding: 0px 15px;
+        background: url("/static/zgwd.png") no-repeat right;
+        background-size: 40% 80%;
+      }
+
+      .card-box:nth-child(2) .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
+        width: 100%;
+        height: 100%;
+        padding: 0px 15px;
+        background: url("/static/zdwd.png") no-repeat right;
+        background-size: 40% 80%;
+      }
+
+      .card-box:nth-child(3) .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
+        width: 100%;
+        height: 100%;
+        padding: 0px 15px;
+        background: url("/static/pjwd.png") no-repeat right;
+        background-size: 40% 80%;
+      }
+
+      .card-box:nth-child(4) .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
+        width: 100%;
+        height: 100%;
+        padding: 0px 15px;
+        background: url("/static/zt.png") no-repeat right;
+        background-size: 40% 80%;
+      }
+
+      .card-box:nth-child(5) .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
+        width: 100%;
+        height: 100%;
+        padding: 0px 15px;
+        background: url("/static/O₂.png") no-repeat right;
+        background-size: 40% 80%;
+      }
+
+      .card-box:nth-child(6) .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
+        width: 100%;
+        height: 100%;
+        padding: 0px 15px;
+        background: url("/static/CO.png") no-repeat right;
+        background-size: 40% 80%;
+      }
+    }
 
-        .echartBox {
-            width: 100%;
-            height: 220px;
-        }
+    .box-item .box-val {
+      height: 28px;
+      line-height: 28px;
+      color: #0eb4fc;
+      font-weight: bold;
     }
 
-    .bot-area {
-        width: 100%;
-        padding: 0px 10px;
-        background-color: #FFF;
-        margin-bottom: 2px;
-        box-sizing: border-box;
-
-        .bot-title {
-            height: 28px;
-            margin-bottom: 5px;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-        }
+    .box-item .box-name {
+      font-size: 12px;
+    }
+  }
 
-        .bot-content {
-            margin-bottom: 15px;
-
-            .content-title {
-                height: 26px;
-                line-height: 26px;
-                padding: 0px 20px;
-                font-size: 12px;
-                background: url('/static/warndata/title.png') no-repeat;
-                background-size: 100% 100%;
-            }
-
-            .content-item-box {
-                padding: 5px 0px;
-
-                .content-item {
-                    height: 50px;
-                    display: flex;
-                    justify-content: space-between;
-                    align-items: center;
-                    // background: linear-gradient(to right, rgba(55, 135, 254, 0.08), rgba(4, 184, 255, 0.08), rgba(60, 161, 237, 0.08));
-                    // border-radius: 10px;
-                    margin-bottom: 5px;
-
-                    .item-l {
-                        width: calc(50% - 10px);
-                        height: 100%;
-                        display: flex;
-                        flex-direction: column;
-                        justify-content: center;
-                        align-items: flex-start;
-                        border-radius: 10px;
-                        padding: 0px 15px;
-                        background: url('/static/nd.png'), linear-gradient(to right, rgba(55, 135, 254, 0.08), rgba(4, 184, 255, 0.08), rgba(60, 161, 237, 0.08));
-                        background-size: auto 100%;
-                        background-position: right;
-                        background-repeat: no-repeat;
-                    }
-
-
-
-                    .item-r {
-                        width: calc(50% - 10px);
-                        height: 100%;
-                        display: flex;
-                        flex-direction: column;
-                        justify-content: center;
-                        align-items: flex-start;
-                        border-radius: 10px;
-                        padding: 0px 15px;
-                        background: url('/static/time.png'), linear-gradient(to right, rgba(55, 135, 254, 0.08), rgba(4, 184, 255, 0.08), rgba(60, 161, 237, 0.08));
-                        background-size: auto 100%;
-                        background-position: right;
-                        background-repeat: no-repeat;
-                    }
-
-                    .item-value {
-                        height: 20px;
-                        line-height: 20px;
-                        color: #0eb4fc;
-                        font-weight: bold;
-                    }
-
-                    .item-label {
-                        font-size: 12px;
-                    }
-                }
-
-
-            }
-
-            .echartbox1 {
-                width: 100%;
-                height: 220px;
-                margin-bottom: 10px;
-            }
-        }
+  .center-area {
+    width: 100%;
+    padding: 10px;
+    background-color: #fff;
+    margin-bottom: 2px;
+    box-sizing: border-box;
+
+    .bot-title {
+      height: 28px;
+      margin-bottom: 5px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+
+    .echartBox {
+      width: 100%;
+      height: 220px;
+    }
+  }
+
+  .bot-area {
+    width: 100%;
+    padding: 0px 10px;
+    background-color: #fff;
+    margin-bottom: 2px;
+    box-sizing: border-box;
+
+    .bot-title {
+      height: 28px;
+      margin-bottom: 5px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
     }
 
+    .bot-content {
+      margin-bottom: 15px;
+
+      .content-title {
+        height: 26px;
+        line-height: 26px;
+        padding: 0px 20px;
+        font-size: 12px;
+        background: url("/static/warndata/title.png") no-repeat;
+        background-size: 100% 100%;
+      }
+
+      .content-item-box {
+        padding: 5px 0px;
+
+        .content-item {
+          height: 50px;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          // background: linear-gradient(to right, rgba(55, 135, 254, 0.08), rgba(4, 184, 255, 0.08), rgba(60, 161, 237, 0.08));
+          // border-radius: 10px;
+          margin-bottom: 5px;
+
+          .item-l {
+            width: calc(50% - 10px);
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: flex-start;
+            border-radius: 10px;
+            padding: 0px 15px;
+            background: url("/static/nd.png"),
+              linear-gradient(
+                to right,
+                rgba(55, 135, 254, 0.08),
+                rgba(4, 184, 255, 0.08),
+                rgba(60, 161, 237, 0.08)
+              );
+            background-size: auto 100%;
+            background-position: right;
+            background-repeat: no-repeat;
+          }
+
+          .item-r {
+            width: calc(50% - 10px);
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: flex-start;
+            border-radius: 10px;
+            padding: 0px 15px;
+            background: url("/static/time.png"),
+              linear-gradient(
+                to right,
+                rgba(55, 135, 254, 0.08),
+                rgba(4, 184, 255, 0.08),
+                rgba(60, 161, 237, 0.08)
+              );
+            background-size: auto 100%;
+            background-position: right;
+            background-repeat: no-repeat;
+          }
+
+          .item-value {
+            height: 20px;
+            line-height: 20px;
+            color: #0eb4fc;
+            font-weight: bold;
+          }
 
+          .item-label {
+            font-size: 12px;
+          }
+        }
+      }
 
+      .echartbox1 {
+        width: 100%;
+        height: 220px;
+        margin-bottom: 10px;
+      }
+    }
+  }
 }
 </style>

+ 233 - 293
pages/warndata/components/fire-detail-mb.vue

@@ -21,9 +21,13 @@
     </view>
     <view class="bot-area">
       <view class="bot-title">
-        <view style="font-weight: bold;">采空区密闭参数</view>
+        <view style="font-weight: bold">采空区密闭参数</view>
       </view>
-      <view class="bot-content" v-for="(item, index) in botContentList" :key="index">
+      <view
+        class="bot-content"
+        v-for="(item, index) in botContentList"
+        :key="index"
+      >
         <view class="content-title">{{ item.title }}</view>
         <view class="content-item-box">
           <view class="content-item">
@@ -44,87 +48,129 @@
           </view>
         </view>
         <view class="echartbox1">
-          <canvas :id="`myChart${index}`" :style="{ width: '100%', height: '220px' }"></canvas>
+          <LineChart
+            v-if="item.title == 'O₂'"
+            :chartData="option1"
+            :style="{
+              width: '100%',
+            }"
+          />
+          <LineChart
+            v-if="item.title == 'C₂H₄'"
+            :chartData="option2"
+            :style="{ width: '100%' }"
+          />
+          <LineChart
+            v-if="item.title == 'CO'"
+            :chartData="option3"
+            :style="{ width: '100%' }"
+          />
+          <LineChart
+            v-if="item.title == 'CH₄'"
+            :chartData="option4"
+            :style="{ width: '100%' }"
+          />
+          <LineChart
+            v-if="item.title == 'CO₂'"
+            :chartData="option5"
+            :style="{ width: '100%' }"
+          />
+          <LineChart
+            v-if="item.title == 'C₂H₂'"
+            :chartData="option6"
+            :style="{ width: '100%' }"
+          />
         </view>
         <view class="echartbox2">
-          <warnZb :resetIndex="index" :widthV="widthV" :heightV="heightV" :coordDw="coordDw" :widthCanvas="widthCanvas"
-            :heightCanvas="heightCanvas" :warnLevel="warnLevel"></warnZb>
+          <warnZb
+            :resetIndex="index"
+            :widthV="widthV"
+            :heightV="heightV"
+            :coordDw="coordDw"
+            :widthCanvas="widthCanvas"
+            :heightCanvas="heightCanvas"
+            :warnLevel="warnLevel"
+          ></warnZb>
         </view>
       </view>
     </view>
   </view>
-
-
-
 </template>
 
 <script>
 import api from "@/api/api";
-import warnZb from './warn-zb.vue'
+import warnZb from "./warn-zb.vue";
 export default {
-  name: 'fireDetailMb',
+  name: "fireDetailMb",
   components: {
-    warnZb
+    warnZb,
   },
   props: {
     detailMb: {
       type: Object,
       default: () => {
-        return {}
-      }
-    }
+        return {};
+      },
+    },
   },
   data() {
     return {
-      widthV: '85%',
-      heightV: '85%',
+      option1: {},
+      option2: {},
+      option3: {},
+      option4: {},
+      option5: {},
+      option6: {},
+      widthV: "85%",
+      heightV: "85%",
       coordDw: [16, 42],
-      widthCanvas: '302px',
-      heightCanvas: '194px',
+      widthCanvas: "302px",
+      heightCanvas: "194px",
       myChart: null,
       xData: [],
       yData: [],
-      legendName: '',
-      axisDw: '',
+      legendName: "",
+      axisDw: "",
       cardList: [
-        { name: '平均温度()', value: 0 },
-        { name: '位置', value: '' },
-        { name: '时间', value: '' },
-
+        { name: "平均温度()", value: 0 },
+        { name: "位置", value: "" },
+        { name: "时间", value: "" },
       ],
       cardList1: [
-        { name: '煤自燃阶段', value: '' },
-        { name: '预警等级', value: '' },
+        { name: "煤自燃阶段", value: "" },
+        { name: "预警等级", value: "" },
       ],
       botContentList: [
-        { title: 'O₂', value: 0, time: '', address: '' },
-        { title: 'C₂H₄', value: 0, time: '', address: '' },
-        { title: 'CO', value: 0, time: '', address: '' },
-        { title: 'CH₄', value: 0, time: '', address: '' },
-        { title: 'CO₂', value: 0, time: '', address: '' },
-        { title: 'C₂H₂', value: 0, time: '', address: '' },
-      ]
+        { title: "O₂", value: 0, time: "", address: "" },
+        { title: "C₂H₄", value: 0, time: "", address: "" },
+        { title: "CO", value: 0, time: "", address: "" },
+        { title: "CH₄", value: 0, time: "", address: "" },
+        { title: "CO₂", value: 0, time: "", address: "" },
+        { title: "C₂H₂", value: 0, time: "", address: "" },
+      ],
     };
   },
   computed: {
     warnLevel: function () {
-      return this.cardList1[1].value
-    }
+      return this.cardList1[1].value;
+    },
   },
   watch: {
     detailMb: {
       handler(newM, oldM) {
-        console.log(newM, 'newM--------------')
-        let that = this
-        that.xData = []
-        that.yData = []
-        if (JSON.stringify(newM) != '{}') {
+        console.log(newM, "newM--------------");
+        let that = this;
+        that.xData = [];
+        that.yData = [];
+        if (JSON.stringify(newM) != "{}") {
           if (newM.bundletube.length != 0) {
-            that.cardList[0].value = newM.temperature[0] ? newM.temperature[0].readData.temperature : '--';
-            that.cardList[1].value = newM.bundletube[0].strinstallpos || '--';
-            that.cardList[2].value = newM.bundletube[0].readTime || '--';
-            that.cardList1[0].value = newM.bundletube[0].syswarnLevel_des
-            that.cardList1[1].value = newM.bundletube[0].syswarnLevel_str
+            that.cardList[0].value = newM.temperature[0]
+              ? newM.temperature[0].readData.temperature
+              : "--";
+            that.cardList[1].value = newM.bundletube[0].strinstallpos || "--";
+            that.cardList[2].value = newM.bundletube[0].readTime || "--";
+            that.cardList1[0].value = newM.bundletube[0].syswarnLevel_des;
+            that.cardList1[1].value = newM.bundletube[0].syswarnLevel_str;
 
             that.botContentList[0].value = newM.bundletube[0].readData.o2val;
             that.botContentList[1].value = newM.bundletube[0].readData.ch2val;
@@ -135,256 +181,132 @@ export default {
             that.botContentList.forEach((el, index) => {
               el.time = newM.bundletube[0].readTime;
               el.address = newM.bundletube[0].strinstallpos;
-              if (el.title == 'O₂') {
-                that.xData = newM.bundletube[0].history.map(x => x.time)
-                that.yData = newM.bundletube[0].history.map(y => y.o2val)
-                that.legendName = 'O₂'
-                that.axisDw = '%'
-              } else if (el.title == 'C₂H₄') {
-                that.xData = newM.bundletube[0].history.map(x => x.time)
-                that.yData = newM.bundletube[0].history.map(y => y.ch2val)
-                that.legendName = 'C₂H₄'
-                that.axisDw = 'ppm'
-              } else if (el.title == 'CO') {
-                that.xData = newM.bundletube[0].history.map(x => x.time)
-                that.yData = newM.bundletube[0].history.map(y => y.coval)
-                that.legendName = 'CO'
-                that.axisDw = 'ppm'
-              } else if (el.title == 'CH₄') {
-                that.xData = newM.bundletube[0].history.map(x => x.time)
-                that.yData = newM.bundletube[0].history.map(y => y.chval)
-                that.legendName = 'CH₄'
-                that.axisDw = 'ppm'
-              } else if (el.title == 'CO₂') {
-                that.xData = newM.bundletube[0].history.map(x => x.time)
-                that.yData = newM.bundletube[0].history.map(y => y.co2val)
-                that.legendName = 'CO₂'
-                that.axisDw = '%'
-              } else if (el.title == 'C₂H₂') {
-                that.xData = newM.bundletube[0].history.map(x => x.time)
-                that.yData = newM.bundletube[0].history.map(y => y.gasval)
-                that.legendName = 'C₂H₂'
-                that.axisDw = 'ppm'
+              if (el.title == "O₂") {
+                that.xData = newM.bundletube[0].history.map((x) => x.time);
+                that.yData = newM.bundletube[0].history.map((y) => y.o2val);
+                that.legendName = "O₂";
+                that.axisDw = "%";
+              } else if (el.title == "C₂H₄") {
+                that.xData = newM.bundletube[0].history.map((x) => x.time);
+                that.yData = newM.bundletube[0].history.map((y) => y.ch2val);
+                that.legendName = "C₂H₄";
+                that.axisDw = "ppm";
+              } else if (el.title == "CO") {
+                that.xData = newM.bundletube[0].history.map((x) => x.time);
+                that.yData = newM.bundletube[0].history.map((y) => y.coval);
+                that.legendName = "CO";
+                that.axisDw = "ppm";
+              } else if (el.title == "CH₄") {
+                that.xData = newM.bundletube[0].history.map((x) => x.time);
+                that.yData = newM.bundletube[0].history.map((y) => y.chval);
+                that.legendName = "CH₄";
+                that.axisDw = "ppm";
+              } else if (el.title == "CO₂") {
+                that.xData = newM.bundletube[0].history.map((x) => x.time);
+                that.yData = newM.bundletube[0].history.map((y) => y.co2val);
+                that.legendName = "CO₂";
+                that.axisDw = "%";
+              } else if (el.title == "C₂H₂") {
+                that.xData = newM.bundletube[0].history.map((x) => x.time);
+                that.yData = newM.bundletube[0].history.map((y) => y.gasval);
+                that.legendName = "C₂H₂";
+                that.axisDw = "ppm";
               }
-              that.initChart(index)
-            })
+              that.initChartH(el);
+            });
           } else {
             that.cardList[0].value = 0;
-            that.cardList[1].value = '--';
-            that.cardList[2].value = '--';
-            that.cardList1[0].value = '--'
-            that.cardList1[1].value = '--'
-
-            that.botContentList[0].value = '--';
-            that.botContentList[1].value = '--';
-            that.botContentList[2].value = '--';
-            that.botContentList[3].value = '--';
-            that.botContentList[4].value = '--';
-            that.botContentList[5].value = '--';
+            that.cardList[1].value = "--";
+            that.cardList[2].value = "--";
+            that.cardList1[0].value = "--";
+            that.cardList1[1].value = "--";
+
+            that.botContentList[0].value = "--";
+            that.botContentList[1].value = "--";
+            that.botContentList[2].value = "--";
+            that.botContentList[3].value = "--";
+            that.botContentList[4].value = "--";
+            that.botContentList[5].value = "--";
+            that.botContentList.forEach((el, index) => {
+              el.time = "--";
+              that.xData = [];
+              that.yData = [];
+              that.initChartH(el);
+            });
           }
-
-
         }
       },
       immediate: true,
-      deep: true
-    }
-  },
-  mounted() {
-
+      deep: true,
+    },
   },
+  mounted() {},
   methods: {
-    initChart(ind) {
-      let canvas = document.getElementById(`myChart${ind}`);
-      this.myChart = this.$echarts.init(canvas)
-      let option = {
-        grid: {
-          top: '20%',
-          left: '4%',
-          bottom: '4%',
-          right: '2%',
-          containLabel: true,
-        },
-        tooltip: {
-          trigger: 'item',
-          backgroundColor: 'rgba(0, 0, 0, .6)',
-          textStyle: {
-            color: '#fff',
-            fontSize: 12,
-          },
-        },
-        legend: {
-          // align: 'center',
-          right: 'center',
-          top: '0%',
-          type: 'plain',
-          textStyle: {
-            color: '#0eb4fc',
-            fontSize: 12,
-          },
-          // icon:'rect',
-          itemGap: 25,
-          itemWidth: 20,
-          icon: 'path://M0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z',
-          data: [
-            {
-              name: this.legendName || '',
-            },
-
-          ],
-        },
-        xAxis: [
-          {
-            type: 'category',
-            boundaryGap: false,
-            axisLabel: {
-              // formatter: '{value}',
-              fontSize: 12,
-              margin: 10,
-              textStyle: {
-                color: '#b3b8cc',
-              },
-              formatter: function (params) {
-                let newParamsName = ''  // 最终拼接成的字符串
-                let paramsNameNumber = params.length // 实际标签的个数
-                let provideNumber = 10  // 每行能显示的字的个数
-                let rowNumber = Math.ceil(paramsNameNumber / provideNumber) // 换行的话,需要显示几行,向上取整
-                /**
-                 * 判断标签的个数是否大于规定的个数, 如果大于,则进行换行处理 如果不大于,即等于或小于,就返回原标签
-                 */
-                // 条件等同于rowNumber>1
-                if (paramsNameNumber > provideNumber) {
-                  /** 循环每一行,p表示行 */
-                  for (var p = 0; p < rowNumber; p++) {
-                    var tempStr = '' // 表示每一次截取的字符串
-                    var start = p * provideNumber // 开始截取的位置
-                    var end = start + provideNumber // 结束截取的位置
-                    // 此处特殊处理最后一行的索引值
-                    if (p == rowNumber - 1) {
-                      // 最后一次不换行
-                      tempStr = params.substring(start, paramsNameNumber)
-                    } else {
-                      // 每一次拼接字符串并换行
-                      tempStr = params.substring(start, end) + '\n'
-                    }
-                    newParamsName += tempStr // 最终拼成的字符串
-                  }
-                } else {
-                  // 将旧标签的值赋给新标签
-                  newParamsName = params
-                }
-                //将最终的字符串返回
-                return newParamsName
-              }
-            },
-            axisLine: {
-              lineStyle: {
-                color: '#f1f5f6',
-              },
-            },
-            axisTick: {
-              show: false,
-            },
-            data: this.xData || [],
-          },
-        ],
-        yAxis: [
-          {
-            boundaryGap: false,
-            type: 'value',
-            max: 50,
-            axisLabel: {
-              textStyle: {
-                color: '#b3b8cc',
+    initChartH(el) {
+      switch (el.title) {
+        case "O₂":
+          return (this.option1 = {
+            categories: this.xData.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yData.slice(-3) || [],
               },
-              formatter: '{value}'
-            },
-            name: `(${this.axisDw})`,
-            nameTextStyle: {
-              color: '#b3b8cc',
-              fontSize: 12,
-              lineHeight: 0,
-            },
-            splitLine: {
-              lineStyle: {
-                color: '#f1f5f6',
+            ],
+          });
+        case "C₂H₄":
+          return (this.option2 = {
+            categories: this.xData.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yData.slice(-3) || [],
               },
-            },
-            axisLine: {
-              show: true,
-              lineStyle: {
-                color: '#f1f5f6',
+            ],
+          });
+        case "CO":
+          return (this.option3 = {
+            categories: this.xData.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yData.slice(-3) || [],
               },
-            },
-            axisTick: {
-              show: false,
-            },
-          },
-          {
-            boundaryGap: false,
-            type: 'value',
-            max: 50,
-            axisLabel: {
-              textStyle: {
-                color: '#b3b8cc',
+            ],
+          });
+        case "CH₄":
+          return (this.option4 = {
+            categories: this.xData.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yData.slice(-3) || [],
               },
-              formatter: '{value}'
-            },
-            name: `(${this.axisDw})`,
-            nameTextStyle: {
-              color: '#fff',
-              fontSize: 12,
-              lineHeight: 10,
-            },
-            splitLine: {
-              lineStyle: {
-                color: '#f1f5f6',
+            ],
+          });
+        case "CO₂":
+          return (this.option5 = {
+            categories: this.xData.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yData.slice(-3) || [],
               },
-            },
-            axisLine: {
-              show: true,
-              lineStyle: {
-                color: '#f1f5f6',
+            ],
+          });
+        case "C₂H₂":
+          return (this.option6 = {
+            categories: this.xData.slice(-3) || [],
+            series: [
+              {
+                name: el.title,
+                data: this.yData.slice(-3) || [],
               },
-            },
-            axisTick: {
-              show: false,
-            },
-          },
-        ],
-        series: [
-          {
-            name: this.legendName || '',
-            type: 'line',
-            smooth: true,
-            showSymbol: true,
-            symbolSize: 8,
-            zlevel: 3,
-            itemStyle: {
-              color: '#19a3df',
-              borderColor: '#a3c8d8',
-            },
-            lineStyle: {
-              normal: {
-                width: 2,
-                color: '#19a3df',
-              },
-            },
-            data: this.yData || [],
-          },
-
-        ],
-      };
-      this.myChart.setOption(option)
-      window.addEventListener('resize', () => {
-        this.myChart.resize()
-      })
-
-
+            ],
+          });
+      }
     },
-
   },
-
 };
 </script>
 
@@ -398,7 +320,7 @@ export default {
   .top-area {
     width: 100%;
     padding: 10px;
-    background-color: #FFF;
+    background-color: #fff;
     margin-bottom: 2px;
     box-sizing: border-box;
 
@@ -414,7 +336,12 @@ export default {
         width: 32%;
         height: 100%;
         border-radius: 5px;
-        background: linear-gradient(to right, rgba(55, 135, 254, 0.08), rgba(4, 184, 255, 0.08), rgba(60, 161, 237, 0.08));
+        background: linear-gradient(
+          to right,
+          rgba(55, 135, 254, 0.08),
+          rgba(4, 184, 255, 0.08),
+          rgba(60, 161, 237, 0.08)
+        );
       }
 
       .card-box:nth-child(1) .box-item {
@@ -425,7 +352,7 @@ export default {
         width: 100%;
         height: 100%;
         padding: 0px 15px;
-        background: url('/static/address.png') no-repeat right;
+        background: url("/static/address.png") no-repeat right;
         background-size: 40% 80%;
       }
 
@@ -437,7 +364,7 @@ export default {
         width: 100%;
         height: 100%;
         padding: 0px 15px;
-        background: url('/static/pjwd.png') no-repeat right;
+        background: url("/static/pjwd.png") no-repeat right;
         background-size: 40% 80%;
       }
 
@@ -449,7 +376,7 @@ export default {
         width: 100%;
         height: 100%;
         padding: 0px 15px;
-        background: url('/static/yjdj.png') no-repeat right;
+        background: url("/static/yjdj.png") no-repeat right;
         background-size: 40% 80%;
       }
     }
@@ -465,8 +392,12 @@ export default {
         width: 49%;
         height: 100%;
         border-radius: 5px;
-        background: linear-gradient(to right, rgba(55, 135, 254, 0.08), rgba(4, 184, 255, 0.08), rgba(60, 161, 237, 0.08));
-
+        background: linear-gradient(
+          to right,
+          rgba(55, 135, 254, 0.08),
+          rgba(4, 184, 255, 0.08),
+          rgba(60, 161, 237, 0.08)
+        );
       }
 
       .card-box:nth-child(1) .box-item {
@@ -477,7 +408,7 @@ export default {
         width: 100%;
         height: 100%;
         padding: 0px 15px;
-        background: url('/static/mzrjd.png') no-repeat right;
+        background: url("/static/mzrjd.png") no-repeat right;
         background-size: 40% 80%;
       }
 
@@ -489,7 +420,7 @@ export default {
         width: 100%;
         height: 100%;
         padding: 0px 15px;
-        background: url('/static/time.png') no-repeat right;
+        background: url("/static/time.png") no-repeat right;
         background-size: 40% 80%;
       }
     }
@@ -510,7 +441,7 @@ export default {
   .bot-area {
     width: 100%;
     padding: 0px 10px;
-    background-color: #FFF;
+    background-color: #fff;
     margin-bottom: 2px;
     box-sizing: border-box;
 
@@ -530,7 +461,7 @@ export default {
         line-height: 26px;
         padding: 0px 20px;
         font-size: 12px;
-        background: url('/static/warndata/title.png') no-repeat;
+        background: url("/static/warndata/title.png") no-repeat;
         background-size: 100% 100%;
       }
 
@@ -542,7 +473,12 @@ export default {
           display: flex;
           justify-content: space-between;
           align-items: center;
-          background: linear-gradient(to right, rgba(55, 135, 254, 0.08), rgba(4, 184, 255, 0.08), rgba(60, 161, 237, 0.08));
+          background: linear-gradient(
+            to right,
+            rgba(55, 135, 254, 0.08),
+            rgba(4, 184, 255, 0.08),
+            rgba(60, 161, 237, 0.08)
+          );
           border-radius: 10px;
           margin-bottom: 5px;
 
@@ -568,7 +504,13 @@ export default {
             width: 4px;
             height: 70%;
             border-left: 2px solid;
-            border-image: linear-gradient(to bottom, transparent, rgba(140, 203, 254, 1), transparent) 1 1 1;
+            border-image: linear-gradient(
+                to bottom,
+                transparent,
+                rgba(140, 203, 254, 1),
+                transparent
+              )
+              1 1 1;
           }
 
           .item-r {
@@ -591,8 +533,6 @@ export default {
             font-size: 12px;
           }
         }
-
-
       }
 
       .echartbox1 {

+ 410 - 569
pages/warndata/components/fire-detail-out.vue

@@ -1,621 +1,462 @@
 <template>
-    <!-- 外因火灾 -->
-    <view class="fire-detail-out">
-        <view class="top-area">
-            <view class="top-card">
-                <view class="card-box" v-for="(item, index) in cardList" :key="index">
-                    <view class="box-item">
-                        <view class="box-val">{{ item.value }}</view>
-                        <view class="box-name">{{ item.name }}</view>
-                    </view>
-                </view>
-            </view>
-
+  <!-- 外因火灾 -->
+  <view class="fire-detail-out">
+    <view class="top-area">
+      <view class="top-card">
+        <view class="card-box" v-for="(item, index) in cardList" :key="index">
+          <view class="box-item">
+            <view class="box-val">{{ item.value }}</view>
+            <view class="box-name">{{ item.name }}</view>
+          </view>
         </view>
-        <view class="center-area">
-            <view class="bot-title">
-                <view style="font-weight: bold;">光钎测温系统温度实时监测</view>
+      </view>
+    </view>
+    <view class="center-area">
+      <view class="bot-title">
+        <view style="font-weight: bold">光钎测温系统温度实时监测</view>
+      </view>
+      <view class="echartBox">
+        <LineChart :chartData="option" :style="{ width: '100%' }"></LineChart>
+      </view>
+    </view>
+    <view class="bot-area" v-for="(item, index) in botList" :key="index">
+      <view class="bot-title">
+        <view style="font-weight: bold">{{ item.title }}</view>
+      </view>
+      <view class="bot-content">
+        <view class="h-table">
+          <view class="table-head" v-if="item.title == '烟雾传感器监测'">
+            <view
+              class="head-item"
+              v-for="(items, index) in headList"
+              :key="index"
+              >{{ items.title }}</view
+            >
+          </view>
+          <view class="table-head" v-else>
+            <view
+              class="head-item1"
+              v-for="(items, index) in headList1"
+              :key="index"
+              >{{ items.title }}
             </view>
-            <view class="echartBox">
-                <canvas id="myChart" :style="{ width: '100%', height: '220px' }"></canvas>
+          </view>
+          <view class="table-content">
+            <view
+              class="content-tr"
+              v-if="item.title == '烟雾传感器监测'"
+              v-for="(ite, ind) in tableDataYw"
+              :key="ind"
+            >
+              <view class="content-td td">{{ ite.strinstallpos }}</view>
+              <view class="content-td td1">{{ ite.val }}</view>
+              <view class="content-td td2">{{ ite.warnLevel_str }}</view>
+              <view class="content-td td3">{{ ite.readTime }}</view>
             </view>
-        </view>
-        <view class="bot-area" v-for="(item, index) in botList" :key="index">
-            <view class="bot-title">
-                <view style="font-weight: bold;">{{ item.title }}</view>
+            <view
+              class="content-tr"
+              v-if="item.title == '一氧化碳传感器监测'"
+              v-for="(ite, ind) in tableDataCo"
+              :key="ind"
+            >
+              <view class="content-td td">{{ ite.strinstallpos }}</view>
+              <view class="content-td td1">{{ ite.warnLevel_str }}</view>
+              <view class="content-td td2">{{ ite.readTime }}</view>
             </view>
-            <view class="bot-content">
-                <view class="h-table">
-                    <view class="table-head" v-if="item.title == '烟雾传感器监测'">
-                        <view class="head-item" v-for="(items, index) in headList" :key="index">{{ items.title }}</view>
-                    </view>
-                    <view class="table-head" v-else>
-                        <view class="head-item1" v-for="(items, index) in headList1" :key="index">{{ items.title }}
-                        </view>
-                    </view>
-                    <view class="table-content">
-                        <view class="content-tr" v-if="item.title == '烟雾传感器监测'" v-for="(ite, ind) in tableDataYw"
-                            :key="ind">
-                            <view class="content-td td">{{ ite.strinstallpos }}</view>
-                            <view class="content-td td1">{{ ite.val }}</view>
-                            <view class="content-td td2">{{ ite.warnLevel_str }}</view>
-                            <view class="content-td td3">{{ ite.readTime }}</view>
-                        </view>
-                        <view class="content-tr" v-if="item.title == '一氧化碳传感器监测'" v-for="(ite, ind) in tableDataCo"
-                            :key="ind">
-                            <view class="content-td td">{{ ite.strinstallpos }}</view>
-                            <view class="content-td td1">{{ ite.warnLevel_str }}</view>
-                            <view class="content-td td2">{{ ite.readTime }}</view>
-                        </view>
-                        <view class="content-tr" v-if="item.title == '自动喷淋灭火装置监测'" v-for="(ite, ind) in tableDataPl"
-                            :key="ind">
-                            <view class="content-td td">{{ ite.strinstallpos }}</view>
-                            <view class="content-td td1">{{ ite.warnLevel_str }}</view>
-                            <view class="content-td td2">{{ ite.readTime }}</view>
-                        </view>
-
-                    </view>
-                </view>
+            <view
+              class="content-tr"
+              v-if="item.title == '自动喷淋灭火装置监测'"
+              v-for="(ite, ind) in tableDataPl"
+              :key="ind"
+            >
+              <view class="content-td td">{{ ite.strinstallpos }}</view>
+              <view class="content-td td1">{{ ite.warnLevel_str }}</view>
+              <view class="content-td td2">{{ ite.readTime }}</view>
             </view>
+          </view>
         </view>
+      </view>
     </view>
+  </view>
 </template>
 
 <script>
 import api from "@/api/api";
 export default {
-    name: 'fireDetailOut',
-    props: {
-        detailWy: {
-            type: Object,
-            default: () => {
-                return {}
-            }
-        }
-    },
-    data() {
-        return {
-            myChart: null,
-            xData: [],
-            yData: [],
-            cardList: [
-                { name: '最高温度()', value: 0 },
-                { name: '最低温度()', value: 0 },
-                { name: '平均温度()', value: 0 },
-                { name: '状态', value: '正常' },
-            ],
-            botList: [
-                { title: '烟雾传感器监测' },
-                { title: '一氧化碳传感器监测' },
-                { title: '自动喷淋灭火装置监测' },
-            ],
-            headList: [
-                { title: '设备名称' },
-                { title: '值' },
-                { title: '状态' },
-                { title: '时间' },
-            ],
-            headList1: [
-                { title: '设备名称' },
-                { title: '状态' },
-                { title: '时间' },
-            ],
-            tableDataYw: [],
-            tableDataCo: [],
-            tableDataPl: [],
-        };
+  name: "fireDetailOut",
+  props: {
+    detailWy: {
+      type: Object,
+      default: () => {
+        return {};
+      },
     },
-    watch: {
-        detailWy: {
-            handler(newW, oldW) {
-                console.log(newW, 'newW--------------')
-                let that = this
-                that.xData = []
-                that.yData = []
-                if (JSON.stringify(newW) != '{}') {
-                    if (newW.fiber.length != 0) {
-                        that.cardList[0].value = newW.fiber[0].readData.fmax;
-                        that.cardList[1].value = newW.fiber[0].readData.fmin;
-                        that.cardList[2].value = newW.fiber[0].readData.favg;
-                        that.cardList[3].value = newW.fiber[0].warnFlag ? '存在风险' : '正常';
-                        JSON.parse(newW.fiber[0].readData.fibreTemperature).forEach((el) => {
-                            that.xData.push(el.pos);
-                            that.yData.push(el.value);
-                        });
-                        that.initChart()
-                    } else {
-                        that.cardList[0].value = '--';
-                        that.cardList[1].value = '--';
-                        that.cardList[2].value = '--';
-                        that.cardList[3].value = '正常';
-                    }
-
-                    if (newW.smoke.length != 0) {
-                        that.tableDataYw = newW.smoke.map((el) => {
-                            return {
-                                strinstallpos: el.strinstallpos,
-                                val: el.readData.smokeval,
-                                warnLevel_str: el.warnLevel_str == '正常' ? '低风险' : el.warnLevel_str,
-                                readTime: el.readTime,
-                            }
-                        });
-                    } else {
-                        that.tableDataYw = []
-                    }
-
-                    if (newW.co.length != 0) {
-                        that.tableDataCo = newW.co
-                    } else {
-                        that.tableDataCo = []
-                    }
-
-                    if (newW.spray.length != 0) {
-                        that.tableDataPl = newW.spray
-                    } else {
-                        that.tableDataPl = []
-                    }
-                }
-            },
-            immediate: true,
-            deep: true
+  },
+  data() {
+    return {
+      option: "",
+      myChart: null,
+      xData: [],
+      yData: [],
+      cardList: [
+        { name: "最高温度()", value: 0 },
+        { name: "最低温度()", value: 0 },
+        { name: "平均温度()", value: 0 },
+        { name: "状态", value: "正常" },
+      ],
+      botList: [
+        { title: "烟雾传感器监测" },
+        { title: "一氧化碳传感器监测" },
+        { title: "自动喷淋灭火装置监测" },
+      ],
+      headList: [
+        { title: "设备名称" },
+        { title: "值" },
+        { title: "状态" },
+        { title: "时间" },
+      ],
+      headList1: [{ title: "设备名称" }, { title: "状态" }, { title: "时间" }],
+      tableDataYw: [],
+      tableDataCo: [],
+      tableDataPl: [],
+    };
+  },
+  watch: {
+    detailWy: {
+      handler(newW, oldW) {
+        console.log(newW, "newW--------------");
+        let that = this;
+        that.xData = [];
+        that.yData = [];
+        if (JSON.stringify(newW) != "{}") {
+          if (newW.fiber.length != 0) {
+            that.cardList[0].value = newW.fiber[0].readData.fmax;
+            that.cardList[1].value = newW.fiber[0].readData.fmin;
+            that.cardList[2].value = newW.fiber[0].readData.favg;
+            that.cardList[3].value = newW.fiber[0].warnFlag
+              ? "存在风险"
+              : "正常";
+            JSON.parse(newW.fiber[0].readData.fibreTemperature).forEach(
+              (el) => {
+                that.xData.push(el.pos);
+                that.yData.push(el.value);
+                this.initChart();
+              }
+            );
+          } else {
+            that.cardList[0].value = "--";
+            that.cardList[1].value = "--";
+            that.cardList[2].value = "--";
+            that.cardList[3].value = "正常";
+          }
+
+          if (newW.smoke.length != 0) {
+            that.tableDataYw = newW.smoke.map((el) => {
+              return {
+                strinstallpos: el.strinstallpos,
+                val: el.readData.smokeval,
+                warnLevel_str:
+                  el.warnLevel_str == "正常" ? "低风险" : el.warnLevel_str,
+                readTime: el.readTime,
+              };
+            });
+          } else {
+            that.tableDataYw = [];
+          }
+
+          if (newW.co.length != 0) {
+            that.tableDataCo = newW.co;
+          } else {
+            that.tableDataCo = [];
+          }
+
+          if (newW.spray.length != 0) {
+            that.tableDataPl = newW.spray;
+          } else {
+            that.tableDataPl = [];
+          }
         }
+      },
+      immediate: true,
+      deep: true,
     },
-    mounted() {
-
-    },
-    methods: {
-        //初始化echarts实例
-        initChart() {
-            let canvas = document.getElementById('myChart');
-            this.myChart = this.$echarts.init(canvas)
-            let option = {
-                grid: {
-                    top: '20%',
-                    left: '4%',
-                    bottom: '4%',
-                    right: '2%',
-                    containLabel: true,
-                },
-                tooltip: {
-                    trigger: 'item',
-                    backgroundColor: 'rgba(0, 0, 0, .6)',
-                    textStyle: {
-                        color: '#fff',
-                        fontSize: 12,
-                    },
-                },
-                legend: {
-                    // align: 'center',
-                    right: 'center',
-                    top: '0%',
-                    type: 'plain',
-                    textStyle: {
-                        color: '#0eb4fc',
-                        fontSize: 12,
-                    },
-                    // icon:'rect',
-                    itemGap: 25,
-                    itemWidth: 20,
-                    icon: 'path://M0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z',
-                    data: [
-                        {
-                            name: '当前温度',
-                        },
-
-                    ],
-                },
-                xAxis: [
-                    {
-                        type: 'category',
-                        boundaryGap: false,
-                        axisLabel: {
-                            // formatter: '{value}',
-                            fontSize: 12,
-                            margin: 10,
-                            textStyle: {
-                                color: '#b3b8cc',
-                            },
-                            formatter: function (params) {
-                                let newParamsName = ''  // 最终拼接成的字符串
-                                let paramsNameNumber = params.length // 实际标签的个数
-                                let provideNumber = 10  // 每行能显示的字的个数
-                                let rowNumber = Math.ceil(paramsNameNumber / provideNumber) // 换行的话,需要显示几行,向上取整
-                                /**
-                                 * 判断标签的个数是否大于规定的个数, 如果大于,则进行换行处理 如果不大于,即等于或小于,就返回原标签
-                                 */
-                                // 条件等同于rowNumber>1
-                                if (paramsNameNumber > provideNumber) {
-                                    /** 循环每一行,p表示行 */
-                                    for (var p = 0; p < rowNumber; p++) {
-                                        var tempStr = '' // 表示每一次截取的字符串
-                                        var start = p * provideNumber // 开始截取的位置
-                                        var end = start + provideNumber // 结束截取的位置
-                                        // 此处特殊处理最后一行的索引值
-                                        if (p == rowNumber - 1) {
-                                            // 最后一次不换行
-                                            tempStr = params.substring(start, paramsNameNumber)
-                                        } else {
-                                            // 每一次拼接字符串并换行
-                                            tempStr = params.substring(start, end) + '\n'
-                                        }
-                                        newParamsName += tempStr // 最终拼成的字符串
-                                    }
-                                } else {
-                                    // 将旧标签的值赋给新标签
-                                    newParamsName = params
-                                }
-                                //将最终的字符串返回
-                                return newParamsName
-                            }
-                        },
-                        axisLine: {
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                        data: this.xData || [],
-                    },
-                ],
-                yAxis: [
-                    {
-                        boundaryGap: false,
-                        type: 'value',
-                        max: 2000,
-                        axisLabel: {
-                            textStyle: {
-                                color: '#b3b8cc',
-                            },
-                            formatter: '{value}'
-                        },
-                        name: '(­°C)',
-                        nameTextStyle: {
-                            color: '#b3b8cc',
-                            fontSize: 12,
-                            lineHeight: 0,
-                        },
-                        splitLine: {
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisLine: {
-                            show: true,
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                    },
-                    {
-                        boundaryGap: false,
-                        type: 'value',
-                        max: 2000,
-                        axisLabel: {
-                            textStyle: {
-                                color: '#b3b8cc',
-                            },
-                            formatter: '{value}'
-                        },
-                        name: '(­°C)',
-                        nameTextStyle: {
-                            color: '#fff',
-                            fontSize: 12,
-                            lineHeight: 10,
-                        },
-                        splitLine: {
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisLine: {
-                            show: true,
-                            lineStyle: {
-                                color: '#f1f5f6',
-                            },
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                    },
-                ],
-                series: [
-                    {
-                        name: '当前温度',
-                        type: 'line',
-                        smooth: true,
-                        showSymbol: true,
-                        symbolSize: 8,
-                        zlevel: 3,
-                        itemStyle: {
-                            color: '#19a3df',
-                            borderColor: '#a3c8d8',
-                        },
-                        lineStyle: {
-                            normal: {
-                                width: 2,
-                                color: '#19a3df',
-                            },
-                        },
-                        data: this.yData || [],
-                    },
-
-                ],
-            };
-            this.myChart.setOption(option)
-            window.addEventListener('resize', () => {
-                this.myChart.resize()
-            })
-        },
-
+  },
+  mounted() {},
+  methods: {
+    //初始化echarts实例
+    initChart() {
+      this.option = {
+        categories: this.xData.slice(-10) || [],
+        series: [
+          {
+            name: "当前温度",
+            data: this.yData.slice(-10) || [],
+          },
+        ],
+      };
     },
-    computed: {},
+  },
+  computed: {},
 };
 </script>
 
 <style lang="scss" scoped>
 .fire-detail-out {
+  width: 100%;
+  height: 100%;
+
+  // box-sizing: border-box;
+  // overflow-y: auto;
+  .top-area {
+    width: 100%;
+    padding: 10px;
+    background-color: #fff;
+    margin-bottom: 2px;
+    box-sizing: border-box;
+
+    .top-card {
+      width: 100%;
+      display: flex;
+      justify-content: flex-start;
+      align-items: flex-start;
+      flex-wrap: wrap;
+
+      .card-box {
+        width: calc(50% - 5px);
+        height: 60px;
+        border-radius: 5px;
+        background: linear-gradient(
+          to right,
+          rgba(55, 135, 254, 0.08),
+          rgba(4, 184, 255, 0.08),
+          rgba(60, 161, 237, 0.08)
+        );
+
+        &:nth-child(1) {
+          margin-bottom: 10px;
+          margin-right: 5px;
+        }
+
+        &:nth-child(2) {
+          margin-bottom: 10px;
+          margin-left: 5px;
+        }
+
+        &:nth-child(3) {
+          margin-right: 5px;
+        }
+
+        &:nth-child(4) {
+          margin-left: 5px;
+        }
+      }
+
+      .card-box:nth-child(1) .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
+        width: 100%;
+        height: 100%;
+        padding: 0px 15px;
+        background: url("/static/zgwd.png") no-repeat right;
+        background-size: auto 80%;
+      }
+
+      .card-box:nth-child(2) .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
+        width: 100%;
+        height: 100%;
+        padding: 0px 15px;
+        background: url("/static/zdwd.png") no-repeat right;
+        background-size: auto 80%;
+      }
+
+      .card-box:nth-child(3) .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
+        width: 100%;
+        height: 100%;
+        padding: 0px 15px;
+        background: url("/static/pjwd.png") no-repeat right;
+        background-size: auto 80%;
+      }
+
+      .card-box:nth-child(4) .box-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: flex-start;
+        width: 100%;
+        height: 100%;
+        padding: 0px 15px;
+        background: url("/static/zt.png") no-repeat right;
+        background-size: auto 80%;
+      }
+    }
+
+    .box-item .box-val {
+      height: 28px;
+      line-height: 28px;
+      color: #0eb4fc;
+      font-weight: bold;
+    }
+
+    .box-item .box-name {
+      font-size: 12px;
+    }
+  }
+
+  .center-area {
+    width: 100%;
+    padding: 10px;
+    background-color: #fff;
+    margin-bottom: 2px;
+    box-sizing: border-box;
+
+    .bot-title {
+      height: 28px;
+      margin-bottom: 5px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+
+    .echartBox {
+      width: 100%;
+      height: 220px;
+    }
+  }
+
+  .bot-area {
     width: 100%;
-    height: 100%;
+    padding: 10px;
+    background-color: #fff;
+    margin-bottom: 2px;
+    box-sizing: border-box;
+
+    .bot-title {
+      height: 28px;
+      margin-bottom: 5px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+
+    .bot-content {
+      width: 100%;
+      height: 240px;
 
-    // box-sizing: border-box;
-    // overflow-y: auto;
-    .top-area {
+      .h-table {
         width: 100%;
-        padding: 10px;
-        background-color: #FFF;
-        margin-bottom: 2px;
-        box-sizing: border-box;
+        height: 100%;
+        border: 1px solid #0eb4fc;
 
-        .top-card {
-            width: 100%;
+        .table-head {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          height: 36px;
+          border-bottom: 1px solid #0eb4fc;
+
+          .head-item {
+            font-size: 12px;
+            color: #0eb4fc;
             display: flex;
-            justify-content: flex-start;
-            align-items: flex-start;
-            flex-wrap: wrap;
-
-            .card-box {
-                width: calc(50% - 5px);
-                height: 60px;
-                border-radius: 5px;
-                background: linear-gradient(to right, rgba(55, 135, 254, 0.08), rgba(4, 184, 255, 0.08), rgba(60, 161, 237, 0.08));
-
-                &:nth-child(1) {
-                    margin-bottom: 10px;
-                    margin-right: 5px;
-                }
-
-                &:nth-child(2) {
-                    margin-bottom: 10px;
-                    margin-left: 5px;
-                }
-
-                &:nth-child(3) {
-                    margin-right: 5px;
-                }
-
-                &:nth-child(4) {
-                    margin-left: 5px;
-                }
-            }
+            justify-content: center;
+            align-items: center;
+            font-weight: bold;
 
-            .card-box:nth-child(1) .box-item {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: flex-start;
-                width: 100%;
-                height: 100%;
-                padding: 0px 15px;
-                background: url('/static/zgwd.png') no-repeat right;
-                background-size: auto 80%;
+            &:nth-child(1) {
+              width: 30%;
             }
 
-            .card-box:nth-child(2) .box-item {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: flex-start;
-                width: 100%;
-                height: 100%;
-                padding: 0px 15px;
-                background: url('/static/zdwd.png') no-repeat right;
-                background-size: auto 80%;
+            &:nth-child(2) {
+              width: 20%;
             }
 
-            .card-box:nth-child(3) .box-item {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: flex-start;
-                width: 100%;
-                height: 100%;
-                padding: 0px 15px;
-                background: url('/static/pjwd.png') no-repeat right;
-                background-size: auto 80%;
+            &:nth-child(3) {
+              width: 20%;
             }
 
-            .card-box:nth-child(4) .box-item {
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                align-items: flex-start;
-                width: 100%;
-                height: 100%;
-                padding: 0px 15px;
-                background: url('/static/zt.png') no-repeat right;
-                background-size: auto 80%;
+            &:nth-child(4) {
+              width: 30%;
             }
+          }
 
-
-        }
-
-        .box-item .box-val {
-            height: 28px;
-            line-height: 28px;
+          .head-item1 {
+            font-size: 12px;
             color: #0eb4fc;
+            display: flex;
+            justify-content: center;
+            align-items: center;
             font-weight: bold;
-        }
 
-        .box-item .box-name {
-            font-size: 12px;
-        }
-    }
+            &:nth-child(1) {
+              width: 30%;
+            }
 
-    .center-area {
-        width: 100%;
-        padding: 10px;
-        background-color: #FFF;
-        margin-bottom: 2px;
-        box-sizing: border-box;
-
-        .bot-title {
-            height: 28px;
-            margin-bottom: 5px;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-        }
+            &:nth-child(2) {
+              width: 30%;
+            }
 
-        .echartBox {
-            width: 100%;
-            height: 220px;
+            &:nth-child(3) {
+              width: 40%;
+            }
+          }
         }
-    }
 
-    .bot-area {
-        width: 100%;
-        padding: 10px;
-        background-color: #FFF;
-        margin-bottom: 2px;
-        box-sizing: border-box;
-
-        .bot-title {
-            height: 28px;
-            margin-bottom: 5px;
+        .table-content {
+          height: calc(100% - 36px);
+          overflow-y: auto;
+
+          .content-tr {
+            height: 80px;
             display: flex;
             justify-content: space-between;
             align-items: center;
-        }
 
-        .bot-content {
-            width: 100%;
-            height: 240px;
-
-            .h-table {
-                width: 100%;
-                height: 100%;
-                border: 1px solid #0eb4fc;
-
-                .table-head {
-                    display: flex;
-                    justify-content: space-between;
-                    align-items: center;
-                    height: 36px;
-                    border-bottom: 1px solid #0eb4fc;
-
-                    .head-item {
-                        font-size: 12px;
-                        color: #0eb4fc;
-                        display: flex;
-                        justify-content: center;
-                        align-items: center;
-                        font-weight: bold;
-
-                        &:nth-child(1) {
-                            width: 30%;
-                        }
-
-                        &:nth-child(2) {
-                            width: 20%;
-                        }
-
-                        &:nth-child(3) {
-                            width: 20%;
-                        }
-
-                        &:nth-child(4) {
-                            width: 30%;
-                        }
-
-
-                    }
-
-                    .head-item1 {
-                        font-size: 12px;
-                        color: #0eb4fc;
-                        display: flex;
-                        justify-content: center;
-                        align-items: center;
-                        font-weight: bold;
-
-                        &:nth-child(1) {
-                            width: 30%;
-                        }
-
-                        &:nth-child(2) {
-                            width: 30%;
-                        }
-
-                        &:nth-child(3) {
-                            width: 40%;
-                        }
-
-                    }
-                }
-
-                .table-content {
-                    height: calc(100% - 36px);
-                    overflow-y: auto;
-
-                    .content-tr {
-                        height: 32px;
-                        display: flex;
-                        justify-content: space-between;
-                        align-items: center;
-
-                        &:nth-child(odd) {
-                            background-color: #f3faff;
-                        }
-
-                        &:nth-child(even) {
-                            background-color: #e8f5ff;
-                        }
-
-                        .content-td {
-                            height: 100%;
-                            font-size: 12px;
-                            display: flex;
-                            justify-content: center;
-                            align-items: center;
-                            text-align: center;
-                        }
-
-                        .td {
-                            width: 30%;
-                        }
-
-                        .td1 {
-                            width: 20%;
-                        }
-
-                        .td2 {
-                            width: 20%;
-                        }
-
-                        .td3 {
-                            width: 30%;
-                        }
-
-                    }
-                }
+            &:nth-child(odd) {
+              background-color: #f3faff;
+            }
+
+            &:nth-child(even) {
+              background-color: #e8f5ff;
+            }
+
+            .content-td {
+              height: 100%;
+              font-size: 12px;
+              display: flex;
+              justify-content: center;
+              align-items: center;
+              text-align: center;
             }
+
+            .td {
+              width: 30%;
+            }
+
+            .td1 {
+              width: 20%;
+            }
+
+            .td2 {
+              width: 20%;
+            }
+
+            .td3 {
+              width: 30%;
+            }
+          }
         }
+      }
     }
-
+  }
 }
 </style>

+ 132 - 344
pages/warndata/components/vent-detail.vue

@@ -27,28 +27,20 @@
             </view>
           </view>
         </view>
-        <view class="top-card1">
-          <view
-            class="card-box"
-            v-for="(item, index) in cardList1"
-            :key="index"
-          >
-            <view class="box-item">
-              <view class="box-val">{{ item.value }}</view>
-              <view class="box-name">{{ item.name }}</view>
-            </view>
-          </view>
-        </view>
       </view>
       <view class="center-area">
         <view class="top-title">
           <view style="font-weight: bold">通风信息状态监测</view>
         </view>
         <view class="echartBox">
-          <canvas
+          <!-- <canvas
             id="myChart"
             :style="{ width: '100%', height: '180px' }"
-          ></canvas>
+          ></canvas> -->
+          <LineChart
+            :chartData="option"
+            :style="{ width: '100%', height: '180px' }"
+          ></LineChart>
         </view>
       </view>
       <view class="bot-area">
@@ -93,7 +85,6 @@ export default {
   data() {
     return {
       mainTitle: "",
-      myChart: null,
       timer: "",
       PageCur: "0",
       tabList: [],
@@ -102,10 +93,6 @@ export default {
         { name: "回风量(m³/min)", value: 0 },
         { name: "需风量(m³/min)", value: 0 },
       ],
-      cardList1: [
-        { name: "O₂(%)", value: 0 },
-        { name: "CO(%)", value: 0 },
-      ],
       //echarts图表数据
       maxY: 0,
       xData: [],
@@ -113,16 +100,15 @@ export default {
       yDataH: [],
       yDataX: [],
       cardListTf: [],
+      option: {},
     };
   },
   mounted() {
     this.getTabList();
-    // than.initChart();
     this.getWindDeviceList();
+    // than.initChart();
   },
   beforeDestroy() {
-    this.myChart.clear();
-    this.myChart.dispose();
     this.timer = null;
     clearTimeout(this.timer);
   },
@@ -147,33 +133,40 @@ export default {
       );
     },
     //获取顶部tab选项数据
-    getTabList() {
-      new Promise((resolve, reject) => {
-        api
-          .sysTypeWarn({ type: "vent" })
-          .then((response) => {
-            if (response.data.code == 200 && response.data.result.length != 0) {
-              let result = response.data.result;
-              this.tabList = result.map((el) => {
-                //lxh
-                return {
-                  name: el.deviceName,
-                  warn: "低风险",
-                  deviceID: el.deviceID,
-                  strtype: el.deviceType,
-                };
-              });
-              this.mainTitle = this.tabList[0].name;
-              this.getMonitor(this.tabList[0].deviceID, true);
-            } else {
-              reject(response);
-            }
-          })
-          .catch((error) => {
-            console.log("catch===>response", response);
-            reject(error);
-          });
-      });
+    async getTabList() {
+      try {
+        await new Promise((resolve, reject) => {
+          api
+            .sysTypeWarn({ type: "vent" })
+            .then((response) => {
+              if (
+                response.data.code == 200 &&
+                response.data.result.length != 0
+              ) {
+                let result = response.data.result;
+                this.tabList = result.map((el) => {
+                  //lxh
+                  return {
+                    name: el.deviceName,
+                    warn: "低风险",
+                    deviceID: el.deviceID,
+                    strtype: el.deviceType,
+                  };
+                });
+                this.mainTitle = this.tabList[0].name;
+                this.getMonitor(this.tabList[0].deviceID, true);
+              } else {
+                reject(response);
+              }
+            })
+            .catch((error) => {
+              console.log("catch===>response", response);
+              reject(error);
+            });
+        });
+      } catch (error) {
+        console.error("数据加载失败:", error);
+      }
     },
     formatRoundNum(num) {
       let interger = Math.ceil(num);
@@ -182,240 +175,9 @@ export default {
         Math.ceil(interger / Math.pow(10, leng - 1)) * Math.pow(10, leng - 1)
       );
     },
-    //初始化echarts实例
-    initChart() {
-      let canvas = document.getElementById("myChart");
-      this.myChart = this.$echarts.init(canvas);
-      let option = {
-        grid: {
-          top: "24%",
-          left: "0%",
-          bottom: "6%",
-          right: "2%",
-          containLabel: true,
-        },
-        tooltip: {
-          trigger: "item",
-          backgroundColor: "rgba(0, 0, 0, .6)",
-          textStyle: {
-            color: "#fff",
-            fontSize: 12,
-          },
-        },
-        legend: {
-          // align: 'center',
-          right: "0%",
-          top: "0%",
-          type: "plain",
-          textStyle: {
-            color: "#0eb4fc",
-            fontSize: 12,
-          },
-          // icon:'rect',
-          itemGap: 25,
-          itemWidth: 20,
-          icon: "path://M0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z",
-          data: [
-            {
-              name: "进风量",
-            },
-            {
-              name: "回风量",
-            },
-
-            {
-              name: "需风量",
-            },
-          ],
-        },
-        xAxis: [
-          {
-            type: "category",
-            boundaryGap: false,
-            axisLabel: {
-              // formatter: '{value}',
-              fontSize: 12,
-              margin: 10,
-              textStyle: {
-                color: "#b3b8cc",
-              },
-              // formatter: function (params) {
-              //     let newParamsName = ref('')  // 最终拼接成的字符串
-              //     let paramsNameNumber = ref(params.length) // 实际标签的个数
-              //     let provideNumber = ref(10)  // 每行能显示的字的个数
-              //     let rowNumber = Math.ceil(paramsNameNumber.value / provideNumber.value) // 换行的话,需要显示几行,向上取整
-              //     /**
-              //      * 判断标签的个数是否大于规定的个数, 如果大于,则进行换行处理 如果不大于,即等于或小于,就返回原标签
-              //      */
-              //     // 条件等同于rowNumber>1
-              //     if (paramsNameNumber.value > provideNumber.value) {
-              //         /** 循环每一行,p表示行 */
-              //         for (var p = 0; p < rowNumber; p++) {
-              //             var tempStr = '' // 表示每一次截取的字符串
-              //             var start = p * provideNumber.value // 开始截取的位置
-              //             var end = start + provideNumber.value // 结束截取的位置
-              //             // 此处特殊处理最后一行的索引值
-              //             if (p == rowNumber - 1) {
-              //                 // 最后一次不换行
-              //                 tempStr = params.substring(start, paramsNameNumber.value)
-              //             } else {
-              //                 // 每一次拼接字符串并换行
-              //                 tempStr = params.substring(start, end) + '\n'
-              //             }
-              //             newParamsName.value += tempStr // 最终拼成的字符串
-              //         }
-              //     } else {
-              //         // 将旧标签的值赋给新标签
-              //         newParamsName.value = params
-              //     }
-              //     //将最终的字符串返回
-              //     return newParamsName.value
-              // }
-            },
-            axisLine: {
-              lineStyle: {
-                color: "#f1f5f6",
-              },
-            },
-            axisTick: {
-              show: false,
-            },
-            data: this.xData || [],
-          },
-        ],
-        yAxis: [
-          {
-            boundaryGap: false,
-            type: "value",
-            max: this.maxY,
-            axisLabel: {
-              textStyle: {
-                color: "#b3b8cc",
-              },
-              formatter: "{value}",
-            },
-            name: "(m³/min)",
-            nameTextStyle: {
-              color: "#b3b8cc",
-              fontSize: 12,
-              lineHeight: 0,
-            },
-            splitLine: {
-              lineStyle: {
-                color: "#f1f5f6",
-              },
-            },
-            axisLine: {
-              show: true,
-              lineStyle: {
-                color: "#f1f5f6",
-              },
-            },
-            axisTick: {
-              show: false,
-            },
-          },
-          {
-            boundaryGap: false,
-            type: "value",
-            max: this.maxY,
-            axisLabel: {
-              textStyle: {
-                color: "#b3b8cc",
-              },
-              formatter: "{value}",
-            },
-            name: "(m³/min)",
-            nameTextStyle: {
-              color: "#fff",
-              fontSize: 12,
-              lineHeight: 10,
-            },
-            splitLine: {
-              lineStyle: {
-                color: "#f1f5f6",
-              },
-            },
-            axisLine: {
-              show: true,
-              lineStyle: {
-                color: "#f1f5f6",
-              },
-            },
-            axisTick: {
-              show: false,
-            },
-          },
-        ],
-        series: [
-          {
-            name: "进风量",
-            type: "line",
-            smooth: true,
-            showSymbol: true,
-            symbolSize: 8,
-            zlevel: 3,
-            itemStyle: {
-              color: "#19a3df",
-              borderColor: "#a3c8d8",
-            },
-            lineStyle: {
-              normal: {
-                width: 2,
-                color: "#19a3df",
-              },
-            },
-            data: this.yDataJ || [],
-          },
-          {
-            name: "回风量",
-            type: "line",
-            smooth: true,
-            showSymbol: true,
-            symbolSize: 8,
-            zlevel: 3,
-            itemStyle: {
-              color: "#4fffad",
-              borderColor: "#a3c8d8",
-            },
-            lineStyle: {
-              normal: {
-                width: 2,
-                color: "#4fffad",
-              },
-            },
-            data: this.yDataH || [],
-          },
-          {
-            name: "需风量",
-            type: "line",
-            smooth: true,
-            showSymbol: true,
-            symbolSize: 8,
-            zlevel: 3,
-            itemStyle: {
-              color: "#fc8452",
-              borderColor: "#a3c8d8",
-            },
-            lineStyle: {
-              normal: {
-                width: 2,
-                color: "#fc8452",
-              },
-            },
-
-            data: this.yDataX || [],
-          },
-        ],
-      };
-      this.myChart.setOption(option);
-      window.addEventListener("resize", () => {
-        this.myChart.resize();
-      });
-    },
     //获取选项详情数据
     getSysWarnList(id, type) {
-      new Promise((resolve, reject) => {
+      return new Promise((resolve, reject) => {
         api
           .sysWarn({ sysid: id, type: type })
           .then((response) => {
@@ -444,17 +206,34 @@ export default {
                   this.xData.push(v.time);
                 });
               }
-              let max1 = this.yDataJ.reduce((acr, cur) => {
-                return acr > cur ? acr : cur;
-              });
-              let max2 = this.yDataH.reduce((acr1, cur1) => {
-                return acr1 > cur1 ? acr1 : cur1;
-              });
-              this.maxY =
-                max1 >= max2
-                  ? this.formatRoundNum(max1 * 1.5)
-                  : this.formatRoundNum(max2 * 1.5);
-              this.initChart();
+              // let max1 = this.yDataJ.reduce((acr, cur) => {
+              //   return acr > cur ? acr : cur;
+              // });
+              // let max2 = this.yDataH.reduce((acr1, cur1) => {
+              //   return acr1 > cur1 ? acr1 : cur1;
+              // });
+              // this.maxY =
+              //   max1 >= max2
+              //     ? this.formatRoundNum(max1 * 1.5)
+              //     : this.formatRoundNum(max2 * 1.5);
+              this.option = {
+                categories: this.xData.slice(-3) || [],
+                series: [
+                  {
+                    name: "进风量",
+                    data: this.yDataJ.slice(-3) || [],
+                  },
+                  {
+                    name: "回风量",
+                    data: this.yDataH.slice(-3) || [],
+                  },
+                  {
+                    name: "需风量",
+                    data: this.yDataX.slice(-3) || [],
+                  },
+                ],
+              };
+              // this.initChart();
             } else {
               reject(response);
             }
@@ -466,60 +245,69 @@ export default {
       });
     },
     //获取通风监控测点信息
-    getWindDeviceList() {
-      new Promise((resolve, reject) => {
-        api
-          .getDeviceVent({ devicetype: "windrect", pagetype: "normal" })
-          .then((response) => {
-            if (response.data.code == 200) {
-              let data = response.data.result;
-              if (data.msgTxt[0].datalist.length != 0) {
-                let list = data.msgTxt[0].datalist;
-                if (list.length > 0) {
-                  this.cardListTf = list.map((el) => {
-                    //lxh
-                    const readData = el.readData;
-                    el = Object.assign(el, readData);
-                    return {
-                      label: "通信状态",
-                      value: el.netStatus == "0" ? "断开" : "连接",
-                      listR: [
-                        {
-                          id: 0,
-                          label: "安装位置",
-                          dw: "",
-                          value: el.strinstallpos,
-                        },
-                        { id: 1, label: "风量", dw: "(m³/min)", value: el.m3 },
-                        { id: 2, label: "风速", dw: "(m/s)", value: el.va },
-                        { id: 4, label: "时间", dw: "", value: el.readTime },
-                        {
-                          id: 3,
-                          label: "是否报警",
-                          dw: "",
-                          value:
-                            el.warnFlag == "0"
-                              ? "正常"
-                              : el.warnFlag == 1
-                              ? "报警"
-                              : el.warnFlag == 2
-                              ? "断开"
-                              : "未监测",
-                        },
-                      ],
-                    };
-                  });
+    async getWindDeviceList() {
+      try {
+        await new Promise((resolve, reject) => {
+          api
+            .getDeviceVent({ devicetype: "windrect", pagetype: "normal" })
+            .then((response) => {
+              if (response.data.code == 200) {
+                let data = response.data.result;
+                if (data.msgTxt[0].datalist.length != 0) {
+                  let list = data.msgTxt[0].datalist;
+                  if (list.length > 0) {
+                    this.cardListTf = list.map((el) => {
+                      //lxh
+                      const readData = el.readData;
+                      el = Object.assign(el, readData);
+                      return {
+                        label: "通信状态",
+                        value: el.netStatus == "0" ? "断开" : "连接",
+                        listR: [
+                          {
+                            id: 0,
+                            label: "安装位置",
+                            dw: "",
+                            value: el.strinstallpos,
+                          },
+                          {
+                            id: 1,
+                            label: "风量",
+                            dw: "(m³/min)",
+                            value: el.m3,
+                          },
+                          { id: 2, label: "风速", dw: "(m/s)", value: el.va },
+                          { id: 4, label: "时间", dw: "", value: el.readTime },
+                          {
+                            id: 3,
+                            label: "是否报警",
+                            dw: "",
+                            value:
+                              el.warnFlag == "0"
+                                ? "正常"
+                                : el.warnFlag == 1
+                                ? "报警"
+                                : el.warnFlag == 2
+                                ? "断开"
+                                : "未监测",
+                          },
+                        ],
+                      };
+                    });
+                  }
                 }
+              } else {
+                reject(response);
               }
-            } else {
-              reject(response);
-            }
-          })
-          .catch((error) => {
-            console.log("catch===>response", response);
-            reject(error);
-          });
-      });
+            })
+            .catch((error) => {
+              console.log("catch===>response", response);
+              reject(error);
+            });
+        });
+      } catch (error) {
+        console.error("数据加载失败:", error);
+      }
     },
   },
   computed: {},

+ 267 - 193
pages/warndata/warndata.vue

@@ -13,231 +13,251 @@
       </view>
     </u-navbar>
 
-    <view class="main" v-if="isShowDetail">
-      <view class="flcard" v-if="isShow1">
-        <view class="typeBar">
-          <view class="icon-vent">
-            <text class="text-style">通风监测预警</text>
+    <view>
+      <view class="main" v-if="isShowDetail">
+        <view class="flcard" v-if="isShow1">
+          <view class="typeBar">
+            <view class="icon-vent">
+              <text class="text-style">通风监测预警</text>
+            </view>
+            <u-icon @click="toggleIsShow1" name="arrow-up-fill"></u-icon>
           </view>
-          <u-icon @click="toggleIsShow1" name="arrow-up-fill"></u-icon>
         </view>
-      </view>
-      <view class="flcard" v-else>
-        <view class="typeBar">
-          <text class="text-style">通风监测预警</text>
-          <u-icon @click="toggleIsShow1" name="arrow-down-fill"></u-icon>
-        </view>
-      </view>
-      <view class="flcard" @click="getDetail('vent')" v-show="isShow1">
-        <view class="datacard demo-layout bg-purple-light">
-          <view style="margin-top: 10rpx">
-            <text class="text-style1">{{ windData.zongjinfeng }}</text>
+        <view class="flcard" v-else>
+          <view class="typeBar">
+            <text class="text-style">通风监测预警</text>
+            <u-icon @click="toggleIsShow1" name="arrow-down-fill"></u-icon>
           </view>
-          <view style="margin-top: 10rpx">总进风量(m³/min):</view>
         </view>
-        <view class="datacard demo-layout bg-purple-light">
-          <view style="margin-top: 10rpx">
-            <text class="text-style1">{{ windData.zonghuifeng }}</text>
+        <view class="flcard" @click="getDetail('vent')" v-show="isShow1">
+          <view class="datacard demo-layout bg-purple-light">
+            <view style="margin-top: 10rpx">
+              <text class="text-style1">{{ windData.zongjinfeng }}</text>
+            </view>
+            <view style="margin-top: 10rpx">总进风量(m³/min):</view>
+          </view>
+          <view class="datacard demo-layout bg-purple-light">
+            <view style="margin-top: 10rpx">
+              <text class="text-style1">{{ windData.zonghuifeng }}</text>
+            </view>
+            <view style="margin-top: 10rpx">总回风量(m³/min):</view>
+          </view>
+          <view class="datacard demo-layout bg-purple-light">
+            <view style="margin-top: 10rpx">
+              <text class="text-style1">{{ xufengliang }}</text>
+            </view>
+            <view style="margin-top: 10rpx">总需风量(m³/min):</view>
           </view>
-          <view style="margin-top: 10rpx">总回风量(m³/min):</view>
         </view>
-        <view class="datacard demo-layout bg-purple-light">
-          <view style="margin-top: 10rpx">
-            <text class="text-style1">{{ xufengliang }}</text>
+        <view class="flcard" v-if="isShow2">
+          <view class="typeBar">
+            <view class="icon-vent">
+              <text class="text-style">火灾监测预警</text>
+            </view>
+            <u-icon @click="toggleIsShow2" name="arrow-up-fill"></u-icon>
           </view>
-          <view style="margin-top: 10rpx">总需风量(m³/min):</view>
         </view>
-      </view>
-      <view class="flcard" v-if="isShow2">
-        <view class="typeBar">
-          <view class="icon-vent">
+        <view class="flcard" v-else>
+          <view class="typeBar">
             <text class="text-style">火灾监测预警</text>
+            <u-icon @click="toggleIsShow2" name="arrow-down-fill"></u-icon>
           </view>
-          <u-icon @click="toggleIsShow2" name="arrow-up-fill"></u-icon>
         </view>
-      </view>
-      <view class="flcard" v-else>
-        <view class="typeBar">
-          <text class="text-style">火灾监测预警</text>
-          <u-icon @click="toggleIsShow2" name="arrow-down-fill"></u-icon>
-        </view>
-      </view>
-      <view class="flcard" v-show="isShow2" @click="getDetail('fire')">
-        <view class="firecontainer">
-          <view class="title">
-            <span class="firetext">内因火灾</span>
+        <view class="flcard" v-show="isShow2" @click="getDetail('fire')">
+          <view class="firecontainer">
+            <view class="title">
+              <span class="firetext">内因火灾</span>
+            </view>
+            <view class="fire-style">
+              <view
+                v-for="(item, index) in internalInfo"
+                :key="index"
+                class="fire-item1"
+                v-if="item && Object.keys(item).length > 0"
+              >
+                <view class="firecard">
+                  <text
+                    :class="
+                      item.Maxlevel > 0 ? 'red-text-style' : 'text-style1'
+                    "
+                    >{{ item.value
+                    }}{{
+                      item.code === "o2val" ||
+                      item.code === "co2val" ||
+                      item.code === "ch4val" ||
+                      item.code === "smokeval"
+                        ? "(%)"
+                        : item.code === "fmax" ||
+                          item.code === "temperature" ||
+                          item.code === "fireval"
+                        ? "(℃)"
+                        : "(ppm)"
+                    }}
+                  </text>
+                  <view style="margin-top: 10rpx">{{ item.monitorcode }}</view>
+                </view>
+              </view>
+            </view>
           </view>
-          <view class="fire-style">
-            <view
-              v-for="(item, index) in internalInfo"
-              :key="index"
-              class="fire-item1"
-              v-if="item && Object.keys(item).length > 0"
-            >
-              <view class="firecard">
-                <text
-                  :class="item.Maxlevel > 0 ? 'red-text-style' : 'text-style1'"
-                  >{{ item.value
-                  }}{{
-                    item.code === "o2val" ||
-                    item.code === "co2val" ||
-                    item.code === "ch4val"
-                      ? "(%)"
-                      : item.code === "fmax" || item.code === "temperature"
-                      ? "(℃)"
-                      : "(ppm)"
-                  }}
-                </text>
-                <view style="margin-top: 10rpx">{{ item.name }}</view>
+          <view class="firecontainer">
+            <view class="title">
+              <span class="firetext">外因火灾</span>
+            </view>
+            <view class="fire-style">
+              <view
+                v-for="(item, index) in externalInfo"
+                :key="index"
+                class="fire-item1"
+              >
+                <view class="firecard">
+                  <text
+                    :class="
+                      item.Maxlevel > 0 ? 'red-text-style' : 'text-style1'
+                    "
+                    >{{ item.value
+                    }}{{
+                      item.code === "o2val" ||
+                      item.code === "co2val" ||
+                      item.code === "ch4val" ||
+                      item.code === "smokeval"
+                        ? "(%)"
+                        : item.code === "fmax" ||
+                          item.code === "temperature" ||
+                          item.code === "fireval"
+                        ? "(℃)"
+                        : "(ppm)"
+                    }}
+                  </text>
+                  <view style="margin-top: 10rpx">{{ item.monitorcode }}</view>
+                </view>
               </view>
             </view>
           </view>
         </view>
-        <view class="firecontainer">
-          <view class="title">
-            <span class="firetext">外因火灾</span>
-          </view>
-          <view class="fire-style">
-            <view
-              v-for="(item, index) in externalInfo"
-              :key="index"
-              class="fire-item1"
-            >
-              <view class="firecard">
-                <text
-                  :class="item.Maxlevel > 0 ? 'red-text-style' : 'text-style1'"
-                  >{{ item.value
-                  }}{{
-                    item.code === "o2val" ||
-                    item.code === "co2val" ||
-                    item.code === "ch4val"
-                      ? "(%)"
-                      : item.code === "fmax" || item.code === "temperature"
-                      ? "(℃)"
-                      : "(ppm)"
-                  }}
-                </text>
-                <view style="margin-top: 10rpx">{{ item.name }}</view>
-              </view>
+        <view class="flcard" v-if="isShow3">
+          <view class="typeBar">
+            <view class="icon-vent">
+              <text class="text-style">粉尘监测预警</text>
             </view>
+            <u-icon @click="toggleIsShow3" name="arrow-up-fill"></u-icon>
           </view>
         </view>
-      </view>
-      <view class="flcard" v-if="isShow3">
-        <view class="typeBar">
-          <view class="icon-vent">
+        <view class="flcard" v-else>
+          <view class="typeBar">
             <text class="text-style">粉尘监测预警</text>
+            <u-icon @click="toggleIsShow3" name="arrow-down-fill"></u-icon>
           </view>
-          <u-icon @click="toggleIsShow3" name="arrow-up-fill"></u-icon>
         </view>
-      </view>
-      <view class="flcard" v-else>
-        <view class="typeBar">
-          <text class="text-style">粉尘监测预警</text>
-          <u-icon @click="toggleIsShow3" name="arrow-down-fill"></u-icon>
-        </view>
-      </view>
-      <view class="flcard" v-show="isShow3" @click="getDetail('dust')">
-        <view class="firecard fire-style">
-          <view v-for="(value, key) in dustData" :key="key" class="fire-item">
-            <view style="margin-top: 20rpx">
-              <image
-                src="/static/warndata/alarm.svg"
-                class="icon-style"
-                :style="{ backgroundColor: key === 'alarm' ? 'red' : key }"
-              ></image>
-              <span style="margin-top: 10rpx">
-                {{ dustMap[key] }} :{{ value }}</span
-              >
+        <view class="flcard" v-show="isShow3" @click="getDetail('dust')">
+          <view class="firecard fire-style">
+            <view v-for="(value, key) in dustData" :key="key" class="fire-item">
+              <view style="margin-top: 20rpx">
+                <image
+                  src="/static/warndata/alarm.svg"
+                  class="icon-style"
+                  :style="{ backgroundColor: key === 'alarm' ? 'red' : key }"
+                ></image>
+                <span style="margin-top: 10rpx">
+                  {{ dustMap[key] }} :{{ value }}</span
+                >
+              </view>
             </view>
           </view>
         </view>
-      </view>
 
-      <view class="flcard" v-if="isShow4">
-        <view class="typeBar">
-          <view class="icon-vent">
-            <text class="text-style">瓦斯监测预警</text>
-          </view>
-          <u-icon @click="toggleIsShow4" name="arrow-up-fill"></u-icon>
-        </view>
-      </view>
-      <view class="flcard" v-else>
-        <view class="typeBar">
-          <text class="text-style">瓦斯监测预警</text>
-          <u-icon @click="toggleIsShow4" name="arrow-down-fill"></u-icon>
-        </view>
-      </view>
-      <view class="flcard" v-show="isShow4" @click="getDetail('gas')">
-        <view class="firecontainer">
-          <view class="title">
-            <span class="firetext" v-if="gasDevice.length > 0"
-              >安全监测系统监测点</span
-            >
-          </view>
-          <view class="gascard" v-for="(item, index) in gasDevice" :key="index">
-            <view style="margin-top: 20rpx">
-              <text class="text-style1">{{ item.gasNumber }}</text>
-              <view style="margin: 10rpx">{{ item.systemname }}</view>
+        <view class="flcard" v-if="isShow4">
+          <view class="typeBar">
+            <view class="icon-vent">
+              <text class="text-style">瓦斯监测预警</text>
             </view>
+            <u-icon @click="toggleIsShow4" name="arrow-up-fill"></u-icon>
           </view>
         </view>
-        <view class="firecontainer">
-          <view class="title">
-            <span class="firetext" v-if="gasDevice.length > 0"
-              >瓦斯抽采系统监测点</span
-            >
+        <view class="flcard" v-else>
+          <view class="typeBar">
+            <text class="text-style">瓦斯监测预警</text>
+            <u-icon @click="toggleIsShow4" name="arrow-down-fill"></u-icon>
           </view>
-          <view class="gascontainer">
+        </view>
+        <view class="flcard" v-show="isShow4" @click="getDetail('gas')">
+          <view class="firecontainer">
+            <view class="title">
+              <span class="firetext" v-if="gasDevice.length > 0"
+                >安全监测系统监测点</span
+              >
+            </view>
             <view
               class="gascard"
               v-for="(item, index) in gasDevice"
               :key="index"
             >
               <view style="margin-top: 20rpx">
-                <text class="text-style1">{{ item.pumpNumber }}</text>
+                <text class="text-style1">{{ item.gasNumber }}</text>
                 <view style="margin: 10rpx">{{ item.systemname }}</view>
               </view>
             </view>
           </view>
+          <view class="firecontainer">
+            <view class="title">
+              <span class="firetext" v-if="gasDevice.length > 0"
+                >瓦斯抽采系统监测点</span
+              >
+            </view>
+            <view class="gascontainer">
+              <view
+                class="gascard"
+                v-for="(item, index) in gasDevice"
+                :key="index"
+              >
+                <view style="margin-top: 20rpx">
+                  <text class="text-style1">{{ item.pumpNumber }}</text>
+                  <view style="margin: 10rpx">{{ item.systemname }}</view>
+                </view>
+              </view>
+            </view>
+          </view>
         </view>
-      </view>
-      <view class="flcard" v-if="isShow5">
-        <view class="typeBar">
-          <view class="icon-vent">
-            <text class="text-style">设备监测预警</text>
+        <view class="flcard" v-if="isShow5">
+          <view class="typeBar">
+            <view class="icon-vent">
+              <text class="text-style">设备监测预警</text>
+            </view>
+            <u-icon @click="toggleIsShow5" name="arrow-up-fill"></u-icon>
           </view>
-          <u-icon @click="toggleIsShow5" name="arrow-up-fill"></u-icon>
         </view>
-      </view>
-      <view class="flcard" v-else>
-        <view class="typeBar">
-          <text class="text-style">设备监测预警</text>
-          <u-icon @click="toggleIsShow5" name="arrow-down-fill"></u-icon>
+        <view class="flcard" v-else>
+          <view class="typeBar">
+            <text class="text-style">设备监测预警</text>
+            <u-icon @click="toggleIsShow5" name="arrow-down-fill"></u-icon>
+          </view>
         </view>
-      </view>
-      <view
-        class="flcard demo-layout bg-purple-light"
-        v-show="isShow5"
-        @click="getDetail('device')"
-      >
-        <view class="deviceCard">
-          <view
-            class="item-container"
-            v-for="(item, index) in devicekindData"
-            :key="index"
-            :style="{ backgroundImage: itemBackground(item) }"
-          >
-            <view class="item">
-              <text style="margin-right: 10px">{{ item.name }}</text>
-              <text>{{ item.status }}</text>
+        <view
+          class="flcard demo-layout bg-purple-light"
+          v-show="isShow5"
+          @click="getDetail('device')"
+        >
+          <view class="deviceCard">
+            <view
+              class="item-container"
+              v-for="(item, index) in devicekindData"
+              :key="index"
+              :style="{ backgroundImage: itemBackground(item) }"
+            >
+              <view class="item">
+                <text style="margin-right: 10px">{{ item.name }}</text>
+                <text>{{ item.status }}</text>
+              </view>
             </view>
           </view>
         </view>
       </view>
-    </view>
-    <view class="main" v-else>
-      <component :is="detailComponent"></component>
+      <view class="main" v-else>
+        <ventDetail v-if="Type == 'vent'"></ventDetail>
+        <deviceDetail v-if="Type == 'device'"></deviceDetail>
+        <fireDetail v-if="Type == 'fire'"></fireDetail>
+        <dustDetail v-if="Type == 'dust'"></dustDetail>
+        <gasDetail v-if="Type == 'gas'"></gasDetail>
+      </view>
     </view>
   </view>
 </template>
@@ -304,10 +324,13 @@ export default {
       isShow3: false,
       isShow4: false,
       isShow5: false,
+      Type: "", // 当前点击的类型
     };
   },
   mounted() {
-    this.getWranInfo();
+    this.$nextTick(() => {
+      this.getWarnInfo();
+    });
   },
   components: {
     ventDetail,
@@ -318,8 +341,8 @@ export default {
   },
   methods: {
     //获取预警信息
-    getWranInfo() {
-      new Promise((resolve, reject) => {
+    getWarnInfo() {
+      return new Promise((resolve, reject) => {
         api
           .getWarnInfo()
           .then((response) => {
@@ -327,8 +350,68 @@ export default {
               this.windData = response.data.result.ventInfo;
               this.devicekindData = response.data.result.info.devicekindInfo;
               this.fireData = response.data.result.info.sysInfo.fireS;
-              this.externalInfo = this.fireData.summaryInfo.external;
-              this.internalInfo = this.fireData.summaryInfo.internal;
+              const externalInfo1 = this.fireData.summaryInfo.external;
+              const internalInfo1 = this.fireData.summaryInfo.internal;
+              for (let key in externalInfo1) {
+                if (!externalInfo1.hasOwnProperty(key)) continue;
+                const item = externalInfo1[key];
+                // 跳过空对象(如 ch4val: {})
+                if (Object.keys(item).length === 0) continue;
+                if (item.code == "coval") {
+                  item.monitorcode = "一氧化碳";
+                } else if (item.code == "ch4val") {
+                  item.monitorcode = "甲烷";
+                } else if (item.code == "o2val") {
+                  item.monitorcode = "氧气";
+                } else if (item.code == "co2val") {
+                  item.monitorcode = "二氧化碳";
+                } else if (item.code == "fmax") {
+                  item.monitorcode = "温度";
+                } else if (item.code == "chval") {
+                  item.monitorcode = "乙炔";
+                } else if (item.code == "ch2val") {
+                  item.monitorcode = "乙烯";
+                } else if (item.code == "temperature") {
+                  item.monitorcode = "温度";
+                } else if (item.code == "gasval") {
+                  item.monitorcode = "瓦斯";
+                } else if (item.code == "fireval") {
+                  item.monitorcode = "温度";
+                } else if (item.code == "smokeval") {
+                  item.monitorcode = "烟雾";
+                }
+              }
+              for (let key in internalInfo1) {
+                if (!internalInfo1.hasOwnProperty(key)) continue;
+                const item = internalInfo1[key];
+                // 跳过空对象(如 ch4val: {})
+                if (Object.keys(item).length === 0) continue;
+                if (item.code == "coval") {
+                  item.monitorcode = "一氧化碳";
+                } else if (item.code == "ch4val") {
+                  item.monitorcode = "甲烷";
+                } else if (item.code == "o2val") {
+                  item.monitorcode = "氧气";
+                } else if (item.code == "co2val") {
+                  item.monitorcode = "二氧化碳";
+                } else if (item.code == "chval") {
+                  item.monitorcode = "乙炔";
+                } else if (item.code == "ch2val") {
+                  item.monitorcode = "乙烯";
+                } else if (item.code == "fmax") {
+                  item.monitorcode = "温度";
+                } else if (item.code == "temperature") {
+                  item.monitorcode = "温度";
+                } else if (item.code == "gasval") {
+                  item.monitorcode = "瓦斯";
+                } else if (item.code == "fireval") {
+                  item.monitorcode = "温度";
+                } else if (item.code == "smokeval") {
+                  item.monitorcode = "烟雾";
+                }
+              }
+              this.externalInfo = externalInfo1;
+              this.internalInfo = internalInfo1;
               this.gasData = response.data.result.info.sysInfo.gasS;
               this.gasDevice = this.gasData.devices;
               this.xufengliang = this.windData.sysdata.xufengliang;
@@ -349,17 +432,8 @@ export default {
     },
     //跳转监测详情
     getDetail(data) {
-      const componentMap = {
-        vent: { title: "通风监测预警", component: ventDetail },
-        device: { title: "设备监测预警", component: deviceDetail },
-        fire: { title: "火灾监测预警", component: fireDetail },
-        dust: { title: "粉尘监测预警", component: dustDetail },
-        gas: { title: "瓦斯监测预警", component: gasDetail },
-      };
-      const config = componentMap[data] || {};
-      this.titleName = config.title;
       this.isShowDetail = false;
-      this.detailComponent = config.component;
+      this.Type = data; // 将当前点击的类型存储到 Type 中
     },
     toggleIsShow1() {
       this.isShow1 = !this.isShow1; // 切换 isShow 的值
@@ -396,7 +470,7 @@ export default {
 }
 
 .main {
-  // margin-top: 100rpx;
+  margin-top: 80px;
   display: flex;
   flex-direction: column;
   flex: 1;

+ 320 - 0
uni_modules/qiun-data-charts/changelog.md

@@ -0,0 +1,320 @@
+## 2.5.0-20230101(2023-01-01)
+- 秋云图表组件 修改条件编译顺序,确保uniapp的cli方式的项目依赖不完整时可以正常显示
+- 秋云图表组件 恢复props属性directory的使用,以修复vue3项目中,开启echarts后,echarts目录识别错误的bug
+- uCharts.js 修复区域图、混合图只有一个数据时图表显示不正确的bug
+- uCharts.js 修复折线图、区域图中时间轴类别图表tooltip指示点显示不正确的bug
+- uCharts.js 修复x轴使用labelCount时,并且boundaryGap = 'justify' 并且关闭Y轴显示的时候,最后一个坐标值不显示的bug
+- uCharts.js 修复折线图只有一组数据时 ios16 渲染颜色不正确的bug
+- uCharts.js 修复玫瑰图半径显示不正确的bug
+- uCharts.js 柱状图、山峰图增加正负图功能,y轴网格如果需要显示0轴则由 min max 及 splitNumber 确定,后续版本优化自动显示0轴
+- uCharts.js 柱状图column增加 opts.extra.column.labelPosition,数据标签位置,有效值为 outside外部, insideTop内顶部, center内中间, bottom内底部
+- uCharts.js 雷达图radar增加 opts.extra.radar.labelShow,否显示各项标识文案是,默认true
+- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.boxPadding,提示窗边框填充距离,默认3px
+- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.fontSize,提示窗字体大小配置,默认13px
+- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.lineHeight,提示窗文字行高,默认20px
+- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.legendShow,是否显示左侧图例,默认true
+- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.legendShape,图例形状,图例标识样式,有效值为 auto自动跟随图例, diamond◆, circle●, triangle▲, square■, rect▬, line-
+- uCharts.js 标记线markLine增加 opts.extra.markLine.labelFontSize,字体大小配置,默认13px
+- uCharts.js 标记线markLine增加 opts.extra.markLine.labelPadding,标签边框内填充距离,默认6px
+- uCharts.js 折线图line增加 opts.extra.line.linearType,渐变色类型,可选值 none关闭渐变色,custom 自定义渐变色。使用自定义渐变色时请赋值serie.linearColor作为颜色值
+- uCharts.js 折线图line增加 serie.linearColor,渐变色数组,格式为2维数组[起始位置,颜色值],例如[[0,'#0EE2F8'],[0.3,'#2BDCA8'],[0.6,'#1890FF'],[1,'#9A60B4']]
+- uCharts.js 折线图line增加 opts.extra.line.onShadow,是否开启折线阴影,开启后请赋值serie.setShadow阴影设置
+- uCharts.js 折线图line增加 serie.setShadow,阴影配置,格式为4位数组:[offsetX,offsetY,blur,color]
+- uCharts.js 折线图line增加 opts.extra.line.animation,动画效果方向,可选值为vertical 垂直动画效果,horizontal 水平动画效果
+- uCharts.js X轴xAxis增加 opts.xAxis.lineHeight,X轴字体行高,默认20px
+- uCharts.js X轴xAxis增加 opts.xAxis.marginTop,X轴文字距离轴线的距离,默认0px
+- uCharts.js X轴xAxis增加 opts.xAxis.title,当前X轴标题
+- uCharts.js X轴xAxis增加 opts.xAxis.titleFontSize,标题字体大小,默认13px
+- uCharts.js X轴xAxis增加 opts.xAxis.titleOffsetY,标题纵向偏移距离,负数为向上偏移,正数向下偏移
+- uCharts.js X轴xAxis增加 opts.xAxis.titleOffsetX,标题横向偏移距离,负数为向左偏移,正数向右偏移
+- uCharts.js X轴xAxis增加 opts.xAxis.titleFontColor,标题字体颜色,默认#666666
+
+## 报错TypeError: Cannot read properties of undefined (reading 'length')
+- 如果是uni-modules版本组件,请先登录HBuilderX账号;
+- 在HBuilderX中的manifest.json,点击重新获取uniapp的appid,或者删除appid重新粘贴,重新运行;
+- 如果是cli项目请使用码云上的非uniCloud版本组件;
+- 或者添加uniCloud的依赖;
+- 或者使用原生uCharts;
+## 2.4.5-20221130(2022-11-30)
+- uCharts.js 优化tooltip当文字很多变为左侧显示时,如果画布仍显显示不下,提示框错位置变为以左侧0位置起画
+- uCharts.js 折线图修复特殊情况下只有单点数据,并改变线宽后点变为圆形的bug
+- uCharts.js 修复Y轴disabled启用后无效并报错的bug
+- uCharts.js 修复仪表盘起始结束角度特殊情况下显示不正确的bug
+- uCharts.js 雷达图新增参数 opts.extra.radar.radius , 自定义雷达图半径
+- uCharts.js 折线图、区域图增加tooltip指示点,opts.extra.line.activeType/opts.extra.area.activeType,可选值"none"不启用激活指示点,"hollow"空心点模式,"solid"实心点模式
+## 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。
+## 2.3.7-20220118(2022-01-18)
+## 注意,使用vue3的前提是需要3.3.8.20220114-alpha版本的HBuilder!
+## 2.3.67-20220118(2022-01-18)
+- 秋云图表组件 组件初步支持vue3,全端编译会有些问题,具体详见下面修改:
+1. 小程序端运行时,在uni_modules文件夹的qiun-data-charts.js中搜索 new uni_modules_qiunDataCharts_js_sdk_uCharts_uCharts.uCharts,将.uCharts去掉。
+2. 小程序端发行时,在uni_modules文件夹的qiun-data-charts.js中搜索 new e.uCharts,将.uCharts去掉,变为 new e。
+3. 如果觉得上述步骤比较麻烦,如果您的项目只编译到小程序端,可以修改u-charts.js最后一行导出方式,将 export default uCharts;变更为 export default { uCharts: uCharts }; 这样变更后,H5和App端的renderjs会有问题,请开发者自行选择。(此问题非组件问题,请等待DC官方修复Vue3的小程序端)
+## 2.3.6-20220111(2022-01-11)
+- 秋云图表组件 修改组件 props 属性中的 background 默认值为 rgba(0,0,0,0)
+## 2.3.6-20211201(2021-12-01)
+- uCharts.js 修复bar条状图开启圆角模式时,值很小时圆角渲染错误的bug
+## 2.3.5-20211014(2021-10-15)
+- uCharts.js 增加vue3的编译支持(仅原生uCharts,qiun-data-charts组件后续会支持,请关注更新)
+## 2.3.4-20211012(2021-10-12)
+- 秋云图表组件 修复 mac os x 系统 mouseover 事件丢失的 bug
+## 2.3.3-20210706(2021-07-06)
+- uCharts.js 增加雷达图开启数据点值(opts.dataLabel)的显示
+## 2.3.2-20210627(2021-06-27)
+- 秋云图表组件 修复tooltipCustom个别情况下传值不正确报错TypeError: Cannot read property 'name' of undefined的bug
+## 2.3.1-20210616(2021-06-16)
+- uCharts.js 修复圆角柱状图使用4角圆角时,当数值过大时不正确的bug
+## 2.3.0-20210612(2021-06-12)
+- uCharts.js 【重要】uCharts增加nvue兼容,可在nvue项目中使用gcanvas组件渲染uCharts,[详见码云uCharts-demo-nvue](https://gitee.com/uCharts/uCharts)
+- 秋云图表组件 增加tapLegend属性,是否开启图例点击交互事件
+- 秋云图表组件 getIndex事件中增加返回uCharts实例中的opts参数,以便在页面中调用参数
+- 示例项目 pages/other/other.vue增加app端自定义tooltip的方法,详见showOptsTooltip方法
+## 2.2.1-20210603(2021-06-03)
+- uCharts.js 修复饼图、圆环图、玫瑰图,当起始角度不为0时,tooltip位置不准确的bug
+- uCharts.js 增加温度计式柱状图开启顶部半圆形的配置
+## 2.2.0-20210529(2021-05-29)
+- uCharts.js 增加条状图type="bar"
+- 示例项目 pages/ucharts/ucharts.vue增加条状图的demo
+## 2.1.7-20210524(2021-05-24)
+- uCharts.js 修复大数据量模式下曲线图不平滑的bug
+## 2.1.6-20210523(2021-05-23)
+- 秋云图表组件 修复小程序端开启滚动条更新数据后滚动条位置不符合预期的bug
+## 2.1.5-2021051702(2021-05-17)
+- uCharts.js 修复自定义Y轴min和max值为0时不能正确显示的bug
+## 2.1.5-20210517(2021-05-17)
+- uCharts.js 修复Y轴自定义min和max时,未按指定的最大值最小值显示坐标轴刻度的bug
+## 2.1.4-20210516(2021-05-16)
+- 秋云图表组件 优化onWindowResize防抖方法
+- 秋云图表组件 修复APP端uCharts更新数据时,清空series显示loading图标后再显示图表,图表抖动的bug
+- uCharts.js 修复开启canvas2d后,x轴、y轴、series自定义字体大小未按比例缩放的bug
+- 示例项目 修复format-e.vue拼写错误导致app端使用uCharts渲染图表
+## 2.1.3-20210513(2021-05-13)
+- 秋云图表组件 修改uCharts变更chartData数据为updateData方法,支持带滚动条的数据动态打点
+- 秋云图表组件 增加onWindowResize防抖方法 fix by ど誓言,如尘般染指流年づ 
+- 秋云图表组件 H5或者APP变更chartData数据显示loading图表时,原数据闪现的bug
+- 秋云图表组件 props增加errorReload禁用错误点击重新加载的方法
+- uCharts.js 增加tooltip显示category(x轴对应点位)标题的功能,opts.extra.tooltip.showCategory,默认为false
+- uCharts.js 修复mix混合图只有柱状图时,tooltip的分割线显示位置不正确的bug
+- uCharts.js 修复开启滚动条,图表在拖动中动态打点,滚动条位置不正确的bug
+- uCharts.js 修复饼图类数据格式为echarts数据格式,series为空数组报错的bug
+- 示例项目 修改uCharts.js更新到v2.1.2版本后,@getIndex方法获取索引值变更为e.currentIndex.index
+- 示例项目 pages/updata/updata.vue增加滚动条拖动更新(数据动态打点)的demo
+- 示例项目 pages/other/other.vue增加errorReload禁用错误点击重新加载的demo
+## 2.1.2-20210509(2021-05-09)
+秋云图表组件 修复APP端初始化时就传入chartData或lacaldata不显示图表的bug
+## 2.1.1-20210509(2021-05-09)
+- 秋云图表组件 变更ECharts的eopts配置在renderjs内执行,支持在config-echarts.js配置文件内写function配置。
+- 秋云图表组件 修复APP端报错Prop being mutated: "onmouse"错误的bug。
+- 秋云图表组件 修复APP端报错Error: Not Found:Page[6][-1,27] at view.umd.min.js:1的bug。
+## 2.1.0-20210507(2021-05-07)
+- 秋云图表组件 修复初始化时就有数据或者数据更新的时候loading加载动画闪动的bug
+- uCharts.js 修复x轴format方法categories为字符串类型时返回NaN的bug
+- uCharts.js 修复series.textColor、legend.fontColor未执行全局默认颜色的bug
+## 2.1.0-20210506(2021-05-06)
+- 秋云图表组件 修复极个别情况下报错item.properties undefined的bug
+- 秋云图表组件 修复极个别情况下关闭加载动画reshow不起作用,无法显示图表的bug
+- 示例项目 pages/ucharts/ucharts.vue 增加时间轴折线图(type="tline")、时间轴区域图(type="tarea")、散点图(type="scatter")、气泡图demo(type="bubble")、倒三角形漏斗图(opts.extra.funnel.type="triangle")、金字塔形漏斗图(opts.extra.funnel.type="pyramid")
+- 示例项目 pages/format-u/format-u.vue 增加X轴format格式化示例
+- uCharts.js 升级至v2.1.0版本
+- uCharts.js 修复 玫瑰图面积模式点击tooltip位置不正确的bug
+- uCharts.js 修复 玫瑰图点击图例,只剩一个类别显示空白的bug
+- uCharts.js 修复 饼图类图点击图例,其他图表tooltip位置某些情况下不准的bug
+- uCharts.js 修复 x轴为矢量轴(时间轴)情况下,点击tooltip位置不正确的bug
+- uCharts.js 修复 词云图获取点击索引偶尔不准的bug
+- uCharts.js 增加 直角坐标系图表X轴format格式化方法(原生uCharts.js用法请使用formatter)
+- uCharts.js 增加 漏斗图扩展配置,倒三角形(opts.extra.funnel.type="triangle"),金字塔形(opts.extra.funnel.type="pyramid")
+- uCharts.js 增加 散点图(opts.type="scatter")、气泡图(opts.type="bubble")
+- 后期计划 完善散点图、气泡图,增加markPoints标记点,增加横向条状图。
+## 2.0.0-20210502(2021-05-02)
+- uCharts.js 修复词云图获取点击索引不正确的bug
+## 2.0.0-20210501(2021-05-01)
+- 秋云图表组件 修复QQ小程序、百度小程序在关闭动画效果情况下,v-for循环使用图表,显示不正确的bug
+## 2.0.0-20210426(2021-04-26)
+- 秋云图表组件 修复QQ小程序不支持canvas2d的bug
+- 秋云图表组件 修复钉钉小程序某些情况点击坐标计算错误的bug
+- uCharts.js 增加 extra.column.categoryGap 参数,柱状图类每个category点位(X轴点)柱子组之间的间距
+- uCharts.js 增加 yAxis.data[i].titleOffsetY 参数,标题纵向偏移距离,负数为向上偏移,正数向下偏移
+- uCharts.js 增加 yAxis.data[i].titleOffsetX 参数,标题横向偏移距离,负数为向左偏移,正数向右偏移
+- uCharts.js 增加 extra.gauge.labelOffset 参数,仪表盘标签文字径向便宜距离,默认13px
+## 2.0.0-20210422-2(2021-04-22)
+秋云图表组件 修复 formatterAssign 未判断 args[key] == null 的情况导致栈溢出的 bug
+## 2.0.0-20210422(2021-04-22)
+- 秋云图表组件 修复H5、APP、支付宝小程序、微信小程序canvas2d模式下横屏模式的bug
+## 2.0.0-20210421(2021-04-21)
+- uCharts.js 修复多行图例的情况下,图例在上方或者下方时,图例float为左侧或者右侧时,第二行及以后的图例对齐方式不正确的bug
+## 2.0.0-20210420(2021-04-20)
+- 秋云图表组件 修复微信小程序开启canvas2d模式后,windows版微信小程序不支持canvas2d模式的bug
+- 秋云图表组件 修改非uni_modules版本为v2.0版本qiun-data-charts组件
+## 2.0.0-20210419(2021-04-19)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
+## 初次使用如果提示未注册&lt;qiun-data-charts&gt;组件,请重启HBuilderX,如仍不好用,请重启电脑;
+## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。
+## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。
+## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn)
+## <font color=#FF0000> 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! </font> 
+## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
+## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- uCharts.js 修复混合图中柱状图单独设置颜色不生效的bug
+- uCharts.js 修复多Y轴单独设置fontSize时,开启canvas2d后,未对应放大字体的bug
+## 2.0.0-20210418(2021-04-18)
+- 秋云图表组件 增加directory配置,修复H5端history模式下如果发布到二级目录无法正确加载echarts.min.js的bug
+## 2.0.0-20210416(2021-04-16)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
+## 初次使用如果提示未注册&lt;qiun-data-charts&gt;组件,请重启HBuilderX,如仍不好用,请重启电脑;
+## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。
+## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。
+## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn)
+## <font color=#FF0000> 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! </font> 
+## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
+## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- 秋云图表组件 修复APP端某些情况下报错`Not Found Page`的bug,fix by 高级bug开发技术员
+- 示例项目 修复APP端v-for循环某些情况下报错`Not Found Page`的bug,fix by 高级bug开发技术员
+- uCharts.js 修复非直角坐标系tooltip提示窗右侧超出未变换方向显示的bug
+## 2.0.0-20210415(2021-04-15)
+- 秋云图表组件 修复H5端发布到二级目录下echarts无法加载的bug
+- 秋云图表组件 修复某些情况下echarts.off('finished')移除监听事件报错的bug
+## 2.0.0-20210414(2021-04-14)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
+## 初次使用如果提示未注册&lt;qiun-data-charts&gt;组件,请重启HBuilderX,如仍不好用,请重启电脑;
+## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。
+## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。
+## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn)
+## <font color=#FF0000> 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! </font> 
+## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
+## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- 秋云图表组件 修复H5端在cli项目下ECharts引用地址错误的bug
+- 示例项目 增加ECharts的formatter用法的示例(详见示例项目format-e.vue)
+- uCharts.js 增加圆环图中心背景色的配置extra.ring.centerColor
+- uCharts.js 修复微信小程序安卓端柱状图开启透明色后显示不正确的bug
+## 2.0.0-20210413(2021-04-13)
+- 秋云图表组件 修复百度小程序多个图表真机未能正确获取根元素dom尺寸的bug
+- 秋云图表组件 修复百度小程序横屏模式方向不正确的bug
+- 秋云图表组件 修改ontouch时,@getTouchStart@getTouchMove@getTouchEnd的触发条件
+- uCharts.js 修复饼图类数据格式series属性不生效的bug
+- uCharts.js 增加时序区域图 详见示例项目中ucharts.vue
+## 2.0.0-20210412-2(2021-04-12)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
+## 初次使用如果提示未注册&lt;qiun-data-charts&gt;组件,请重启HBuilderX。如仍不好用,请重启电脑,此问题已于DCloud官方确认,HBuilderX下个版本会修复。
+## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
+## [图表组件在uniCloudAdmin中的应用 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- 秋云图表组件 修复uCharts在APP端横屏模式下不能正确渲染的bug
+- 示例项目 增加ECharts柱状图渐变色、圆角柱状图、横向柱状图(条状图)的示例
+## 2.0.0-20210412(2021-04-12)
+- 秋云图表组件 修复created中判断echarts导致APP端无法识别,改回mounted中判断echarts初始化
+- uCharts.js 修复2d模式下series.textOffset未乘像素比的bug
+## 2.0.0-20210411(2021-04-11)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
+## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,并清空小程序开发者工具缓存。
+## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
+## [图表组件在uniCloudAdmin中的应用 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- uCharts.js 折线图区域图增加connectNulls断点续连的功能,详见示例项目中ucharts.vue
+- 秋云图表组件 变更初始化方法为created,变更type2d默认值为true,优化2d模式下组件初始化后dom获取不到的bug
+- 秋云图表组件 修复左右布局时,右侧图表点击坐标错误的bug,修复tooltip柱状图自定义颜色显示object的bug
+## 2.0.0-20210410(2021-04-10)
+- 修复左右布局时,右侧图表点击坐标错误的bug,修复柱状图自定义颜色tooltip显示object的bug
+- 增加标记线及柱状图自定义颜色的demo
+## 2.0.0-20210409(2021-04-08)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧【使用HBuilderX导入插件】即可体验,DEMO演示及在线生成工具(v2.0文档)[https://demo.ucharts.cn](https://demo.ucharts.cn)
+## 图表组件在uniCloudAdmin中的应用 [UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- uCharts.js 修复钉钉小程序百度小程序measureText不准确的bug,修复2d模式下饼图类activeRadius为按比例放大的bug
+- 修复组件在支付宝小程序端点击位置不准确的bug
+## 2.0.0-20210408(2021-04-07)
+- 修复组件在支付宝小程序端不能显示的bug(目前支付宝小程不能点击交互,后续修复)
+- uCharts.js 修复高分屏下柱状图类,圆弧进度条 自定义宽度不能按比例放大的bug
+## 2.0.0-20210407(2021-04-06)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧【使用HBuilderX导入插件】即可体验,DEMO演示及在线生成工具(v2.0文档)[https://demo.ucharts.cn](https://demo.ucharts.cn)
+## 增加 通过tofix和unit快速格式化y轴的demo add by `howcode`
+## 增加 图表组件在uniCloudAdmin中的应用 [UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+## 2.0.0-20210406(2021-04-05)
+# 秋云图表组件+uCharts v2.0版本同步上线,使用方法详见https://demo.ucharts.cn帮助页
+## 2.0.0(2021-04-05)
+# 秋云图表组件+uCharts v2.0版本同步上线,使用方法详见https://demo.ucharts.cn帮助页

+ 1618 - 0
uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue

@@ -0,0 +1,1618 @@
+<!-- 
+ * qiun-data-charts 秋云高性能跨全端图表组件
+ * Copyright (c) 2021 QIUN® 秋云 https://www.ucharts.cn All rights reserved.
+ * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+ * 复制使用请保留本段注释,感谢支持开源!
+ * 为方便更多开发者使用,如有更好的建议请提交码云 Pull Requests !
+ *
+ * uCharts®官方网站
+ * https://www.uCharts.cn
+ * 
+ * 开源地址:
+ * https://gitee.com/uCharts/uCharts
+ * 
+ * uni-app插件市场地址:
+ * http://ext.dcloud.net.cn/plugin?id=271
+ * 
+ -->
+<template>
+  <view class="chartsview" :id="'ChartBoxId'+cid">
+    <view v-if="mixinDatacomLoading">
+      <!-- 自定义加载状态,请改这里 -->
+      <qiun-loading :loadingType="loadingType" />
+    </view>
+    <view v-if="mixinDatacomErrorMessage && errorShow" @tap="reloading">
+      <!-- 自定义错误提示,请改这里 -->
+      <qiun-error :errorMessage="errorMessage" />
+    </view>
+    <!-- APP和H5采用renderjs渲染图表 -->
+    <!-- #ifdef APP-VUE || H5 -->
+    <block v-if="echarts">
+      <view
+        :style="{ background: background }"
+        style="width: 100%;height: 100%;"
+        :data-directory="directory"
+        :id="'EC'+cid" 
+        :prop="echartsOpts" 
+        :change:prop="rdcharts.ecinit" 
+        :resize="echartsResize"
+        :change:resize="rdcharts.ecresize"
+        v-show="showchart"
+      />
+    </block>
+    <block v-else>
+      <view
+        v-on:tap="rdcharts.tap"
+        v-on:mousemove="rdcharts.mouseMove"
+        v-on:mousedown="rdcharts.mouseDown"
+        v-on:mouseup="rdcharts.mouseUp"
+        v-on:touchstart="rdcharts.touchStart"
+        v-on:touchmove="rdcharts.touchMove"
+        v-on:touchend="rdcharts.touchEnd"
+        :id="'UC'+cid"
+        :prop="uchartsOpts"
+        :change:prop="rdcharts.ucinit"
+      >
+        <canvas
+          :id="cid"
+          :canvasId="cid"
+          :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
+          :disable-scroll="disableScroll"
+          @error="_error"
+          v-show="showchart"
+        />
+      </view>
+    </block>
+    <!-- #endif -->
+    <!-- 支付宝小程序 -->
+    <!-- #ifdef MP-ALIPAY -->
+    <block v-if="ontouch">
+      <canvas
+        :id="cid"
+        :canvasId="cid"
+        :width="cWidth * pixel"
+        :height="cHeight * pixel"
+        :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
+        :disable-scroll="disScroll"
+        @tap="_tap"
+        @touchstart="_touchStart"
+        @touchmove="_touchMove"
+        @touchend="_touchEnd"
+        @error="_error"
+        v-show="showchart"
+      />
+    </block>
+    <block v-if="!ontouch">
+      <canvas
+        :id="cid"
+        :canvasId="cid"
+        :width="cWidth * pixel"
+        :height="cHeight * pixel"
+        :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
+        :disable-scroll="disScroll"
+        @tap="_tap"
+        @error="_error"
+        v-show="showchart"
+      />
+    </block>
+    <!-- #endif -->
+    <!-- 其他小程序通过vue渲染图表 -->
+    <!-- #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-TOUTIAO || MP-KUAISHOU || MP-LARK || MP-JD || MP-360 -->
+    <block v-if="type2d">
+      <view v-if="ontouch" @tap="_tap">
+        <canvas
+          :id="cid"
+          :canvasId="cid"
+          :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
+          type="2d"
+          :disable-scroll="disScroll"
+          @touchstart="_touchStart"
+          @touchmove="_touchMove"
+          @touchend="_touchEnd"
+          @error="_error"
+          v-show="showchart"
+        />
+      </view>
+      <view v-if="!ontouch" @tap="_tap">
+        <canvas
+          :id="cid"
+          :canvasId="cid"
+          :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
+          type="2d"
+          :disable-scroll="disScroll"
+          @error="_error"
+          v-show="showchart"
+        />
+      </view>
+    </block>
+    <block v-if="!type2d">
+      <view v-if="ontouch" @tap="_tap">
+        <canvas
+          :id="cid"
+          :canvasId="cid"
+          :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
+          @touchstart="_touchStart"
+          @touchmove="_touchMove"
+          @touchend="_touchEnd"
+          :disable-scroll="disScroll"
+          @error="_error"
+          v-if="showchart"
+        />
+      </view>
+      <view v-if="!ontouch" >
+        <canvas
+          :id="cid"
+          :canvasId="cid"
+          :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
+          :disable-scroll="disScroll"
+          @tap="_tap"
+          @error="_error"
+          v-if="showchart"
+        />
+      </view>
+    </block>
+    <!-- #endif -->
+  </view>
+</template>
+
+<script>
+import uCharts from '../../js_sdk/u-charts/u-charts.js';
+import cfu from '../../js_sdk/u-charts/config-ucharts.js';
+// #ifdef APP-VUE || H5
+import cfe from '../../js_sdk/u-charts/config-echarts.js';
+// #endif
+
+function deepCloneAssign(origin = {}, ...args) {
+  for (let i in args) {
+    for (let key in args[i]) {
+      if (args[i].hasOwnProperty(key)) {
+        origin[key] = args[i][key] && typeof args[i][key] === 'object' ? deepCloneAssign(Array.isArray(args[i][key]) ? [] : {}, origin[key], args[i][key]) : args[i][key];
+      }
+    }
+  }
+  return origin;
+}
+
+function formatterAssign(args,formatter) {
+  for (let key in args) {
+    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;
+    }
+  }
+  return args;
+}
+
+// 时间转换函数,为了匹配uniClinetDB读取出的时间与categories不同
+function getFormatDate(date) {
+	var seperator = "-";
+	var year = date.getFullYear();
+	var month = date.getMonth() + 1;
+	var strDate = date.getDate();
+	if (month >= 1 && month <= 9) {
+			month = "0" + month;
+	}
+	if (strDate >= 0 && strDate <= 9) {
+			strDate = "0" + strDate;
+	}
+	var currentdate = year + seperator + month + seperator + strDate;
+	return currentdate;
+}
+
+var lastMoveTime = null;
+/**
+ * 防抖
+ *
+ * @param { Function } fn 要执行的方法
+ * @param { Number } wait  防抖多少毫秒
+ *
+ * 在 vue 中使用(注意:不能使用箭头函数,否则this指向不对,并且不能再次封装如:
+ * move(){  // 错误调用方式
+ *   debounce(function () {
+ *   console.log(this.title);
+ * }, 1000)});
+ * 应该直接使用:// 正确调用方式
+ * move: debounce(function () {
+ *   console.log(this.title);
+ * }, 1000)
+ */
+function debounce(fn, wait) {
+  let timer = false;
+  return function() {
+    clearTimeout(timer);
+    timer && clearTimeout(timer);
+    timer = setTimeout(() => {
+      timer = false;
+      fn.apply(this, arguments); // 把参数传进去
+    }, wait);
+  };
+}
+
+export default {
+  name: 'qiun-data-charts',
+  mixins: [uniCloud.mixinDatacom],
+  props: {
+    type: {
+      type: String,
+      default: null
+    },
+    canvasId: {
+      type: String,
+      default: 'uchartsid'
+    },
+    canvas2d: {
+      type: Boolean,
+      default: false
+    },
+    background: {
+      type: String,
+      default: 'rgba(0,0,0,0)'
+    },
+    animation: {
+      type: Boolean,
+      default: true
+    },
+    chartData: {
+      type: Object,
+      default() {
+        return {
+          categories: [],
+          series: []
+        };
+      }
+    },
+    opts: {
+      type: Object,
+      default() {
+        return {};
+      }
+    },
+    eopts: {
+      type: Object,
+      default() {
+        return {};
+      }
+    },
+    loadingType: {
+      type: Number,
+      default: 2
+    },
+    errorShow: {
+      type: Boolean,
+      default: true
+    },
+    errorReload: {
+      type: Boolean,
+      default: true
+    },
+    errorMessage: {
+      type: String,
+      default: null
+    },
+    inScrollView: {
+      type: Boolean,
+      default: false
+    },
+    reshow: {
+      type: Boolean,
+      default: false
+    },
+    reload: {
+      type: Boolean,
+      default: false
+    },
+    disableScroll: {
+      type: Boolean,
+      default: false
+    },
+    optsWatch: {
+      type: Boolean,
+      default: true
+    },
+    onzoom: {
+      type: Boolean,
+      default: false
+    },
+    ontap: {
+      type: Boolean,
+      default: true
+    },
+    ontouch: {
+      type: Boolean,
+      default: false
+    },
+    onmouse: {
+      type: Boolean,
+      default: true
+    },
+    onmovetip: {
+      type: Boolean,
+      default: false
+    },
+    echartsH5: {
+      type: Boolean,
+      default: false
+    },
+    echartsApp: {
+      type: Boolean,
+      default: false
+    },
+    tooltipShow: {
+      type: Boolean,
+      default: true
+    },
+    tooltipFormat: {
+      type: String,
+      default: undefined
+    },
+    tooltipCustom: {
+      type: Object,
+      default: undefined
+    },
+    startDate: {
+      type: String,
+      default: undefined
+    },
+    endDate: {
+      type: String,
+      default: undefined
+    },
+    textEnum: {
+      type: Array,
+      default () {
+        return []
+      }
+    },
+    groupEnum: {
+      type: Array,
+      default () {
+        return []
+      }
+    },
+    pageScrollTop: {
+      type: Number,
+      default: 0
+    },
+    directory: {
+      type: String,
+      default: '/'
+    },
+    tapLegend: {
+      type: Boolean,
+      default: true
+    },
+    menus: {
+      type: Array,
+      default () {
+        return []
+      }
+    }
+  },
+  data() {
+    return {
+      cid: 'uchartsid',
+      inWx: false,
+      inAli: false,
+      inTt: false,
+      inBd: false,
+      inH5: false,
+      inApp: false,
+      inWin: false,
+      type2d: true,
+      disScroll: false,
+      openmouse: false,
+      pixel: 1,
+      cWidth: 375,
+      cHeight: 250,
+      showchart: false,
+      echarts: false,
+      echartsResize:{
+        state:false
+      },
+      uchartsOpts: {},
+      echartsOpts: {},
+      drawData:{},
+      lastDrawTime:null,
+    };
+  },
+  created(){
+    this.cid = this.canvasId
+    if (this.canvasId == 'uchartsid' || this.canvasId == '') {
+      let t = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
+      let len = t.length
+      let id = ''
+      for (let i = 0; i < 32; i++) {
+        id += t.charAt(Math.floor(Math.random() * len))
+      }
+      this.cid = id
+    }
+    const systemInfo = uni.getSystemInfoSync()
+    if(systemInfo.platform === 'windows' || systemInfo.platform === 'mac'){
+      this.inWin = true;
+    }
+    // #ifdef MP-WEIXIN
+    this.inWx = true;
+    if (this.canvas2d === false || systemInfo.platform === 'windows' || systemInfo.platform === 'mac') {
+      this.type2d = false;
+    }else{
+      this.type2d = true;
+      this.pixel = systemInfo.pixelRatio;
+    }
+    // #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;
+    this.pixel = systemInfo.pixelRatio;
+    // #endif
+    // #ifdef MP-BAIDU
+    this.inBd = true;
+    // #endif
+    // #ifdef MP-TOUTIAO
+    this.inTt = true;
+    // #endif
+    this.disScroll = this.disableScroll;
+  },
+  mounted() {
+    // #ifdef APP-VUE
+    this.inApp = true;
+    if (this.echartsApp === true) {
+      this.echarts = true;
+      this.openmouse = false;
+    }
+    // #endif
+    // #ifdef APP-NVUE
+    this.inApp = true;
+    this.mixinDatacomLoading = false
+    this.mixinDatacomErrorMessage = "暂不支持NVUE"
+    // #endif
+    // #ifdef H5
+    this.inH5 = true;
+    if(this.inWin === true){
+      this.openmouse = this.onmouse;
+    }
+    if (this.echartsH5 === true) {
+      this.echarts = true;
+    }
+    // #endif
+    this.$nextTick(()=>{
+      this.beforeInit();
+    })
+    // #ifndef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || APP-VUE
+    const time = this.inH5 ? 500 : 200;
+    const _this = this;
+    uni.onWindowResize(
+      debounce(function(res) {
+        if (_this.mixinDatacomLoading == true) {
+          return;
+        }
+        let errmsg = _this.mixinDatacomErrorMessage;
+        if (errmsg !== null && errmsg !== 'null' && errmsg !== '') {
+          return;
+        }
+        if (_this.echarts) {
+          _this.echartsResize.state = !_this.echartsResize.state;
+        } else {
+          _this.resizeHandler();
+        }
+      }, time)
+    );
+    // #endif
+  },
+  destroyed(){
+    if(this.echarts === true){
+      delete cfe.option[this.cid]
+      delete cfe.instance[this.cid]
+    }else{
+      delete cfu.option[this.cid]
+      delete cfu.instance[this.cid]
+    }
+    // #ifndef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO
+    uni.offWindowResize(()=>{})
+    // #endif
+  },
+  watch: {
+    chartDataProps: {
+      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.showchart = false;
+              this.mixinDatacomErrorMessage = null;
+            }
+          }
+        } else {
+          this.mixinDatacomLoading = false;
+          this._clearChart();
+          this.showchart = false;
+          this.mixinDatacomErrorMessage = '参数错误:chartData数据类型错误';
+        }
+      },
+      immediate: false,
+      deep: true
+    },
+    localdata:{
+      handler(val, oldval) {
+        if (JSON.stringify(val) !== JSON.stringify(oldval)) {
+          if (val.length > 0) {
+            this.beforeInit();
+          }else{
+            this.mixinDatacomLoading = true;
+            this._clearChart();
+            this.showchart = false;
+            this.mixinDatacomErrorMessage = null;
+          }
+        }
+      },
+      immediate: false,
+      deep: true
+    },
+    optsProps: {
+      handler(val, oldval) {
+        if (typeof val === 'object') {
+          if (JSON.stringify(val) !== JSON.stringify(oldval) && this.echarts === false && this.optsWatch == true) {
+            this.checkData(this.drawData);
+          }
+        } else {
+          this.mixinDatacomLoading = false;
+          this._clearChart();
+          this.showchart = false;
+          this.mixinDatacomErrorMessage = '参数错误:opts数据类型错误';
+        }
+      },
+      immediate: false,
+      deep: true
+    },
+    eoptsProps: {
+      handler(val, oldval) {
+        if (typeof val === 'object') {
+          if (JSON.stringify(val) !== JSON.stringify(oldval) && this.echarts === true) {
+            this.checkData(this.drawData);
+          }
+        } else {
+          this.mixinDatacomLoading = false;
+          this.showchart = false;
+          this.mixinDatacomErrorMessage = '参数错误:eopts数据类型错误';
+        }
+      },
+      immediate: false,
+      deep: true
+    },
+    reshow(val, oldval) {
+      if (val === true && this.mixinDatacomLoading === false) {
+        setTimeout(() => {
+          this.mixinDatacomErrorMessage = null;
+          this.echartsResize.state = !this.echartsResize.state;
+          this.checkData(this.drawData);
+        }, 200);
+      }
+    },
+    reload(val, oldval) {
+      if (val === true) {
+        this.showchart = false;
+        this.mixinDatacomErrorMessage = null;
+        this.reloading();
+      }
+    },
+    mixinDatacomErrorMessage(val, oldval) {
+      if (val) {
+        this.emitMsg({name: 'error', params: {type:"error", errorShow: this.errorShow, msg: val, id: this.cid}});
+        if(this.errorShow){
+          console.log('[秋云图表组件]' + val);
+        }
+      }
+    },
+    errorMessage(val, oldval) {
+      if (val && this.errorShow && val !== null && val !== 'null' && val !== '') {
+        this.showchart = false;
+        this.mixinDatacomLoading = false;
+        this.mixinDatacomErrorMessage = val;
+      } else {
+        this.showchart = false;
+        this.mixinDatacomErrorMessage = null;
+        this.reloading();
+      }
+    }
+  },
+  computed: {
+    optsProps() {
+      return JSON.parse(JSON.stringify(this.opts));
+    },
+    eoptsProps() {
+      return JSON.parse(JSON.stringify(this.eopts));
+    },
+    chartDataProps() {
+      return JSON.parse(JSON.stringify(this.chartData));
+    },
+  },
+  methods: {
+    beforeInit(){
+      this.mixinDatacomErrorMessage = null;
+      if (typeof this.chartData === 'object' && this.chartData != null && this.chartData.series !== undefined && this.chartData.series.length > 0) {
+        //拷贝一下chartData,为了opts变更后统一数据来源
+        this.drawData = deepCloneAssign({}, this.chartData);
+        this.mixinDatacomLoading = false;
+        this.showchart = true;
+        this.checkData(this.chartData);
+      }else if(this.localdata.length>0){
+        this.mixinDatacomLoading = false;
+        this.showchart = true;
+        this.localdataInit(this.localdata);
+      }else if(this.collection !== ''){
+        this.mixinDatacomLoading = false;
+        this.getCloudData();
+      }else{
+        this.mixinDatacomLoading = true;
+      }
+    },
+    localdataInit(resdata){
+      //替换enum类型为正确的描述
+      if(this.groupEnum.length>0){
+        for (let i = 0; i < resdata.length; i++) {
+          for (let j = 0; j < this.groupEnum.length; j++) {
+            if(resdata[i].group === this.groupEnum[j].value){
+              resdata[i].group = this.groupEnum[j].text
+            }
+          }
+        }
+      }
+      if(this.textEnum.length>0){
+        for (let i = 0; i < resdata.length; i++) {
+          for (let j = 0; j < this.textEnum.length; j++) {
+            if(resdata[i].text === this.textEnum[j].value){
+              resdata[i].text = this.textEnum[j].text
+            }
+          }
+        }
+      }
+      let needCategories = false;
+      let tmpData = {categories:[], series:[]}
+      let tmpcategories = []
+      let tmpseries = [];
+      //拼接categories
+      if(this.echarts === true){
+        needCategories = cfe.categories.includes(this.type)
+      }else{
+        needCategories = cfu.categories.includes(this.type)
+      }
+      if(needCategories === true){
+        //如果props中的chartData带有categories,则优先使用chartData的categories
+        if(this.chartData && this.chartData.categories && this.chartData.categories.length>0){
+          tmpcategories = this.chartData.categories
+        }else{
+          //如果是日期类型的数据,不管是本地数据还是云数据,都按起止日期自动拼接categories
+          if(this.startDate && this.endDate){
+            let idate = new Date(this.startDate)
+            let edate = new Date(this.endDate)
+            while (idate <= edate) {
+            	tmpcategories.push(getFormatDate(idate))
+            	idate = idate.setDate(idate.getDate() + 1)
+            	idate = new Date(idate)
+            }
+          //否则从结果中去重并拼接categories
+          }else{
+            let tempckey = {};
+            resdata.map(function(item, index) {
+              if (item.text != undefined && !tempckey[item.text]) {
+                tmpcategories.push(item.text)
+                tempckey[item.text] = true
+              }
+            });
+          }
+        }
+        tmpData.categories = tmpcategories
+      }
+      //拼接series
+      let tempskey = {};
+      resdata.map(function(item, index) {
+        if (item.group != undefined && !tempskey[item.group]) {
+          tmpseries.push({ name: item.group, data: [] });
+          tempskey[item.group] = true;
+        }
+      });
+      //如果没有获取到分组名称(可能是带categories的数据,也可能是不带的饼图类)
+      if (tmpseries.length == 0) {
+        tmpseries = [{ name: '默认分组', data: [] }];
+        //如果是需要categories的图表类型
+        if(needCategories === true){
+          for (let j = 0; j < tmpcategories.length; j++) {
+            let seriesdata = 0;
+            for (let i = 0; i < resdata.length; i++) {
+              if (resdata[i].text == tmpcategories[j]) {
+                seriesdata = resdata[i].value;
+              }
+            }
+            tmpseries[0].data.push(seriesdata);
+          }
+        //如果是饼图类的图表类型
+        }else{
+          for (let i = 0; i < resdata.length; i++) {
+            tmpseries[0].data.push({"name": resdata[i].text,"value": resdata[i].value});
+          }
+        }
+      //如果有分组名
+      } else {
+        for (let k = 0; k < tmpseries.length; k++) {
+          //如果有categories
+          if (tmpcategories.length > 0) {
+            for (let j = 0; j < tmpcategories.length; j++) {
+              let seriesdata = 0;
+              for (let i = 0; i < resdata.length; i++) {
+                if (tmpseries[k].name == resdata[i].group && resdata[i].text == tmpcategories[j]) {
+                  seriesdata = resdata[i].value;
+                }
+              }
+              tmpseries[k].data.push(seriesdata);
+            }
+          //如果传了group而没有传text,即没有categories(正常情况下这种数据是不符合数据要求规范的)
+          } else {
+            for (let i = 0; i < resdata.length; i++) {
+              if (tmpseries[k].name == resdata[i].group) {
+                tmpseries[k].data.push(resdata[i].value);
+              }
+            }
+          }
+        }
+      }
+      tmpData.series = tmpseries
+      //拷贝一下chartData,为了opts变更后统一数据来源
+      this.drawData = deepCloneAssign({}, tmpData);
+      this.checkData(tmpData)
+    },
+    reloading() {
+      if(this.errorReload === false){
+        return;
+      }
+      this.showchart = false;
+      this.mixinDatacomErrorMessage = null;
+      if (this.collection !== '') {
+        this.mixinDatacomLoading = false;
+        this.onMixinDatacomPropsChange(true);
+      } else {
+        this.beforeInit();
+      }
+    },
+    checkData(anyData) {
+      let cid = this.cid
+      //复位opts或eopts
+      if(this.echarts === true){
+        cfe.option[cid] = deepCloneAssign({}, this.eopts);
+        cfe.option[cid].id = cid;
+        cfe.option[cid].type = this.type;
+      }else{
+        if (this.type && cfu.type.includes(this.type)) {
+          cfu.option[cid] = deepCloneAssign({}, cfu[this.type], this.opts);
+          cfu.option[cid].canvasId = cid;
+        } else {
+          this.mixinDatacomLoading = false;
+          this.showchart = false;
+          this.mixinDatacomErrorMessage = '参数错误:props参数中type类型不正确';
+        }
+      }
+      //挂载categories和series
+      let newData = deepCloneAssign({}, anyData);
+      if (newData.series !== undefined && newData.series.length > 0) {
+        this.mixinDatacomErrorMessage = null;
+        if (this.echarts === true) {
+          cfe.option[cid].chartData = newData;
+          this.$nextTick(()=>{
+            this.init()
+          })
+        }else{
+          cfu.option[cid].categories = newData.categories;
+          cfu.option[cid].series = newData.series;
+          this.$nextTick(()=>{
+            this.init()
+          })
+        }
+      }
+    },
+    resizeHandler() {
+      //渲染防抖
+      let currTime = Date.now();
+      let lastDrawTime = this.lastDrawTime?this.lastDrawTime:currTime-3000;
+      let duration = currTime - lastDrawTime;
+      if (duration < 1000) return;
+      let chartdom = uni
+        .createSelectorQuery()
+        // #ifndef MP-ALIPAY
+        .in(this)
+        // #endif
+        .select('#ChartBoxId'+this.cid)
+        .boundingClientRect(data => {
+          this.showchart = true;
+          if (data.width > 0 && data.height > 0) {
+            if (data.width !== this.cWidth || data.height !== this.cHeight) {
+              this.checkData(this.drawData)
+            }
+          }
+        })
+        .exec();
+    },
+    getCloudData() {
+      if (this.mixinDatacomLoading == true) {
+        return;
+      }
+      this.mixinDatacomLoading = true;
+      this.mixinDatacomGet()
+        .then(res => {
+          this.mixinDatacomResData = res.result.data;
+          this.localdataInit(this.mixinDatacomResData);
+        })
+        .catch(err => {
+          this.mixinDatacomLoading = false;
+          this.showchart = false;
+          this.mixinDatacomErrorMessage = '请求错误:' + err;
+        });
+    },
+    onMixinDatacomPropsChange(needReset, changed) {
+      if (needReset == true && this.collection !== '') {
+        this.showchart = false;
+        this.mixinDatacomErrorMessage = null;
+        this._clearChart();
+        this.getCloudData();
+      }
+    },
+    _clearChart() {
+      let cid = this.cid
+      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() {
+      let cid = this.cid
+      let chartdom = uni
+        .createSelectorQuery()
+        // #ifndef MP-ALIPAY
+        .in(this)
+        // #endif
+        .select('#ChartBoxId'+cid)
+        .boundingClientRect(data => {
+          if (data.width > 0 && data.height > 0) {
+            this.mixinDatacomLoading = false;
+            this.showchart = true;
+            this.lastDrawTime = Date.now();
+            this.cWidth = data.width;
+            this.cHeight = data.height;
+            if(this.echarts !== true){
+              cfu.option[cid].background = this.background == 'rgba(0,0,0,0)' ? '#FFFFFF' : this.background;
+              cfu.option[cid].canvas2d = this.type2d;
+              cfu.option[cid].pixelRatio = this.pixel;
+              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;
+              cfu.option[cid].onmovetip = this.onmovetip;
+              cfu.option[cid].tooltipShow = this.tooltipShow;
+              cfu.option[cid].tooltipFormat = this.tooltipFormat;
+              cfu.option[cid].tooltipCustom = this.tooltipCustom;
+              cfu.option[cid].inScrollView = this.inScrollView;
+              cfu.option[cid].lastDrawTime = this.lastDrawTime;
+              cfu.option[cid].tapLegend = this.tapLegend;
+            }
+            //如果是H5或者App端,采用renderjs渲染图表
+            if (this.inH5 || this.inApp) {
+              if (this.echarts == true) {
+                cfe.option[cid].ontap = this.ontap;
+                cfe.option[cid].onmouse = this.openmouse;
+                cfe.option[cid].tooltipShow = this.tooltipShow;
+                cfe.option[cid].tooltipFormat = this.tooltipFormat;
+                cfe.option[cid].tooltipCustom = this.tooltipCustom;
+                cfe.option[cid].lastDrawTime = this.lastDrawTime;
+                this.echartsOpts = deepCloneAssign({}, cfe.option[cid]);
+              } else {
+                cfu.option[cid].rotateLock = cfu.option[cid].rotate;
+                this.uchartsOpts = deepCloneAssign({}, cfu.option[cid]);
+              }
+            //如果是小程序端,采用uCharts渲染
+            } else {
+              cfu.option[cid] = formatterAssign(cfu.option[cid],cfu.formatter)
+              this.mixinDatacomErrorMessage = null;
+              this.mixinDatacomLoading = false;
+              this.showchart = true;
+              this.$nextTick(()=>{
+                if (this.type2d === true) {
+                  const query = uni.createSelectorQuery().in(this)
+                  query
+                    .select('#' + cid)
+                    .fields({ node: true, size: true })
+                    .exec(res => {
+                      if (res[0]) {
+                        const canvas = res[0].node;
+                        const ctx = canvas.getContext('2d');
+                        cfu.option[cid].context = ctx;
+                        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();
+                            this._newChart(cid)
+                          },100)
+                        }
+                      } else {
+                        this.showchart = false;
+                        this.mixinDatacomErrorMessage = '参数错误:开启2d模式后,未获取到dom节点,canvas-id:' + cid;
+                      }
+                    });
+                } else {
+                  if(this.inAli){
+                    cfu.option[cid].rotateLock = cfu.option[cid].rotate;
+                  }
+                  cfu.option[cid].context = uni.createCanvasContext(cid, this);
+                  if(cfu.instance[cid] && cfu.option[cid] && cfu.option[cid].update === true){
+                    this._updataUChart(cid)
+                  }else{
+                    setTimeout(()=>{
+                      cfu.option[cid].context.restore();
+                      cfu.option[cid].context.save();
+                      this._newChart(cid)
+                    },100)
+                  }
+                }
+              })
+            }
+          } else {
+            this.mixinDatacomLoading = false;
+            this.showchart = false;
+            if (this.reshow == true) {
+              this.mixinDatacomErrorMessage = '布局错误:未获取到父元素宽高尺寸!canvas-id:' + cid;
+            }
+          }
+        })
+        .exec();
+    },
+    saveImage(){
+    	uni.canvasToTempFilePath({
+    	  canvasId: this.cid,
+    	  success: res=>{
+    	    //#ifdef H5
+    			var a = document.createElement("a");
+    			a.href = res.tempFilePath;
+    			a.download = this.cid;
+    			a.target = '_blank'
+    			a.click();
+    	    //#endif
+    	    //#ifndef H5
+    	      uni.saveImageToPhotosAlbum({
+              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) {
+      if (this.mixinDatacomLoading == true) {
+        return;
+      }
+      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, 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, opts: cfu.instance[cid].opts}});
+      });
+      cfu.instance[cid].addEventListener('scrollRight', () => {
+        this.emitMsg({name: 'scrollRight', params: {type:"scrollRight", scrollRight: true, id: cid, opts: cfu.instance[cid].opts}});
+      });
+    },
+    _updataUChart(cid) {
+      cfu.instance[cid].updateData(cfu.option[cid])
+    },
+    _tooltipDefault(item, category, index, opts) {
+      if (category) {
+        let data = item.data
+        if(typeof item.data === "object"){
+          data = item.data.value
+        }
+        return category + ' ' + item.name + ':' + data;
+      } else {
+        if (item.properties && item.properties.name) {
+          return item.properties.name;
+        } else {
+          return item.name + ':' + item.data;
+        }
+      }
+    },
+    _showTooltip(e) {
+      let cid = this.cid
+      let tc = cfu.option[cid].tooltipCustom
+      if (tc && tc !== undefined && tc !== null) {
+        let offset = undefined;
+        if (tc.x >= 0 && tc.y >= 0) {
+          offset = { x: tc.x, y: tc.y + 10 };
+        }
+        cfu.instance[cid].showToolTip(e, {
+          index: tc.index,
+          offset: offset,
+          textList: tc.textList,
+          formatter: (item, category, index, opts) => {
+            if (typeof cfu.option[cid].tooltipFormat === 'string' && cfu.formatter[cfu.option[cid].tooltipFormat]) {
+              return cfu.formatter[cfu.option[cid].tooltipFormat](item, category, index, opts);
+            } else {
+              return this._tooltipDefault(item, category, index, opts);
+            }
+          }
+        });
+      } else {
+        cfu.instance[cid].showToolTip(e, {
+          formatter: (item, category, index, opts) => {
+            if (typeof cfu.option[cid].tooltipFormat === 'string' && cfu.formatter[cfu.option[cid].tooltipFormat]) {
+              return cfu.formatter[cfu.option[cid].tooltipFormat](item, category, index, opts);
+            } else {
+              return this._tooltipDefault(item, category, index, opts);
+            }
+          }
+        });
+      }
+    },
+    _tap(e,move) {
+      let cid = this.cid
+      let currentIndex = null;
+      let legendIndex = null;
+      if (this.inScrollView === true || this.inAli) {
+        let chartdom = uni
+          .createSelectorQuery()
+          // #ifndef MP-ALIPAY
+          .in(this)
+          .select('#ChartBoxId'+cid)
+          // #endif
+          // #ifdef MP-ALIPAY
+          .select('#'+this.cid)
+          // #endif
+          .boundingClientRect(data => {
+            e.changedTouches=[];
+            if (this.inAli) {
+              e.changedTouches.unshift({ x: e.detail.clientX - data.left, y: e.detail.clientY - data.top});
+            }else{
+              e.changedTouches.unshift({ x: e.detail.x - data.left, y: e.detail.y - data.top - this.pageScrollTop});
+            }
+            if(move){
+              if (this.tooltipShow === true) {
+                this._showTooltip(e);
+              }
+            }else{
+              currentIndex = cfu.instance[cid].getCurrentDataIndex(e);
+              legendIndex = cfu.instance[cid].getLegendDataIndex(e);
+              if(this.tapLegend === true){
+                cfu.instance[cid].touchLegend(e);
+              }
+              if (this.tooltipShow === true) {
+                this._showTooltip(e);
+              }
+              this.emitMsg({name: 'getIndex', params: { type:"getIndex", event:{ x: e.detail.x - data.left, y: e.detail.y - data.top }, currentIndex: currentIndex, legendIndex: legendIndex, id: cid, opts: cfu.instance[cid].opts}});
+            }
+          })
+          .exec();
+      } else {
+        if(move){
+          if (this.tooltipShow === true) {
+            this._showTooltip(e);
+          }
+        }else{
+          e.changedTouches=[];
+          e.changedTouches.unshift({ x: e.detail.x - e.currentTarget.offsetLeft, y: e.detail.y - e.currentTarget.offsetTop });
+          currentIndex = cfu.instance[cid].getCurrentDataIndex(e);
+          legendIndex = cfu.instance[cid].getLegendDataIndex(e);
+          if(this.tapLegend === true){
+            cfu.instance[cid].touchLegend(e);
+          }
+          if (this.tooltipShow === true) {
+            this._showTooltip(e);
+          }
+          this.emitMsg({name: 'getIndex', params: {type:"getIndex", event:{ x: e.detail.x, y: e.detail.y - e.currentTarget.offsetTop }, currentIndex: currentIndex, legendIndex: legendIndex, id: cid, opts: cfu.instance[cid].opts}});
+        }
+      }
+    },
+    _touchStart(e) {
+      let cid = this.cid
+      lastMoveTime=Date.now();
+      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, opts: cfu.instance[cid].opts}});
+    },
+    _touchMove(e) {
+      let cid = this.cid
+      let currMoveTime = Date.now();
+      let duration = currMoveTime - lastMoveTime;
+      let touchMoveLimit = cfu.option[cid].touchMoveLimit || 24;
+      if (duration < Math.floor(1000 / touchMoveLimit)) return;//每秒60帧
+      lastMoveTime = currMoveTime;
+      if(cfu.option[cid].enableScroll === true && e.changedTouches.length == 1){
+        cfu.instance[cid].scroll(e);
+      }
+      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 && e.touches.length == 0){
+        cfu.instance[cid].scrollEnd(e);
+      }
+      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)
+      }
+    },
+    // #endif
+    _error(e) {
+      this.mixinDatacomErrorMessage = e.detail.errMsg;
+    },
+    emitMsg(msg) {
+      this.$emit(msg.name, msg.params);
+    },
+    getRenderType() {
+      //防止如果开启echarts且父元素为v-if的情况renderjs监听不到prop变化的问题
+      if(this.echarts===true && this.mixinDatacomLoading===false){
+        this.beforeInit()
+      }
+    },
+    toJSON(){
+      return this
+    }
+  }
+};
+</script>
+
+<!-- #ifdef APP-VUE || H5 -->
+<script module="rdcharts" lang="renderjs">
+import uChartsRD from '../../js_sdk/u-charts/u-charts.js';
+import cfu from '../../js_sdk/u-charts/config-ucharts.js';
+import cfe from '../../js_sdk/u-charts/config-echarts.js';
+
+var that = {};
+var rootdom = null;
+
+function rddeepCloneAssign(origin = {}, ...args) {
+  for (let i in args) {
+    for (let key in args[i]) {
+      if (args[i].hasOwnProperty(key)) {
+        origin[key] = args[i][key] && typeof args[i][key] === 'object' ? rddeepCloneAssign(Array.isArray(args[i][key]) ? [] : {}, origin[key], args[i][key]) : args[i][key];
+      }
+    }
+  }
+  return origin;
+}
+
+function rdformatterAssign(args,formatter) {
+  for (let key in args) {
+    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;
+    }
+  }
+  return args;
+}
+
+export default {
+  data() {
+    return {
+      rid:null
+    }
+  },
+  mounted() {
+    rootdom = {top:0,left:0}
+    // #ifdef H5
+    let dm = document.querySelectorAll('uni-main')[0]
+    if(dm === undefined){
+      dm = document.querySelectorAll('uni-page-wrapper')[0]
+    }
+    rootdom = {top:dm.offsetTop,left:dm.offsetLeft}
+    // #endif
+    setTimeout(()=>{
+      if(this.rid === null){
+        this.$ownerInstance && this.$ownerInstance.callMethod('getRenderType')
+      }
+    },200)
+  },
+  destroyed(){
+    delete cfu.option[this.rid]
+    delete cfu.instance[this.rid]
+    delete cfe.option[this.rid]
+    delete cfe.instance[this.rid]
+  },
+  methods: {
+    //==============以下是ECharts的方法====================
+    ecinit(newVal, oldVal, owner, instance){
+      let cid = JSON.stringify(newVal.id)
+      this.rid = cid
+      that[cid] = this.$ownerInstance || instance
+      let eopts = JSON.parse(JSON.stringify(newVal))
+      let type = eopts.type;
+      //载入并覆盖默认配置
+      if (type && cfe.type.includes(type)) {
+        cfe.option[cid] = rddeepCloneAssign({}, cfe[type], eopts);
+      }else{
+        cfe.option[cid] = rddeepCloneAssign({}, eopts);
+      }
+      let newData = eopts.chartData;
+      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 (typeof window.echarts === 'object') {
+          this.newEChart()
+      }else{
+        const script = document.createElement('script')
+        // #ifdef APP-VUE
+        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'
+        // #endif
+        script.onload = this.newEChart
+        document.head.appendChild(script)
+      }
+    },
+    ecresize(newVal, oldVal, owner, instance){
+      if(cfe.instance[this.rid]){
+        cfe.instance[this.rid].resize()
+      }
+    },
+    newEChart(){
+      let cid = this.rid
+      if(cfe.instance[cid] === undefined){
+        cfe.instance[cid] = echarts.init(that[cid].$el.children[0])
+        //ontap开启后才触发click事件
+        if(cfe.option[cid].ontap === true){
+          cfe.instance[cid].on('click', resdata => {
+            let event = JSON.parse(JSON.stringify({
+              x:resdata.event.offsetX,y:resdata.event.offsetY
+            }))
+            that[cid].callMethod('emitMsg',{name:"getIndex", params:{type:"getIndex", event:event, currentIndex:resdata.dataIndex, value:resdata.data, seriesName: resdata.seriesName,id:cid}})
+          })
+          // 增加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", res:resdata, id:cid}})
+          })
+        }
+        this.updataEChart(cid,cfe.option[cid])
+      }else{
+        this.updataEChart(cid,cfe.option[cid])
+      }
+    },
+    updataEChart(cid,option){
+      //替换option内format属性为formatter的预定义方法
+      option = rdformatterAssign(option,cfe.formatter)
+      if(option.tooltip){
+        option.tooltip.show = option.tooltipShow?true:false;
+        option.tooltip.position = this.tooltipPosition()
+        //tooltipFormat方法,替换组件的tooltipFormat为config-echarts.js内对应的方法
+        if (typeof option.tooltipFormat === 'string' && cfe.formatter[option.tooltipFormat]) {
+          option.tooltip.formatter = option.tooltip.formatter ? option.tooltip.formatter : cfe.formatter[option.tooltipFormat]
+        }
+      }
+      // 颜色渐变添加的方法
+      if (option.series) {
+      	for (let i in option.series) {
+      		let linearGradient = option.series[i].linearGradient
+      		if (linearGradient) {
+      			option.series[i].color = new echarts.graphic.LinearGradient(linearGradient[0],linearGradient[1],linearGradient[2],linearGradient[3],linearGradient[4])
+      		}
+      	}
+      }
+      cfe.instance[cid].setOption(option, option.notMerge)
+      cfe.instance[cid].on('finished', function(){
+        that[cid].callMethod('emitMsg',{name:"complete",params:{type:"complete",complete:true,id:cid}})
+        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) => {
+      	let x = point[0]
+      	let y = point[1]
+      	let viewWidth = size.viewSize[0]
+      	let viewHeight = size.viewSize[1]
+      	let boxWidth = size.contentSize[0]
+      	let boxHeight = size.contentSize[1]
+      	let posX = x + 30 
+      	let posY = y + 30 
+      	if (posX + boxWidth > viewWidth) { 
+      		posX = x - boxWidth - 30
+      	}
+      	if (posY + boxHeight > viewHeight) {
+      		posY = y - boxHeight - 30
+      	}
+      	return [posX, posY]
+      }
+    },
+    //==============以下是uCharts的方法====================
+    ucinit(newVal, oldVal, owner, instance){
+      if(JSON.stringify(newVal) == JSON.stringify(oldVal)){
+        return;
+      }
+      if(!newVal.canvasId){
+        return;
+      }
+      let cid = JSON.parse(JSON.stringify(newVal.canvasId))
+      this.rid = cid
+      that[cid] = this.$ownerInstance || instance
+      cfu.option[cid] = JSON.parse(JSON.stringify(newVal))
+      cfu.option[cid] = rdformatterAssign(cfu.option[cid],cfu.formatter)
+      let canvasdom = document.getElementById(cid)
+      if(canvasdom && canvasdom.children[0]){
+        cfu.option[cid].context = canvasdom.children[0].getContext("2d")
+        if(cfu.instance[cid] && cfu.option[cid] && cfu.option[cid].update === true){
+          this.updataUChart()
+        }else{
+          setTimeout(()=>{
+            cfu.option[cid].context.restore();
+            cfu.option[cid].context.save();
+            this.newUChart()
+          },100)
+        }
+      }
+    },
+    newUChart() {
+      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, 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, opts: cfu.instance[cid].opts}})
+      });
+      cfu.instance[cid].addEventListener('scrollRight', () => {
+        that[cid].callMethod('emitMsg',{name:"scrollRight",params:{type:"scrollRight",scrollRight:true,id:cid, opts: cfu.instance[cid].opts}})
+      });
+    },
+    updataUChart() {
+      let cid = this.rid
+      cfu.instance[cid].updateData(cfu.option[cid])
+    },
+    tooltipDefault(item, category, index, opts) {
+      if (category) {
+        let data = item.data
+        if(typeof item.data === "object"){
+          data = item.data.value
+        }
+        return category + ' ' + item.name + ':' + data;
+      } else {
+        if (item.properties && item.properties.name) {
+          return item.properties.name ;
+        } else {
+          return item.name + ':' + item.data;
+        }
+      }
+    },
+    showTooltip(e,cid) {
+      let tc = cfu.option[cid].tooltipCustom
+      if (tc && tc !== undefined && tc !== null) {
+        let offset = undefined;
+        if (tc.x >= 0 && tc.y >= 0) {
+          offset = { x: tc.x, y: tc.y + 10 };
+        }
+        cfu.instance[cid].showToolTip(e, {
+          index: tc.index,
+          offset: offset,
+          textList: tc.textList,
+          formatter: (item, category, index, opts) => {
+            if (typeof cfu.option[cid].tooltipFormat === 'string' && cfu.formatter[cfu.option[cid].tooltipFormat]) {
+              return cfu.formatter[cfu.option[cid].tooltipFormat](item, category, index, opts);
+            } else {
+              return this.tooltipDefault(item, category, index, opts);
+            }
+          }
+        });
+      } else {
+        cfu.instance[cid].showToolTip(e, {
+          formatter: (item, category, index, opts) => {
+            if (typeof cfu.option[cid].tooltipFormat === 'string' && cfu.formatter[cfu.option[cid].tooltipFormat]) {
+              return cfu.formatter[cfu.option[cid].tooltipFormat](item, category, index, opts);
+            } else {
+              return this.tooltipDefault(item, category, index, opts);
+            }
+          }
+        });
+      }
+    },
+    tap(e) {
+      let cid = this.rid
+      let ontap = cfu.option[cid].ontap
+      let tooltipShow = cfu.option[cid].tooltipShow
+      let tapLegend = cfu.option[cid].tapLegend
+      if(ontap == false) return;
+      let currentIndex=null
+      let legendIndex=null
+      let rchartdom = document.getElementById('UC'+cid).getBoundingClientRect()
+      let tmpe = {}
+      if(e.detail.x){//tap或者click的事件
+        tmpe = { x: e.detail.x - rchartdom.left, y:e.detail.y - rchartdom.top + rootdom.top}
+      }else{//mouse的事件
+        tmpe = { x: e.clientX - rchartdom.left, y:e.clientY - rchartdom.top + rootdom.top}
+      }
+      e.changedTouches = [];
+      e.changedTouches.unshift(tmpe)
+      currentIndex=cfu.instance[cid].getCurrentDataIndex(e)
+      legendIndex=cfu.instance[cid].getLegendDataIndex(e)
+      if(tapLegend === true){
+        cfu.instance[cid].touchLegend(e);
+      }
+      if(tooltipShow==true){
+        this.showTooltip(e,cid)
+      }
+      that[cid].callMethod('emitMsg',{name:"getIndex",params:{type:"getIndex",event:tmpe,currentIndex:currentIndex,legendIndex:legendIndex,id:cid, opts: cfu.instance[cid].opts}})
+    },
+    touchStart(e) {
+      let cid = this.rid
+      let ontouch = cfu.option[cid].ontouch
+      if(ontouch == false) return;
+      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;
+      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.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;
+      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
+      let onmouse = cfu.option[cid].onmouse
+      if(onmouse == false) return;
+      let rchartdom = document.getElementById('UC'+cid).getBoundingClientRect()
+      let tmpe = {}
+      tmpe = { x: e.clientX - rchartdom.left, y:e.clientY - rchartdom.top + rootdom.top}
+      e.changedTouches = [];
+      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, opts: cfu.instance[cid].opts}})
+    },
+    mouseMove(e) {
+      let cid = this.rid
+      let onmouse = cfu.option[cid].onmouse
+      let tooltipShow = cfu.option[cid].tooltipShow
+      if(onmouse == false) return;
+      let rchartdom = document.getElementById('UC'+cid).getBoundingClientRect()
+      let tmpe = {}
+      tmpe = { x: e.clientX - rchartdom.left, y:e.clientY - rchartdom.top + rootdom.top}
+      e.changedTouches = [];
+      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, opts: cfu.instance[cid].opts}})
+      }else if(cfu.instance[cid]){
+        if(tooltipShow==true){
+          this.showTooltip(e,cid)
+        }
+      }
+    },
+    mouseUp(e) {
+      let cid = this.rid
+      let onmouse = cfu.option[cid].onmouse
+      if(onmouse == false) return;
+      let rchartdom = document.getElementById('UC'+cid).getBoundingClientRect()
+      let tmpe = {}
+      tmpe = { x: e.clientX - rchartdom.left, y:e.clientY - rchartdom.top + rootdom.top}
+      e.changedTouches = [];
+      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, opts: cfu.instance[cid].opts}})
+    },
+  }
+}
+</script>
+<!-- #endif -->
+
+<style scoped>
+.chartsview {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex: 1;
+  justify-content: center;
+  align-items: center;
+}
+</style>

Файловите разлики са ограничени, защото са твърде много
+ 42 - 0
uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue


+ 162 - 0
uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue

@@ -0,0 +1,162 @@
+<template>
+	 <view class="container loading1">
+		<view class="shape shape1"></view>
+		<view class="shape shape2"></view>
+		<view class="shape shape3"></view>
+		<view class="shape shape4"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'loading1',
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style scoped="true">
+.container {
+  width: 30px;
+  height: 30px;
+  position: relative;
+}
+.container.loading1 {
+  -webkit-transform: rotate(45deg);
+          transform: rotate(45deg);
+}
+
+.container .shape {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+.container .shape.shape1 {
+  left: 0;
+  background-color: #1890FF;
+}
+.container .shape.shape2 {
+  right: 0;
+  background-color: #91CB74;
+}
+.container .shape.shape3 {
+  bottom: 0;
+  background-color: #FAC858;
+}
+.container .shape.shape4 {
+  bottom: 0;
+  right: 0;
+  background-color: #EE6666;
+}
+
+.loading1 .shape1 {
+  -webkit-animation: animation1shape1 0.5s ease 0s infinite alternate;
+          animation: animation1shape1 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation1shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(16px, 16px);
+            transform: translate(16px, 16px);
+  }
+}
+
+@keyframes animation1shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(16px, 16px);
+            transform: translate(16px, 16px);
+  }
+}
+.loading1 .shape2 {
+  -webkit-animation: animation1shape2 0.5s ease 0s infinite alternate;
+          animation: animation1shape2 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation1shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-16px, 16px);
+            transform: translate(-16px, 16px);
+  }
+}
+
+@keyframes animation1shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-16px, 16px);
+            transform: translate(-16px, 16px);
+  }
+}
+.loading1 .shape3 {
+  -webkit-animation: animation1shape3 0.5s ease 0s infinite alternate;
+          animation: animation1shape3 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation1shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(16px, -16px);
+            transform: translate(16px, -16px);
+  }
+}
+
+@keyframes animation1shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(16px, -16px);
+            transform: translate(16px, -16px);
+  }
+}
+.loading1 .shape4 {
+  -webkit-animation: animation1shape4 0.5s ease 0s infinite alternate;
+          animation: animation1shape4 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation1shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-16px, -16px);
+            transform: translate(-16px, -16px);
+  }
+}
+
+@keyframes animation1shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-16px, -16px);
+            transform: translate(-16px, -16px);
+  }
+}
+
+
+</style>

+ 170 - 0
uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue

@@ -0,0 +1,170 @@
+<template>
+	 <view class="container loading2">
+		<view class="shape shape1"></view>
+		<view class="shape shape2"></view>
+		<view class="shape shape3"></view>
+		<view class="shape shape4"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'loading2',
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style scoped="true">
+.container {
+  width: 30px;
+  height: 30px;
+  position: relative;
+}
+
+.container.loading2 {
+  -webkit-transform: rotate(10deg);
+          transform: rotate(10deg);
+}
+.container.loading2 .shape {
+  border-radius: 5px;
+}
+.container.loading2{
+  -webkit-animation: rotation 1s infinite;
+          animation: rotation 1s infinite;
+}
+
+.container .shape {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+.container .shape.shape1 {
+  left: 0;
+  background-color: #1890FF;
+}
+.container .shape.shape2 {
+  right: 0;
+  background-color: #91CB74;
+}
+.container .shape.shape3 {
+  bottom: 0;
+  background-color: #FAC858;
+}
+.container .shape.shape4 {
+  bottom: 0;
+  right: 0;
+  background-color: #EE6666;
+}
+
+
+.loading2 .shape1 {
+  -webkit-animation: animation2shape1 0.5s ease 0s infinite alternate;
+          animation: animation2shape1 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation2shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(20px, 20px);
+            transform: translate(20px, 20px);
+  }
+}
+
+@keyframes animation2shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(20px, 20px);
+            transform: translate(20px, 20px);
+  }
+}
+.loading2 .shape2 {
+  -webkit-animation: animation2shape2 0.5s ease 0s infinite alternate;
+          animation: animation2shape2 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation2shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-20px, 20px);
+            transform: translate(-20px, 20px);
+  }
+}
+
+@keyframes animation2shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-20px, 20px);
+            transform: translate(-20px, 20px);
+  }
+}
+.loading2 .shape3 {
+  -webkit-animation: animation2shape3 0.5s ease 0s infinite alternate;
+          animation: animation2shape3 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation2shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(20px, -20px);
+            transform: translate(20px, -20px);
+  }
+}
+
+@keyframes animation2shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(20px, -20px);
+            transform: translate(20px, -20px);
+  }
+}
+.loading2 .shape4 {
+  -webkit-animation: animation2shape4 0.5s ease 0s infinite alternate;
+          animation: animation2shape4 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation2shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-20px, -20px);
+            transform: translate(-20px, -20px);
+  }
+}
+
+@keyframes animation2shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-20px, -20px);
+            transform: translate(-20px, -20px);
+  }
+}
+
+</style>

+ 173 - 0
uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue

@@ -0,0 +1,173 @@
+<template>
+	 <view class="container loading3">
+		<view class="shape shape1"></view>
+		<view class="shape shape2"></view>
+		<view class="shape shape3"></view>
+		<view class="shape shape4"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'loading3',
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style scoped="true">
+.container {
+  width: 30px;
+  height: 30px;
+  position: relative;
+}
+
+ .container.loading3 {
+  -webkit-animation: rotation 1s infinite;
+          animation: rotation 1s infinite;
+}
+.container.loading3 .shape1 {
+  border-top-left-radius: 10px;
+}
+.container.loading3 .shape2 {
+  border-top-right-radius: 10px;
+}
+.container.loading3 .shape3 {
+  border-bottom-left-radius: 10px;
+}
+.container.loading3 .shape4 {
+  border-bottom-right-radius: 10px;
+}
+
+.container .shape {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+.container .shape.shape1 {
+  left: 0;
+  background-color: #1890FF;
+}
+.container .shape.shape2 {
+  right: 0;
+  background-color: #91CB74;
+}
+.container .shape.shape3 {
+  bottom: 0;
+  background-color: #FAC858;
+}
+.container .shape.shape4 {
+  bottom: 0;
+  right: 0;
+  background-color: #EE6666;
+}
+
+.loading3 .shape1 {
+  -webkit-animation: animation3shape1 0.5s ease 0s infinite alternate;
+          animation: animation3shape1 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation3shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(5px, 5px);
+            transform: translate(5px, 5px);
+  }
+}
+
+@keyframes animation3shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(5px, 5px);
+            transform: translate(5px, 5px);
+  }
+}
+.loading3 .shape2 {
+  -webkit-animation: animation3shape2 0.5s ease 0s infinite alternate;
+          animation: animation3shape2 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation3shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-5px, 5px);
+            transform: translate(-5px, 5px);
+  }
+}
+
+@keyframes animation3shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-5px, 5px);
+            transform: translate(-5px, 5px);
+  }
+}
+.loading3 .shape3 {
+  -webkit-animation: animation3shape3 0.5s ease 0s infinite alternate;
+          animation: animation3shape3 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation3shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(5px, -5px);
+            transform: translate(5px, -5px);
+  }
+}
+
+@keyframes animation3shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(5px, -5px);
+            transform: translate(5px, -5px);
+  }
+}
+.loading3 .shape4 {
+  -webkit-animation: animation3shape4 0.5s ease 0s infinite alternate;
+          animation: animation3shape4 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation3shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-5px, -5px);
+            transform: translate(-5px, -5px);
+  }
+}
+
+@keyframes animation3shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-5px, -5px);
+            transform: translate(-5px, -5px);
+  }
+}
+</style>

+ 222 - 0
uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue

@@ -0,0 +1,222 @@
+<template>
+	 <view class="container loading5">
+		<view class="shape shape1"></view>
+		<view class="shape shape2"></view>
+		<view class="shape shape3"></view>
+		<view class="shape shape4"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'loading5',
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style scoped="true">
+.container {
+  width: 30px;
+  height: 30px;
+  position: relative;
+}
+
+.container.loading5 .shape {
+  width: 15px;
+  height: 15px;
+}
+
+.container .shape {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+.container .shape.shape1 {
+  left: 0;
+  background-color: #1890FF;
+}
+.container .shape.shape2 {
+  right: 0;
+  background-color: #91CB74;
+}
+.container .shape.shape3 {
+  bottom: 0;
+  background-color: #FAC858;
+}
+.container .shape.shape4 {
+  bottom: 0;
+  right: 0;
+  background-color: #EE6666;
+}
+
+.loading5 .shape1 {
+  animation: animation5shape1 2s ease 0s infinite reverse;
+}
+
+@-webkit-keyframes animation5shape1 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, 15px);
+            transform: translate(0, 15px);
+  }
+  50% {
+    -webkit-transform: translate(15px, 15px);
+            transform: translate(15px, 15px);
+  }
+  75% {
+    -webkit-transform: translate(15px, 0);
+            transform: translate(15px, 0);
+  }
+}
+
+@keyframes animation5shape1 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, 15px);
+            transform: translate(0, 15px);
+  }
+  50% {
+    -webkit-transform: translate(15px, 15px);
+            transform: translate(15px, 15px);
+  }
+  75% {
+    -webkit-transform: translate(15px, 0);
+            transform: translate(15px, 0);
+  }
+}
+.loading5 .shape2 {
+  animation: animation5shape2 2s ease 0s infinite reverse;
+}
+
+@-webkit-keyframes animation5shape2 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(-15px, 0);
+            transform: translate(-15px, 0);
+  }
+  50% {
+    -webkit-transform: translate(-15px, 15px);
+            transform: translate(-15px, 15px);
+  }
+  75% {
+    -webkit-transform: translate(0, 15px);
+            transform: translate(0, 15px);
+  }
+}
+
+@keyframes animation5shape2 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(-15px, 0);
+            transform: translate(-15px, 0);
+  }
+  50% {
+    -webkit-transform: translate(-15px, 15px);
+            transform: translate(-15px, 15px);
+  }
+  75% {
+    -webkit-transform: translate(0, 15px);
+            transform: translate(0, 15px);
+  }
+}
+.loading5 .shape3 {
+  animation: animation5shape3 2s ease 0s infinite reverse;
+}
+
+@-webkit-keyframes animation5shape3 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(15px, 0);
+            transform: translate(15px, 0);
+  }
+  50% {
+    -webkit-transform: translate(15px, -15px);
+            transform: translate(15px, -15px);
+  }
+  75% {
+    -webkit-transform: translate(0, -15px);
+            transform: translate(0, -15px);
+  }
+}
+
+@keyframes animation5shape3 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(15px, 0);
+            transform: translate(15px, 0);
+  }
+  50% {
+    -webkit-transform: translate(15px, -15px);
+            transform: translate(15px, -15px);
+  }
+  75% {
+    -webkit-transform: translate(0, -15px);
+            transform: translate(0, -15px);
+  }
+}
+.loading5 .shape4 {
+  animation: animation5shape4 2s ease 0s infinite reverse;
+}
+
+@-webkit-keyframes animation5shape4 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, -15px);
+            transform: translate(0, -15px);
+  }
+  50% {
+    -webkit-transform: translate(-15px, -15px);
+            transform: translate(-15px, -15px);
+  }
+  75% {
+    -webkit-transform: translate(-15px, 0);
+            transform: translate(-15px, 0);
+  }
+}
+
+@keyframes animation5shape4 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, -15px);
+            transform: translate(0, -15px);
+  }
+  50% {
+    -webkit-transform: translate(-15px, -15px);
+            transform: translate(-15px, -15px);
+  }
+  75% {
+    -webkit-transform: translate(-15px, 0);
+            transform: translate(-15px, 0);
+  }
+}
+
+</style>

+ 229 - 0
uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue

@@ -0,0 +1,229 @@
+<template>
+	 <view class="container loading6">
+		<view class="shape shape1"></view>
+		<view class="shape shape2"></view>
+		<view class="shape shape3"></view>
+		<view class="shape shape4"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'loading6',
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+<style scoped="true">
+.container {
+  width: 30px;
+  height: 30px;
+  position: relative;
+}
+
+.container.loading6 {
+  -webkit-animation: rotation 1s infinite;
+          animation: rotation 1s infinite;
+}
+.container.loading6 .shape {
+  width: 12px;
+  height: 12px;
+  border-radius: 2px;
+}
+.container .shape {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+.container .shape.shape1 {
+  left: 0;
+  background-color: #1890FF;
+}
+.container .shape.shape2 {
+  right: 0;
+  background-color: #91CB74;
+}
+.container .shape.shape3 {
+  bottom: 0;
+  background-color: #FAC858;
+}
+.container .shape.shape4 {
+  bottom: 0;
+  right: 0;
+  background-color: #EE6666;
+}
+
+
+.loading6 .shape1 {
+  -webkit-animation: animation6shape1 2s linear 0s infinite normal;
+          animation: animation6shape1 2s linear 0s infinite normal;
+}
+
+@-webkit-keyframes animation6shape1 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, 18px);
+            transform: translate(0, 18px);
+  }
+  50% {
+    -webkit-transform: translate(18px, 18px);
+            transform: translate(18px, 18px);
+  }
+  75% {
+    -webkit-transform: translate(18px, 0);
+            transform: translate(18px, 0);
+  }
+}
+
+@keyframes animation6shape1 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, 18px);
+            transform: translate(0, 18px);
+  }
+  50% {
+    -webkit-transform: translate(18px, 18px);
+            transform: translate(18px, 18px);
+  }
+  75% {
+    -webkit-transform: translate(18px, 0);
+            transform: translate(18px, 0);
+  }
+}
+.loading6 .shape2 {
+  -webkit-animation: animation6shape2 2s linear 0s infinite normal;
+          animation: animation6shape2 2s linear 0s infinite normal;
+}
+
+@-webkit-keyframes animation6shape2 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(-18px, 0);
+            transform: translate(-18px, 0);
+  }
+  50% {
+    -webkit-transform: translate(-18px, 18px);
+            transform: translate(-18px, 18px);
+  }
+  75% {
+    -webkit-transform: translate(0, 18px);
+            transform: translate(0, 18px);
+  }
+}
+
+@keyframes animation6shape2 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(-18px, 0);
+            transform: translate(-18px, 0);
+  }
+  50% {
+    -webkit-transform: translate(-18px, 18px);
+            transform: translate(-18px, 18px);
+  }
+  75% {
+    -webkit-transform: translate(0, 18px);
+            transform: translate(0, 18px);
+  }
+}
+.loading6 .shape3 {
+  -webkit-animation: animation6shape3 2s linear 0s infinite normal;
+          animation: animation6shape3 2s linear 0s infinite normal;
+}
+
+@-webkit-keyframes animation6shape3 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(18px, 0);
+            transform: translate(18px, 0);
+  }
+  50% {
+    -webkit-transform: translate(18px, -18px);
+            transform: translate(18px, -18px);
+  }
+  75% {
+    -webkit-transform: translate(0, -18px);
+            transform: translate(0, -18px);
+  }
+}
+
+@keyframes animation6shape3 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(18px, 0);
+            transform: translate(18px, 0);
+  }
+  50% {
+    -webkit-transform: translate(18px, -18px);
+            transform: translate(18px, -18px);
+  }
+  75% {
+    -webkit-transform: translate(0, -18px);
+            transform: translate(0, -18px);
+  }
+}
+.loading6 .shape4 {
+  -webkit-animation: animation6shape4 2s linear 0s infinite normal;
+          animation: animation6shape4 2s linear 0s infinite normal;
+}
+
+@-webkit-keyframes animation6shape4 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, -18px);
+            transform: translate(0, -18px);
+  }
+  50% {
+    -webkit-transform: translate(-18px, -18px);
+            transform: translate(-18px, -18px);
+  }
+  75% {
+    -webkit-transform: translate(-18px, 0);
+            transform: translate(-18px, 0);
+  }
+}
+
+@keyframes animation6shape4 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, -18px);
+            transform: translate(0, -18px);
+  }
+  50% {
+    -webkit-transform: translate(-18px, -18px);
+            transform: translate(-18px, -18px);
+  }
+  75% {
+    -webkit-transform: translate(-18px, 0);
+            transform: translate(-18px, 0);
+  }
+}
+</style>

+ 36 - 0
uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue

@@ -0,0 +1,36 @@
+<template>
+	<view>
+	 <Loading1 v-if="loadingType==1"/>
+	 <Loading2 v-if="loadingType==2"/>
+	 <Loading3 v-if="loadingType==3"/>
+	 <Loading4 v-if="loadingType==4"/>
+	 <Loading5 v-if="loadingType==5"/>
+	</view>
+</template>
+
+<script>
+	import Loading1 from "./loading1.vue";
+	import Loading2 from "./loading2.vue";
+	import Loading3 from "./loading3.vue";
+	import Loading4 from "./loading4.vue";
+	import Loading5 from "./loading5.vue";
+	export default {
+		components:{Loading1,Loading2,Loading3,Loading4,Loading5},
+		name: 'qiun-loading',
+		props: {
+			loadingType: {
+				type: Number,
+				default: 2
+			},
+		},
+		data() {
+			return {
+				
+			};
+		},
+	}
+</script>
+
+<style>
+
+</style>

+ 422 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js

@@ -0,0 +1,422 @@
+/*
+ * uCharts®
+ * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台
+ * Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
+ * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+ * 复制使用请保留本段注释,感谢支持开源!
+ * 
+ * uCharts®官方网站
+ * https://www.uCharts.cn
+ * 
+ * 开源地址:
+ * https://gitee.com/uCharts/uCharts
+ * 
+ * uni-app插件市场地址:
+ * http://ext.dcloud.net.cn/plugin?id=271
+ * 
+ */
+
+// 通用配置项
+
+// 主题颜色配置:如每个图表类型需要不同主题,请在对应图表类型上更改color属性
+const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
+
+const cfe = {
+  //demotype为自定义图表类型
+	"type": ["pie", "ring", "rose", "funnel", "line", "column", "area", "radar", "gauge","candle","demotype"],
+  //增加自定义图表类型,如果需要categories,请在这里加入您的图表类型例如最后的"demotype"
+	"categories": ["line", "column", "area", "radar", "gauge", "candle","demotype"],
+  //instance为实例变量承载属性,option为eopts承载属性,不要删除
+	"instance": {},
+	"option": {},
+  //下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换
+  "formatter":{
+    "tooltipDemo1":function(res){
+      let result = ''
+      for (let i in res) {
+      	if (i == 0) {
+      		result += res[i].axisValueLabel + '年销售额'
+      	}
+      	let value = '--'
+      	if (res[i].data !== null) {
+      		value = res[i].data
+      	}
+      	// #ifdef H5
+      	result += '\n' + res[i].seriesName + ':' + value + ' 万元'
+      	// #endif
+      	
+      	// #ifdef APP-PLUS
+      	result += '<br/>' + res[i].marker + res[i].seriesName + ':' + value + ' 万元'
+      	// #endif
+      }
+      return result;
+    },
+    legendFormat:function(name){
+      return "自定义图例+"+name;
+    },
+    yAxisFormatDemo:function (value, index) {
+      return value + '元';
+    },
+    seriesFormatDemo:function(res){
+      return res.name + '年' + res.value + '元';
+    }
+  },
+  //这里演示了自定义您的图表类型的option,可以随意命名,之后在组件上 type="demotype" 后,组件会调用这个花括号里的option,如果组件上还存在eopts参数,会将demotype与eopts中option合并后渲染图表。
+  "demotype":{
+    "color": color,
+    //在这里填写echarts的option即可
+    
+  },
+  //下面是自定义配置,请添加项目所需的通用配置
+	"column": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'axis'
+		},
+		"grid": {
+			"top": 30,
+			"bottom": 50,
+			"right": 15,
+			"left": 40
+		},
+		"legend": {
+			"bottom": 'left',
+		},
+		"toolbox": {
+			"show": false,
+		},
+		"xAxis": {
+			"type": 'category',
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+			"boundaryGap": true,
+			"data": []
+		},
+		"yAxis": {
+			"type": 'value',
+			"axisTick": {
+				"show": false,
+			},
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'bar',
+			"data": [],
+			"barwidth": 20,
+			"label": {
+				"show": true,
+        "color": "#666666",
+				"position": 'top',
+			},
+		},
+	},
+	"line": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'axis'
+		},
+		"grid": {
+			"top": 30,
+			"bottom": 50,
+			"right": 15,
+			"left": 40
+		},
+		"legend": {
+			"bottom": 'left',
+		},
+		"toolbox": {
+			"show": false,
+		},
+		"xAxis": {
+			"type": 'category',
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+			"boundaryGap": true,
+			"data": []
+		},
+		"yAxis": {
+			"type": 'value',
+			"axisTick": {
+				"show": false,
+			},
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'line',
+			"data": [],
+			"barwidth": 20,
+			"label": {
+				"show": true,
+        "color": "#666666",
+				"position": 'top',
+			},
+		},
+	},
+	"area": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'axis'
+		},
+		"grid": {
+			"top": 30,
+			"bottom": 50,
+			"right": 15,
+			"left": 40
+		},
+		"legend": {
+			"bottom": 'left',
+		},
+		"toolbox": {
+			"show": false,
+		},
+		"xAxis": {
+			"type": 'category',
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+			"boundaryGap": true,
+			"data": []
+		},
+		"yAxis": {
+			"type": 'value',
+			"axisTick": {
+				"show": false,
+			},
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'line',
+			"data": [],
+			"areaStyle": {},
+			"label": {
+				"show": true,
+        "color": "#666666",
+				"position": 'top',
+			},
+		},
+	},
+	"pie": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'item'
+		},
+		"grid": {
+			"top": 40,
+			"bottom": 30,
+			"right": 15,
+			"left": 15
+		},
+		"legend": {
+			"bottom": 'left',
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'pie',
+			"data": [],
+			"radius": '50%',
+			"label": {
+				"show": true,
+        "color": "#666666",
+				"position": 'top',
+			},
+		},
+	},
+	"ring": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'item'
+		},
+		"grid": {
+			"top": 40,
+			"bottom": 30,
+			"right": 15,
+			"left": 15
+		},
+		"legend": {
+			"bottom": 'left',
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'pie',
+			"data": [],
+			"radius": ['40%', '70%'],
+			"avoidLabelOverlap": false,
+			"label": {
+				"show": true,
+        "color": "#666666",
+				"position": 'top',
+			},
+			"labelLine": {
+				"show": true
+			},
+		},
+	},
+	"rose": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'item'
+		},
+		"legend": {
+			"top": 'bottom'
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'pie',
+			"data": [],
+			"radius": "55%",
+			"center": ['50%', '50%'],
+			"roseType": 'area',
+		},
+	},
+	"funnel": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'item',
+			"formatter": "{b} : {c}%"
+		},
+		"legend": {
+			"top": 'bottom'
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'funnel',
+			"left": '10%',
+			"top": 60,
+			"bottom": 60,
+			"width": '80%',
+			"min": 0,
+			"max": 100,
+			"minSize": '0%',
+			"maxSize": '100%',
+			"sort": 'descending',
+			"gap": 2,
+			"label": {
+				"show": true,
+				"position": 'inside'
+			},
+			"labelLine": {
+				"length": 10,
+				"lineStyle": {
+					"width": 1,
+					"type": 'solid'
+				}
+			},
+			"itemStyle": {
+				"bordercolor": '#fff',
+				"borderwidth": 1
+			},
+			"emphasis": {
+				"label": {
+					"fontSize": 20
+				}
+			},
+			"data": [],
+		},
+	},
+	"gauge": {
+		"color": color,
+		"tooltip": {
+        "formatter": '{a} <br/>{b} : {c}%'
+    },
+		"seriesTemplate": {
+			"name": '业务指标',
+      "type": 'gauge',
+      "detail": {"formatter": '{value}%'},
+      "data": [{"value": 50, "name": '完成率'}]
+		},
+	},
+	"candle": {
+		"xAxis": {
+			"data": []
+		},
+		"yAxis": {},
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"dataZoom": [{
+				"type": 'inside',
+				"xAxisIndex": [0, 1],
+				"start": 10,
+				"end": 100
+			},
+			{
+				"show": true,
+				"xAxisIndex": [0, 1],
+				"type": 'slider',
+				"bottom": 10,
+				"start": 10,
+				"end": 100
+			}
+		],
+		"seriesTemplate": {
+			"name": '',
+			"type": 'k',
+			"data": [],
+		},
+	}
+}
+
+export default cfe;

+ 679 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js

@@ -0,0 +1,679 @@
+/*
+ * uCharts®
+ * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台
+ * Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
+ * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+ * 复制使用请保留本段注释,感谢支持开源!
+ *
+ * uCharts®官方网站
+ * https://www.uCharts.cn
+ *
+ * 开源地址:
+ * https://gitee.com/uCharts/uCharts
+ *
+ * uni-app插件市场地址:
+ * http://ext.dcloud.net.cn/plugin?id=271
+ *
+ */
+
+// 主题颜色配置:如每个图表类型需要不同主题,请在对应图表类型上更改color属性
+const color = [
+  "#1890FF",
+  "#91CB74",
+  "#FAC858",
+  "#EE6666",
+  "#73C0DE",
+  "#3CA272",
+  "#FC8452",
+  "#9A60B4",
+  "#ea7ccc",
+];
+
+//事件转换函数,主要用作格式化x轴为时间轴,根据需求自行修改
+const formatDateTime = (timeStamp, returnType) => {
+  var date = new Date();
+  date.setTime(timeStamp * 1000);
+  var y = date.getFullYear();
+  var m = date.getMonth() + 1;
+  m = m < 10 ? "0" + m : m;
+  var d = date.getDate();
+  d = d < 10 ? "0" + d : d;
+  var h = date.getHours();
+  h = h < 10 ? "0" + h : h;
+  var minute = date.getMinutes();
+  var second = date.getSeconds();
+  minute = minute < 10 ? "0" + minute : minute;
+  second = second < 10 ? "0" + second : second;
+  if (returnType == "full") {
+    return y + "-" + m + "-" + d + " " + h + ":" + minute + ":" + second;
+  }
+  if (returnType == "y-m-d") {
+    return y + "-" + m + "-" + d;
+  }
+  if (returnType == "h:m") {
+    return h + ":" + minute;
+  }
+  if (returnType == "h:m:s") {
+    return h + ":" + minute + ":" + second;
+  }
+  return [y, m, d, h, minute, second];
+};
+
+const cfu = {
+  //demotype为自定义图表类型,一般不需要自定义图表类型,只需要改根节点上对应的类型即可
+  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",
+    "mount",
+    "bar",
+    "area",
+    "radar",
+    "gauge",
+    "candle",
+    "mix",
+    "demotype",
+  ],
+  //instance为实例变量承载属性,不要删除
+  instance: {},
+  //option为opts及eopts承载属性,不要删除
+  option: {},
+  //下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换
+  formatter: {
+    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");
+    },
+    xAxisDemo3: function (val, index, opts) {
+      return formatDateTime(val, "h:m:s");
+    },
+    seriesDemo1: function (val, index, series, opts) {
+      return val + "元";
+    },
+    tooltipDemo1: function (item, category, index, opts) {
+      if (index == 0) {
+        return "随便用" + item.data + "年";
+      } else {
+        return "其他我没改" + item.data + "天";
+      }
+    },
+    pieDemo: function (val, index, series, opts) {
+      if (index !== undefined) {
+        return series[index].name + ":" + series[index].data + "元";
+      }
+    },
+  },
+  //这里演示了自定义您的图表类型的option,可以随意命名,之后在组件上 type="demotype" 后,组件会调用这个花括号里的option,如果组件上还存在opts参数,会将demotype与opts中option合并后渲染图表。
+  demotype: {
+    //我这里把曲线图当做了自定义图表类型,您可以根据需要随意指定类型或配置
+    type: "line",
+    color: color,
+    padding: [15, 10, 0, 15],
+    xAxis: {
+      disableGrid: true,
+    },
+    yAxis: {
+      gridType: "dash",
+      dashLength: 2,
+    },
+    legend: {},
+    extra: {
+      line: {
+        type: "curve",
+        width: 2,
+      },
+    },
+  },
+  //下面是自定义配置,请添加项目所需的通用配置
+  pie: {
+    type: "pie",
+    color: color,
+    padding: [5, 5, 5, 5],
+    extra: {
+      pie: {
+        activeOpacity: 0.5,
+        activeRadius: 10,
+        offsetAngle: 0,
+        labelWidth: 15,
+        border: true,
+        borderWidth: 3,
+        borderColor: "#FFFFFF",
+      },
+    },
+  },
+  ring: {
+    type: "ring",
+    color: color,
+    padding: [5, 5, 5, 5],
+    rotate: false,
+    dataLabel: true,
+    legend: {
+      show: true,
+      position: "right",
+      lineHeight: 25,
+    },
+    title: {
+      name: "收益率",
+      fontSize: 15,
+      color: "#666666",
+    },
+    subtitle: {
+      name: "70%",
+      fontSize: 25,
+      color: "#7cb5ec",
+    },
+    extra: {
+      ring: {
+        ringWidth: 30,
+        activeOpacity: 0.5,
+        activeRadius: 10,
+        offsetAngle: 0,
+        labelWidth: 15,
+        border: true,
+        borderWidth: 3,
+        borderColor: "#FFFFFF",
+      },
+    },
+  },
+  rose: {
+    type: "rose",
+    color: color,
+    padding: [5, 5, 5, 5],
+    legend: {
+      show: true,
+      position: "left",
+      lineHeight: 25,
+    },
+    extra: {
+      rose: {
+        type: "area",
+        minRadius: 50,
+        activeOpacity: 0.5,
+        activeRadius: 10,
+        offsetAngle: 0,
+        labelWidth: 15,
+        border: false,
+        borderWidth: 2,
+        borderColor: "#FFFFFF",
+      },
+    },
+  },
+  word: {
+    type: "word",
+    color: color,
+    extra: {
+      word: {
+        type: "normal",
+        autoColors: false,
+      },
+    },
+  },
+  funnel: {
+    type: "funnel",
+    color: color,
+    padding: [15, 15, 0, 15],
+    extra: {
+      funnel: {
+        activeOpacity: 0.3,
+        activeWidth: 10,
+        border: true,
+        borderWidth: 2,
+        borderColor: "#FFFFFF",
+        fillOpacity: 1,
+        labelAlign: "right",
+      },
+    },
+  },
+  map: {
+    type: "map",
+    color: color,
+    padding: [0, 0, 0, 0],
+    dataLabel: true,
+    extra: {
+      map: {
+        border: true,
+        borderWidth: 1,
+        borderColor: "#666666",
+        fillOpacity: 0.6,
+        activeBorderColor: "#F04864",
+        activeFillColor: "#FACC14",
+        activeFillOpacity: 1,
+      },
+    },
+  },
+  arcbar: {
+    type: "arcbar",
+    color: color,
+    title: {
+      name: "百分比",
+      fontSize: 25,
+      color: "#00FF00",
+    },
+    subtitle: {
+      name: "默认标题",
+      fontSize: 15,
+      color: "#666666",
+    },
+    extra: {
+      arcbar: {
+        type: "default",
+        width: 12,
+        backgroundColor: "#E9E9E9",
+        startAngle: 0.75,
+        endAngle: 0.25,
+        gap: 2,
+      },
+    },
+  },
+  line: {
+    type: "line",
+    color: color,
+    padding: [15, 10, 0, 15],
+    xAxis: {
+      disableGrid: true,
+    },
+    yAxis: {
+      gridType: "dash",
+      dashLength: 2,
+    },
+    legend: {},
+    extra: {
+      line: {
+        type: "straight",
+        width: 2,
+        activeType: "hollow",
+      },
+    },
+  },
+  tline: {
+    type: "line",
+    color: color,
+    padding: [15, 10, 0, 15],
+    xAxis: {
+      disableGrid: false,
+      boundaryGap: "justify",
+    },
+    yAxis: {
+      gridType: "dash",
+      dashLength: 2,
+      data: [
+        {
+          min: 0,
+          max: 80,
+        },
+      ],
+    },
+    legend: {},
+    extra: {
+      line: {
+        type: "curve",
+        width: 2,
+        activeType: "hollow",
+      },
+    },
+  },
+  tarea: {
+    type: "area",
+    color: color,
+    padding: [15, 10, 0, 15],
+    xAxis: {
+      disableGrid: true,
+      boundaryGap: "justify",
+    },
+    yAxis: {
+      gridType: "dash",
+      dashLength: 2,
+      data: [
+        {
+          min: 0,
+          max: 80,
+        },
+      ],
+    },
+    legend: {},
+    extra: {
+      area: {
+        type: "curve",
+        opacity: 0.2,
+        addLine: true,
+        width: 2,
+        gradient: true,
+        activeType: "hollow",
+      },
+    },
+  },
+  column: {
+    type: "column",
+    color: color,
+    padding: [15, 15, 0, 5],
+    xAxis: {
+      disableGrid: true,
+    },
+    yAxis: {
+      data: [{ min: 0 }],
+    },
+    legend: {},
+    extra: {
+      column: {
+        type: "group",
+        width: 30,
+        activeBgColor: "#000000",
+        activeBgOpacity: 0.08,
+      },
+    },
+  },
+  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,
+    padding: [15, 30, 0, 5],
+    xAxis: {
+      boundaryGap: "justify",
+      disableGrid: false,
+      min: 0,
+      axisLine: false,
+    },
+    yAxis: {},
+    legend: {},
+    extra: {
+      bar: {
+        type: "group",
+        width: 30,
+        meterBorde: 1,
+        meterFillColor: "#FFFFFF",
+        activeBgColor: "#000000",
+        activeBgOpacity: 0.08,
+      },
+    },
+  },
+  area: {
+    type: "area",
+    color: color,
+    padding: [15, 15, 0, 15],
+    xAxis: {
+      disableGrid: true,
+    },
+    yAxis: {
+      gridType: "dash",
+      dashLength: 2,
+    },
+    legend: {},
+    extra: {
+      area: {
+        type: "straight",
+        opacity: 0.2,
+        addLine: true,
+        width: 2,
+        gradient: false,
+        activeType: "hollow",
+      },
+    },
+  },
+  radar: {
+    type: "radar",
+    color: color,
+    padding: [5, 5, 5, 5],
+    dataLabel: false,
+    legend: {
+      show: true,
+      position: "right",
+      lineHeight: 25,
+    },
+    extra: {
+      radar: {
+        gridType: "radar",
+        gridColor: "#CCCCCC",
+        gridCount: 3,
+        opacity: 0.2,
+        max: 200,
+        labelShow: true,
+      },
+    },
+  },
+  gauge: {
+    type: "gauge",
+    color: color,
+    title: {
+      name: "66Km/H",
+      fontSize: 25,
+      color: "#2fc25b",
+      offsetY: 50,
+    },
+    subtitle: {
+      name: "实时速度",
+      fontSize: 15,
+      color: "#1890ff",
+      offsetY: -50,
+    },
+    extra: {
+      gauge: {
+        type: "default",
+        width: 30,
+        labelColor: "#666666",
+        startAngle: 0.75,
+        endAngle: 0.25,
+        startNumber: 0,
+        endNumber: 100,
+        labelFormat: "",
+        splitLine: {
+          fixRadius: 0,
+          splitNumber: 10,
+          width: 30,
+          color: "#FFFFFF",
+          childNumber: 5,
+          childWidth: 12,
+        },
+        pointer: {
+          width: 24,
+          color: "auto",
+        },
+      },
+    },
+  },
+  candle: {
+    type: "candle",
+    color: color,
+    padding: [15, 15, 0, 15],
+    enableScroll: true,
+    enableMarkLine: true,
+    dataLabel: false,
+    xAxis: {
+      labelCount: 4,
+      itemCount: 40,
+      disableGrid: true,
+      gridColor: "#CCCCCC",
+      gridType: "solid",
+      dashLength: 4,
+      scrollShow: true,
+      scrollAlign: "left",
+      scrollColor: "#A6A6A6",
+      scrollBackgroundColor: "#EFEBEF",
+    },
+    yAxis: {},
+    legend: {},
+    extra: {
+      candle: {
+        color: {
+          upLine: "#f04864",
+          upFill: "#f04864",
+          downLine: "#2fc25b",
+          downFill: "#2fc25b",
+        },
+        average: {
+          show: true,
+          name: ["MA5", "MA10", "MA30"],
+          day: [5, 10, 20],
+          color: ["#1890ff", "#2fc25b", "#facc14"],
+        },
+      },
+      markLine: {
+        type: "dash",
+        dashLength: 5,
+        data: [
+          {
+            value: 2150,
+            lineColor: "#f04864",
+            showLabel: true,
+          },
+          {
+            value: 2350,
+            lineColor: "#f04864",
+            showLabel: true,
+          },
+        ],
+      },
+    },
+  },
+  mix: {
+    type: "mix",
+    color: color,
+    padding: [15, 15, 0, 15],
+    xAxis: {
+      disableGrid: true,
+    },
+    yAxis: {
+      disabled: false,
+      disableGrid: false,
+      splitNumber: 5,
+      gridType: "dash",
+      dashLength: 4,
+      gridColor: "#CCCCCC",
+      padding: 10,
+      showTitle: true,
+      data: [],
+    },
+    legend: {},
+    extra: {
+      mix: {
+        column: {
+          width: 20,
+        },
+      },
+    },
+  },
+  scatter: {
+    type: "scatter",
+    color: color,
+    padding: [15, 15, 0, 15],
+    dataLabel: false,
+    xAxis: {
+      disableGrid: false,
+      gridType: "dash",
+      splitNumber: 5,
+      boundaryGap: "justify",
+      min: 0,
+    },
+    yAxis: {
+      disableGrid: false,
+      gridType: "dash",
+    },
+    legend: {},
+    extra: {
+      scatter: {},
+    },
+  },
+  bubble: {
+    type: "bubble",
+    color: color,
+    padding: [15, 15, 0, 15],
+    xAxis: {
+      disableGrid: false,
+      gridType: "dash",
+      splitNumber: 5,
+      boundaryGap: "justify",
+      min: 0,
+      max: 250,
+    },
+    yAxis: {
+      disableGrid: false,
+      gridType: "dash",
+      data: [
+        {
+          min: 0,
+          max: 150,
+        },
+      ],
+    },
+    legend: {},
+    extra: {
+      bubble: {
+        border: 2,
+        opacity: 0.5,
+      },
+    },
+  },
+};
+
+export default cfu;

+ 5 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md

@@ -0,0 +1,5 @@
+# uCharts JSSDK说明
+1、如不使用uCharts组件,可直接引用u-charts.js,打包编译后会`自动压缩`,压缩后体积约为`120kb`。
+2、如果120kb的体积仍需压缩,请手到uCharts官网通过在线定制选择您需要的图表。
+3、config-ucharts.js为uCharts组件的用户配置文件,升级前请`自行备份config-ucharts.js`文件,以免被强制覆盖。
+4、config-echarts.js为ECharts组件的用户配置文件,升级前请`自行备份config-echarts.js`文件,以免被强制覆盖。

+ 7706 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js

@@ -0,0 +1,7706 @@
+/*
+ * 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 (R) 官方网站
+ * https://www.uCharts.cn
+ * 
+ * 开源地址:
+ * https://gitee.com/uCharts/uCharts
+ * 
+ * uni-app插件市场地址:
+ * http://ext.dcloud.net.cn/plugin?id=271
+ * 
+ */
+
+'use strict';
+
+var config = {
+  version: 'v2.5.0-20230101',
+  yAxisWidth: 15,
+  xAxisHeight: 22,
+  padding: [10, 10, 10, 10],
+  rotate: false,
+  fontSize: 13,
+  fontColor: '#666666',
+  dataPointShape: ['circle', 'circle', 'circle', 'circle'],
+  color: ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'],
+  linearColor: ['#0EE2F8', '#2BDCA8', '#FA7D8D', '#EB88E2', '#2AE3A0', '#0EE2F8', '#EB88E2', '#6773E3', '#F78A85'],
+  pieChartLinePadding: 15,
+  pieChartTextPadding: 5,
+  titleFontSize: 20,
+  subtitleFontSize: 15,
+  radarLabelTextMargin: 13,
+};
+
+var assign = function(target, ...varArgs) {
+  if (target == null) {
+    throw new TypeError('[uCharts] Cannot convert undefined or null to object');
+  }
+  if (!varArgs || varArgs.length <= 0) {
+    return target;
+  }
+  // 深度合并对象
+  function deepAssign(obj1, obj2) {
+    for (let key in obj2) {
+      obj1[key] = obj1[key] && obj1[key].toString() === "[object Object]" ?
+        deepAssign(obj1[key], obj2[key]) : obj1[key] = obj2[key];
+    }
+    return obj1;
+  }
+  varArgs.forEach(val => {
+    target = deepAssign(target, val);
+  });
+  return target;
+};
+
+var util = {
+  toFixed: function toFixed(num, limit) {
+    limit = limit || 2;
+    if (this.isFloat(num)) {
+      num = num.toFixed(limit);
+    }
+    return num;
+  },
+  isFloat: function isFloat(num) {
+    return num % 1 !== 0;
+  },
+  approximatelyEqual: function approximatelyEqual(num1, num2) {
+    return Math.abs(num1 - num2) < 1e-10;
+  },
+  isSameSign: function isSameSign(num1, num2) {
+    return Math.abs(num1) === num1 && Math.abs(num2) === num2 || Math.abs(num1) !== num1 && Math.abs(num2) !== num2;
+  },
+  isSameXCoordinateArea: function isSameXCoordinateArea(p1, p2) {
+    return this.isSameSign(p1.x, p2.x);
+  },
+  isCollision: function isCollision(obj1, obj2) {
+    obj1.end = {};
+    obj1.end.x = obj1.start.x + obj1.width;
+    obj1.end.y = obj1.start.y - obj1.height;
+    obj2.end = {};
+    obj2.end.x = obj2.start.x + obj2.width;
+    obj2.end.y = obj2.start.y - obj2.height;
+    var flag = obj2.start.x > obj1.end.x || obj2.end.x < obj1.start.x || obj2.end.y > obj1.start.y || obj2.start.y < obj1.end.y;
+    return !flag;
+  }
+};
+
+//兼容H5点击事件
+function getH5Offset(e) {
+  e.mp = {
+    changedTouches: []
+  };
+  e.mp.changedTouches.push({
+    x: e.offsetX,
+    y: e.offsetY
+  });
+  return e;
+}
+
+// hex 转 rgba
+function hexToRgb(hexValue, opc) {
+  var rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+  var hex = hexValue.replace(rgx, function(m, r, g, b) {
+    return r + r + g + g + b + b;
+  });
+  var rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+  var r = parseInt(rgb[1], 16);
+  var g = parseInt(rgb[2], 16);
+  var b = parseInt(rgb[3], 16);
+  return 'rgba(' + r + ',' + g + ',' + b + ',' + opc + ')';
+}
+
+function findRange(num, type, limit) {
+  if (isNaN(num)) {
+    throw new Error('[uCharts] series数据需为Number格式');
+  }
+  limit = limit || 10;
+  type = type ? type : 'upper';
+  var multiple = 1;
+  while (limit < 1) {
+    limit *= 10;
+    multiple *= 10;
+  }
+  if (type === 'upper') {
+    num = Math.ceil(num * multiple);
+  } else {
+    num = Math.floor(num * multiple);
+  }
+  while (num % limit !== 0) {
+    if (type === 'upper') {
+      if (num == num + 1) { //修复数据值过大num++无效的bug by 向日葵 @xrk_jy
+        break;
+      }
+      num++;
+    } else {
+      num--;
+    }
+  }
+  return num / multiple;
+}
+
+function calCandleMA(dayArr, nameArr, colorArr, kdata) {
+  let seriesTemp = [];
+  for (let k = 0; k < dayArr.length; k++) {
+    let seriesItem = {
+      data: [],
+      name: nameArr[k],
+      color: colorArr[k]
+    };
+    for (let i = 0, len = kdata.length; i < len; i++) {
+      if (i < dayArr[k]) {
+        seriesItem.data.push(null);
+        continue;
+      }
+      let sum = 0;
+      for (let j = 0; j < dayArr[k]; j++) {
+        sum += kdata[i - j][1];
+      }
+      seriesItem.data.push(+(sum / dayArr[k]).toFixed(3));
+    }
+    seriesTemp.push(seriesItem);
+  }
+  return seriesTemp;
+}
+
+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;
+    self.uevent.trigger('scrollLeft');
+    self.scrollOption.position = 'left'
+    opts.xAxis.scrollPosition = 'left';
+  } else if (Math.abs(distance) >= dataChartWidth - dataChartAreaWidth) {
+    validDistance = dataChartAreaWidth - dataChartWidth;
+    self.uevent.trigger('scrollRight');
+    self.scrollOption.position = 'right'
+    opts.xAxis.scrollPosition = 'right';
+  } else {
+    self.scrollOption.position = distance
+    opts.xAxis.scrollPosition = distance;
+  }
+  return validDistance;
+}
+
+function isInAngleRange(angle, startAngle, endAngle) {
+  function adjust(angle) {
+    while (angle < 0) {
+      angle += 2 * Math.PI;
+    }
+    while (angle > 2 * Math.PI) {
+      angle -= 2 * Math.PI;
+    }
+    return angle;
+  }
+  angle = adjust(angle);
+  startAngle = adjust(startAngle);
+  endAngle = adjust(endAngle);
+  if (startAngle > endAngle) {
+    endAngle += 2 * Math.PI;
+    if (angle < startAngle) {
+      angle += 2 * Math.PI;
+    }
+  }
+  return angle >= startAngle && angle <= endAngle;
+}
+
+function createCurveControlPoints(points, i) {
+  function isNotMiddlePoint(points, i) {
+    if (points[i - 1] && points[i + 1]) {
+      return points[i].y >= Math.max(points[i - 1].y, points[i + 1].y) || points[i].y <= Math.min(points[i - 1].y,
+        points[i + 1].y);
+    } else {
+      return false;
+    }
+  }
+  function isNotMiddlePointX(points, i) {
+    if (points[i - 1] && points[i + 1]) {
+      return points[i].x >= Math.max(points[i - 1].x, points[i + 1].x) || points[i].x <= Math.min(points[i - 1].x,
+        points[i + 1].x);
+    } else {
+      return false;
+    }
+  }
+  var a = 0.2;
+  var b = 0.2;
+  var pAx = null;
+  var pAy = null;
+  var pBx = null;
+  var pBy = null;
+  if (i < 1) {
+    pAx = points[0].x + (points[1].x - points[0].x) * a;
+    pAy = points[0].y + (points[1].y - points[0].y) * a;
+  } else {
+    pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a;
+    pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a;
+  }
+
+  if (i > points.length - 3) {
+    var last = points.length - 1;
+    pBx = points[last].x - (points[last].x - points[last - 1].x) * b;
+    pBy = points[last].y - (points[last].y - points[last - 1].y) * b;
+  } else {
+    pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b;
+    pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b;
+  }
+  if (isNotMiddlePoint(points, i + 1)) {
+    pBy = points[i + 1].y;
+  }
+  if (isNotMiddlePoint(points, i)) {
+    pAy = points[i].y;
+  }
+  if (isNotMiddlePointX(points, i + 1)) {
+    pBx = points[i + 1].x;
+  }
+  if (isNotMiddlePointX(points, i)) {
+    pAx = points[i].x;
+  }
+  if (pAy >= Math.max(points[i].y, points[i + 1].y) || pAy <= Math.min(points[i].y, points[i + 1].y)) {
+    pAy = points[i].y;
+  }
+  if (pBy >= Math.max(points[i].y, points[i + 1].y) || pBy <= Math.min(points[i].y, points[i + 1].y)) {
+    pBy = points[i + 1].y;
+  }
+  if (pAx >= Math.max(points[i].x, points[i + 1].x) || pAx <= Math.min(points[i].x, points[i + 1].x)) {
+    pAx = points[i].x;
+  }
+  if (pBx >= Math.max(points[i].x, points[i + 1].x) || pBx <= Math.min(points[i].x, points[i + 1].x)) {
+    pBx = points[i + 1].x;
+  }
+  return {
+    ctrA: {
+      x: pAx,
+      y: pAy
+    },
+    ctrB: {
+      x: pBx,
+      y: pBy
+    }
+  };
+}
+
+
+function convertCoordinateOrigin(x, y, center) {
+  return {
+    x: center.x + x,
+    y: center.y - y
+  };
+}
+
+function avoidCollision(obj, target) {
+  if (target) {
+    // is collision test
+    while (util.isCollision(obj, target)) {
+      if (obj.start.x > 0) {
+        obj.start.y--;
+      } else if (obj.start.x < 0) {
+        obj.start.y++;
+      } else {
+        if (obj.start.y > 0) {
+          obj.start.y++;
+        } else {
+          obj.start.y--;
+        }
+      }
+    }
+  }
+  return obj;
+}
+
+function fixPieSeries(series, opts, config){
+  let pieSeriesArr = [];
+  if(series.length>0 && series[0].data.constructor.toString().indexOf('Array') > -1){
+    opts._pieSeries_ = series;
+    let oldseries = series[0].data;
+    for (var i = 0; i < oldseries.length; i++) {
+      oldseries[i].formatter = series[0].formatter;
+      oldseries[i].data = oldseries[i].value;
+      pieSeriesArr.push(oldseries[i]);
+    }
+    opts.series = pieSeriesArr;
+  }else{
+    pieSeriesArr = series;
+  }
+  return pieSeriesArr;
+}
+
+function fillSeries(series, opts, config) {
+  var index = 0;
+  for (var i = 0; i < series.length; i++) {
+    let item = series[i];
+    if (!item.color) {
+      item.color = config.color[index];
+      index = (index + 1) % config.color.length;
+    }
+    if (!item.linearIndex) {
+      item.linearIndex = i;
+    }
+    if (!item.index) {
+      item.index = 0;
+    }
+    if (!item.type) {
+      item.type = opts.type;
+    }
+    if (typeof item.show == "undefined") {
+      item.show = true;
+    }
+    if (!item.type) {
+      item.type = opts.type;
+    }
+    if (!item.pointShape) {
+      item.pointShape = "circle";
+    }
+    if (!item.legendShape) {
+      switch (item.type) {
+        case 'line':
+          item.legendShape = "line";
+          break;
+        case 'column':
+        case 'bar':
+          item.legendShape = "rect";
+          break;
+        case 'area':
+        case 'mount':
+          item.legendShape = "triangle";
+          break;
+        default:
+          item.legendShape = "circle";
+      }
+    }
+  }
+  return series;
+}
+
+function fillCustomColor(linearType, customColor, series, config) {
+  var newcolor = customColor || [];
+  if (linearType == 'custom' && newcolor.length == 0 ) {
+    newcolor = config.linearColor;
+  }
+  if (linearType == 'custom' && newcolor.length < series.length) {
+    let chazhi = series.length - newcolor.length;
+    for (var i = 0; i < chazhi; i++) {
+      newcolor.push(config.linearColor[(i + 1) % config.linearColor.length]);
+    }
+  }
+  return newcolor;
+}
+
+function getDataRange(minData, maxData) {
+  var limit = 0;
+  var range = maxData - minData;
+  if (range >= 10000) {
+    limit = 1000;
+  } else if (range >= 1000) {
+    limit = 100;
+  } else if (range >= 100) {
+    limit = 10;
+  } else if (range >= 10) {
+    limit = 5;
+  } else if (range >= 1) {
+    limit = 1;
+  } else if (range >= 0.1) {
+    limit = 0.1;
+  } else if (range >= 0.01) {
+    limit = 0.01;
+  } else if (range >= 0.001) {
+    limit = 0.001;
+  } else if (range >= 0.0001) {
+    limit = 0.0001;
+  } else if (range >= 0.00001) {
+    limit = 0.00001;
+  } else {
+    limit = 0.000001;
+  }
+  return {
+    minRange: findRange(minData, 'lower', limit),
+    maxRange: findRange(maxData, 'upper', limit)
+  };
+}
+
+function measureText(text, fontSize, context) {
+  var width = 0;
+  text = String(text);
+  // #ifdef MP-ALIPAY || MP-BAIDU || APP-NVUE
+  context = false;
+  // #endif
+  if (context !== false && context !== undefined && context.setFontSize && context.measureText) {
+    context.setFontSize(fontSize);
+    return context.measureText(text).width;
+  } else {
+    var text = text.split('');
+    for (let i = 0; i < text.length; i++) {
+      let item = text[i];
+      if (/[a-zA-Z]/.test(item)) {
+        width += 7;
+      } else if (/[0-9]/.test(item)) {
+        width += 5.5;
+      } else if (/\./.test(item)) {
+        width += 2.7;
+      } else if (/-/.test(item)) {
+        width += 3.25;
+      } else if (/:/.test(item)) {
+        width += 2.5;
+      } else if (/[\u4e00-\u9fa5]/.test(item)) {
+        width += 10;
+      } else if (/\(|\)/.test(item)) {
+        width += 3.73;
+      } else if (/\s/.test(item)) {
+        width += 2.5;
+      } else if (/%/.test(item)) {
+        width += 8;
+      } else {
+        width += 10;
+      }
+    }
+    return width * fontSize / 10;
+  }
+}
+
+function dataCombine(series) {
+  return series.reduce(function(a, b) {
+    return (a.data ? a.data : a).concat(b.data);
+  }, []);
+}
+
+function dataCombineStack(series, len) {
+  var sum = new Array(len);
+  for (var j = 0; j < sum.length; j++) {
+    sum[j] = 0;
+  }
+  for (var i = 0; i < series.length; i++) {
+    for (var j = 0; j < sum.length; j++) {
+      sum[j] += series[i].data[j];
+    }
+  }
+  return series.reduce(function(a, b) {
+    return (a.data ? a.data : a).concat(b.data).concat(sum);
+  }, []);
+}
+
+function getTouches(touches, opts, e) {
+  let x, y;
+  if (touches.clientX) {
+    if (opts.rotate) {
+      y = opts.height - touches.clientX * opts.pix;
+      x = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pix / 2) * (opts.pix - 1)) * opts.pix;
+    } else {
+      x = touches.clientX * opts.pix;
+      y = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pix / 2) * (opts.pix - 1)) * opts.pix;
+    }
+  } else {
+    if (opts.rotate) {
+      y = opts.height - touches.x * opts.pix;
+      x = touches.y * opts.pix;
+    } else {
+      x = touches.x * opts.pix;
+      y = touches.y * opts.pix;
+    }
+  }
+  return {
+    x: x,
+    y: y
+  }
+}
+
+function getSeriesDataItem(series, index, group) {
+  var data = [];
+  var newSeries = [];
+  var indexIsArr = index.constructor.toString().indexOf('Array') > -1;
+  if(indexIsArr){
+    let tempSeries = filterSeries(series);
+    for (var i = 0; i < group.length; i++) {
+      newSeries.push(tempSeries[group[i]]);
+    }
+  }else{
+    newSeries = series;
+  };
+  for (let i = 0; i < newSeries.length; i++) {
+    let item = newSeries[i];
+    let tmpindex = -1;
+    if(indexIsArr){
+      tmpindex = index[i];
+    }else{
+      tmpindex = index;
+    }
+    if (item.data[tmpindex] !== null && typeof item.data[tmpindex] !== 'undefined' && item.show) {
+      let seriesItem = {};
+      seriesItem.color = item.color;
+      seriesItem.type = item.type;
+      seriesItem.style = item.style;
+      seriesItem.pointShape = item.pointShape;
+      seriesItem.disableLegend = item.disableLegend;
+      seriesItem.legendShape = item.legendShape;
+      seriesItem.name = item.name;
+      seriesItem.show = item.show;
+      seriesItem.data = item.formatter ? item.formatter(item.data[tmpindex]) : item.data[tmpindex];
+      data.push(seriesItem);
+    }
+  }
+  return data;
+}
+
+function getMaxTextListLength(list, fontSize, context) {
+  var lengthList = list.map(function(item) {
+    return measureText(item, fontSize, context);
+  });
+  return Math.max.apply(null, lengthList);
+}
+
+function getRadarCoordinateSeries(length) {
+  var eachAngle = 2 * Math.PI / length;
+  var CoordinateSeries = [];
+  for (var i = 0; i < length; i++) {
+    CoordinateSeries.push(eachAngle * i);
+  }
+  return CoordinateSeries.map(function(item) {
+    return -1 * item + Math.PI / 2;
+  });
+}
+
+function getToolTipData(seriesData, opts, index, group, categories) {
+  var option = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
+  var calPoints = opts.chartData.calPoints?opts.chartData.calPoints:[];
+  let points = {};
+  if(group.length > 0){
+    let filterPoints = [];
+    for (let i = 0; i < group.length; i++) {
+      filterPoints.push(calPoints[group[i]])
+    }
+    points = filterPoints[0][index[0]];
+  }else{
+    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;
+    if (opts.categories && opts.categories.length>0) {
+      titleText = categories[index];
+    };
+    return {
+      text: option.formatter ? option.formatter(item, titleText, index, opts) : item.name + ': ' + item.data,
+      color: item.color,
+      legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
+    };
+  });
+  var offset = {
+    x: Math.round(points.x),
+    y: Math.round(points.y)
+  };
+  return {
+    textList: textList,
+    offset: offset
+  };
+}
+
+function getMixToolTipData(seriesData, opts, index, categories) {
+  var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
+  var points = opts.chartData.xAxisPoints[index] + opts.chartData.eachSpacing / 2;
+  var textList = seriesData.map(function(item) {
+    return {
+      text: option.formatter ? option.formatter(item, categories[index], index, opts) : item.name + ': ' + item.data,
+      color: item.color,
+      disableLegend: item.disableLegend ? true : false,
+      legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
+    };
+  });
+  textList = textList.filter(function(item) {
+    if (item.disableLegend !== true) {
+      return item;
+    }
+  });
+  var offset = {
+    x: Math.round(points),
+    y: 0
+  };
+  return {
+    textList: textList,
+    offset: offset
+  };
+}
+
+function getCandleToolTipData(series, seriesData, opts, index, categories, extra) {
+  var option = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};
+  var calPoints = opts.chartData.calPoints;
+  let upColor = extra.color.upFill;
+  let downColor = extra.color.downFill;
+  //颜色顺序为开盘,收盘,最低,最高
+  let color = [upColor, upColor, downColor, upColor];
+  var textList = [];
+  seriesData.map(function(item) {
+    if (index == 0) {
+      if (item.data[1] - item.data[0] < 0) {
+        color[1] = downColor;
+      } else {
+        color[1] = upColor;
+      }
+    } else {
+      if (item.data[0] < series[index - 1][1]) {
+        color[0] = downColor;
+      }
+      if (item.data[1] < item.data[0]) {
+        color[1] = downColor;
+      }
+      if (item.data[2] > series[index - 1][1]) {
+        color[2] = upColor;
+      }
+      if (item.data[3] < series[index - 1][1]) {
+        color[3] = downColor;
+      }
+    }
+    let text1 = {
+      text: '开盘:' + item.data[0],
+      color: color[0],
+      legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
+    };
+    let text2 = {
+      text: '收盘:' + item.data[1],
+      color: color[1],
+      legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
+    };
+    let text3 = {
+      text: '最低:' + item.data[2],
+      color: color[2],
+      legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
+    };
+    let text4 = {
+      text: '最高:' + item.data[3],
+      color: color[3],
+      legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
+    };
+    textList.push(text1, text2, text3, text4);
+  });
+  var validCalPoints = [];
+  var offset = {
+    x: 0,
+    y: 0
+  };
+  for (let i = 0; i < calPoints.length; i++) {
+    let points = calPoints[i];
+    if (typeof points[index] !== 'undefined' && points[index] !== null) {
+      validCalPoints.push(points[index]);
+    }
+  }
+  offset.x = Math.round(validCalPoints[0][0].x);
+  return {
+    textList: textList,
+    offset: offset
+  };
+}
+
+function filterSeries(series) {
+  let tempSeries = [];
+  for (let i = 0; i < series.length; i++) {
+    if (series[i].show == true) {
+      tempSeries.push(series[i])
+    }
+  }
+  return tempSeries;
+}
+
+function findCurrentIndex(currentPoints, calPoints, opts, config) {
+  var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
+  var current={ index:-1, group:[] };
+  var spacing = opts.chartData.eachSpacing / 2;
+  let xAxisPoints = [];
+  if (calPoints && calPoints.length > 0) {
+    if (!opts.categories) {
+      spacing = 0;
+    }else{
+      for (let i = 1; i < opts.chartData.xAxisPoints.length; i++) {
+        xAxisPoints.push(opts.chartData.xAxisPoints[i] - spacing);
+      }
+      if ((opts.type == 'line' || opts.type == 'area') && opts.xAxis.boundaryGap == 'justify') {
+        xAxisPoints = opts.chartData.xAxisPoints;
+      }
+    }
+    if (isInExactChartArea(currentPoints, opts, config)) {
+      if (!opts.categories) {
+        let timePoints = Array(calPoints.length);
+        for (let i = 0; i < calPoints.length; i++) {
+          timePoints[i] = Array(calPoints[i].length)
+          for (let j = 0; j < calPoints[i].length; j++) {
+            timePoints[i][j] = (Math.abs(calPoints[i][j].x - currentPoints.x));
+          }
+        };
+        let pointValue =  Array(timePoints.length);
+        let pointIndex =  Array(timePoints.length);
+        for (let i = 0; i < timePoints.length; i++) {
+          pointValue[i] = Math.min.apply(null, timePoints[i]);
+          pointIndex[i] = timePoints[i].indexOf(pointValue[i]);
+        }
+        let minValue = Math.min.apply(null, pointValue);
+        current.index = [];
+        for (let i = 0; i < pointValue.length; i++) {
+          if(pointValue[i] == minValue){
+            current.group.push(i);
+            current.index.push(pointIndex[i]);
+          }
+        };
+      }else{
+        xAxisPoints.forEach(function(item, index) {
+          if (currentPoints.x + offset + spacing > item) {
+            current.index = index;
+          }
+        });
+      }
+    }
+  }
+  return current;
+}
+
+function findBarChartCurrentIndex(currentPoints, calPoints, opts, config) {
+  var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
+  var current={ index:-1, group:[] };
+  var spacing = opts.chartData.eachSpacing / 2;
+  let yAxisPoints = opts.chartData.yAxisPoints;
+  if (calPoints && calPoints.length > 0) {
+    if (isInExactChartArea(currentPoints, opts, config)) {
+      yAxisPoints.forEach(function(item, index) {
+        if (currentPoints.y + offset + spacing > item) {
+          current.index = index;
+        }
+      });
+    }
+  }
+  return current;
+}
+
+function findLegendIndex(currentPoints, legendData, opts) {
+  let currentIndex = -1;
+  let gap = 0;
+  if (isInExactLegendArea(currentPoints, legendData.area)) {
+    let points = legendData.points;
+    let index = -1;
+    for (let i = 0, len = points.length; i < len; i++) {
+      let item = points[i];
+      for (let j = 0; j < item.length; j++) {
+        index += 1;
+        let area = item[j]['area'];
+        if (area && currentPoints.x > area[0] - gap && currentPoints.x < area[2] + gap && currentPoints.y > area[1] - gap && currentPoints.y < area[3] + gap) {
+          currentIndex = index;
+          break;
+        }
+      }
+    }
+    return currentIndex;
+  }
+  return currentIndex;
+}
+
+function isInExactLegendArea(currentPoints, area) {
+  return currentPoints.x > area.start.x && currentPoints.x < area.end.x && currentPoints.y > area.start.y && currentPoints.y < area.end.y;
+}
+
+function isInExactChartArea(currentPoints, opts, config) {
+  return currentPoints.x <= opts.width - opts.area[1] + 10 && currentPoints.x >= opts.area[3] - 10 && currentPoints.y >= opts.area[0] && currentPoints.y <= opts.height - opts.area[2];
+}
+
+function findRadarChartCurrentIndex(currentPoints, radarData, count) {
+  var eachAngleArea = 2 * Math.PI / count;
+  var currentIndex = -1;
+  if (isInExactPieChartArea(currentPoints, radarData.center, radarData.radius)) {
+    var fixAngle = function fixAngle(angle) {
+      if (angle < 0) {
+        angle += 2 * Math.PI;
+      }
+      if (angle > 2 * Math.PI) {
+        angle -= 2 * Math.PI;
+      }
+      return angle;
+    };
+    var angle = Math.atan2(radarData.center.y - currentPoints.y, currentPoints.x - radarData.center.x);
+    angle = -1 * angle;
+    if (angle < 0) {
+      angle += 2 * Math.PI;
+    }
+    var angleList = radarData.angleList.map(function(item) {
+      item = fixAngle(-1 * item);
+      return item;
+    });
+    angleList.forEach(function(item, index) {
+      var rangeStart = fixAngle(item - eachAngleArea / 2);
+      var rangeEnd = fixAngle(item + eachAngleArea / 2);
+      if (rangeEnd < rangeStart) {
+        rangeEnd += 2 * Math.PI;
+      }
+      if (angle >= rangeStart && angle <= rangeEnd || angle + 2 * Math.PI >= rangeStart && angle + 2 * Math.PI <= rangeEnd) {
+        currentIndex = index;
+      }
+    });
+  }
+  return currentIndex;
+}
+
+function findFunnelChartCurrentIndex(currentPoints, funnelData) {
+  var currentIndex = -1;
+  for (var i = 0, len = funnelData.series.length; i < len; i++) {
+    var item = funnelData.series[i];
+    if (currentPoints.x > item.funnelArea[0] && currentPoints.x < item.funnelArea[2] && currentPoints.y > item.funnelArea[1] && currentPoints.y < item.funnelArea[3]) {
+      currentIndex = i;
+      break;
+    }
+  }
+  return currentIndex;
+}
+
+function findWordChartCurrentIndex(currentPoints, wordData) {
+  var currentIndex = -1;
+  for (var i = 0, len = wordData.length; i < len; i++) {
+    var item = wordData[i];
+    if (currentPoints.x > item.area[0] && currentPoints.x < item.area[2] && currentPoints.y > item.area[1] && currentPoints.y < item.area[3]) {
+      currentIndex = i;
+      break;
+    }
+  }
+  return currentIndex;
+}
+
+function findMapChartCurrentIndex(currentPoints, opts) {
+  var currentIndex = -1;
+  var cData = opts.chartData.mapData;
+  var data = opts.series;
+  var tmp = pointToCoordinate(currentPoints.y, currentPoints.x, cData.bounds, cData.scale, cData.xoffset, cData.yoffset);
+  var poi = [tmp.x, tmp.y];
+  for (var i = 0, len = data.length; i < len; i++) {
+    var item = data[i].geometry.coordinates;
+    if (isPoiWithinPoly(poi, item, opts.chartData.mapData.mercator)) {
+      currentIndex = i;
+      break;
+    }
+  }
+  return currentIndex;
+}
+
+function findRoseChartCurrentIndex(currentPoints, pieData, opts) {
+  var currentIndex = -1;
+  var series = getRoseDataPoints(opts._series_, opts.extra.rose.type, pieData.radius, pieData.radius);
+  if (pieData && pieData.center && isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) {
+    var angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x);
+    angle = -angle;
+    if(opts.extra.rose && opts.extra.rose.offsetAngle){
+      angle = angle - opts.extra.rose.offsetAngle * Math.PI / 180;
+    }
+    for (var i = 0, len = series.length; i < len; i++) {
+      if (isInAngleRange(angle, series[i]._start_, series[i]._start_ + series[i]._rose_proportion_ * 2 * Math.PI)) {
+        currentIndex = i;
+        break;
+      }
+    }
+  }
+  return currentIndex;
+}
+
+function findPieChartCurrentIndex(currentPoints, pieData, opts) {
+  var currentIndex = -1;
+  var series = getPieDataPoints(pieData.series);
+  if (pieData && pieData.center && isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) {
+    var angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x);
+    angle = -angle;
+    if(opts.extra.pie && opts.extra.pie.offsetAngle){
+      angle = angle - opts.extra.pie.offsetAngle * Math.PI / 180;
+    }
+    if(opts.extra.ring && opts.extra.ring.offsetAngle){
+      angle = angle - opts.extra.ring.offsetAngle * Math.PI / 180;
+    }
+    for (var i = 0, len = series.length; i < len; i++) {
+      if (isInAngleRange(angle, series[i]._start_, series[i]._start_ + series[i]._proportion_ * 2 * Math.PI)) {
+        currentIndex = i;
+        break;
+      }
+    }
+  }
+  return currentIndex;
+}
+
+function isInExactPieChartArea(currentPoints, center, radius) {
+  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 = [];
+  points.forEach(function(item, index) {
+    if(eachSeries.connectNulls){
+      if (item !== null) {
+        items.push(item);
+      }
+    }else{
+      if (item !== null) {
+        items.push(item);
+      } else {
+        if (items.length) {
+          newPoints.push(items);
+        }
+        items = [];
+      }
+    }
+    
+  });
+  if (items.length) {
+    newPoints.push(items);
+  }
+  return newPoints;
+}
+
+
+function calLegendData(series, opts, config, chartData, context) {
+  let legendData = {
+    area: {
+      start: {
+        x: 0,
+        y: 0
+      },
+      end: {
+        x: 0,
+        y: 0
+      },
+      width: 0,
+      height: 0,
+      wholeWidth: 0,
+      wholeHeight: 0
+    },
+    points: [],
+    widthArr: [],
+    heightArr: []
+  };
+  if (opts.legend.show === false) {
+    chartData.legendData = legendData;
+    return legendData;
+  }
+  let padding = opts.legend.padding * opts.pix;
+  let margin = opts.legend.margin * opts.pix;
+  let fontSize = opts.legend.fontSize ? opts.legend.fontSize * opts.pix : config.fontSize;
+  let shapeWidth = 15 * opts.pix;
+  let shapeRight = 5 * opts.pix;
+  let lineHeight = Math.max(opts.legend.lineHeight * opts.pix, fontSize);
+  if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
+    let legendList = [];
+    let widthCount = 0;
+    let widthCountArr = [];
+    let currentRow = [];
+    for (let i = 0; i < series.length; i++) {
+      let item = series[i];
+      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);
+        widthCount = itemWidth;
+        currentRow = [item];
+      } else {
+        widthCount += itemWidth;
+        currentRow.push(item);
+      }
+    }
+    if (currentRow.length) {
+      legendList.push(currentRow);
+      widthCountArr.push(widthCount - opts.legend.itemGap * opts.pix);
+      legendData.widthArr = widthCountArr;
+      let legendWidth = Math.max.apply(null, widthCountArr);
+      switch (opts.legend.float) {
+        case 'left':
+          legendData.area.start.x = opts.area[3];
+          legendData.area.end.x = opts.area[3] + legendWidth + 2 * padding;
+          break;
+        case 'right':
+          legendData.area.start.x = opts.width - opts.area[1] - legendWidth - 2 * padding;
+          legendData.area.end.x = opts.width - opts.area[1];
+          break;
+        default:
+          legendData.area.start.x = (opts.width - legendWidth) / 2 - padding;
+          legendData.area.end.x = (opts.width + legendWidth) / 2 + padding;
+      }
+      legendData.area.width = legendWidth + 2 * padding;
+      legendData.area.wholeWidth = legendWidth + 2 * padding;
+      legendData.area.height = legendList.length * lineHeight + 2 * padding;
+      legendData.area.wholeHeight = legendList.length * lineHeight + 2 * padding + 2 * margin;
+      legendData.points = legendList;
+    }
+  } else {
+    let len = series.length;
+    let maxHeight = opts.height - opts.area[0] - opts.area[2] - 2 * margin - 2 * padding;
+    let maxLength = Math.min(Math.floor(maxHeight / lineHeight), len);
+    legendData.area.height = maxLength * lineHeight + padding * 2;
+    legendData.area.wholeHeight = maxLength * lineHeight + padding * 2;
+    switch (opts.legend.float) {
+      case 'top':
+        legendData.area.start.y = opts.area[0] + margin;
+        legendData.area.end.y = opts.area[0] + margin + legendData.area.height;
+        break;
+      case 'bottom':
+        legendData.area.start.y = opts.height - opts.area[2] - margin - legendData.area.height;
+        legendData.area.end.y = opts.height - opts.area[2] - margin;
+        break;
+      default:
+        legendData.area.start.y = (opts.height - legendData.area.height) / 2;
+        legendData.area.end.y = (opts.height + legendData.area.height) / 2;
+    }
+    let lineNum = len % maxLength === 0 ? len / maxLength : Math.floor((len / maxLength) + 1);
+    let currentRow = [];
+    for (let i = 0; i < lineNum; i++) {
+      let temp = series.slice(i * maxLength, i * maxLength + maxLength);
+      currentRow.push(temp);
+    }
+    legendData.points = currentRow;
+    if (currentRow.length) {
+      for (let i = 0; i < currentRow.length; i++) {
+        let item = currentRow[i];
+        let maxWidth = 0;
+        for (let j = 0; j < item.length; j++) {
+          let itemWidth = shapeWidth + shapeRight + measureText(item[j].name || 'undefined', fontSize, context) + opts.legend.itemGap * opts.pix;
+          if (itemWidth > maxWidth) {
+            maxWidth = itemWidth;
+          }
+        }
+        legendData.widthArr.push(maxWidth);
+        legendData.heightArr.push(item.length * lineHeight + padding * 2);
+      }
+      let legendWidth = 0
+      for (let i = 0; i < legendData.widthArr.length; i++) {
+        legendWidth += legendData.widthArr[i];
+      }
+      legendData.area.width = legendWidth - opts.legend.itemGap * opts.pix + 2 * padding;
+      legendData.area.wholeWidth = legendData.area.width + padding;
+    }
+  }
+  switch (opts.legend.position) {
+    case 'top':
+      legendData.area.start.y = opts.area[0] + margin;
+      legendData.area.end.y = opts.area[0] + margin + legendData.area.height;
+      break;
+    case 'bottom':
+      legendData.area.start.y = opts.height - opts.area[2] - legendData.area.height - margin;
+      legendData.area.end.y = opts.height - opts.area[2] - margin;
+      break;
+    case 'left':
+      legendData.area.start.x = opts.area[3];
+      legendData.area.end.x = opts.area[3] + legendData.area.width;
+      break;
+    case 'right':
+      legendData.area.start.x = opts.width - opts.area[1] - legendData.area.width;
+      legendData.area.end.x = opts.width - opts.area[1];
+      break;
+  }
+  chartData.legendData = legendData;
+  return legendData;
+}
+
+function calCategoriesData(categories, opts, config, eachSpacing, context) {
+  var result = {
+    angle: 0,
+    xAxisHeight: opts.xAxis.lineHeight * opts.pix + opts.xAxis.marginTop * opts.pix
+  };
+  var fontSize = opts.xAxis.fontSize * opts.pix;
+  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) {
+    result.angle = opts.xAxis.rotateAngle * Math.PI / 180;
+    let tempHeight = opts.xAxis.marginTop * opts.pix * 2 +  Math.abs(maxTextLength * Math.sin(result.angle))
+    tempHeight = tempHeight < fontSize + opts.xAxis.marginTop * opts.pix * 2 ? tempHeight + opts.xAxis.marginTop * opts.pix * 2 : tempHeight;
+    result.xAxisHeight = tempHeight;
+  }
+  if (opts.enableScroll && opts.xAxis.scrollShow) {
+    result.xAxisHeight += 6 * opts.pix;
+  }
+  if (opts.xAxis.disabled){
+    result.xAxisHeight = 0;
+  }
+  return result;
+}
+
+function getXAxisTextList(series, opts, config, stack) {
+  var index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1;
+  var data;
+  if (stack == 'stack') {
+    data = dataCombineStack(series, opts.categories.length);
+  } else {
+    data = dataCombine(series);
+  }
+  var sorted = [];
+  // remove null from data
+  data = data.filter(function(item) {
+    //return item !== null;
+    if (typeof item === 'object' && item !== null) {
+      if (item.constructor.toString().indexOf('Array') > -1) {
+        return item !== null;
+      } else {
+        return item.value !== null;
+      }
+    } else {
+      return item !== null;
+    }
+  });
+  data.map(function(item) {
+    if (typeof item === 'object') {
+      if (item.constructor.toString().indexOf('Array') > -1) {
+        if (opts.type == 'candle') {
+          item.map(function(subitem) {
+            sorted.push(subitem);
+          })
+        } else {
+          sorted.push(item[0]);
+        }
+      } else {
+        sorted.push(item.value);
+      }
+    } else {
+      sorted.push(item);
+    }
+  })
+
+  var minData = 0;
+  var maxData = 0;
+  if (sorted.length > 0) {
+    minData = Math.min.apply(this, sorted);
+    maxData = Math.max.apply(this, sorted);
+  }
+  //为了兼容v1.9.0之前的项目
+  if (index > -1) {
+    if (typeof opts.xAxis.data[index].min === 'number') {
+      minData = Math.min(opts.xAxis.data[index].min, minData);
+    }
+    if (typeof opts.xAxis.data[index].max === 'number') {
+      maxData = Math.max(opts.xAxis.data[index].max, maxData);
+    }
+  } else {
+    if (typeof opts.xAxis.min === 'number') {
+      minData = Math.min(opts.xAxis.min, minData);
+    }
+    if (typeof opts.xAxis.max === 'number') {
+      maxData = Math.max(opts.xAxis.max, maxData);
+    }
+  }
+  if (minData === maxData) {
+    var rangeSpan = maxData || 10;
+    maxData += rangeSpan;
+  }
+  //var dataRange = getDataRange(minData, maxData);
+  var minRange = minData;
+  var maxRange = maxData;
+  var range = [];
+  var eachRange = (maxRange - minRange) / opts.xAxis.splitNumber;
+  for (var i = 0; i <= opts.xAxis.splitNumber; i++) {
+    range.push(minRange + eachRange * i);
+  }
+  return range;
+}
+
+function calXAxisData(series, opts, config, context) {
+  //堆叠图重算Y轴
+  var columnstyle = assign({}, {
+    type: ""
+  }, opts.extra.bar);
+  var result = {
+    angle: 0,
+    xAxisHeight: opts.xAxis.lineHeight * opts.pix + opts.xAxis.marginTop * opts.pix
+  };
+  result.ranges = getXAxisTextList(series, opts, config, columnstyle.type);
+  result.rangesFormat = result.ranges.map(function(item) {
+    //item = opts.xAxis.formatter ? opts.xAxis.formatter(item) : util.toFixed(item, 2);
+    item = util.toFixed(item, 2);
+    return item;
+  });
+  var xAxisScaleValues = result.ranges.map(function(item) {
+    // 如果刻度值是浮点数,则保留两位小数
+    item = util.toFixed(item, 2);
+    // 若有自定义格式则调用自定义的格式化函数
+    //item = opts.xAxis.formatter ? opts.xAxis.formatter(Number(item)) : item;
+    return item;
+  });
+  result = Object.assign(result, getXAxisPoints(xAxisScaleValues, opts, config));
+  // 计算X轴刻度的属性譬如每个刻度的间隔,刻度的起始点\结束点以及总长
+  var eachSpacing = result.eachSpacing;
+  var textLength = xAxisScaleValues.map(function(item) {
+    return measureText(item, opts.xAxis.fontSize * opts.pix, context);
+  });
+  if (opts.xAxis.disabled === true) {
+    result.xAxisHeight = 0;
+  }
+  return result;
+}
+
+function getRadarDataPoints(angleList, center, radius, series, opts) {
+  var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
+  var radarOption = opts.extra.radar || {};
+  radarOption.max = radarOption.max || 0;
+  var maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series)));
+  var data = [];
+  for (let i = 0; i < series.length; i++) {
+    let each = series[i];
+    let listItem = {};
+    listItem.color = each.color;
+    listItem.legendShape = each.legendShape;
+    listItem.pointShape = each.pointShape;
+    listItem.data = [];
+    each.data.forEach(function(item, index) {
+      let tmp = {};
+      tmp.angle = angleList[index];
+      tmp.proportion = item / maxData;
+      tmp.value = item;
+      tmp.position = convertCoordinateOrigin(radius * tmp.proportion * process * Math.cos(tmp.angle), radius * tmp.proportion * process * Math.sin(tmp.angle), center);
+      listItem.data.push(tmp);
+    });
+    data.push(listItem);
+  }
+  return data;
+}
+
+function getPieDataPoints(series, radius) {
+  var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+  var count = 0;
+  var _start_ = 0;
+  for (let i = 0; i < series.length; i++) {
+    let item = series[i];
+    item.data = item.data === null ? 0 : item.data;
+    count += item.data;
+  }
+  for (let i = 0; i < series.length; i++) {
+    let item = series[i];
+    item.data = item.data === null ? 0 : item.data;
+    if (count === 0) {
+      item._proportion_ = 1 / series.length * process;
+    } else {
+      item._proportion_ = item.data / count * process;
+    }
+    item._radius_ = radius;
+  }
+  for (let i = 0; i < series.length; i++) {
+    let item = series[i];
+    item._start_ = _start_;
+    _start_ += 2 * item._proportion_ * Math.PI;
+  }
+  return series;
+}
+
+function getFunnelDataPoints(series, radius, option, eachSpacing) {
+  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  for (let i = 0; i < series.length; i++) {
+    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(option.type !== 'pyramid'){
+  //   series.reverse();
+  // }
+  return series;
+}
+
+function getRoseDataPoints(series, type, minRadius, radius) {
+  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  var count = 0;
+  var _start_ = 0;
+  var dataArr = [];
+  for (let i = 0; i < series.length; i++) {
+    let item = series[i];
+    item.data = item.data === null ? 0 : item.data;
+    count += item.data;
+    dataArr.push(item.data);
+  }
+  var minData = Math.min.apply(null, dataArr);
+  var maxData = Math.max.apply(null, dataArr);
+  var radiusLength = radius - minRadius;
+  for (let i = 0; i < series.length; i++) {
+    let item = series[i];
+    item.data = item.data === null ? 0 : item.data;
+    if (count === 0) {
+      item._proportion_ = 1 / series.length * process;
+      item._rose_proportion_ = 1 / series.length * process;
+    } else {
+      item._proportion_ = item.data / count * process;
+      if(type == 'area'){
+        item._rose_proportion_ = 1 / series.length * process;
+      }else{
+        item._rose_proportion_ = item.data / count * process;
+      }
+    }
+    item._radius_ = minRadius + radiusLength * ((item.data - minData) / (maxData - minData)) || radius;
+  }
+  for (let i = 0; i < series.length; i++) {
+    let item = series[i];
+    item._start_ = _start_;
+    _start_ += 2 * item._rose_proportion_ * Math.PI;
+  }
+  return series;
+}
+
+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;
+  }
+  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.endAngle < arcbarOption.startAngle) {
+        totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle;
+      } else {
+        totalAngle = arcbarOption.startAngle - arcbarOption.endAngle;
+      }
+    }
+    item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle;
+    if (item._proportion_ >= 2) {
+      item._proportion_ = item._proportion_ % 2;
+    }
+  }
+  return series;
+}
+
+function getGaugeAxisPoints(categories, startAngle, endAngle) {
+  let totalAngle;
+  if (endAngle < startAngle) {
+    totalAngle = 2 + endAngle - startAngle;
+  } else {
+    totalAngle = startAngle - endAngle;
+  }
+  let tempStartAngle = startAngle;
+  for (let i = 0; i < categories.length; i++) {
+    categories[i].value = categories[i].value === null ? 0 : categories[i].value;
+    categories[i]._startAngle_ = tempStartAngle;
+    categories[i]._endAngle_ = totalAngle * categories[i].value + startAngle;
+    if (categories[i]._endAngle_ >= 2) {
+      categories[i]._endAngle_ = categories[i]._endAngle_ % 2;
+    }
+    tempStartAngle = categories[i]._endAngle_;
+  }
+  return categories;
+}
+
+function getGaugeDataPoints(series, categories, gaugeOption) {
+  let process = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
+  for (let i = 0; i < series.length; i++) {
+    let item = series[i];
+    item.data = item.data === null ? 0 : item.data;
+    if (gaugeOption.pointer.color == 'auto') {
+      for (let i = 0; i < categories.length; i++) {
+        if (item.data <= categories[i].value) {
+          item.color = categories[i].color;
+          break;
+        }
+      }
+    } else {
+      item.color = gaugeOption.pointer.color;
+    }
+    let totalAngle;
+    if (gaugeOption.endAngle < gaugeOption.startAngle) {
+      totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle;
+    } else {
+      totalAngle = gaugeOption.startAngle - gaugeOption.endAngle;
+    }
+    item._endAngle_ = totalAngle * item.data + gaugeOption.startAngle;
+    item._oldAngle_ = gaugeOption.oldAngle;
+    if (gaugeOption.oldAngle < gaugeOption.endAngle) {
+      item._oldAngle_ += 2;
+    }
+    if (item.data >= gaugeOption.oldData) {
+      item._proportion_ = (item._endAngle_ - item._oldAngle_) * process + gaugeOption.oldAngle;
+    } else {
+      item._proportion_ = item._oldAngle_ - (item._oldAngle_ - item._endAngle_) * process;
+    }
+    if (item._proportion_ >= 2) {
+      item._proportion_ = item._proportion_ % 2;
+    }
+  }
+  return series;
+}
+
+function getPieTextMaxLength(series, config, context, opts) {
+  series = getPieDataPoints(series);
+  let maxLength = 0;
+  for (let i = 0; i < series.length; i++) {
+    let item = series[i];
+    let text = item.formatter ? item.formatter(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%';
+    maxLength = Math.max(maxLength, measureText(text, item.textSize * opts.pix || config.fontSize, context));
+  }
+  return maxLength;
+}
+
+function fixColumeData(points, eachSpacing, columnLen, index, config, opts) {
+  return points.map(function(item) {
+    if (item === null) {
+      return null;
+    }
+    var seriesGap = 0;
+    var categoryGap = 0;
+    if (opts.type == 'mix') {
+      seriesGap = opts.extra.mix.column.seriesGap * opts.pix || 0;
+      categoryGap = opts.extra.mix.column.categoryGap * opts.pix || 0;
+    } else {
+      seriesGap = opts.extra.column.seriesGap * opts.pix || 0;
+      categoryGap = opts.extra.column.categoryGap * opts.pix || 0;
+    }
+    seriesGap =  Math.min(seriesGap, eachSpacing / columnLen)
+    categoryGap =  Math.min(categoryGap, eachSpacing / columnLen)
+    item.width = Math.ceil((eachSpacing - 2 * categoryGap - seriesGap * (columnLen - 1)) / columnLen);
+    if (opts.extra.mix && opts.extra.mix.column.width && +opts.extra.mix.column.width > 0) {
+      item.width = Math.min(item.width, +opts.extra.mix.column.width * opts.pix);
+    }
+    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 (item.width <= 0) {
+      item.width = 1;
+    }
+    item.x += (index + 0.5 - columnLen / 2) * (item.width + seriesGap);
+    return item;
+  });
+}
+
+function fixBarData(points, eachSpacing, columnLen, index, config, opts) {
+  return points.map(function(item) {
+    if (item === null) {
+      return null;
+    }
+    var seriesGap = 0;
+    var categoryGap = 0;
+    seriesGap = opts.extra.bar.seriesGap * opts.pix || 0;
+    categoryGap = opts.extra.bar.categoryGap * opts.pix || 0;
+    seriesGap =  Math.min(seriesGap, eachSpacing / columnLen)
+    categoryGap =  Math.min(categoryGap, eachSpacing / columnLen)
+    item.width = Math.ceil((eachSpacing - 2 * categoryGap - seriesGap * (columnLen - 1)) / columnLen);
+    if (opts.extra.bar && opts.extra.bar.width && +opts.extra.bar.width > 0) {
+      item.width = Math.min(item.width, +opts.extra.bar.width * opts.pix);
+    }
+    if (item.width <= 0) {
+      item.width = 1;
+    }
+    item.y += (index + 0.5 - columnLen / 2) * (item.width + seriesGap);
+    return item;
+  });
+}
+
+function fixColumeMeterData(points, eachSpacing, columnLen, index, config, opts, border) {
+  var categoryGap = opts.extra.column.categoryGap * opts.pix || 0;
+  return points.map(function(item) {
+    if (item === null) {
+      return null;
+    }
+    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 -= border;
+    }
+    return item;
+  });
+}
+
+function fixColumeStackData(points, eachSpacing, columnLen, index, config, opts, series) {
+  var categoryGap = opts.extra.column.categoryGap * opts.pix || 0;
+  return points.map(function(item, indexn) {
+    if (item === null) {
+      return null;
+    }
+    item.width = Math.ceil(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 (item.width <= 0) {
+      item.width = 1;
+    }
+    return item;
+  });
+}
+
+function fixBarStackData(points, eachSpacing, columnLen, index, config, opts, series) {
+  var categoryGap = opts.extra.bar.categoryGap * opts.pix || 0;
+  return points.map(function(item, indexn) {
+    if (item === null) {
+      return null;
+    }
+    item.width = Math.ceil(eachSpacing - 2 * categoryGap);
+    if (opts.extra.bar && opts.extra.bar.width && +opts.extra.bar.width > 0) {
+      item.width = Math.min(item.width, +opts.extra.bar.width * opts.pix);
+    }
+    if (item.width <= 0) {
+      item.width = 1;
+    }
+    return item;
+  });
+}
+
+function getXAxisPoints(categories, opts, config) {
+  var spacingValid = opts.width - opts.area[1] - opts.area[3];
+  var dataCount = opts.enableScroll ? Math.min(opts.xAxis.itemCount, categories.length) : categories.length;
+  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 + widthRatio / 2 * eachSpacing + index * eachSpacing);
+  });
+  if (opts.xAxis.boundaryGap !== 'justify') {
+    if (opts.enableScroll === true) {
+      xAxisPoints.push(startX + widthRatio * eachSpacing + categories.length * eachSpacing);
+    } else {
+      xAxisPoints.push(endX);
+    }
+  }
+  return {
+    xAxisPoints: xAxisPoints,
+    startX: startX,
+    endX: endX,
+    eachSpacing: eachSpacing
+  };
+}
+
+function getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
+  var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
+  var points = [];
+  var validHeight = opts.height - opts.area[0] - opts.area[2];
+  data.forEach(function(item, index) {
+    if (item === null) {
+      points.push(null);
+    } else {
+      var cPoints = [];
+      item.forEach(function(items, indexs) {
+        var point = {};
+        point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
+        var value = items.value || items;
+        var height = validHeight * (value - minRange) / (maxRange - minRange);
+        height *= process;
+        point.y = opts.height - Math.round(height) - opts.area[2];
+        cPoints.push(point);
+      });
+      points.push(cPoints);
+    }
+  });
+  return points;
+}
+
+function getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
+  var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
+  var boundaryGap = 'center';
+  if (opts.type == 'line' || opts.type == 'area' || opts.type == 'scatter' || opts.type == 'bubble' ) {
+    boundaryGap = opts.xAxis.boundaryGap;
+  }
+  var points = [];
+  var validHeight = opts.height - opts.area[0] - opts.area[2];
+  var validWidth = opts.width - opts.area[1] - opts.area[3];
+  data.forEach(function(item, index) {
+    if (item === null) {
+      points.push(null);
+    } else {
+      var point = {};
+      point.color = item.color;
+      point.x = xAxisPoints[index];
+      var value = item;
+      if (typeof item === 'object' && item !== null) {
+        if (item.constructor.toString().indexOf('Array') > -1) {
+          let xranges, xminRange, xmaxRange;
+          xranges = [].concat(opts.chartData.xAxisData.ranges);
+          xminRange = xranges.shift();
+          xmaxRange = xranges.pop();
+          value = item[1];
+          point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
+          if(opts.type == 'bubble'){
+            point.r = item[2];
+            point.t = item[3];
+          }
+        } else {
+          value = item.value;
+        }
+      }
+      if (boundaryGap == 'center') {
+        point.x += eachSpacing / 2;
+      }
+      var height = validHeight * (value - minRange) / (maxRange - minRange);
+      height *= process;
+      point.y = opts.height - height - opts.area[2];
+      points.push(point);
+    }
+  });
+  return points;
+}
+
+function getLineDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, lineOption, process){
+  var process = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 1;
+  var boundaryGap = opts.xAxis.boundaryGap;
+  var points = [];
+  var validHeight = opts.height - opts.area[0] - opts.area[2];
+  var validWidth = opts.width - opts.area[1] - opts.area[3];
+  data.forEach(function(item, index) {
+    if (item === null) {
+      points.push(null);
+    } else {
+      var point = {};
+      point.color = item.color;
+      if(lineOption.animation == 'vertical'){
+        point.x = xAxisPoints[index];
+        var value = item;
+        if (typeof item === 'object' && item !== null) {
+          if (item.constructor.toString().indexOf('Array') > -1) {
+            let xranges, xminRange, xmaxRange;
+            xranges = [].concat(opts.chartData.xAxisData.ranges);
+            xminRange = xranges.shift();
+            xmaxRange = xranges.pop();
+            value = item[1];
+            point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
+          } else {
+            value = item.value;
+          }
+        }
+        if (boundaryGap == 'center') {
+          point.x += eachSpacing / 2;
+        }
+        var height = validHeight * (value - minRange) / (maxRange - minRange);
+        height *= process;
+        point.y = opts.height - height - opts.area[2];
+        points.push(point);
+      }else{
+        point.x = xAxisPoints[0] + eachSpacing * index * process;
+        var value = item;
+        if (boundaryGap == 'center') {
+          point.x += eachSpacing / 2;
+        }
+        var height = validHeight * (value - minRange) / (maxRange - minRange);
+        point.y = opts.height - height - opts.area[2];
+        points.push(point);
+      }
+    }
+  });
+  return points;
+}
+
+function getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, zeroPoints, process){
+  var process = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 1;
+  var points = [];
+  var validHeight = opts.height - opts.area[0] - opts.area[2];
+  var validWidth = opts.width - opts.area[1] - opts.area[3];
+  data.forEach(function(item, index) {
+    if (item === null) {
+      points.push(null);
+    } else {
+      var point = {};
+      point.color = item.color;
+      point.x = xAxisPoints[index];
+      var value = item;
+      if (typeof item === 'object' && item !== null) {
+        if (item.constructor.toString().indexOf('Array') > -1) {
+          let xranges, xminRange, xmaxRange;
+          xranges = [].concat(opts.chartData.xAxisData.ranges);
+          xminRange = xranges.shift();
+          xmaxRange = xranges.pop();
+          value = item[1];
+          point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
+        } else {
+          value = item.value;
+        }
+      }
+      point.x += eachSpacing / 2;
+      var height = validHeight * (value * process - minRange) / (maxRange - minRange);
+      point.y = opts.height - height - opts.area[2];
+      points.push(point);
+    }
+  });
+  return points;
+}
+
+function getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints) {
+  var process = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 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 * process - minRange) / (maxRange - minRange);
+      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 = [];
+  var validHeight = opts.height - opts.area[0] - opts.area[2];
+  var validWidth = opts.width - opts.area[1] - opts.area[3];
+  data.forEach(function(item, index) {
+    if (item === null) {
+      points.push(null);
+    } else {
+      var point = {};
+      point.color = item.color;
+      point.y = yAxisPoints[index];
+      var value = item;
+      if (typeof item === 'object' && item !== null) {
+        value = item.value;
+      }
+      var height = validWidth * (value - minRange) / (maxRange - minRange);
+      height *= process;
+      point.height = height;
+      point.value = value;
+      point.x = height + opts.area[3];
+      points.push(point);
+    }
+  });
+  return points;
+}
+
+function getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, stackSeries) {
+  var process = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : 1;
+  var points = [];
+  var validHeight = opts.height - opts.area[0] - opts.area[2];
+  data.forEach(function(item, index) {
+    if (item === null) {
+      points.push(null);
+    } else {
+      var point = {};
+      point.color = item.color;
+      point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
+
+      if (seriesIndex > 0) {
+        var value = 0;
+        for (let i = 0; i <= seriesIndex; i++) {
+          value += stackSeries[i].data[index];
+        }
+        var value0 = value - item;
+        var height = validHeight * (value - minRange) / (maxRange - minRange);
+        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;
+      }
+      var heightc = height0;
+      height *= process;
+      heightc *= process;
+      point.y = opts.height - Math.round(height) - opts.area[2];
+      point.y0 = opts.height - Math.round(heightc) - opts.area[2];
+      points.push(point);
+    }
+  });
+  return points;
+}
+
+function getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, stackSeries) {
+  var process = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : 1;
+  var points = [];
+  var validHeight = opts.width - opts.area[1] - opts.area[3];
+  data.forEach(function(item, index) {
+    if (item === null) {
+      points.push(null);
+    } else {
+      var point = {};
+      point.color = item.color;
+      point.y = yAxisPoints[index];
+      if (seriesIndex > 0) {
+        var value = 0;
+        for (let i = 0; i <= seriesIndex; i++) {
+          value += stackSeries[i].data[index];
+        }
+        var value0 = value - item;
+        var height = validHeight * (value - minRange) / (maxRange - minRange);
+        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;
+      }
+      var heightc = height0;
+      height *= process;
+      heightc *= process;
+      point.height = height - heightc;
+      point.x = opts.area[3] + height;
+      point.x0 = opts.area[3] + heightc;
+      points.push(point);
+    }
+  });
+  return points;
+}
+
+function getYAxisTextList(series, opts, config, stack, yData) {
+  var index = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : -1;
+  var data;
+  if (stack == 'stack') {
+    data = dataCombineStack(series, opts.categories.length);
+  } else {
+    data = dataCombine(series);
+  }
+  var sorted = [];
+  // remove null from data
+  data = data.filter(function(item) {
+    //return item !== null;
+    if (typeof item === 'object' && item !== null) {
+      if (item.constructor.toString().indexOf('Array') > -1) {
+        return item !== null;
+      } else {
+        return item.value !== null;
+      }
+    } else {
+      return item !== null;
+    }
+  });
+  data.map(function(item) {
+    if (typeof item === 'object') {
+      if (item.constructor.toString().indexOf('Array') > -1) {
+        if (opts.type == 'candle') {
+          item.map(function(subitem) {
+            sorted.push(subitem);
+          })
+        } else {
+          sorted.push(item[1]);
+        }
+      } else {
+        sorted.push(item.value);
+      }
+    } else {
+      sorted.push(item);
+    }
+  })
+  var minData = yData.min || 0;
+  var maxData = yData.max || 0;
+  if (sorted.length > 0) {
+    minData = Math.min.apply(this, sorted);
+    maxData = Math.max.apply(this, sorted);
+  }
+  if (minData === maxData) {
+    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.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);
+  }
+  return range.reverse();
+}
+
+function calYAxisData(series, opts, config, context) {
+  //堆叠图重算Y轴
+  var columnstyle = assign({}, {
+    type: ""
+  }, opts.extra.column);
+  //如果是多Y轴,重新计算
+  var YLength = opts.yAxis.data.length;
+  var newSeries = new Array(YLength);
+  if (YLength > 0) {
+    for (let i = 0; i < YLength; i++) {
+      newSeries[i] = [];
+      for (let j = 0; j < series.length; j++) {
+        if (series[j].index == i) {
+          newSeries[i].push(series[j]);
+        }
+      }
+    }
+    var rangesArr = new Array(YLength);
+    var rangesFormatArr = new Array(YLength);
+    var yAxisWidthArr = new Array(YLength);
+
+    for (let i = 0; i < YLength; i++) {
+      let yData = opts.yAxis.data[i];
+      //如果总开关不显示,强制每个Y轴为不显示
+      if (opts.yAxis.disabled == true) {
+        yData.disabled = true;
+      }
+      if(yData.type === 'categories'){
+        if(!yData.formatter){
+          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,index,opts) => {return util.toFixed(val, yData.tofix || 0) + (yData.unit || '')};
+        }
+        rangesArr[i] = getYAxisTextList(newSeries[i], opts, config, columnstyle.type, yData, i);
+      }
+      let yAxisFontSizes = yData.fontSize * opts.pix || config.fontSize;
+      yAxisWidthArr[i] = {
+        position: yData.position ? yData.position : 'left',
+        width: 0
+      };
+      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;
+      });
+      let calibration = yData.calibration ? 4 * opts.pix : 0;
+      yAxisWidthArr[i].width += calibration + 3 * opts.pix;
+      if (yData.disabled === true) {
+        yAxisWidthArr[i].width = 0;
+      }
+    }
+  } else {
+    var rangesArr = new Array(1);
+    var rangesFormatArr = new Array(1);
+    var yAxisWidthArr = new Array(1);
+    if(opts.type === 'bar'){
+      rangesArr[0] = opts.categories;
+      if(!opts.yAxis.formatter){
+        opts.yAxis.formatter = (val,index,opts) => {return val + (opts.yAxis.unit || '')}
+      }
+    }else{
+      if(!opts.yAxis.formatter){
+        opts.yAxis.formatter = (val,index,opts) => {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,index) {
+      item = opts.yAxis.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;
+    if (opts.yAxis.disabled === true) {
+      yAxisWidthArr[0] = {
+        position: 'left',
+        width: 0
+      };
+      opts.yAxis.data[0] = {
+        disabled: true
+      };
+    } else {
+      opts.yAxis.data[0] = {
+        disabled: false,
+        position: 'left',
+        max: opts.yAxis.max,
+        min: opts.yAxis.min,
+        formatter: opts.yAxis.formatter
+      };
+      if(opts.type === 'bar'){
+        opts.yAxis.data[0].categories = opts.categories;
+        opts.yAxis.data[0].type = 'categories';
+      }
+    }
+  }
+  return {
+    rangesFormat: rangesFormatArr,
+    ranges: rangesArr,
+    yAxisWidth: yAxisWidthArr
+  };
+}
+
+function calTooltipYAxisData(point, series, opts, config, eachSpacing) {
+  let ranges = [].concat(opts.chartData.yAxisData.ranges);
+  let spacingValid = opts.height - opts.area[0] - opts.area[2];
+  let minAxis = opts.area[0];
+  let items = [];
+  for (let i = 0; i < ranges.length; i++) {
+    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 && opts.yAxis.data[i].formatter ? opts.yAxis.data[i].formatter(item, i, opts) : item.toFixed(0);
+    items.push(String(item))
+  }
+  return items;
+}
+
+function calMarkLineData(points, opts) {
+  let minRange, maxRange;
+  let spacingValid = opts.height - opts.area[0] - opts.area[2];
+  for (let i = 0; i < points.length; i++) {
+    points[i].yAxisIndex = points[i].yAxisIndex ? points[i].yAxisIndex : 0;
+    let range = [].concat(opts.chartData.yAxisData.ranges[points[i].yAxisIndex]);
+    minRange = range.pop();
+    maxRange = range.shift();
+    let height = spacingValid * (points[i].value - minRange) / (maxRange - minRange);
+    points[i].y = opts.height - Math.round(height) - opts.area[2];
+  }
+  return points;
+}
+
+function contextRotate(context, opts) {
+  if (opts.rotateLock !== true) {
+    context.translate(opts.height, 0);
+    context.rotate(90 * Math.PI / 180);
+  } else if (opts._rotate_ !== true) {
+    context.translate(opts.height, 0);
+    context.rotate(90 * Math.PI / 180);
+    opts._rotate_ = true;
+  }
+}
+
+function drawPointShape(points, color, shape, context, opts) {
+  context.beginPath();
+  if (opts.dataPointShapeType == 'hollow') {
+    context.setStrokeStyle(color);
+    context.setFillStyle(opts.background);
+    context.setLineWidth(2 * opts.pix);
+  } else {
+    context.setStrokeStyle("#ffffff");
+    context.setFillStyle(color);
+    context.setLineWidth(1 * opts.pix);
+  }
+  if (shape === 'diamond') {
+    points.forEach(function(item, index) {
+      if (item !== null) {
+        context.moveTo(item.x, item.y - 4.5);
+        context.lineTo(item.x - 4.5, item.y);
+        context.lineTo(item.x, item.y + 4.5);
+        context.lineTo(item.x + 4.5, item.y);
+        context.lineTo(item.x, item.y - 4.5);
+      }
+    });
+  } else if (shape === 'circle') {
+    points.forEach(function(item, index) {
+      if (item !== null) {
+        context.moveTo(item.x + 2.5 * opts.pix, item.y);
+        context.arc(item.x, item.y, 3 * opts.pix, 0, 2 * Math.PI, false);
+      }
+    });
+  } else if (shape === 'square') {
+    points.forEach(function(item, index) {
+      if (item !== null) {
+        context.moveTo(item.x - 3.5, item.y - 3.5);
+        context.rect(item.x - 3.5, item.y - 3.5, 7, 7);
+      }
+    });
+  } else if (shape === 'triangle') {
+    points.forEach(function(item, index) {
+      if (item !== null) {
+        context.moveTo(item.x, item.y - 4.5);
+        context.lineTo(item.x - 4.5, item.y + 4.5);
+        context.lineTo(item.x + 4.5, item.y + 4.5);
+        context.lineTo(item.x, item.y - 4.5);
+      }
+    });
+  } else if (shape === 'none') {
+    return;
+  }
+  context.closePath();
+  context.fill();
+  context.stroke();
+}
+
+function drawActivePoint(points, color, shape, context, opts, option, seriesIndex) {
+  if(!opts.tooltip){
+    return
+  }
+  if(opts.tooltip.group.length>0 && opts.tooltip.group.includes(seriesIndex) == false){
+    return
+  }
+  var pointIndex = typeof opts.tooltip.index === 'number' ? opts.tooltip.index : opts.tooltip.index[opts.tooltip.group.indexOf(seriesIndex)];
+  context.beginPath();
+  if (option.activeType == 'hollow') {
+    context.setStrokeStyle(color);
+    context.setFillStyle(opts.background);
+    context.setLineWidth(2 * opts.pix);
+  } else {
+    context.setStrokeStyle("#ffffff");
+    context.setFillStyle(color);
+    context.setLineWidth(1 * opts.pix);
+  }
+  if (shape === 'diamond') {
+    points.forEach(function(item, index) {
+      if (item !== null && pointIndex == index ) {
+        context.moveTo(item.x, item.y - 4.5);
+        context.lineTo(item.x - 4.5, item.y);
+        context.lineTo(item.x, item.y + 4.5);
+        context.lineTo(item.x + 4.5, item.y);
+        context.lineTo(item.x, item.y - 4.5);
+      }
+    });
+  } else if (shape === 'circle') {
+    points.forEach(function(item, index) {
+      if (item !== null && pointIndex == index) {
+        context.moveTo(item.x + 2.5 * opts.pix, item.y);
+        context.arc(item.x, item.y, 3 * opts.pix, 0, 2 * Math.PI, false);
+      }
+    });
+  } else if (shape === 'square') {
+    points.forEach(function(item, index) {
+      if (item !== null && pointIndex == index) {
+        context.moveTo(item.x - 3.5, item.y - 3.5);
+        context.rect(item.x - 3.5, item.y - 3.5, 7, 7);
+      }
+    });
+  } else if (shape === 'triangle') {
+    points.forEach(function(item, index) {
+      if (item !== null && pointIndex == index) {
+        context.moveTo(item.x, item.y - 4.5);
+        context.lineTo(item.x - 4.5, item.y + 4.5);
+        context.lineTo(item.x + 4.5, item.y + 4.5);
+        context.lineTo(item.x, item.y - 4.5);
+      }
+    });
+  } else if (shape === 'none') {
+    return;
+  }
+  context.closePath();
+  context.fill();
+  context.stroke();
+}
+
+function drawRingTitle(opts, config, context, center) {
+  var titlefontSize = opts.title.fontSize || config.titleFontSize;
+  var subtitlefontSize = opts.subtitle.fontSize || config.subtitleFontSize;
+  var title = opts.title.name || '';
+  var subtitle = opts.subtitle.name || '';
+  var titleFontColor = opts.title.color || opts.fontColor;
+  var subtitleFontColor = opts.subtitle.color || opts.fontColor;
+  var titleHeight = title ? titlefontSize : 0;
+  var subtitleHeight = subtitle ? subtitlefontSize : 0;
+  var margin = 5;
+  if (subtitle) {
+    var textWidth = measureText(subtitle, subtitlefontSize * opts.pix, context);
+    var startX = center.x - textWidth / 2 + (opts.subtitle.offsetX|| 0) * opts.pix ;
+    var startY = center.y + subtitlefontSize * opts.pix / 2 + (opts.subtitle.offsetY || 0) * opts.pix;
+    if (title) {
+      startY += (titleHeight * opts.pix + margin) / 2;
+    }
+    context.beginPath();
+    context.setFontSize(subtitlefontSize * opts.pix);
+    context.setFillStyle(subtitleFontColor);
+    context.fillText(subtitle, startX, startY);
+    context.closePath();
+    context.stroke();
+  }
+  if (title) {
+    var _textWidth = measureText(title, titlefontSize * opts.pix, context);
+    var _startX = center.x - _textWidth / 2 + (opts.title.offsetX || 0);
+    var _startY = center.y + titlefontSize * opts.pix / 2 + (opts.title.offsetY || 0) * opts.pix;
+    if (subtitle) {
+      _startY -= (subtitleHeight * opts.pix + margin) / 2;
+    }
+    context.beginPath();
+    context.setFontSize(titlefontSize * opts.pix);
+    context.setFillStyle(titleFontColor);
+    context.fillText(title, _startX, _startY);
+    context.closePath();
+    context.stroke();
+  }
+}
+
+function drawPointText(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.textSize ? series.textSize * opts.pix : config.fontSize;
+      context.setFontSize(fontSize);
+      context.setFillStyle(series.textColor || opts.fontColor);
+      var value = data[index]
+      if (typeof data[index] === 'object' && data[index] !== null) {
+        if (data[index].constructor.toString().indexOf('Array')>-1) {
+          value = data[index][1];
+        } else {
+          value = data[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 drawColumePointText(points, series, config, context, opts) {
+  // 绘制数据文案
+  var data = series.data;
+  var textOffset = series.textOffset ? series.textOffset : 0;
+  var Position = opts.extra.column.labelPosition;
+  points.forEach(function(item, index) {
+    if (item !== null) {
+      context.beginPath();
+      var fontSize = series.textSize ? series.textSize * opts.pix : config.fontSize;
+      context.setFontSize(fontSize);
+      context.setFillStyle(series.textColor || opts.fontColor);
+      var value = data[index]
+      if (typeof data[index] === 'object' && data[index] !== null) {
+        if (data[index].constructor.toString().indexOf('Array')>-1) {
+          value = data[index][1];
+        } else {
+          value = data[index].value
+        }
+      }
+      var formatVal = series.formatter ? series.formatter(value,index,series,opts) : value;
+      context.setTextAlign('center');
+      var startY = item.y - 4 * opts.pix + textOffset * opts.pix;
+      if(item.y > series.zeroPoints){
+        startY = item.y + textOffset * opts.pix + fontSize;
+      }
+      if(Position == 'insideTop'){
+        startY = item.y + fontSize + textOffset * opts.pix;
+        if(item.y > series.zeroPoints){
+          startY = item.y - textOffset * opts.pix - 4 * opts.pix;
+        }
+      }
+      if(Position == 'center'){
+        startY = item.y + textOffset * opts.pix + (opts.height - opts.area[2] - item.y + fontSize)/2;
+        if(series.zeroPoints < opts.height - opts.area[2]){
+          startY = item.y + textOffset * opts.pix + (series.zeroPoints - item.y + fontSize)/2;
+        }
+        if(item.y > series.zeroPoints){
+          startY = item.y - textOffset * opts.pix - (item.y - series.zeroPoints - fontSize)/2;
+        }
+        if(opts.extra.column.type == 'stack'){
+          startY = item.y + textOffset * opts.pix + (item.y0 - item.y + fontSize)/2;
+        }
+      }
+      if(Position == 'bottom'){
+        startY = opts.height - opts.area[2] + textOffset * opts.pix - 4 * opts.pix;
+        if(series.zeroPoints < opts.height - opts.area[2]){
+          startY = series.zeroPoints + textOffset * opts.pix - 4 * opts.pix;
+        }
+        if(item.y > series.zeroPoints){
+          startY = series.zeroPoints - textOffset * opts.pix + fontSize + 2 * opts.pix;
+        }
+        if(opts.extra.column.type == 'stack'){
+          startY = item.y0 + textOffset * opts.pix - 4 * opts.pix;
+        }
+      }
+      context.fillText(String(formatVal), item.x, startY);
+      context.closePath();
+      context.stroke();
+      context.setTextAlign('left');
+    }
+  });
+}
+
+function drawMountPointText(points, series, config, context, opts, zeroPoints) {
+  // 绘制数据文案
+  var data = series.data;
+  var textOffset = series.textOffset ? series.textOffset : 0;
+  var Position = opts.extra.mount.labelPosition;
+  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');
+      var startY = item.y - 4 * opts.pix + textOffset * opts.pix;
+      if(item.y > zeroPoints){
+        startY = item.y + textOffset * opts.pix + fontSize;
+      }
+      context.fillText(String(formatVal), item.x, startY);
+      context.closePath();
+      context.stroke();
+      context.setTextAlign('left');
+    }
+  });
+}
+
+function drawBarPointText(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.textSize ? series.textSize * opts.pix : config.fontSize;
+      context.setFontSize(fontSize);
+      context.setFillStyle(series.textColor || opts.fontColor);
+      var value = data[index]
+      if (typeof data[index] === 'object' && data[index] !== null) {
+        value = data[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();
+      context.stroke();
+    }
+  });
+}
+
+function drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context) {
+  radius -= gaugeOption.width / 2 + gaugeOption.labelOffset * opts.pix;
+  radius = radius < 10 ? 10 : radius;
+  let totalAngle;
+  if (gaugeOption.endAngle < gaugeOption.startAngle) {
+    totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle;
+  } else {
+    totalAngle = gaugeOption.startAngle - gaugeOption.endAngle;
+  }
+  let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
+  let totalNumber = gaugeOption.endNumber - gaugeOption.startNumber;
+  let splitNumber = totalNumber / gaugeOption.splitLine.splitNumber;
+  let nowAngle = gaugeOption.startAngle;
+  let nowNumber = gaugeOption.startNumber;
+  for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) {
+    var pos = {
+      x: radius * Math.cos(nowAngle * Math.PI),
+      y: radius * Math.sin(nowAngle * Math.PI)
+    };
+    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;
+    var startY = pos.y;
+    context.beginPath();
+    context.setFontSize(config.fontSize);
+    context.setFillStyle(gaugeOption.labelColor || opts.fontColor);
+    context.fillText(labelText, startX, startY + config.fontSize / 2);
+    context.closePath();
+    context.stroke();
+    nowAngle += splitAngle;
+    if (nowAngle >= 2) {
+      nowAngle = nowAngle % 2;
+    }
+    nowNumber += splitNumber;
+  }
+}
+
+function drawRadarLabel(angleList, radius, centerPosition, opts, config, context) {
+  var radarOption = opts.extra.radar || {};
+  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();
+    }
+    if(radarOption.labelShow === true){
+      var pos = {
+        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;
+      var startY = posRelativeCanvas.y;
+      if (util.approximatelyEqual(pos.x, 0)) {
+        startX -= measureText(opts.categories[index] || '', config.fontSize, context) / 2;
+      } else if (pos.x < 0) {
+        startX -= measureText(opts.categories[index] || '', config.fontSize, context);
+      }
+      context.beginPath();
+      context.setFontSize(config.fontSize);
+      context.setFillStyle(radarOption.labelColor || opts.fontColor);
+      context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2);
+      context.closePath();
+      context.stroke();
+    }
+  });
+
+}
+
+function drawPieText(series, opts, config, context, radius, center) {
+  var lineRadius = config.pieChartLinePadding;
+  var textObjectCollection = [];
+  var lastTextObject = null;
+  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);
+    }
+    var color = item.color;
+    var radius = item._radius_;
+    return {
+      arc: arc,
+      text: text,
+      color: color,
+      radius: radius,
+      textColor: item.textColor,
+      textSize: item.textSize,
+      labelShow: item.labelShow
+    };
+  });
+  for (let i = 0; i < seriesConvert.length; i++) {
+    let item = seriesConvert[i];
+    // line end
+    let orginX1 = Math.cos(item.arc) * (item.radius + lineRadius);
+    let orginY1 = Math.sin(item.arc) * (item.radius + lineRadius);
+    // line start
+    let orginX2 = Math.cos(item.arc) * item.radius;
+    let orginY2 = Math.sin(item.arc) * item.radius;
+    // text start
+    let orginX3 = orginX1 >= 0 ? orginX1 + config.pieChartTextPadding : orginX1 - config.pieChartTextPadding;
+    let orginY3 = orginY1;
+    let textWidth = measureText(item.text, item.textSize * opts.pix || config.fontSize, context);
+    let startY = orginY3;
+    if (lastTextObject && util.isSameXCoordinateArea(lastTextObject.start, {
+        x: orginX3
+      })) {
+      if (orginX3 > 0) {
+        startY = Math.min(orginY3, lastTextObject.start.y);
+      } else if (orginX1 < 0) {
+        startY = Math.max(orginY3, lastTextObject.start.y);
+      } else {
+        if (orginY3 > 0) {
+          startY = Math.max(orginY3, lastTextObject.start.y);
+        } else {
+          startY = Math.min(orginY3, lastTextObject.start.y);
+        }
+      }
+    }
+    if (orginX3 < 0) {
+      orginX3 -= textWidth;
+    }
+    let textObject = {
+      lineStart: {
+        x: orginX2,
+        y: orginY2
+      },
+      lineEnd: {
+        x: orginX1,
+        y: orginY1
+      },
+      start: {
+        x: orginX3,
+        y: startY
+      },
+      width: textWidth,
+      height: config.fontSize,
+      text: item.text,
+      color: item.color,
+      textColor: item.textColor,
+      textSize: item.textSize
+    };
+    lastTextObject = avoidCollision(textObject, lastTextObject);
+    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);
+    let textPosition = convertCoordinateOrigin(item.start.x, item.start.y, center);
+    context.setLineWidth(1 * opts.pix);
+    context.setFontSize(item.textSize * opts.pix || config.fontSize);
+    context.beginPath();
+    context.setStrokeStyle(item.color);
+    context.setFillStyle(item.color);
+    context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
+    let curveStartX = item.start.x < 0 ? textPosition.x + item.width : textPosition.x;
+    let textStartX = item.start.x < 0 ? textPosition.x - 5 : textPosition.x + 5;
+    context.quadraticCurveTo(lineEndPoistion.x, lineEndPoistion.y, curveStartX, textPosition.y);
+    context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
+    context.stroke();
+    context.closePath();
+    context.beginPath();
+    context.moveTo(textPosition.x + item.width, textPosition.y);
+    context.arc(curveStartX, textPosition.y, 2 * opts.pix, 0, 2 * Math.PI);
+    context.closePath();
+    context.fill();
+    context.beginPath();
+    context.setFontSize(item.textSize * opts.pix || config.fontSize);
+    context.setFillStyle(item.textColor || opts.fontColor);
+    context.fillText(item.text, textStartX, textPosition.y + 3);
+    context.closePath();
+    context.stroke();
+    context.closePath();
+  }
+}
+
+function drawToolTipSplitLine(offsetX, opts, config, context) {
+  var toolTipOption = opts.extra.tooltip || {};
+  toolTipOption.gridType = toolTipOption.gridType == undefined ? 'solid' : toolTipOption.gridType;
+  toolTipOption.dashLength = toolTipOption.dashLength == undefined ? 4 : toolTipOption.dashLength;
+  var startY = opts.area[0];
+  var endY = opts.height - opts.area[2];
+  if (toolTipOption.gridType == 'dash') {
+    context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]);
+  }
+  context.setStrokeStyle(toolTipOption.gridColor || '#cccccc');
+  context.setLineWidth(1 * opts.pix);
+  context.beginPath();
+  context.moveTo(offsetX, startY);
+  context.lineTo(offsetX, endY);
+  context.stroke();
+  context.setLineDash([]);
+  if (toolTipOption.xAxisLabel) {
+    let labelText = opts.categories[opts.tooltip.index];
+    context.setFontSize(config.fontSize);
+    let textWidth = measureText(labelText, config.fontSize, context);
+    let textX = offsetX - 0.5 * textWidth;
+    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);
+    context.setLineWidth(1 * opts.pix);
+    context.rect(textX - toolTipOption.boxPadding * opts.pix, textY, textWidth + 2 * toolTipOption.boxPadding * opts.pix, config.fontSize + 2 * toolTipOption.boxPadding * opts.pix);
+    context.closePath();
+    context.stroke();
+    context.fill();
+    context.beginPath();
+    context.setFontSize(config.fontSize);
+    context.setFillStyle(toolTipOption.labelFontColor || opts.fontColor);
+    context.fillText(String(labelText), textX, textY + toolTipOption.boxPadding * opts.pix + config.fontSize);
+    context.closePath();
+    context.stroke();
+  }
+}
+
+function drawMarkLine(opts, config, context) {
+  let markLineOption = assign({}, {
+    type: 'solid',
+    dashLength: 4,
+    data: []
+  }, opts.extra.markLine);
+  let startX = opts.area[3];
+  let endX = opts.width - opts.area[1];
+  let points = calMarkLineData(markLineOption.data, opts);
+  for (let i = 0; i < points.length; i++) {
+    let item = assign({}, {
+      lineColor: '#DE4A42',
+      showLabel: false,
+      labelFontSize: 13,
+      labelPadding: 6,
+      labelFontColor: '#666666',
+      labelBgColor: '#DFE8FF',
+      labelBgOpacity: 0.8,
+      labelAlign: 'left',
+      labelOffsetX: 0,
+      labelOffsetY: 0,
+    }, points[i]);
+    if (markLineOption.type == 'dash') {
+      context.setLineDash([markLineOption.dashLength, markLineOption.dashLength]);
+    }
+    context.setStrokeStyle(item.lineColor);
+    context.setLineWidth(1 * opts.pix);
+    context.beginPath();
+    context.moveTo(startX, item.y);
+    context.lineTo(endX, item.y);
+    context.stroke();
+    context.setLineDash([]);
+    if (item.showLabel) {
+      let fontSize = item.labelFontSize * opts.pix;
+      let labelText = item.labelText ? item.labelText : item.value;
+      context.setFontSize(fontSize);
+      let textWidth = measureText(labelText, fontSize, context);
+      let bgWidth = textWidth + item.labelPadding * opts.pix * 2;
+      let bgStartX = item.labelAlign == 'left' ? opts.area[3] - bgWidth : opts.width - opts.area[1];
+      bgStartX += item.labelOffsetX;
+      let bgStartY = item.y - 0.5 * fontSize - item.labelPadding * opts.pix;
+      bgStartY += item.labelOffsetY;
+      let textX = bgStartX + item.labelPadding * opts.pix;
+      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, bgStartY, bgWidth, fontSize + 2 * item.labelPadding * opts.pix);
+      context.closePath();
+      context.stroke();
+      context.fill();
+      context.setFontSize(fontSize);
+      context.setTextAlign('left');
+      context.setFillStyle(item.labelFontColor);
+      context.fillText(String(labelText), textX, bgStartY + fontSize + item.labelPadding * opts.pix/2);
+      context.stroke();
+      context.setTextAlign('left');
+    }
+  }
+}
+
+function drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints) {
+  var toolTipOption = assign({}, {
+    gridType: 'solid',
+    dashLength: 4
+  }, opts.extra.tooltip);
+  var startX = opts.area[3];
+  var endX = opts.width - opts.area[1];
+  if (toolTipOption.gridType == 'dash') {
+    context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]);
+  }
+  context.setStrokeStyle(toolTipOption.gridColor || '#cccccc');
+  context.setLineWidth(1 * opts.pix);
+  context.beginPath();
+  context.moveTo(startX, opts.tooltip.offset.y);
+  context.lineTo(endX, opts.tooltip.offset.y);
+  context.stroke();
+  context.setLineDash([]);
+  if (toolTipOption.yAxisLabel) {
+    let boxPadding = toolTipOption.boxPadding * opts.pix;
+    let labelText = calTooltipYAxisData(opts.tooltip.offset.y, opts.series, opts, config, eachSpacing);
+    let widthArr = opts.chartData.yAxisData.yAxisWidth;
+    let tStartLeft = opts.area[3];
+    let tStartRight = opts.width - opts.area[1];
+    for (let i = 0; i < labelText.length; i++) {
+      context.setFontSize(toolTipOption.fontSize * opts.pix);
+      let textWidth = measureText(labelText[i], toolTipOption.fontSize * opts.pix, context);
+      let bgStartX, bgEndX, bgWidth;
+      if (widthArr[i].position == 'left') {
+        bgStartX = tStartLeft - (textWidth + boxPadding * 2) - 2 * opts.pix;
+        bgEndX = Math.max(bgStartX, bgStartX + textWidth + boxPadding * 2);
+      } else {
+        bgStartX = tStartRight + 2 * opts.pix;
+        bgEndX = Math.max(bgStartX + widthArr[i].width, bgStartX + textWidth + boxPadding * 2);
+      }
+      bgWidth = bgEndX - bgStartX;
+      let textX = bgStartX + (bgWidth - textWidth) / 2;
+      let textY = opts.tooltip.offset.y;
+      context.beginPath();
+      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 - boxPadding, bgWidth, config.fontSize + 2 * boxPadding);
+      context.closePath();
+      context.stroke();
+      context.fill();
+      context.beginPath();
+      context.setFontSize(config.fontSize);
+      context.setFillStyle(toolTipOption.labelFontColor || opts.fontColor);
+      context.fillText(labelText[i], textX, textY + 0.5 * config.fontSize);
+      context.closePath();
+      context.stroke();
+      if (widthArr[i].position == 'left') {
+        tStartLeft -= (widthArr[i].width + opts.yAxis.padding * opts.pix);
+      } else {
+        tStartRight += widthArr[i].width + opts.yAxis.padding * opts.pix;
+      }
+    }
+  }
+}
+
+function drawToolTipSplitArea(offsetX, opts, config, context, eachSpacing) {
+  var toolTipOption = assign({}, {
+    activeBgColor: '#000000',
+    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 - toolTipOption.activeWidth / 2, startY, toolTipOption.activeWidth, endY - startY);
+  context.closePath();
+  context.fill();
+  context.setFillStyle("#FFFFFF");
+}
+
+function drawBarToolTipSplitArea(offsetX, opts, config, context, eachSpacing) {
+  var toolTipOption = assign({}, {
+    activeBgColor: '#000000',
+    activeBgOpacity: 0.08
+  }, opts.extra.bar);
+  var startX = opts.area[3];
+  var endX = opts.width - opts.area[1];
+  context.beginPath();
+  context.setFillStyle(hexToRgb(toolTipOption.activeBgColor, toolTipOption.activeBgOpacity));
+  context.rect( startX ,offsetX - eachSpacing / 2 ,  endX - startX,eachSpacing);
+  context.closePath();
+  context.fill();
+  context.setFillStyle("#FFFFFF");
+}
+
+
+function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxisPoints) {
+  var toolTipOption = assign({}, {
+    showBox: true,
+    showArrow: true,
+    showCategory: false,
+    bgColor: '#000000',
+    bgOpacity: 0.7,
+    borderColor: '#000000',
+    borderWidth: 0,
+    borderRadius: 0,
+    borderOpacity: 0.7,
+    boxPadding: 3,
+    fontColor: '#FFFFFF',
+    fontSize: 13,
+    lineHeight: 20,
+    legendShow: true,
+    legendShape: 'auto',
+    splitLine: true,
+  }, opts.extra.tooltip);
+  if(toolTipOption.showCategory==true && opts.categories){
+    textList.unshift({text:opts.categories[opts.tooltip.index],color:null})
+  }
+  var fontSize = toolTipOption.fontSize * opts.pix;
+  var lineHeight = toolTipOption.lineHeight * opts.pix;
+  var boxPadding = toolTipOption.boxPadding * opts.pix;
+  var legendWidth = fontSize;
+  var legendMarginRight = 5 * opts.pix;
+  if(toolTipOption.legendShow == false){
+    legendWidth = 0;
+    legendMarginRight = 0;
+  }
+  var arrowWidth = toolTipOption.showArrow ? 8 * opts.pix : 0;
+  var isOverRightBorder = false;
+  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);
+    }
+  }
+  offset = assign({
+    x: 0,
+    y: 0
+  }, offset);
+  offset.y -= 8 * opts.pix;
+  var textWidth = textList.map(function(item) {
+    return measureText(item.text, fontSize, context);
+  });
+  var toolTipWidth = legendWidth + legendMarginRight + 4 * boxPadding + Math.max.apply(null, textWidth);
+  var toolTipHeight = 2 * boxPadding + textList.length * lineHeight;
+  if (toolTipOption.showBox == false) {
+    return
+  }
+  // if beyond the right border
+  if (offset.x - Math.abs(opts._scrollDistance_ || 0) + arrowWidth + toolTipWidth > opts.width) {
+    isOverRightBorder = true;
+  }
+  if (toolTipHeight + offset.y > opts.height) {
+    offset.y = opts.height - toolTipHeight;
+  }
+  // draw background rect
+  context.beginPath();
+  context.setFillStyle(hexToRgb(toolTipOption.bgColor, toolTipOption.bgOpacity));
+  context.setLineWidth(toolTipOption.borderWidth * opts.pix);
+  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(toolTipWidth > offset.x){
+      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);
+    }
+    context.arc(offset.x - arrowWidth - radius, offset.y + toolTipHeight - radius, radius, 0, Math.PI / 2, false);
+    context.arc(offset.x - arrowWidth - Math.round(toolTipWidth) + radius, offset.y + toolTipHeight - radius, radius,
+      Math.PI / 2, Math.PI, false);
+    context.arc(offset.x - arrowWidth - Math.round(toolTipWidth) + radius, offset.y + radius, radius, -Math.PI, -Math.PI / 2, false);
+    context.arc(offset.x - arrowWidth - radius, offset.y + radius, radius, -Math.PI / 2, 0, false);
+    if (toolTipOption.showArrow) {
+      context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pix - 5 * opts.pix);
+      context.lineTo(offset.x, offset.y + 10 * opts.pix);
+    }
+  } else {
+    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);
+    }
+    context.arc(offset.x + arrowWidth + radius, offset.y + radius, radius, -Math.PI, -Math.PI / 2, false);
+    context.arc(offset.x + arrowWidth + Math.round(toolTipWidth) - radius, offset.y + radius, radius, -Math.PI / 2, 0,
+      false);
+    context.arc(offset.x + arrowWidth + Math.round(toolTipWidth) - radius, offset.y + toolTipHeight - radius, radius, 0,
+      Math.PI / 2, false);
+    context.arc(offset.x + arrowWidth + radius, offset.y + toolTipHeight - radius, radius, Math.PI / 2, Math.PI, false);
+    if (toolTipOption.showArrow) {
+      context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pix + 5 * opts.pix);
+      context.lineTo(offset.x, offset.y + 10 * opts.pix);
+    }
+  }
+  context.closePath();
+  context.fill();
+  if (toolTipOption.borderWidth > 0) {
+    context.stroke();
+  }
+  // draw legend
+  if(toolTipOption.legendShow){
+    textList.forEach(function(item, index) {
+      if (item.color !== null) {
+        context.beginPath();
+        context.setFillStyle(item.color);
+        var startX = offset.x + arrowWidth + 2 * boxPadding;
+        var startY = offset.y + (lineHeight - fontSize) / 2 + lineHeight * index + boxPadding + 1;
+        if (isOverRightBorder) {
+          startX = offset.x - toolTipWidth - arrowWidth + 2 * boxPadding;
+        }
+        switch (item.legendShape) {
+          case 'line':
+            context.moveTo(startX, startY + 0.5 * legendWidth - 2 * opts.pix);
+            context.fillRect(startX, startY + 0.5 * legendWidth - 2 * opts.pix, legendWidth, 4 * opts.pix);
+            break;
+          case 'triangle':
+            context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix);
+            context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix);
+            context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix);
+            context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix);
+            break;
+          case 'diamond':
+            context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix);
+            context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * legendWidth);
+            context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix);
+            context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * legendWidth);
+            context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix);
+            break;
+          case 'circle':
+            context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth);
+            context.arc(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth, 5 * opts.pix, 0, 2 * Math.PI);
+            break;
+          case 'rect':
+            context.moveTo(startX, startY + 0.5 * legendWidth - 5 * opts.pix);
+            context.fillRect(startX, startY + 0.5 * legendWidth - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix);
+            break;
+          case 'square':
+            context.moveTo(startX + 2 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix);
+            context.fillRect(startX + 2 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix, 10 * opts.pix, 10 * opts.pix);
+            break;
+          default:
+            context.moveTo(startX, startY + 0.5 * legendWidth - 5 * opts.pix);
+            context.fillRect(startX, startY + 0.5 * legendWidth - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix);
+        }
+        context.closePath();
+        context.fill();
+      }
+    });
+  }
+  
+  // draw text list
+  textList.forEach(function(item, index) {
+    var startX = offset.x + arrowWidth + 2 * boxPadding + legendWidth + legendMarginRight;
+    if (isOverRightBorder) {
+      startX = offset.x - toolTipWidth - arrowWidth + 2 * boxPadding + legendWidth + legendMarginRight;
+    }
+    var startY = offset.y + lineHeight * index + (lineHeight - fontSize)/2 - 1 + boxPadding + fontSize;
+    context.beginPath();
+    context.setFontSize(fontSize);
+    context.setTextBaseline('normal');
+    context.setFillStyle(toolTipOption.fontColor);
+    context.fillText(item.text, startX, startY);
+    context.closePath();
+    context.stroke();
+  });
+}
+
+function drawColumnDataPoints(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({}, {
+    type: 'group',
+    width: eachSpacing / 2,
+    meterBorder: 4,
+    meterFillColor: '#FFFFFF',
+    barBorderCircle: false,
+    barBorderRadius: [],
+    seriesGap: 2,
+    linearType: 'none',
+    linearOpacity: 1,
+    customColor: [],
+    colorStop: 0,
+    labelPosition: 'outside'
+  }, opts.extra.column);
+  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;
+  }
+  if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
+    drawToolTipSplitArea(opts.tooltip.offset.x, opts, config, context, eachSpacing);
+  }
+  columnOption.customColor = fillCustomColor(columnOption.linearType, columnOption.customColor, series, config);
+  series.forEach(function(eachSeries, seriesIndex) {
+    let ranges, minRange, maxRange;
+    ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+    minRange = ranges.pop();
+    maxRange = ranges.shift();
+    
+    // 计算0轴坐标
+    let spacingValid = opts.height - opts.area[0] - opts.area[2];
+    let zeroHeight = spacingValid * (0 - minRange) / (maxRange - minRange);
+    let zeroPoints = opts.height - Math.round(zeroHeight) - opts.area[2];
+    eachSeries.zeroPoints = zeroPoints;
+    var data = eachSeries.data;
+    switch (columnOption.type) {
+      case 'group':
+        var points = getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, zeroPoints, process);
+        var tooltipPoints = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
+        calPoints.push(tooltipPoints);
+        points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
+        for (let i = 0; i < points.length; i++) {
+          let item = points[i];
+          //fix issues/I27B1N yyoinge & Joeshu
+          if (item !== null && i > leftNum && i < rightNum) {
+            var startX = item.x - item.width / 2;
+            var height = opts.height - item.y - opts.area[2];
+            context.beginPath();
+            var fillColor = item.color || eachSeries.color
+            var strokeColor = item.color || eachSeries.color
+            if (columnOption.linearType !== 'none') {
+              var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints);
+              //透明渐变
+              if (columnOption.linearType == 'opacity') {
+                grd.addColorStop(0, hexToRgb(fillColor, columnOption.linearOpacity));
+                grd.addColorStop(1, hexToRgb(fillColor, 1));
+              } else {
+                grd.addColorStop(0, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity));
+                grd.addColorStop(columnOption.colorStop, hexToRgb(columnOption.customColor[eachSeries.linearIndex],columnOption.linearOpacity));
+                grd.addColorStop(1, hexToRgb(fillColor, 1));
+              }
+              fillColor = grd
+            }
+            // 圆角边框
+            if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) {
+              const left = startX;
+              const top = item.y > zeroPoints ? zeroPoints : item.y;
+              const width = item.width;
+              const height = Math.abs(zeroPoints - item.y);
+              if (columnOption.barBorderCircle) {
+                columnOption.barBorderRadius = [width / 2, width / 2, 0, 0];
+              }
+              if(item.y > zeroPoints){
+                columnOption.barBorderRadius = [0, 0,width / 2, width / 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);
+            } else {
+              context.moveTo(startX, item.y);
+              context.lineTo(startX + item.width, item.y);
+              context.lineTo(startX + item.width, zeroPoints);
+              context.lineTo(startX, zeroPoints);
+              context.lineTo(startX, item.y);
+              context.setLineWidth(1)
+              context.setStrokeStyle(strokeColor);
+            }
+            context.setFillStyle(fillColor);
+            context.closePath();
+            //context.stroke();
+            context.fill();
+          }
+        };
+        break;
+      case 'stack':
+        // 绘制堆叠数据图
+        var points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
+        calPoints.push(points);
+        points = fixColumeStackData(points, eachSpacing, series.length, seriesIndex, config, opts, series);
+        for (let i = 0; i < points.length; i++) {
+          let item = points[i];
+          if (item !== null && i > leftNum && i < rightNum) {
+            context.beginPath();
+            var fillColor = item.color || eachSeries.color;
+            var startX = item.x - item.width / 2 + 1;
+            var height = opts.height - item.y - opts.area[2];
+            var height0 = opts.height - item.y0 - opts.area[2];
+            if (seriesIndex > 0) {
+              height -= height0;
+            }
+            context.setFillStyle(fillColor);
+            context.moveTo(startX, item.y);
+            context.fillRect(startX, item.y, item.width, height);
+            context.closePath();
+            context.fill();
+          }
+        };
+        break;
+      case 'meter':
+        // 绘制温度计数据图
+        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);
+          for (let i = 0; i < points.length; i++) {
+            let item = points[i];
+            if (item !== null && i > leftNum && i < rightNum) {
+              //画背景颜色
+              context.beginPath();
+              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.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) {
+                const left = startX;
+                const top = item.y;
+                const width = item.width;
+                const height = zeroPoints - item.y;
+                if (columnOption.barBorderCircle) {
+                  columnOption.barBorderRadius = [width / 2, width / 2, 0, 0];
+                }
+                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.lineTo(startX + item.width, item.y);
+                context.lineTo(startX + item.width, zeroPoints);
+                context.lineTo(startX, zeroPoints);
+                context.lineTo(startX, item.y);
+                context.fill();
+              }
+              if (seriesIndex == 0 && columnOption.meterBorder > 0) {
+                context.closePath();
+                context.stroke();
+              }
+            }
+          }
+        break;
+    }
+  });
+
+  if (opts.dataLabel !== false && process === 1) {
+    series.forEach(function(eachSeries, seriesIndex) {
+      let ranges, minRange, maxRange;
+      ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+      minRange = ranges.pop();
+      maxRange = ranges.shift();
+      var data = eachSeries.data;
+      switch (columnOption.type) {
+        case 'group':
+          var points = getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+          points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
+          drawColumePointText(points, eachSeries, config, context, opts);
+          break;
+        case 'stack':
+          var points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
+          drawColumePointText(points, eachSeries, config, context, opts);
+          break;
+        case 'meter':
+          var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+          drawColumePointText(points, eachSeries, config, context, opts);
+          break;
+      }
+    });
+  }
+  context.restore();
+  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();
+    
+    // 计算0轴坐标
+    let spacingValid = opts.height - opts.area[0] - opts.area[2];
+    let zeroHeight = spacingValid * (0 - minRange) / (maxRange - minRange);
+    let zeroPoints = opts.height - Math.round(zeroHeight) - opts.area[2];
+    
+    var points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints, 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, zeroPoints);
+              //透明渐变
+              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 > zeroPoints ? zeroPoints : item.y;
+              const width = item.width;
+              const height = Math.abs(zeroPoints - item.y);
+              if (mountOption.barBorderCircle) {
+                mountOption.barBorderRadius = [width / 2, width / 2, 0, 0];
+              }
+              if(item.y > zeroPoints){
+                mountOption.barBorderRadius = [0, 0,width / 2, width / 2];
+              }
+              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, zeroPoints);
+              context.lineTo(startX, zeroPoints);
+              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, zeroPoints);
+              //透明渐变
+              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, zeroPoints);
+            context.lineTo(item.x, item.y);
+            context.lineTo(startX + item.width, zeroPoints);
+            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, zeroPoints);
+              //透明渐变
+              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, zeroPoints);
+            context.bezierCurveTo(item.x - item.width/4, zeroPoints, 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, zeroPoints, startX + item.width, zeroPoints);
+            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, zeroPoints);
+              //透明渐变
+              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, zeroPoints);
+            context.quadraticCurveTo(item.x - 0, zeroPoints - height/4, item.x, item.y);
+            context.quadraticCurveTo(item.x + 0, zeroPoints - height/4, startX + item.width, zeroPoints)
+            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, zeroPoints, process);
+    drawMountPointText(points, series, config, context, opts, zeroPoints);
+  }
+  context.restore();
+  return {
+    xAxisPoints: xAxisPoints,
+    calPoints: points,
+    eachSpacing: eachSpacing
+  };
+}
+
+function drawBarDataPoints(series, opts, config, context) {
+  let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  let yAxisPoints = [];
+  let eachSpacing = (opts.height - opts.area[0] - opts.area[2])/opts.categories.length;
+  for (let i = 0; i < opts.categories.length; i++) {
+    yAxisPoints.push(opts.area[0] + eachSpacing / 2 + eachSpacing * i);
+  }
+  let columnOption = assign({}, {
+    type: 'group',
+    width: eachSpacing / 2,
+    meterBorder: 4,
+    meterFillColor: '#FFFFFF',
+    barBorderCircle: false,
+    barBorderRadius: [],
+    seriesGap: 2,
+    linearType: 'none',
+    linearOpacity: 1,
+    customColor: [],
+    colorStop: 0,
+  }, opts.extra.bar);
+  let calPoints = [];
+  context.save();
+  let leftNum = -2;
+  let rightNum = yAxisPoints.length + 2;
+  if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
+    drawBarToolTipSplitArea(opts.tooltip.offset.y, opts, config, context, eachSpacing);
+  }
+  columnOption.customColor = fillCustomColor(columnOption.linearType, columnOption.customColor, series, config);
+  series.forEach(function(eachSeries, seriesIndex) {
+    let ranges, minRange, maxRange;
+    ranges = [].concat(opts.chartData.xAxisData.ranges);
+    maxRange = ranges.pop();
+    minRange = ranges.shift();
+    var data = eachSeries.data;
+    switch (columnOption.type) {
+      case 'group':
+        var points = getBarDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, process);
+        var tooltipPoints = getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
+        calPoints.push(tooltipPoints);
+        points = fixBarData(points, eachSpacing, series.length, seriesIndex, config, opts);
+        for (let i = 0; i < points.length; i++) {
+          let item = points[i];
+          //fix issues/I27B1N yyoinge & Joeshu
+          if (item !== null && i > leftNum && i < rightNum) {
+            //var startX = item.x - item.width / 2;
+            var startX = opts.area[3];
+            var startY = item.y - item.width / 2;
+            var height = item.height;
+            context.beginPath();
+            var fillColor = item.color || eachSeries.color
+            var strokeColor = item.color || eachSeries.color
+            if (columnOption.linearType !== 'none') {
+              var grd = context.createLinearGradient(startX, item.y, item.x, item.y);
+              //透明渐变
+              if (columnOption.linearType == 'opacity') {
+                grd.addColorStop(0, hexToRgb(fillColor, columnOption.linearOpacity));
+                grd.addColorStop(1, hexToRgb(fillColor, 1));
+              } else {
+                grd.addColorStop(0, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity));
+                grd.addColorStop(columnOption.colorStop, hexToRgb(columnOption.customColor[eachSeries.linearIndex],columnOption.linearOpacity));
+                grd.addColorStop(1, hexToRgb(fillColor, 1));
+              }
+              fillColor = grd
+            }
+            // 圆角边框
+            if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) {
+              const left = startX;
+              const width = item.width;
+              const top = item.y - item.width / 2;
+              const height = item.height;
+              if (columnOption.barBorderCircle) {
+                columnOption.barBorderRadius = [width / 2, width / 2, 0, 0];
+              }
+              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 + r3, top + r3, r3, -Math.PI, -Math.PI / 2);
+              context.arc(item.x - r0, top + r0, r0, -Math.PI / 2, 0);
+              context.arc(item.x - r1, top + width - r1, r1, 0, Math.PI / 2);
+              context.arc(left + r2, top + width - r2, r2, Math.PI / 2, Math.PI);
+            } else {
+              context.moveTo(startX, startY);
+              context.lineTo(item.x, startY);
+              context.lineTo(item.x, startY + item.width);
+              context.lineTo(startX, startY + item.width);
+              context.lineTo(startX, startY);
+              context.setLineWidth(1)
+              context.setStrokeStyle(strokeColor);
+            }
+            context.setFillStyle(fillColor);
+            context.closePath();
+            //context.stroke();
+            context.fill();
+          }
+        };
+        break;
+      case 'stack':
+        // 绘制堆叠数据图
+        var points = getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
+        calPoints.push(points);
+        points = fixBarStackData(points, eachSpacing, series.length, seriesIndex, config, opts, series);
+        for (let i = 0; i < points.length; i++) {
+          let item = points[i];
+          if (item !== null && i > leftNum && i < rightNum) {
+            context.beginPath();
+            var fillColor = item.color || eachSeries.color;
+            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);
+            context.closePath();
+            context.fill();
+          }
+        };
+        break;
+    }
+  });
+
+  if (opts.dataLabel !== false && process === 1) {
+    series.forEach(function(eachSeries, seriesIndex) {
+      let ranges, minRange, maxRange;
+      ranges = [].concat(opts.chartData.xAxisData.ranges);
+      maxRange = ranges.pop();
+      minRange = ranges.shift();
+      var data = eachSeries.data;
+      switch (columnOption.type) {
+        case 'group':
+          var points = getBarDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, process);
+          points = fixBarData(points, eachSpacing, series.length, seriesIndex, config, opts);
+          drawBarPointText(points, eachSeries, config, context, opts);
+          break;
+        case 'stack':
+          var points = getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
+          drawBarPointText(points, eachSeries, config, context, opts);
+          break;
+      }
+    });
+  }
+  return {
+    yAxisPoints: yAxisPoints,
+    calPoints: calPoints,
+    eachSpacing: eachSpacing
+  };
+}
+
+function drawCandleDataPoints(series, seriesMA, opts, config, context) {
+  var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
+  var candleOption = assign({}, {
+    color: {},
+    average: {}
+  }, opts.extra.candle);
+  candleOption.color = assign({}, {
+    upLine: '#f04864',
+    upFill: '#f04864',
+    downLine: '#2fc25b',
+    downFill: '#2fc25b'
+  }, candleOption.color);
+  candleOption.average = assign({}, {
+    show: false,
+    name: [],
+    day: [],
+    color: config.color
+  }, candleOption.average);
+  opts.extra.candle = candleOption;
+  let xAxisData = opts.chartData.xAxisData,
+    xAxisPoints = xAxisData.xAxisPoints,
+    eachSpacing = xAxisData.eachSpacing;
+  let calPoints = [];
+  context.save();
+  let leftNum = -2;
+  let rightNum = xAxisPoints.length + 2;
+  let leftSpace = 0;
+  let rightSpace = opts.width + eachSpacing;
+  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;
+    leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
+    rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
+  }
+  //画均线
+  if (candleOption.average.show || seriesMA) { //Merge pull request !12 from 邱贵翔
+    seriesMA.forEach(function(eachSeries, seriesIndex) {
+      let ranges, minRange, maxRange;
+      ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+      minRange = ranges.pop();
+      maxRange = ranges.shift();
+      var data = eachSeries.data;
+      var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+      var splitPointList = splitPoints(points,eachSeries);
+      for (let i = 0; i < splitPointList.length; i++) {
+        let points = splitPointList[i];
+        context.beginPath();
+        context.setStrokeStyle(eachSeries.color);
+        context.setLineWidth(1);
+        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);
+        } else {
+          context.moveTo(points[0].x, points[0].y);
+          let startPoint = 0;
+          for (let j = 0; j < points.length; j++) {
+            let item = points[j];
+            if (startPoint == 0 && item.x > leftSpace) {
+              context.moveTo(item.x, item.y);
+              startPoint = 1;
+            }
+            if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+              var ctrlPoint = createCurveControlPoints(points, j - 1);
+              context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x,
+                item.y);
+            }
+          }
+          context.moveTo(points[0].x, points[0].y);
+        }
+        context.closePath();
+        context.stroke();
+      }
+    });
+  }
+  //画K线
+  series.forEach(function(eachSeries, seriesIndex) {
+    let ranges, minRange, maxRange;
+    ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+    minRange = ranges.pop();
+    maxRange = ranges.shift();
+    var data = eachSeries.data;
+    var points = getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+    calPoints.push(points);
+    var splitPointList = splitPoints(points,eachSeries);
+    for (let i = 0; i < splitPointList[0].length; i++) {
+      if (i > leftNum && i < rightNum) {
+        let item = splitPointList[0][i];
+        context.beginPath();
+        //如果上涨
+        if (data[i][1] - data[i][0] > 0) {
+          context.setStrokeStyle(candleOption.color.upLine);
+          context.setFillStyle(candleOption.color.upFill);
+          context.setLineWidth(1 * opts.pix);
+          context.moveTo(item[3].x, item[3].y); //顶点
+          context.lineTo(item[1].x, item[1].y); //收盘中间点
+          context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点
+          context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点
+          context.lineTo(item[0].x, item[0].y); //开盘中间点
+          context.lineTo(item[2].x, item[2].y); //底点
+          context.lineTo(item[0].x, item[0].y); //开盘中间点
+          context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点
+          context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点
+          context.lineTo(item[1].x, item[1].y); //收盘中间点
+          context.moveTo(item[3].x, item[3].y); //顶点
+        } else {
+          context.setStrokeStyle(candleOption.color.downLine);
+          context.setFillStyle(candleOption.color.downFill);
+          context.setLineWidth(1 * opts.pix);
+          context.moveTo(item[3].x, item[3].y); //顶点
+          context.lineTo(item[0].x, item[0].y); //开盘中间点
+          context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点
+          context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点
+          context.lineTo(item[1].x, item[1].y); //收盘中间点
+          context.lineTo(item[2].x, item[2].y); //底点
+          context.lineTo(item[1].x, item[1].y); //收盘中间点
+          context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点
+          context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点
+          context.lineTo(item[0].x, item[0].y); //开盘中间点
+          context.moveTo(item[3].x, item[3].y); //顶点
+        }
+        context.closePath();
+        context.fill();
+        context.stroke();
+      }
+    }
+  });
+  context.restore();
+  return {
+    xAxisPoints: xAxisPoints,
+    calPoints: calPoints,
+    eachSpacing: eachSpacing
+  };
+}
+
+function drawAreaDataPoints(series, opts, config, context) {
+  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  var areaOption = assign({}, {
+    type: 'straight',
+    opacity: 0.2,
+    addLine: false,
+    width: 2,
+    gradient: false,
+    activeType: 'none'
+  }, opts.extra.area);
+  let xAxisData = opts.chartData.xAxisData,
+    xAxisPoints = xAxisData.xAxisPoints,
+    eachSpacing = xAxisData.eachSpacing;
+  let endY = opts.height - opts.area[2];
+  let calPoints = [];
+  context.save();
+  let leftSpace = 0;
+  let rightSpace = opts.width + eachSpacing;
+  if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+    context.translate(opts._scrollDistance_, 0);
+    leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
+    rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
+  }
+  series.forEach(function(eachSeries, seriesIndex) {
+    let ranges, minRange, maxRange;
+    ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+    minRange = ranges.pop();
+    maxRange = ranges.shift();
+    let data = eachSeries.data;
+    let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+    calPoints.push(points);
+    let splitPointList = splitPoints(points,eachSeries);
+    for (let i = 0; i < splitPointList.length; i++) {
+      let points = splitPointList[i];
+      // 绘制区域数
+      context.beginPath();
+      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(areaOption.width * opts.pix);
+      if (points.length > 1) {
+        let firstPoint = points[0];
+        let lastPoint = points[points.length - 1];
+        context.moveTo(firstPoint.x, firstPoint.y);
+        let startPoint = 0;
+        if (areaOption.type === 'curve') {
+          for (let j = 0; j < points.length; j++) {
+            let item = points[j];
+            if (startPoint == 0 && item.x > leftSpace) {
+              context.moveTo(item.x, item.y);
+              startPoint = 1;
+            }
+            if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+              let ctrlPoint = createCurveControlPoints(points, j - 1);
+              context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
+            }
+          };
+        } 
+        if (areaOption.type === 'straight') {
+          for (let j = 0; j < points.length; j++) {
+            let item = points[j];
+            if (startPoint == 0 && item.x > leftSpace) {
+              context.moveTo(item.x, item.y);
+              startPoint = 1;
+            }
+            if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+              context.lineTo(item.x, item.y);
+            }
+          };
+        }
+        if (areaOption.type === 'step') {
+          for (let j = 0; j < points.length; j++) {
+            let item = points[j];
+            if (startPoint == 0 && item.x > leftSpace) {
+              context.moveTo(item.x, item.y);
+              startPoint = 1;
+            }
+            if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+              context.lineTo(item.x, points[j - 1].y);
+              context.lineTo(item.x, item.y);
+            }
+          };
+        }
+        context.lineTo(lastPoint.x, endY);
+        context.lineTo(firstPoint.x, endY);
+        context.lineTo(firstPoint.x, firstPoint.y);
+      } else {
+        let item = points[0];
+        context.moveTo(item.x - eachSpacing / 2, item.y);
+        // context.lineTo(item.x + eachSpacing / 2, item.y);
+        // context.lineTo(item.x + eachSpacing / 2, endY);
+        // context.lineTo(item.x - eachSpacing / 2, endY);
+        // context.moveTo(item.x - eachSpacing / 2, item.y);
+      }
+      context.closePath();
+      context.fill();
+      //画连线
+      if (areaOption.addLine) {
+        if (eachSeries.lineType == 'dash') {
+          let dashLength = eachSeries.dashLength ? eachSeries.dashLength : 8;
+          dashLength *= opts.pix;
+          context.setLineDash([dashLength, dashLength]);
+        }
+        context.beginPath();
+        context.setStrokeStyle(eachSeries.color);
+        context.setLineWidth(areaOption.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);
+        } else {
+          context.moveTo(points[0].x, points[0].y);
+          let startPoint = 0;
+          if (areaOption.type === 'curve') {
+            for (let j = 0; j < points.length; j++) {
+              let item = points[j];
+              if (startPoint == 0 && item.x > leftSpace) {
+                context.moveTo(item.x, item.y);
+                startPoint = 1;
+              }
+              if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+                let ctrlPoint = createCurveControlPoints(points, j - 1);
+                context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
+              }
+            };
+          }
+          if (areaOption.type === 'straight') {
+            for (let j = 0; j < points.length; j++) {
+              let item = points[j];
+              if (startPoint == 0 && item.x > leftSpace) {
+                context.moveTo(item.x, item.y);
+                startPoint = 1;
+              }
+              if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+                context.lineTo(item.x, item.y);
+              }
+            };
+          }
+          if (areaOption.type === 'step') {
+            for (let j = 0; j < points.length; j++) {
+              let item = points[j];
+              if (startPoint == 0 && item.x > leftSpace) {
+                context.moveTo(item.x, item.y);
+                startPoint = 1;
+              }
+              if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+                context.lineTo(item.x, points[j - 1].y);
+                context.lineTo(item.x, item.y);
+              }
+            };
+          }
+          context.moveTo(points[0].x, points[0].y);
+        }
+        context.stroke();
+        context.setLineDash([]);
+      }
+    }
+    //画点
+    if (opts.dataPointShape !== false) {
+      drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+    }
+    drawActivePoint(points, eachSeries.color, eachSeries.pointShape, context, opts, areaOption,seriesIndex);
+  });
+
+  if (opts.dataLabel !== false && process === 1) {
+    series.forEach(function(eachSeries, seriesIndex) {
+      let ranges, minRange, maxRange;
+      ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+      minRange = ranges.pop();
+      maxRange = ranges.shift();
+      var data = eachSeries.data;
+      var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+      drawPointText(points, eachSeries, config, context, opts);
+    });
+  }
+  context.restore();
+  return {
+    xAxisPoints: xAxisPoints,
+    calPoints: calPoints,
+    eachSpacing: eachSpacing
+  };
+}
+
+function drawScatterDataPoints(series, opts, config, context) {
+  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  var scatterOption = assign({}, {
+    type: 'circle'
+  }, opts.extra.scatter);
+  let xAxisData = opts.chartData.xAxisData,
+    xAxisPoints = xAxisData.xAxisPoints,
+    eachSpacing = xAxisData.eachSpacing;
+  var calPoints = [];
+  context.save();
+  let leftSpace = 0;
+  let rightSpace = opts.width + eachSpacing;
+  if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+    context.translate(opts._scrollDistance_, 0);
+    leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
+    rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
+  }
+  series.forEach(function(eachSeries, seriesIndex) {
+    let ranges, minRange, maxRange;
+    ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+    minRange = ranges.pop();
+    maxRange = ranges.shift();
+    var data = eachSeries.data;
+    var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+    context.beginPath();
+    context.setStrokeStyle(eachSeries.color);
+    context.setFillStyle(eachSeries.color);
+    context.setLineWidth(1 * opts.pix);
+    var shape = eachSeries.pointShape;
+    if (shape === 'diamond') {
+      points.forEach(function(item, index) {
+        if (item !== null) {
+          context.moveTo(item.x, item.y - 4.5);
+          context.lineTo(item.x - 4.5, item.y);
+          context.lineTo(item.x, item.y + 4.5);
+          context.lineTo(item.x + 4.5, item.y);
+          context.lineTo(item.x, item.y - 4.5);
+        }
+      });
+    } else if (shape === 'circle') {
+      points.forEach(function(item, index) {
+        if (item !== null) {
+          context.moveTo(item.x + 2.5 * opts.pix, item.y);
+          context.arc(item.x, item.y, 3 * opts.pix, 0, 2 * Math.PI, false);
+        }
+      });
+    } else if (shape === 'square') {
+      points.forEach(function(item, index) {
+        if (item !== null) {
+          context.moveTo(item.x - 3.5, item.y - 3.5);
+          context.rect(item.x - 3.5, item.y - 3.5, 7, 7);
+        }
+      });
+    } else if (shape === 'triangle') {
+      points.forEach(function(item, index) {
+        if (item !== null) {
+          context.moveTo(item.x, item.y - 4.5);
+          context.lineTo(item.x - 4.5, item.y + 4.5);
+          context.lineTo(item.x + 4.5, item.y + 4.5);
+          context.lineTo(item.x, item.y - 4.5);
+        }
+      });
+    } else if (shape === 'triangle') {
+      return;
+    }
+    context.closePath();
+    context.fill();
+    context.stroke();
+  });
+  if (opts.dataLabel !== false && process === 1) {
+    series.forEach(function(eachSeries, seriesIndex) {
+      let ranges, minRange, maxRange;
+      ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+      minRange = ranges.pop();
+      maxRange = ranges.shift();
+      var data = eachSeries.data;
+      var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+      drawPointText(points, eachSeries, config, context, opts);
+    });
+  }
+  context.restore();
+  return {
+    xAxisPoints: xAxisPoints,
+    calPoints: calPoints,
+    eachSpacing: eachSpacing
+  };
+}
+
+function drawBubbleDataPoints(series, opts, config, context) {
+  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  var bubbleOption = assign({}, {
+    opacity: 1,
+    border:2
+  }, opts.extra.bubble);
+  let xAxisData = opts.chartData.xAxisData,
+    xAxisPoints = xAxisData.xAxisPoints,
+    eachSpacing = xAxisData.eachSpacing;
+  var calPoints = [];
+  context.save();
+  let leftSpace = 0;
+  let rightSpace = opts.width + eachSpacing;
+  if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+    context.translate(opts._scrollDistance_, 0);
+    leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
+    rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
+  }
+  series.forEach(function(eachSeries, seriesIndex) {
+    let ranges, minRange, maxRange;
+    ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+    minRange = ranges.pop();
+    maxRange = ranges.shift();
+    var data = eachSeries.data;
+    var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+    context.beginPath();
+    context.setStrokeStyle(eachSeries.color);
+    context.setLineWidth(bubbleOption.border * opts.pix);
+    context.setFillStyle(hexToRgb(eachSeries.color, bubbleOption.opacity));
+    points.forEach(function(item, index) {
+      context.moveTo(item.x + item.r, item.y);
+      context.arc(item.x, item.y, item.r * opts.pix, 0, 2 * Math.PI, false);
+    });
+    context.closePath();
+    context.fill();
+    context.stroke();
+    
+    if (opts.dataLabel !== false && process === 1) {
+      points.forEach(function(item, index) {
+        context.beginPath();
+        var fontSize = eachSeries.textSize * opts.pix || config.fontSize;
+        context.setFontSize(fontSize);
+        context.setFillStyle(eachSeries.textColor || "#FFFFFF");
+        context.setTextAlign('center');
+        context.fillText(String(item.t), item.x, item.y + fontSize/2);
+        context.closePath();
+        context.stroke();
+        context.setTextAlign('left');
+      });
+    }
+  });
+  context.restore();
+  return {
+    xAxisPoints: xAxisPoints,
+    calPoints: calPoints,
+    eachSpacing: eachSpacing
+  };
+}
+
+function drawLineDataPoints(series, opts, config, context) {
+  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  var lineOption = assign({}, {
+    type: 'straight',
+    width: 2,
+    activeType: 'none',
+    linearType: 'none',
+    onShadow: false,
+    animation: 'vertical',
+  }, opts.extra.line);
+  lineOption.width *= opts.pix;
+  let xAxisData = opts.chartData.xAxisData,
+    xAxisPoints = xAxisData.xAxisPoints,
+    eachSpacing = xAxisData.eachSpacing;
+  var calPoints = [];
+  context.save();
+  let leftSpace = 0;
+  let rightSpace = opts.width + eachSpacing;
+  if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+    context.translate(opts._scrollDistance_, 0);
+    leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
+    rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
+  }
+  series.forEach(function(eachSeries, seriesIndex) {
+    // 这段很神奇的代码用于解决ios16的setStrokeStyle失效的bug
+    context.beginPath();
+    context.setStrokeStyle(eachSeries.color);
+    context.moveTo(-10000, -10000);
+    context.lineTo(-10001, -10001);
+    context.stroke();
+    let ranges, minRange, maxRange;
+    ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+    minRange = ranges.pop();
+    maxRange = ranges.shift();
+    var data = eachSeries.data;
+    var points = getLineDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, lineOption, process);
+    calPoints.push(points);
+    var splitPointList = splitPoints(points,eachSeries);
+    if (eachSeries.lineType == 'dash') {
+      let dashLength = eachSeries.dashLength ? eachSeries.dashLength : 8;
+      dashLength *= opts.pix;
+      context.setLineDash([dashLength, dashLength]);
+    }
+    context.beginPath();
+    var strokeColor = eachSeries.color;
+    if (lineOption.linearType !== 'none' && eachSeries.linearColor && eachSeries.linearColor.length > 0) {
+      var grd = context.createLinearGradient(opts.chartData.xAxisData.startX, opts.height/2, opts.chartData.xAxisData.endX, opts.height/2);
+      for (var i = 0; i < eachSeries.linearColor.length; i++) {
+        grd.addColorStop(eachSeries.linearColor[i][0], hexToRgb(eachSeries.linearColor[i][1], 1));
+      }
+      strokeColor = grd
+    }
+    context.setStrokeStyle(strokeColor);
+    if (lineOption.onShadow == true && eachSeries.setShadow && eachSeries.setShadow.length > 0) {
+      context.setShadow(eachSeries.setShadow[0], eachSeries.setShadow[1], eachSeries.setShadow[2], eachSeries.setShadow[3]);
+    }else{
+      context.setShadow(0, 0, 0, 'rgba(0,0,0,0)');
+    }
+    context.setLineWidth(lineOption.width);
+    splitPointList.forEach(function(points, index) {
+      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);
+      } else {
+        context.moveTo(points[0].x, points[0].y);
+        let startPoint = 0;
+        if (lineOption.type === 'curve') {
+          for (let j = 0; j < points.length; j++) {
+            let item = points[j];
+            if (startPoint == 0 && item.x > leftSpace) {
+              context.moveTo(item.x, item.y);
+              startPoint = 1;
+            }
+            if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+              var ctrlPoint = createCurveControlPoints(points, j - 1);
+              context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
+            }
+          };
+        }
+        if (lineOption.type === 'straight') {
+          for (let j = 0; j < points.length; j++) {
+            let item = points[j];
+            if (startPoint == 0 && item.x > leftSpace) {
+              context.moveTo(item.x, item.y);
+              startPoint = 1;
+            }
+            if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+              context.lineTo(item.x, item.y);
+            }
+          };
+        }
+        if (lineOption.type === 'step') {
+          for (let j = 0; j < points.length; j++) {
+            let item = points[j];
+            if (startPoint == 0 && item.x > leftSpace) {
+              context.moveTo(item.x, item.y);
+              startPoint = 1;
+            }
+            if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+              context.lineTo(item.x, points[j - 1].y);
+              context.lineTo(item.x, item.y);
+            }
+          };
+        }
+        context.moveTo(points[0].x, points[0].y);
+      }
+    });
+    context.stroke();
+    context.setLineDash([]);
+    if (opts.dataPointShape !== false) {
+      drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+    }
+    drawActivePoint(points, eachSeries.color, eachSeries.pointShape, context, opts, lineOption);
+  });
+  if (opts.dataLabel !== false && process === 1) {
+    series.forEach(function(eachSeries, seriesIndex) {
+      let ranges, minRange, maxRange;
+      ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+      minRange = ranges.pop();
+      maxRange = ranges.shift();
+      var data = eachSeries.data;
+      var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+      drawPointText(points, eachSeries, config, context, opts);
+    });
+  }
+  context.restore();
+  return {
+    xAxisPoints: xAxisPoints,
+    calPoints: calPoints,
+    eachSpacing: eachSpacing
+  };
+}
+
+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,
+    barBorderRadius: [],
+    seriesGap: 2,
+    linearType: 'none',
+    linearOpacity: 1,
+    customColor: [],
+    colorStop: 0,
+  }, opts.extra.mix.column);
+  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;
+  var columnLength = 0;
+  series.forEach(function(eachSeries, seriesIndex) {
+    if (eachSeries.type == 'column') {
+      columnLength += 1;
+    }
+  });
+  context.save();
+  let leftNum = -2;
+  let rightNum = xAxisPoints.length + 2;
+  let leftSpace = 0;
+  let rightSpace = opts.width + eachSpacing;
+  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;
+    leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
+    rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
+  }
+  columnOption.customColor = fillCustomColor(columnOption.linearType, columnOption.customColor, series, config);
+  series.forEach(function(eachSeries, seriesIndex) {
+    let ranges, minRange, maxRange;
+    ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+    minRange = ranges.pop();
+    maxRange = ranges.shift();
+    var data = eachSeries.data;
+    var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+    calPoints.push(points);
+    // 绘制柱状数据图
+    if (eachSeries.type == 'column') {
+      points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts);
+      for (let i = 0; i < points.length; i++) {
+        let item = points[i];
+        if (item !== null && i > leftNum && i < rightNum) {
+          var startX = item.x - item.width / 2;
+          var height = opts.height - item.y - opts.area[2];
+          context.beginPath();
+          var fillColor = item.color || eachSeries.color
+          var strokeColor = item.color || eachSeries.color
+          if (columnOption.linearType !== 'none') {
+            var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]);
+            //透明渐变
+            if (columnOption.linearType == 'opacity') {
+              grd.addColorStop(0, hexToRgb(fillColor, columnOption.linearOpacity));
+              grd.addColorStop(1, hexToRgb(fillColor, 1));
+            } else {
+              grd.addColorStop(0, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity));
+              grd.addColorStop(columnOption.colorStop, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity));
+              grd.addColorStop(1, hexToRgb(fillColor, 1));
+            }
+            fillColor = grd
+          }
+          // 圆角边框
+          if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle) {
+            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];
+            }
+            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);
+          } 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.setLineWidth(1)
+            context.setStrokeStyle(strokeColor);
+          }
+          context.setFillStyle(fillColor);
+          context.closePath();
+          context.fill();
+        }
+      }
+      columnIndex += 1;
+    }
+    //绘制区域图数据
+    if (eachSeries.type == 'area') {
+      let splitPointList = splitPoints(points,eachSeries);
+      for (let i = 0; i < splitPointList.length; i++) {
+        let points = splitPointList[i];
+        // 绘制区域数据
+        context.beginPath();
+        context.setStrokeStyle(eachSeries.color);
+        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];
+          let lastPoint = points[points.length - 1];
+          context.moveTo(firstPoint.x, firstPoint.y);
+          let startPoint = 0;
+          if (eachSeries.style === 'curve') {
+            for (let j = 0; j < points.length; j++) {
+              let item = points[j];
+              if (startPoint == 0 && item.x > leftSpace) {
+                context.moveTo(item.x, item.y);
+                startPoint = 1;
+              }
+              if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+                var ctrlPoint = createCurveControlPoints(points, j - 1);
+                context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
+              }
+            };
+          } else {
+            for (let j = 0; j < points.length; j++) {
+              let item = points[j];
+              if (startPoint == 0 && item.x > leftSpace) {
+                context.moveTo(item.x, item.y);
+                startPoint = 1;
+              }
+              if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+                context.lineTo(item.x, item.y);
+              }
+            };
+          }
+          context.lineTo(lastPoint.x, endY);
+          context.lineTo(firstPoint.x, endY);
+          context.lineTo(firstPoint.x, firstPoint.y);
+        } else {
+          let item = points[0];
+          context.moveTo(item.x - eachSpacing / 2, item.y);
+          // context.lineTo(item.x + eachSpacing / 2, item.y);
+          // context.lineTo(item.x + eachSpacing / 2, endY);
+          // context.lineTo(item.x - eachSpacing / 2, endY);
+          // context.moveTo(item.x - eachSpacing / 2, item.y);
+        }
+        context.closePath();
+        context.fill();
+      }
+    }
+    // 绘制折线数据图
+    if (eachSeries.type == 'line') {
+      var splitPointList = splitPoints(points,eachSeries);
+      splitPointList.forEach(function(points, index) {
+        if (eachSeries.lineType == 'dash') {
+          let dashLength = eachSeries.dashLength ? eachSeries.dashLength : 8;
+          dashLength *= opts.pix;
+          context.setLineDash([dashLength, dashLength]);
+        }
+        context.beginPath();
+        context.setStrokeStyle(eachSeries.color);
+        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);
+        } else {
+          context.moveTo(points[0].x, points[0].y);
+          let startPoint = 0;
+          if (eachSeries.style == 'curve') {
+            for (let j = 0; j < points.length; j++) {
+              let item = points[j];
+              if (startPoint == 0 && item.x > leftSpace) {
+                context.moveTo(item.x, item.y);
+                startPoint = 1;
+              }
+              if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+                var ctrlPoint = createCurveControlPoints(points, j - 1);
+                context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,
+                  item.x, item.y);
+              }
+            }
+          } else {
+            for (let j = 0; j < points.length; j++) {
+              let item = points[j];
+              if (startPoint == 0 && item.x > leftSpace) {
+                context.moveTo(item.x, item.y);
+                startPoint = 1;
+              }
+              if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
+                context.lineTo(item.x, item.y);
+              }
+            }
+          }
+          context.moveTo(points[0].x, points[0].y);
+        }
+        context.stroke();
+        context.setLineDash([]);
+      });
+    }
+    // 绘制点数据图
+    if (eachSeries.type == 'point') {
+      eachSeries.addPoint = true;
+    }
+    if (eachSeries.addPoint == true && eachSeries.type !== 'column') {
+      drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
+    }
+  });
+  if (opts.dataLabel !== false && process === 1) {
+    var columnIndex = 0;
+    series.forEach(function(eachSeries, seriesIndex) {
+      let ranges, minRange, maxRange;
+      ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
+      minRange = ranges.pop();
+      maxRange = ranges.shift();
+      var data = eachSeries.data;
+      var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
+      if (eachSeries.type !== 'column') {
+        drawPointText(points, eachSeries, config, context, opts);
+      } else {
+        points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts);
+        drawPointText(points, eachSeries, config, context, opts);
+        columnIndex += 1;
+      }
+    });
+  }
+  context.restore();
+  return {
+    xAxisPoints: xAxisPoints,
+    calPoints: calPoints,
+    eachSpacing: eachSpacing,
+  }
+}
+
+
+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 == 'mount' || opts.type == 'candle' || opts.type == 'mix')) {
+    drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints)
+  }
+  context.save();
+  if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
+    context.translate(opts._scrollDistance_, 0);
+  }
+  if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
+    drawToolTip(opts.tooltip.textList, opts.tooltip.offset, opts, config, context, eachSpacing, xAxisPoints);
+  }
+  context.restore();
+
+}
+
+function drawXAxis(categories, opts, config, context) {
+
+  let xAxisData = opts.chartData.xAxisData,
+    xAxisPoints = xAxisData.xAxisPoints,
+    startX = xAxisData.startX,
+    endX = xAxisData.endX,
+    eachSpacing = xAxisData.eachSpacing;
+  var boundaryGap = 'center';
+  if (opts.type == 'bar' || opts.type == 'line' || opts.type == 'area'|| opts.type == 'scatter' || opts.type == 'bubble') {
+    boundaryGap = opts.xAxis.boundaryGap;
+  }
+  var startY = opts.height - opts.area[2];
+  var endY = opts.area[0];
+
+  //绘制滚动条
+  if (opts.enableScroll && opts.xAxis.scrollShow) {
+    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_) {
+      scrollLeft = -opts._scrollDistance_ * (scrollScreenWidth) / scrollTotalWidth;
+    }
+    context.beginPath();
+    context.setLineCap('round');
+    context.setLineWidth(6 * opts.pix);
+    context.setStrokeStyle(opts.xAxis.scrollBackgroundColor || "#EFEBEF");
+    context.moveTo(startX, scrollY);
+    context.lineTo(endX, scrollY);
+    context.stroke();
+    context.closePath();
+    context.beginPath();
+    context.setLineCap('round');
+    context.setLineWidth(6 * opts.pix);
+    context.setStrokeStyle(opts.xAxis.scrollColor || "#A6A6A6");
+    context.moveTo(startX + scrollLeft, scrollY);
+    context.lineTo(startX + scrollLeft + scrollWidth, scrollY);
+    context.stroke();
+    context.closePath();
+    context.setLineCap('butt');
+  }
+  context.save();
+  if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
+    context.translate(opts._scrollDistance_, 0);
+  }
+  //绘制X轴刻度线
+  if (opts.xAxis.calibration === true) {
+    context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
+    context.setLineCap('butt');
+    context.setLineWidth(1 * opts.pix);
+    xAxisPoints.forEach(function(item, index) {
+      if (index > 0) {
+        context.beginPath();
+        context.moveTo(item - eachSpacing / 2, startY);
+        context.lineTo(item - eachSpacing / 2, startY + 3 * opts.pix);
+        context.closePath();
+        context.stroke();
+      }
+    });
+  }
+  //绘制X轴网格
+  if (opts.xAxis.disableGrid !== true) {
+    context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
+    context.setLineCap('butt');
+    context.setLineWidth(1 * opts.pix);
+    if (opts.xAxis.gridType == 'dash') {
+      context.setLineDash([opts.xAxis.dashLength * opts.pix, opts.xAxis.dashLength * opts.pix]);
+    }
+    opts.xAxis.gridEval = opts.xAxis.gridEval || 1;
+    xAxisPoints.forEach(function(item, index) {
+      if (index % opts.xAxis.gridEval == 0) {
+        context.beginPath();
+        context.moveTo(item, startY);
+        context.lineTo(item, endY);
+        context.stroke();
+      }
+    });
+    context.setLineDash([]);
+  }
+  //绘制X轴文案
+  if (opts.xAxis.disabled !== true) {
+    // 对X轴列表做抽稀处理
+    //默认全部显示X轴标签
+    let maxXAxisListLength = categories.length;
+    //如果设置了X轴单屏数量
+    if (opts.xAxis.labelCount) {
+      //如果设置X轴密度
+      if (opts.xAxis.itemCount) {
+        maxXAxisListLength = Math.ceil(categories.length / opts.xAxis.itemCount * opts.xAxis.labelCount);
+      } else {
+        maxXAxisListLength = opts.xAxis.labelCount;
+      }
+      maxXAxisListLength -= 1;
+    }
+
+    let ratio = Math.ceil(categories.length / maxXAxisListLength);
+
+    let newCategories = [];
+    let cgLength = categories.length;
+    for (let i = 0; i < cgLength; i++) {
+      if (i % ratio !== 0) {
+        newCategories.push("");
+      } else {
+        newCategories.push(categories[i]);
+      }
+    }
+    newCategories[cgLength - 1] = categories[cgLength - 1];
+    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,index,opts) : item;
+        var offset = -measureText(String(xitem), xAxisFontSize, context) / 2;
+        if (boundaryGap == 'center') {
+          offset += eachSpacing / 2;
+        }
+        var scrollHeight = 0;
+        if (opts.xAxis.scrollShow) {
+          scrollHeight = 6 * opts.pix;
+        }
+        // 如果在主视图区域内
+        var _scrollDistance_ = opts._scrollDistance_ || 0;
+        var truePoints = boundaryGap == 'center' ? xAxisPoints[index] + eachSpacing / 2 : xAxisPoints[index];
+        if((truePoints - Math.abs(_scrollDistance_)) >= (opts.area[3] - 1) && (truePoints - Math.abs(_scrollDistance_)) <= (opts.width - opts.area[1] + 1)){
+          context.beginPath();
+          context.setFontSize(xAxisFontSize);
+          context.setFillStyle(opts.xAxis.fontColor || opts.fontColor);
+          context.fillText(String(xitem), xAxisPoints[index] + offset, startY + opts.xAxis.marginTop * opts.pix + (opts.xAxis.lineHeight - opts.xAxis.fontSize) * opts.pix / 2 + opts.xAxis.fontSize * opts.pix);
+          context.closePath();
+          context.stroke();
+        }
+      });
+    } else {
+      newCategories.forEach(function(item, index) {
+        var xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item) : item;
+        // 如果在主视图区域内
+        var _scrollDistance_ = opts._scrollDistance_ || 0;
+        var truePoints = boundaryGap == 'center' ? xAxisPoints[index] + eachSpacing / 2 : xAxisPoints[index];
+        if((truePoints - Math.abs(_scrollDistance_)) >= (opts.area[3] - 1) && (truePoints - Math.abs(_scrollDistance_)) <= (opts.width - opts.area[1] + 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 + opts.xAxis.marginTop * 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();
+        }
+      });
+    }
+  }
+  context.restore();
+  
+  //画X轴标题
+  if (opts.xAxis.title) {
+    context.beginPath();
+    context.setFontSize(opts.xAxis.titleFontSize * opts.pix);
+    context.setFillStyle(opts.xAxis.titleFontColor);
+    context.fillText(String(opts.xAxis.title), opts.width - opts.area[1] + opts.xAxis.titleOffsetX * opts.pix,opts.height - opts.area[2] + opts.xAxis.marginTop * opts.pix + (opts.xAxis.lineHeight - opts.xAxis.titleFontSize) * opts.pix / 2 + (opts.xAxis.titleFontSize + opts.xAxis.titleOffsetY) * opts.pix);
+    context.closePath();
+    context.stroke();
+  }
+  
+  //绘制X轴轴线
+  if (opts.xAxis.axisLine) {
+    context.beginPath();
+    context.setStrokeStyle(opts.xAxis.axisLineColor);
+    context.setLineWidth(1 * opts.pix);
+    context.moveTo(startX, opts.height - opts.area[2]);
+    context.lineTo(endX, opts.height - opts.area[2]);
+    context.stroke();
+  }
+}
+
+function drawYAxisGrid(categories, opts, config, context) {
+  if (opts.yAxis.disableGrid === true) {
+    return;
+  }
+  let spacingValid = opts.height - opts.area[0] - opts.area[2];
+  let eachSpacing = spacingValid / opts.yAxis.splitNumber;
+  let startX = opts.area[3];
+  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
+  if (opts.xAxis.axisLine === false) {
+    startY = 0
+  }
+  for (let i = startY; i < opts.yAxis.splitNumber + 1; i++) {
+    points.push(opts.height - opts.area[2] - eachSpacing * i);
+  }
+  context.save();
+  if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
+    context.translate(opts._scrollDistance_, 0);
+  }
+  if (opts.yAxis.gridType == 'dash') {
+    context.setLineDash([opts.yAxis.dashLength * opts.pix, opts.yAxis.dashLength * opts.pix]);
+  }
+  context.setStrokeStyle(opts.yAxis.gridColor);
+  context.setLineWidth(1 * opts.pix);
+  points.forEach(function(item, index) {
+    context.beginPath();
+    context.moveTo(startX, item);
+    context.lineTo(endX, item);
+    context.stroke();
+  });
+  context.setLineDash([]);
+  context.restore();
+}
+
+function drawYAxis(series, opts, config, context) {
+  if (opts.yAxis.disabled === true) {
+    return;
+  }
+  var spacingValid = opts.height - opts.area[0] - opts.area[2];
+  var eachSpacing = spacingValid / opts.yAxis.splitNumber;
+  var startX = opts.area[3];
+  var endX = opts.width - opts.area[1];
+  var endY = opts.height - opts.area[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, endY + 2 * opts.pix);
+  }
+  if (opts.enableScroll == true && opts.xAxis.scrollPosition && opts.xAxis.scrollPosition !== 'right') {
+    context.fillRect(endX, 0, opts.width, endY + 2 * opts.pix);
+  }
+  context.closePath();
+  context.stroke();
+  
+  let tStartLeft = opts.area[3];
+  let tStartRight = opts.width - opts.area[1];
+  let tStartCenter = opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2;
+  if (opts.yAxis.data) {
+    for (let i = 0; i < opts.yAxis.data.length; i++) {
+      let yData = opts.yAxis.data[i];
+      var points = [];
+      if(yData.type === 'categories'){
+        for (let i = 0; i <= yData.categories.length; i++) {
+          points.push(opts.area[0] + spacingValid / yData.categories.length / 2 + spacingValid / yData.categories.length * i);
+        }
+      }else{
+        for (let i = 0; i <= opts.yAxis.splitNumber; i++) {
+          points.push(opts.area[0] + eachSpacing * i);
+        }
+      }
+      if (yData.disabled !== true) {
+        let rangesFormat = opts.chartData.yAxisData.rangesFormat[i];
+        let yAxisFontSize = yData.fontSize ? yData.fontSize * opts.pix : config.fontSize;
+        let yAxisWidth = opts.chartData.yAxisData.yAxisWidth[i];
+        let textAlign = yData.textAlign || "right";
+        //画Y轴刻度及文案
+        rangesFormat.forEach(function(item, index) {
+          var pos = points[index];
+          context.beginPath();
+          context.setFontSize(yAxisFontSize);
+          context.setLineWidth(1 * opts.pix);
+          context.setStrokeStyle(yData.axisLineColor || '#cccccc');
+          context.setFillStyle(yData.fontColor || opts.fontColor);
+          let tmpstrat = 0;
+          let gapwidth = 4 * opts.pix;
+          if (yAxisWidth.position == 'left') {
+            //画刻度线
+            if (yData.calibration == true) {
+              context.moveTo(tStartLeft, pos);
+              context.lineTo(tStartLeft - 3 * opts.pix, pos);
+              gapwidth += 3 * opts.pix;
+            }
+            //画文字
+            switch (textAlign) {
+              case "left":
+                context.setTextAlign('left');
+                tmpstrat = tStartLeft - yAxisWidth.width
+                break;
+              case "right":
+                context.setTextAlign('right');
+                tmpstrat = tStartLeft - gapwidth
+                break;
+              default:
+                context.setTextAlign('center');
+                tmpstrat = tStartLeft - yAxisWidth.width / 2
+            }
+            context.fillText(String(item), tmpstrat, pos + yAxisFontSize / 2 - 3 * opts.pix);
+
+          } else if (yAxisWidth.position == 'right') {
+            //画刻度线
+            if (yData.calibration == true) {
+              context.moveTo(tStartRight, pos);
+              context.lineTo(tStartRight + 3 * opts.pix, pos);
+              gapwidth += 3 * opts.pix;
+            }
+            switch (textAlign) {
+              case "left":
+                context.setTextAlign('left');
+                tmpstrat = tStartRight + gapwidth
+                break;
+              case "right":
+                context.setTextAlign('right');
+                tmpstrat = tStartRight + yAxisWidth.width
+                break;
+              default:
+                context.setTextAlign('center');
+                tmpstrat = tStartRight + yAxisWidth.width / 2
+            }
+            context.fillText(String(item), tmpstrat, pos + yAxisFontSize / 2 - 3 * opts.pix);
+          } else if (yAxisWidth.position == 'center') {
+            //画刻度线
+            if (yData.calibration == true) {
+              context.moveTo(tStartCenter, pos);
+              context.lineTo(tStartCenter - 3 * opts.pix, pos);
+              gapwidth += 3 * opts.pix;
+            }
+            //画文字
+            switch (textAlign) {
+              case "left":
+                context.setTextAlign('left');
+                tmpstrat = tStartCenter - yAxisWidth.width
+                break;
+              case "right":
+                context.setTextAlign('right');
+                tmpstrat = tStartCenter - gapwidth
+                break;
+              default:
+                context.setTextAlign('center');
+                tmpstrat = tStartCenter - yAxisWidth.width / 2
+            }
+            context.fillText(String(item), tmpstrat, pos + yAxisFontSize / 2 - 3 * opts.pix);
+          }
+          context.closePath();
+          context.stroke();
+          context.setTextAlign('left');
+        });
+        //画Y轴轴线
+        if (yData.axisLine !== false) {
+          context.beginPath();
+          context.setStrokeStyle(yData.axisLineColor || '#cccccc');
+          context.setLineWidth(1 * opts.pix);
+          if (yAxisWidth.position == 'left') {
+            context.moveTo(tStartLeft, opts.height - opts.area[2]);
+            context.lineTo(tStartLeft, opts.area[0]);
+          } else if (yAxisWidth.position == 'right') {
+            context.moveTo(tStartRight, opts.height - opts.area[2]);
+            context.lineTo(tStartRight, opts.area[0]);
+          } else if (yAxisWidth.position == 'center') {
+            context.moveTo(tStartCenter, opts.height - opts.area[2]);
+            context.lineTo(tStartCenter, opts.area[0]);
+          }
+          context.stroke();
+        }
+        //画Y轴标题
+        if (opts.yAxis.showTitle) {
+          let titleFontSize = yData.titleFontSize * opts.pix || config.fontSize;
+          let title = yData.title;
+          context.beginPath();
+          context.setFontSize(titleFontSize);
+          context.setFillStyle(yData.titleFontColor || opts.fontColor);
+          if (yAxisWidth.position == 'left') {
+            context.fillText(title, tStartLeft - measureText(title, titleFontSize, context) / 2 + (yData.titleOffsetX || 0), opts.area[0] - (10 - (yData.titleOffsetY || 0)) * opts.pix);
+          } else if (yAxisWidth.position == 'right') {
+            context.fillText(title, tStartRight - measureText(title, titleFontSize, context) / 2 + (yData.titleOffsetX || 0), opts.area[0] - (10 - (yData.titleOffsetY || 0)) * opts.pix);
+          } else if (yAxisWidth.position == 'center') {
+            context.fillText(title, tStartCenter - measureText(title, titleFontSize, context) / 2 + (yData.titleOffsetX || 0), opts.area[0] - (10 - (yData.titleOffsetY || 0)) * opts.pix);
+          }
+          context.closePath();
+          context.stroke();
+        }
+        if (yAxisWidth.position == 'left') {
+          tStartLeft -= (yAxisWidth.width + opts.yAxis.padding * opts.pix);
+        } else {
+          tStartRight += yAxisWidth.width + opts.yAxis.padding * opts.pix;
+        }
+      }
+    }
+  }
+
+}
+
+function drawLegend(series, opts, config, context, chartData) {
+  if (opts.legend.show === false) {
+    return;
+  }
+  let legendData = chartData.legendData;
+  let legendList = legendData.points;
+  let legendArea = legendData.area;
+  let padding = opts.legend.padding * opts.pix;
+  let fontSize = opts.legend.fontSize * opts.pix;
+  let shapeWidth = 15 * opts.pix;
+  let shapeRight = 5 * opts.pix;
+  let itemGap = opts.legend.itemGap * opts.pix;
+  let lineHeight = Math.max(opts.legend.lineHeight * opts.pix, fontSize);
+  //画背景及边框
+  context.beginPath();
+  context.setLineWidth(opts.legend.borderWidth * opts.pix);
+  context.setStrokeStyle(opts.legend.borderColor);
+  context.setFillStyle(opts.legend.backgroundColor);
+  context.moveTo(legendArea.start.x, legendArea.start.y);
+  context.rect(legendArea.start.x, legendArea.start.y, legendArea.width, legendArea.height);
+  context.closePath();
+  context.fill();
+  context.stroke();
+  legendList.forEach(function(itemList, listIndex) {
+    let width = 0;
+    let height = 0;
+    width = legendData.widthArr[listIndex];
+    height = legendData.heightArr[listIndex];
+    let startX = 0;
+    let startY = 0;
+    if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
+      switch (opts.legend.float) {
+        case 'left':
+          startX = legendArea.start.x + padding;
+        break;
+        case 'right':
+          startX = legendArea.start.x + legendArea.width - width;
+        break;
+        default:
+        startX = legendArea.start.x + (legendArea.width - width) / 2;
+      }
+      startY = legendArea.start.y + padding + listIndex * lineHeight;
+    } else {
+      if (listIndex == 0) {
+        width = 0;
+      } else {
+        width = legendData.widthArr[listIndex - 1];
+      }
+      startX = legendArea.start.x + padding + width;
+      startY = legendArea.start.y + padding + (legendArea.height - height) / 2;
+    }
+    context.setFontSize(config.fontSize);
+    for (let i = 0; i < itemList.length; i++) {
+      let item = itemList[i];
+      item.area = [0, 0, 0, 0];
+      item.area[0] = startX;
+      item.area[1] = startY;
+      item.area[3] = startY + lineHeight;
+      context.beginPath();
+      context.setLineWidth(1 * opts.pix);
+      context.setStrokeStyle(item.show ? item.color : opts.legend.hiddenColor);
+      context.setFillStyle(item.show ? item.color : opts.legend.hiddenColor);
+      switch (item.legendShape) {
+        case 'line':
+          context.moveTo(startX, startY + 0.5 * lineHeight - 2 * opts.pix);
+          context.fillRect(startX, startY + 0.5 * lineHeight - 2 * opts.pix, 15 * opts.pix, 4 * opts.pix);
+          break;
+        case 'triangle':
+          context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix);
+          context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * lineHeight + 5 * opts.pix);
+          context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * lineHeight + 5 * opts.pix);
+          context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix);
+          break;
+        case 'diamond':
+          context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix);
+          context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * lineHeight);
+          context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight + 5 * opts.pix);
+          context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * lineHeight);
+          context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix);
+          break;
+        case 'circle':
+          context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight);
+          context.arc(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight, 5 * opts.pix, 0, 2 * Math.PI);
+          break;
+        case 'rect':
+          context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pix);
+          context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix);
+          break;
+        case 'square':
+          context.moveTo(startX + 5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix);
+          context.fillRect(startX + 5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix, 10 * opts.pix, 10 * opts.pix);
+          break;
+        case 'none':
+          break;
+        default:
+          context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pix);
+          context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix);
+      }
+      context.closePath();
+      context.fill();
+      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(legendText, startX, startY + fontTrans);
+      context.closePath();
+      context.stroke();
+      if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
+        startX += measureText(legendText, fontSize, context) + itemGap;
+        item.area[2] = startX;
+      } else {
+        item.area[2] = startX + measureText(legendText, fontSize, context) + itemGap;;
+        startX -= shapeWidth + shapeRight;
+        startY += lineHeight;
+      }
+    }
+  });
+}
+
+function drawPieDataPoints(series, opts, config, context) {
+  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  var pieOption = assign({}, {
+    activeOpacity: 0.5,
+    activeRadius: 10,
+    offsetAngle: 0,
+    labelWidth: 15,
+    ringWidth: 30,
+    customRadius: 0,
+    border: false,
+    borderWidth: 2,
+    borderColor: '#FFFFFF',
+    centerColor: '#FFFFFF',
+    linearType: 'none',
+    customColor: [],
+  }, opts.type == "pie" ? opts.extra.pie : opts.extra.ring);
+  var centerPosition = {
+    x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+    y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
+  };
+  if (config.pieChartLinePadding == 0) {
+    config.pieChartLinePadding = pieOption.activeRadius * opts.pix;
+  }
+
+  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;
+  }
+  series = getPieDataPoints(series, radius, process);
+  var activeRadius = pieOption.activeRadius * opts.pix;
+  pieOption.customColor = fillCustomColor(pieOption.linearType, pieOption.customColor, series, config);
+  series = series.map(function(eachSeries) {
+    eachSeries._start_ += (pieOption.offsetAngle) * Math.PI / 180;
+    return eachSeries;
+  });
+  series.forEach(function(eachSeries, seriesIndex) {
+    if (opts.tooltip) {
+      if (opts.tooltip.index == seriesIndex) {
+        context.beginPath();
+        context.setFillStyle(hexToRgb(eachSeries.color, pieOption.activeOpacity || 0.5));
+        context.moveTo(centerPosition.x, centerPosition.y);
+        context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_ + activeRadius, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI);
+        context.closePath();
+        context.fill();
+      }
+    }
+    context.beginPath();
+    context.setLineWidth(pieOption.borderWidth * opts.pix);
+    context.lineJoin = "round";
+    context.setStrokeStyle(pieOption.borderColor);
+    var fillcolor = eachSeries.color;
+    if (pieOption.linearType == 'custom') {
+      var grd;
+      if(context.createCircularGradient){
+        grd = context.createCircularGradient(centerPosition.x, centerPosition.y, eachSeries._radius_)
+      }else{
+        grd = context.createRadialGradient(centerPosition.x, centerPosition.y, 0,centerPosition.x, centerPosition.y, eachSeries._radius_)
+      }
+      grd.addColorStop(0, hexToRgb(pieOption.customColor[eachSeries.linearIndex], 1))
+      grd.addColorStop(1, hexToRgb(eachSeries.color, 1))
+      fillcolor = grd
+    }
+    context.setFillStyle(fillcolor);
+    context.moveTo(centerPosition.x, centerPosition.y);
+    context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI);
+    context.closePath();
+    context.fill();
+    if (pieOption.border == true) {
+      context.stroke();
+    }
+  });
+  if (opts.type === 'ring') {
+    var innerPieWidth = radius * 0.6;
+    if (typeof pieOption.ringWidth === 'number' && pieOption.ringWidth > 0) {
+      innerPieWidth = Math.max(0, radius - pieOption.ringWidth * opts.pix);
+    }
+    context.beginPath();
+    context.setFillStyle(pieOption.centerColor);
+    context.moveTo(centerPosition.x, centerPosition.y);
+    context.arc(centerPosition.x, centerPosition.y, innerPieWidth, 0, 2 * Math.PI);
+    context.closePath();
+    context.fill();
+  }
+  if (opts.dataLabel !== false && process === 1) {
+    drawPieText(series, opts, config, context, radius, centerPosition);
+  }
+  if (process === 1 && opts.type === 'ring') {
+    drawRingTitle(opts, config, context, centerPosition);
+  }
+  return {
+    center: centerPosition,
+    radius: radius,
+    series: series
+  };
+}
+
+function drawRoseDataPoints(series, opts, config, context) {
+  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  var roseOption = assign({}, {
+    type: 'area',
+    activeOpacity: 0.5,
+    activeRadius: 10,
+    offsetAngle: 0,
+    labelWidth: 15,
+    border: false,
+    borderWidth: 2,
+    borderColor: '#FFFFFF',
+    linearType: 'none',
+    customColor: [],
+  }, opts.extra.rose);
+  if (config.pieChartLinePadding == 0) {
+    config.pieChartLinePadding = roseOption.activeRadius * opts.pix;
+  }
+  var centerPosition = {
+    x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+    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;
+  if(radius < minRadius){
+    radius = minRadius + 10;
+  }
+  series = getRoseDataPoints(series, roseOption.type, minRadius, radius, process);
+  var activeRadius = roseOption.activeRadius * opts.pix;
+  roseOption.customColor = fillCustomColor(roseOption.linearType, roseOption.customColor, series, config);
+  series = series.map(function(eachSeries) {
+    eachSeries._start_ += (roseOption.offsetAngle || 0) * Math.PI / 180;
+    return eachSeries;
+  });
+  series.forEach(function(eachSeries, seriesIndex) {
+    if (opts.tooltip) {
+      if (opts.tooltip.index == seriesIndex) {
+        context.beginPath();
+        context.setFillStyle(hexToRgb(eachSeries.color, roseOption.activeOpacity || 0.5));
+        context.moveTo(centerPosition.x, centerPosition.y);
+        context.arc(centerPosition.x, centerPosition.y, activeRadius + eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._rose_proportion_ * Math.PI);
+        context.closePath();
+        context.fill();
+      }
+    }
+    context.beginPath();
+    context.setLineWidth(roseOption.borderWidth * opts.pix);
+    context.lineJoin = "round";
+    context.setStrokeStyle(roseOption.borderColor);
+    var fillcolor = eachSeries.color;
+    if (roseOption.linearType == 'custom') {
+      var grd;
+      if(context.createCircularGradient){
+        grd = context.createCircularGradient(centerPosition.x, centerPosition.y, eachSeries._radius_)
+      }else{
+        grd = context.createRadialGradient(centerPosition.x, centerPosition.y, 0,centerPosition.x, centerPosition.y, eachSeries._radius_)
+      }
+      grd.addColorStop(0, hexToRgb(roseOption.customColor[eachSeries.linearIndex], 1))
+      grd.addColorStop(1, hexToRgb(eachSeries.color, 1))
+      fillcolor = grd
+    }
+    context.setFillStyle(fillcolor);
+    context.moveTo(centerPosition.x, centerPosition.y);
+    context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._rose_proportion_ * Math.PI);
+    context.closePath();
+    context.fill();
+    if (roseOption.border == true) {
+      context.stroke();
+    }
+  });
+
+  if (opts.dataLabel !== false && process === 1) {
+    drawPieText(series, opts, config, context, radius, centerPosition);
+  }
+  return {
+    center: centerPosition,
+    radius: radius,
+    series: series
+  };
+}
+
+function drawArcbarDataPoints(series, opts, config, context) {
+  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  var arcbarOption = assign({}, {
+    startAngle: 0.75,
+    endAngle: 0.25,
+    type: 'default',
+    direction: 'cw',
+    lineCap: 'round',
+    width: 12 ,
+    gap: 2 ,
+    linearType: 'none',
+    customColor: [],
+  }, opts.extra.arcbar);
+  series = getArcbarDataPoints(series, arcbarOption, process);
+  var centerPosition;
+  if (arcbarOption.centerX || arcbarOption.centerY) {
+    centerPosition = {
+      x: arcbarOption.centerX ? arcbarOption.centerX : opts.width / 2,
+      y: arcbarOption.centerY ? arcbarOption.centerY : opts.height / 2
+    };
+  } else {
+    centerPosition = {
+      x: opts.width / 2,
+      y: opts.height / 2
+    };
+  }
+  var radius;
+  if (arcbarOption.radius) {
+    radius = arcbarOption.radius;
+  } else {
+    radius = Math.min(centerPosition.x, centerPosition.y);
+    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++) {
+    let eachSeries = series[i];
+    //背景颜色
+    context.setLineWidth(arcbarOption.width * opts.pix);
+    context.setStrokeStyle(arcbarOption.backgroundColor || '#E9E9E9');
+    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, arcbarOption.direction == 'ccw');
+    } else {
+      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();
+    //进度条
+    var fillColor = eachSeries.color
+    if(arcbarOption.linearType == 'custom'){
+      var grd = context.createLinearGradient(centerPosition.x - radius, centerPosition.y, centerPosition.x + radius, centerPosition.y);
+      grd.addColorStop(1, hexToRgb(arcbarOption.customColor[eachSeries.linearIndex], 1))
+      grd.addColorStop(0, hexToRgb(eachSeries.color, 1))
+      fillColor = grd;
+    }
+    context.setLineWidth(arcbarOption.width * opts.pix);
+    context.setStrokeStyle(fillColor);
+    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, arcbarOption.direction == 'ccw');
+    context.stroke();
+  }
+  drawRingTitle(opts, config, context, centerPosition);
+  return {
+    center: centerPosition,
+    radius: radius,
+    series: series
+  };
+}
+
+function drawGaugeDataPoints(categories, series, opts, config, context) {
+  var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
+  var gaugeOption = assign({}, {
+    type: 'default',
+    startAngle: 0.75,
+    endAngle: 0.25,
+    width: 15,
+    labelOffset:13,
+    splitLine: {
+      fixRadius: 0,
+      splitNumber: 10,
+      width: 15,
+      color: '#FFFFFF',
+      childNumber: 5,
+      childWidth: 5
+    },
+    pointer: {
+      width: 15,
+      color: 'auto'
+    }
+  }, opts.extra.gauge);
+  if (gaugeOption.oldAngle == undefined) {
+    gaugeOption.oldAngle = gaugeOption.startAngle;
+  }
+  if (gaugeOption.oldData == undefined) {
+    gaugeOption.oldData = 0;
+  }
+  categories = getGaugeAxisPoints(categories, gaugeOption.startAngle, gaugeOption.endAngle);
+  var centerPosition = {
+    x: opts.width / 2,
+    y: opts.height / 2
+  };
+  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新样式
+  if (gaugeOption.type == 'progress') {
+    //## 第一步画中心圆形背景和进度条背景
+    //中心圆形背景
+    var pieRadius = radius - gaugeOption.width * 3;
+    context.beginPath();
+    let gradient = context.createLinearGradient(centerPosition.x, centerPosition.y - pieRadius, centerPosition.x, centerPosition.y + pieRadius);
+    //配置渐变填充(起点:中心点向上减半径;结束点中心点向下加半径)
+    gradient.addColorStop('0', hexToRgb(series[0].color, 0.3));
+    gradient.addColorStop('1.0', hexToRgb("#FFFFFF", 0.1));
+    context.setFillStyle(gradient);
+    context.arc(centerPosition.x, centerPosition.y, pieRadius, 0, 2 * Math.PI, false);
+    context.fill();
+    //画进度条背景
+    context.setLineWidth(gaugeOption.width);
+    context.setStrokeStyle(hexToRgb(series[0].color, 0.3));
+    context.setLineCap('round');
+    context.beginPath();
+    context.arc(centerPosition.x, centerPosition.y, innerRadius, gaugeOption.startAngle * Math.PI, gaugeOption.endAngle * Math.PI, false);
+    context.stroke();
+    //## 第二步画刻度线
+    if (gaugeOption.endAngle < gaugeOption.startAngle) {
+      totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle;
+    } else {
+      totalAngle = gaugeOption.startAngle - gaugeOption.endAngle;
+    }
+    let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
+    let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber;
+    let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius;
+    let endX = -radius - gaugeOption.width - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width;
+    context.save();
+    context.translate(centerPosition.x, centerPosition.y);
+    context.rotate((gaugeOption.startAngle - 1) * Math.PI);
+    let len = gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1;
+    let proc = series[0].data * process;
+    for (let i = 0; i < len; i++) {
+      context.beginPath();
+      //刻度线随进度变色
+      if (proc > (i / len)) {
+        context.setStrokeStyle(hexToRgb(series[0].color, 1));
+      } else {
+        context.setStrokeStyle(hexToRgb(series[0].color, 0.3));
+      }
+      context.setLineWidth(3 * opts.pix);
+      context.moveTo(startX, 0);
+      context.lineTo(endX, 0);
+      context.stroke();
+      context.rotate(childAngle * Math.PI);
+    }
+    context.restore();
+    //## 第三步画进度条
+    series = getGaugeArcbarDataPoints(series, gaugeOption, process);
+    context.setLineWidth(gaugeOption.width);
+    context.setStrokeStyle(series[0].color);
+    context.setLineCap('round');
+    context.beginPath();
+    context.arc(centerPosition.x, centerPosition.y, innerRadius, gaugeOption.startAngle * Math.PI, series[0]._proportion_ * Math.PI, false);
+    context.stroke();
+    //## 第四步画指针
+    let pointerRadius = radius - gaugeOption.width * 2.5;
+    context.save();
+    context.translate(centerPosition.x, centerPosition.y);
+    context.rotate((series[0]._proportion_ - 1) * Math.PI);
+    context.beginPath();
+    context.setLineWidth(gaugeOption.width / 3);
+    let gradient3 = context.createLinearGradient(0, -pointerRadius * 0.6, 0, pointerRadius * 0.6);
+    gradient3.addColorStop('0', hexToRgb('#FFFFFF', 0));
+    gradient3.addColorStop('0.5', hexToRgb(series[0].color, 1));
+    gradient3.addColorStop('1.0', hexToRgb('#FFFFFF', 0));
+    context.setStrokeStyle(gradient3);
+    context.arc(0, 0, pointerRadius, 0.85 * Math.PI, 1.15 * Math.PI, false);
+    context.stroke();
+    context.beginPath();
+    context.setLineWidth(1);
+    context.setStrokeStyle(series[0].color);
+    context.setFillStyle(series[0].color);
+    context.moveTo(-pointerRadius - gaugeOption.width / 3 / 2, -4);
+    context.lineTo(-pointerRadius - gaugeOption.width / 3 / 2 - 4, 0);
+    context.lineTo(-pointerRadius - gaugeOption.width / 3 / 2, 4);
+    context.lineTo(-pointerRadius - gaugeOption.width / 3 / 2, -4);
+    context.stroke();
+    context.fill();
+    context.restore();
+    //default百度样式
+  } else {
+    //画背景
+    context.setLineWidth(gaugeOption.width);
+    context.setLineCap('butt');
+    for (let i = 0; i < categories.length; i++) {
+      let eachCategories = categories[i];
+      context.beginPath();
+      context.setStrokeStyle(eachCategories.color);
+      context.arc(centerPosition.x, centerPosition.y, radius, eachCategories._startAngle_ * Math.PI, eachCategories._endAngle_ * Math.PI, false);
+      context.stroke();
+    }
+    context.save();
+    //画刻度线
+    if (gaugeOption.endAngle < gaugeOption.startAngle) {
+      totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle;
+    } else {
+      totalAngle = gaugeOption.startAngle - gaugeOption.endAngle;
+    }
+    let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
+    let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber;
+    let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius;
+    let endX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width;
+    let childendX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.childWidth;
+    context.translate(centerPosition.x, centerPosition.y);
+    context.rotate((gaugeOption.startAngle - 1) * Math.PI);
+    for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) {
+      context.beginPath();
+      context.setStrokeStyle(gaugeOption.splitLine.color);
+      context.setLineWidth(2 * opts.pix);
+      context.moveTo(startX, 0);
+      context.lineTo(endX, 0);
+      context.stroke();
+      context.rotate(splitAngle * Math.PI);
+    }
+    context.restore();
+    context.save();
+    context.translate(centerPosition.x, centerPosition.y);
+    context.rotate((gaugeOption.startAngle - 1) * Math.PI);
+    for (let i = 0; i < gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1; i++) {
+      context.beginPath();
+      context.setStrokeStyle(gaugeOption.splitLine.color);
+      context.setLineWidth(1 * opts.pix);
+      context.moveTo(startX, 0);
+      context.lineTo(childendX, 0);
+      context.stroke();
+      context.rotate(childAngle * Math.PI);
+    }
+    context.restore();
+    //画指针
+    series = getGaugeDataPoints(series, categories, gaugeOption, process);
+    for (let i = 0; i < series.length; i++) {
+      let eachSeries = series[i];
+      context.save();
+      context.translate(centerPosition.x, centerPosition.y);
+      context.rotate((eachSeries._proportion_ - 1) * Math.PI);
+      context.beginPath();
+      context.setFillStyle(eachSeries.color);
+      context.moveTo(gaugeOption.pointer.width, 0);
+      context.lineTo(0, -gaugeOption.pointer.width / 2);
+      context.lineTo(-innerRadius, 0);
+      context.lineTo(0, gaugeOption.pointer.width / 2);
+      context.lineTo(gaugeOption.pointer.width, 0);
+      context.closePath();
+      context.fill();
+      context.beginPath();
+      context.setFillStyle('#FFFFFF');
+      context.arc(0, 0, gaugeOption.pointer.width / 6, 0, 2 * Math.PI, false);
+      context.fill();
+      context.restore();
+    }
+    if (opts.dataLabel !== false) {
+      drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context);
+    }
+  }
+  //画仪表盘标题,副标题
+  drawRingTitle(opts, config, context, centerPosition);
+  if (process === 1 && opts.type === 'gauge') {
+    opts.extra.gauge.oldAngle = series[0]._proportion_;
+    opts.extra.gauge.oldData = series[0].data;
+  }
+  return {
+    center: centerPosition,
+    radius: radius,
+    innerRadius: innerRadius,
+    categories: categories,
+    totalAngle: totalAngle
+  };
+}
+
+function drawRadarDataPoints(series, opts, config, context) {
+  var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  var radarOption = assign({}, {
+    gridColor: '#cccccc',
+    gridType: 'radar',
+    gridEval:1,
+    axisLabel:false,
+    axisLabelTofix:0,
+    labelShow:true,
+    labelColor:'#666666',
+    labelPointShow:false,
+    labelPointRadius:3,
+    labelPointColor:'#cccccc',
+    opacity: 0.2,
+    gridCount: 3,
+    border:false,
+    borderWidth:2,
+    linearType: 'none',
+    customColor: [],
+  }, opts.extra.radar);
+  var coordinateAngle = getRadarCoordinateSeries(opts.categories.length);
+  var centerPosition = {
+    x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+    y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
+  };
+  var xr = (opts.width - opts.area[1] - opts.area[3]) / 2
+  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;
+  radius = radarOption.radius ? radarOption.radius : radius;
+  // 画分割线
+  context.beginPath();
+  context.setLineWidth(1 * opts.pix);
+  context.setStrokeStyle(radarOption.gridColor);
+  coordinateAngle.forEach(function(angle,index) {
+    var pos = convertCoordinateOrigin(radius * Math.cos(angle), radius * Math.sin(angle), centerPosition);
+    context.moveTo(centerPosition.x, centerPosition.y);
+    if (index % radarOption.gridEval == 0) {
+      context.lineTo(pos.x, pos.y);
+    }
+  });
+  context.stroke();
+  context.closePath();
+  
+  // 画背景网格
+  var _loop = function _loop(i) {
+    var startPos = {};
+    context.beginPath();
+    context.setLineWidth(1 * opts.pix);
+    context.setStrokeStyle(radarOption.gridColor);
+    if (radarOption.gridType == 'radar') {
+      coordinateAngle.forEach(function(angle, index) {
+        var pos = convertCoordinateOrigin(radius / radarOption.gridCount * i * Math.cos(angle), radius /
+          radarOption.gridCount * i * Math.sin(angle), centerPosition);
+        if (index === 0) {
+          startPos = pos;
+          context.moveTo(pos.x, pos.y);
+        } else {
+          context.lineTo(pos.x, pos.y);
+        }
+      });
+      context.lineTo(startPos.x, startPos.y);
+    } else {
+      var pos = convertCoordinateOrigin(radius / radarOption.gridCount * i * Math.cos(1.5), radius / radarOption.gridCount * i * Math.sin(1.5), centerPosition);
+      context.arc(centerPosition.x, centerPosition.y, centerPosition.y - pos.y, 0, 2 * Math.PI, false);
+    }
+    context.stroke();
+    context.closePath();
+  };
+  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);
+    
+    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);
+      } else {
+        context.lineTo(item.position.x, item.position.y);
+      }
+    });
+    context.closePath();
+    context.fill();
+    if(radarOption.border === true){
+      context.stroke();
+    }
+    context.closePath();
+    if (opts.dataPointShape !== false) {
+      var points = eachSeries.data.map(function(item) {
+        return item.position;
+      });
+      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);
+  
+  // draw dataLabel
+  if (opts.dataLabel !== false && process === 1) {
+    radarDataPoints.forEach(function(eachSeries, seriesIndex) {
+      context.beginPath();
+      var fontSize = eachSeries.textSize * opts.pix || config.fontSize;
+      context.setFontSize(fontSize);
+      context.setFillStyle(eachSeries.textColor || opts.fontColor);
+      eachSeries.data.forEach(function(item, index) {
+        //如果是中心点垂直的上下点位
+        if(Math.abs(item.position.x - centerPosition.x)<2){
+          //如果在上面
+          if(item.position.y < centerPosition.y){
+            context.setTextAlign('center');
+            context.fillText(item.value, item.position.x, item.position.y - 4);
+          }else{
+            context.setTextAlign('center');
+            context.fillText(item.value, item.position.x, item.position.y + fontSize + 2);
+          }
+        }else{
+          //如果在左侧
+          if(item.position.x < centerPosition.x){
+            context.setTextAlign('right');
+            context.fillText(item.value, item.position.x - 4, item.position.y + fontSize / 2 - 2);
+          }else{
+            context.setTextAlign('left');
+            context.fillText(item.value, item.position.x + 4, item.position.y + fontSize / 2 - 2);
+          }
+        }
+      });
+      context.closePath();
+      context.stroke();
+    });
+    context.setTextAlign('left');
+  }
+  
+  return {
+    center: centerPosition,
+    radius: radius,
+    angleList: coordinateAngle
+  };
+}
+
+// 经纬度转墨卡托
+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;
+}
+
+function getBoundingBox(data) {
+  var bounds = {},coords;
+  bounds.xMin = 180;
+  bounds.xMax = 0;
+  bounds.yMin = 90;
+  bounds.yMax = 0
+  for (var i = 0; i < data.length; i++) {
+    var coorda = data[i].geometry.coordinates
+    for (var k = 0; k < coorda.length; k++) {
+      coords = coorda[k];
+      if (coords.length == 1) {
+        coords = coords[0]
+      }
+      for (var j = 0; j < coords.length; j++) {
+        var longitude = coords[j][0];
+        var latitude = coords[j][1];
+        var point = {
+          x: longitude,
+          y: latitude
+        }
+        bounds.xMin = bounds.xMin < point.x ? bounds.xMin : point.x;
+        bounds.xMax = bounds.xMax > point.x ? bounds.xMax : point.x;
+        bounds.yMin = bounds.yMin < point.y ? bounds.yMin : point.y;
+        bounds.yMax = bounds.yMax > point.y ? bounds.yMax : point.y;
+      }
+    }
+  }
+  return bounds;
+}
+
+function coordinateToPoint(latitude, longitude, bounds, scale, xoffset, yoffset) {
+  return {
+    x: (longitude - bounds.xMin) * scale + xoffset,
+    y: (bounds.yMax - latitude) * scale + yoffset
+  };
+}
+
+function pointToCoordinate(pointY, pointX, bounds, scale, xoffset, yoffset) {
+  return {
+    x: (pointX - xoffset) / scale + bounds.xMin,
+    y: bounds.yMax - (pointY - yoffset) / scale
+  };
+}
+
+function isRayIntersectsSegment(poi, s_poi, e_poi) {
+  if (s_poi[1] == e_poi[1]) {
+    return false;
+  }
+  if (s_poi[1] > poi[1] && e_poi[1] > poi[1]) {
+    return false;
+  }
+  if (s_poi[1] < poi[1] && e_poi[1] < poi[1]) {
+    return false;
+  }
+  if (s_poi[1] == poi[1] && e_poi[1] > poi[1]) {
+    return false;
+  }
+  if (e_poi[1] == poi[1] && s_poi[1] > poi[1]) {
+    return false;
+  }
+  if (s_poi[0] < poi[0] && e_poi[1] < poi[1]) {
+    return false;
+  }
+  let xseg = e_poi[0] - (e_poi[0] - s_poi[0]) * (e_poi[1] - poi[1]) / (e_poi[1] - s_poi[1]);
+  if (xseg < poi[0]) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
+function isPoiWithinPoly(poi, poly, mercator) {
+  let sinsc = 0;
+  for (let i = 0; i < poly.length; i++) {
+    let epoly = poly[i][0];
+    if (poly.length == 1) {
+      epoly = poly[i][0]
+    }
+    for (let j = 0; j < epoly.length - 1; j++) {
+      let s_poi = epoly[j];
+      let e_poi = epoly[j + 1];
+      if (mercator) {
+        s_poi = lonlat2mercator(epoly[j][0], epoly[j][1]);
+        e_poi = lonlat2mercator(epoly[j + 1][0], epoly[j + 1][1]);
+      }
+      if (isRayIntersectsSegment(poi, s_poi, e_poi)) {
+        sinsc += 1;
+      }
+    }
+  }
+  if (sinsc % 2 == 1) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+function drawMapDataPoints(series, opts, config, context) {
+  var mapOption = assign({}, {
+    border: true,
+    mercator: false,
+    borderWidth: 1,
+    active:true,
+    borderColor: '#666666',
+    fillOpacity: 0.6,
+    activeBorderColor: '#f04864',
+    activeFillColor: '#facc14',
+    activeFillOpacity: 1
+  }, opts.extra.map);
+  var coords, point;
+  var data = series;
+  var bounds = getBoundingBox(data);
+  if (mapOption.mercator) {
+    var max = lonlat2mercator(bounds.xMax, bounds.yMax)
+    var min = lonlat2mercator(bounds.xMin, bounds.yMin)
+    bounds.xMax = max[0]
+    bounds.yMax = max[1]
+    bounds.xMin = min[0]
+    bounds.yMin = min[1]
+  }
+  var xScale = opts.width / Math.abs(bounds.xMax - bounds.xMin);
+  var yScale = opts.height / Math.abs(bounds.yMax - bounds.yMin);
+  var scale = xScale < yScale ? xScale : yScale;
+  var xoffset = opts.width / 2 - Math.abs(bounds.xMax - bounds.xMin) / 2 * scale;
+  var yoffset = opts.height / 2 - Math.abs(bounds.yMax - bounds.yMin) / 2 * scale;
+  for (var i = 0; i < data.length; i++) {
+    context.beginPath();
+    context.setLineWidth(mapOption.borderWidth * opts.pix);
+    context.setStrokeStyle(mapOption.borderColor);
+    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));
+      }
+    }
+    var coorda = data[i].geometry.coordinates
+    for (var k = 0; k < coorda.length; k++) {
+      coords = coorda[k];
+      if (coords.length == 1) {
+        coords = coords[0]
+      }
+      for (var j = 0; j < coords.length; j++) {
+        var gaosi = Array(2);
+        if (mapOption.mercator) {
+          gaosi = lonlat2mercator(coords[j][0], coords[j][1])
+        } else {
+          gaosi = coords[j]
+        }
+        point = coordinateToPoint(gaosi[1], gaosi[0], bounds, scale, xoffset, yoffset)
+        if (j === 0) {
+          context.beginPath();
+          context.moveTo(point.x, point.y);
+        } else {
+          context.lineTo(point.x, point.y);
+        }
+      }
+      context.fill();
+      if (mapOption.border == true) {
+        context.stroke();
+      }
+    }
+  }
+  if (opts.dataLabel == true) {
+    for (var i = 0; i < data.length; i++) {
+      var centerPoint = data[i].properties.centroid;
+      if (centerPoint) {
+        if (mapOption.mercator) {
+          centerPoint = lonlat2mercator(data[i].properties.centroid[0], data[i].properties.centroid[1])
+        }
+        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(fontColor)
+        context.fillText(text, point.x - measureText(text, fontSize, context) / 2, point.y + fontSize / 2);
+        context.closePath();
+        context.stroke();
+      }
+    }
+  }
+  opts.chartData.mapData = {
+    bounds: bounds,
+    scale: scale,
+    xoffset: xoffset,
+    yoffset: yoffset,
+    mercator: mapOption.mercator
+  }
+  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;
+  switch (type) {
+    case 'normal':
+      for (let i = 0; i < points.length; i++) {
+        let text = points[i].name;
+        let tHeight = points[i].textSize * opts.pix;
+        let tWidth = measureText(text, tHeight, context);
+        let x, y;
+        let area;
+        let breaknum = 0;
+        while (true) {
+          breaknum++;
+          x = normalInt(-opts.width / 2, opts.width / 2, 5) - tWidth / 2;
+          y = normalInt(-opts.height / 2, opts.height / 2, 5) + tHeight / 2;
+          area = [x - 5 + opts.width / 2, y - 5 - tHeight + opts.height / 2, x + tWidth + 5 + opts.width / 2, y + 5 +
+            opts.height / 2
+          ];
+          let isCollision = collisionNew(area, points, opts.width, opts.height);
+          if (!isCollision) break;
+          if (breaknum == 1000) {
+            area = [-100, -100, -100, -100];
+            break;
+          }
+        };
+        points[i].area = area;
+      }
+      break;
+    case 'vertical':
+      function Spin() {
+        //获取均匀随机值,是否旋转,旋转的概率为(1-0.5)
+        if (Math.random() > 0.7) {
+          return true;
+        } else {
+          return false
+        };
+      };
+      for (let i = 0; i < points.length; i++) {
+        let text = points[i].name;
+        let tHeight = points[i].textSize * opts.pix;
+        let tWidth = measureText(text, tHeight, context);
+        let isSpin = Spin();
+        let x, y, area, areav;
+        let breaknum = 0;
+        while (true) {
+          breaknum++;
+          let isCollision;
+          if (isSpin) {
+            x = normalInt(-opts.width / 2, opts.width / 2, 5) - tWidth / 2;
+            y = normalInt(-opts.height / 2, opts.height / 2, 5) + tHeight / 2;
+            area = [y - 5 - tWidth + opts.width / 2, (-x - 5 + opts.height / 2), y + 5 + opts.width / 2, (-x + tHeight + 5 + opts.height / 2)];
+            areav = [opts.width - (opts.width / 2 - opts.height / 2) - (-x + tHeight + 5 + opts.height / 2) - 5, (opts.height / 2 - opts.width / 2) + (y - 5 - tWidth + opts.width / 2) - 5, opts.width - (opts.width / 2 - opts.height / 2) - (-x + tHeight + 5 + opts.height / 2) + tHeight, (opts.height / 2 - opts.width / 2) + (y - 5 - tWidth + opts.width / 2) + tWidth + 5];
+            isCollision = collisionNew(areav, points, opts.height, opts.width);
+          } else {
+            x = normalInt(-opts.width / 2, opts.width / 2, 5) - tWidth / 2;
+            y = normalInt(-opts.height / 2, opts.height / 2, 5) + tHeight / 2;
+            area = [x - 5 + opts.width / 2, y - 5 - tHeight + opts.height / 2, x + tWidth + 5 + opts.width / 2, y + 5 + opts.height / 2];
+            isCollision = collisionNew(area, points, opts.width, opts.height);
+          }
+          if (!isCollision) break;
+          if (breaknum == 1000) {
+            area = [-1000, -1000, -1000, -1000];
+            break;
+          }
+        };
+        if (isSpin) {
+          points[i].area = areav;
+          points[i].areav = area;
+        } else {
+          points[i].area = area;
+        }
+        points[i].rotate = isSpin;
+      };
+      break;
+  }
+  return points;
+}
+
+function drawWordCloudDataPoints(series, opts, config, context) {
+  let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  let wordOption = assign({}, {
+    type: 'normal',
+    autoColors: true
+  }, opts.extra.word);
+  if (!opts.chartData.wordCloudData) {
+    opts.chartData.wordCloudData = getWordCloudPoint(opts, wordOption.type, context);
+  }
+  context.beginPath();
+  context.setFillStyle(opts.background);
+  context.rect(0, 0, opts.width, opts.height);
+  context.fill();
+  context.save();
+  let points = opts.chartData.wordCloudData;
+  context.translate(opts.width / 2, opts.height / 2);
+  for (let i = 0; i < points.length; i++) {
+    context.save();
+    if (points[i].rotate) {
+      context.rotate(90 * Math.PI / 180);
+    }
+    let text = points[i].name;
+    let tHeight = points[i].textSize * opts.pix;
+    let tWidth = measureText(text, tHeight, context);
+    context.beginPath();
+    context.setStrokeStyle(points[i].color);
+    context.setFillStyle(points[i].color);
+    context.setFontSize(tHeight);
+    if (points[i].rotate) {
+      if (points[i].areav[0] > 0) {
+        if (opts.tooltip) {
+          if (opts.tooltip.index == i) {
+            context.strokeText(text, (points[i].areav[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].areav[1] + 5 + tHeight - opts.height / 2) * process);
+          } else {
+            context.fillText(text, (points[i].areav[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].areav[1] + 5 + tHeight - opts.height / 2) * process);
+          }
+        } else {
+          context.fillText(text, (points[i].areav[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].areav[1] + 5 + tHeight - opts.height / 2) * process);
+        }
+      }
+    } else {
+      if (points[i].area[0] > 0) {
+        if (opts.tooltip) {
+          if (opts.tooltip.index == i) {
+            context.strokeText(text, (points[i].area[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].area[1] + 5 + tHeight - opts.height / 2) * process);
+          } else {
+            context.fillText(text, (points[i].area[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].area[1] + 5 + tHeight - opts.height / 2) * process);
+          }
+        } else {
+          context.fillText(text, (points[i].area[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].area[1] + 5 + tHeight - opts.height / 2) * process);
+        }
+      }
+    }
+    context.stroke();
+    context.restore();
+  }
+  context.restore();
+}
+
+function drawFunnelDataPoints(series, opts, config, context) {
+  let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
+  let funnelOption = assign({}, {
+    type:'funnel',
+    activeWidth: 10,
+    activeOpacity: 0.3,
+    border: false,
+    borderWidth: 2,
+    borderColor: '#FFFFFF',
+    fillOpacity: 1,
+    minSize: 0,
+    labelAlign: 'right',
+    linearType: 'none',
+    customColor: [],
+  }, opts.extra.funnel);
+  let eachSpacing = (opts.height - opts.area[0] - opts.area[2]) / series.length;
+  let centerPosition = {
+    x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
+    y: opts.height - opts.area[2]
+  };
+  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);
+  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 < seriesNew.length; i++) {
+      if (i == seriesNew.length -1) {
+        if (opts.tooltip) {
+          if (opts.tooltip.index == i) {
+            context.beginPath();
+            context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
+            context.moveTo(-activeWidth, -eachSpacing);
+            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();
+          }
+        }
+        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(seriesNew[i].color, funnelOption.fillOpacity);
+        if (funnelOption.linearType == 'custom') {
+          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(-seriesNew[i].radius, 0);
+        context.lineTo(seriesNew[i].radius, 0);
+        context.lineTo(0, -eachSpacing);
+        context.closePath();
+        context.fill();
+        if (funnelOption.border == true) {
+          context.stroke();
+        }
+      } else {
+        if (opts.tooltip) {
+          if (opts.tooltip.index == i) {
+            context.beginPath();
+            context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
+            context.moveTo(0, 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();
+          }
+        }
+        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(seriesNew[i].color, funnelOption.fillOpacity);
+        if (funnelOption.linearType == 'custom') {
+          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(-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();
+        if (funnelOption.border == true) {
+          context.stroke();
+        }
+      }
+      context.translate(0, -eachSpacing)
+    }
+  }else{
+    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(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();
+          }
+        }
+        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(seriesNew[i].color, funnelOption.fillOpacity);
+        if (funnelOption.linearType == 'custom') {
+          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(-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();
+        if (funnelOption.border == true) {
+          context.stroke();
+        }
+      } else {
+        if (opts.tooltip) {
+          if (opts.tooltip.index == i) {
+            context.beginPath();
+            context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
+            context.moveTo(0, 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();
+          }
+        }
+        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(seriesNew[i].color, funnelOption.fillOpacity);
+        if (funnelOption.linearType == 'custom') {
+          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(-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();
+        if (funnelOption.border == true) {
+          context.stroke();
+        }
+      }
+      context.translate(0, eachSpacing)
+    }
+  }
+  
+  context.restore();
+  if (opts.dataLabel !== false && process === 1) {
+    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: 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,opts) : util.toFixed(item._proportion_ * 100) + '%';
+    text = item.labelText ? item.labelText : text;
+    if (labelAlign == 'right') {
+      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;
+      fontSize = item.textSize * opts.pix || opts.fontSize * opts.pix;
+      context.setLineWidth(1 * opts.pix);
+      context.setStrokeStyle(item.color);
+      context.setFillStyle(item.color);
+      context.beginPath();
+      context.moveTo(startX, startY);
+      context.lineTo(endX, startY);
+      context.stroke();
+      context.closePath();
+      context.beginPath();
+      context.moveTo(endX, startY);
+      context.arc(endX, startY, 2 * opts.pix, 0, 2 * Math.PI);
+      context.closePath();
+      context.fill();
+      context.beginPath();
+      context.setFontSize(fontSize);
+      context.setFillStyle(item.textColor || opts.fontColor);
+      context.fillText(text, endX + 5, startY + fontSize / 2 - 2);
+      context.closePath();
+      context.stroke();
+      context.closePath();
+    }
+    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;
+      fontSize = item.textSize * opts.pix || opts.fontSize * opts.pix;
+      context.setLineWidth(1 * opts.pix);
+      context.setStrokeStyle(item.color);
+      context.setFillStyle(item.color);
+      context.beginPath();
+      context.moveTo(startX, startY);
+      context.lineTo(endX, startY);
+      context.stroke();
+      context.closePath();
+      context.beginPath();
+      context.moveTo(endX, startY);
+      context.arc(endX, startY, 2, 0, 2 * Math.PI);
+      context.closePath();
+      context.fill();
+      context.beginPath();
+      context.setFontSize(fontSize);
+      context.setFillStyle(item.textColor || opts.fontColor);
+      context.fillText(text, endX - 5 - measureText(text, fontSize, context), startY + fontSize / 2 - 2);
+      context.closePath();
+      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.save();
+  context.translate(0, 0.5);
+  context.restore();
+  context.draw();
+}
+
+var Timing = {
+  easeIn: function easeIn(pos) {
+    return Math.pow(pos, 3);
+  },
+  easeOut: function easeOut(pos) {
+    return Math.pow(pos - 1, 3) + 1;
+  },
+  easeInOut: function easeInOut(pos) {
+    if ((pos /= 0.5) < 1) {
+      return 0.5 * Math.pow(pos, 3);
+    } else {
+      return 0.5 * (Math.pow(pos - 2, 3) + 2);
+    }
+  },
+  linear: function linear(pos) {
+    return pos;
+  }
+};
+
+function Animation(opts) {
+  this.isStop = false;
+  opts.duration = typeof opts.duration === 'undefined' ? 1000 : opts.duration;
+  opts.timing = opts.timing || 'easeInOut';
+  var delay = 17;
+  function createAnimationFrame() {
+    if (typeof setTimeout !== 'undefined') {
+      return function(step, delay) {
+        setTimeout(function() {
+          var timeStamp = +new Date();
+          step(timeStamp);
+        }, delay);
+      };
+    } else if (typeof requestAnimationFrame !== 'undefined') {
+      return requestAnimationFrame;
+    } else {
+      return function(step) {
+        step(null);
+      };
+    }
+  };
+  var animationFrame = createAnimationFrame();
+  var startTimeStamp = null;
+  var _step = function step(timestamp) {
+    if (timestamp === null || this.isStop === true) {
+      opts.onProcess && opts.onProcess(1);
+      opts.onAnimationFinish && opts.onAnimationFinish();
+      return;
+    }
+    if (startTimeStamp === null) {
+      startTimeStamp = timestamp;
+    }
+    if (timestamp - startTimeStamp < opts.duration) {
+      var process = (timestamp - startTimeStamp) / opts.duration;
+      var timingFunction = Timing[opts.timing];
+      process = timingFunction(process);
+      opts.onProcess && opts.onProcess(process);
+      animationFrame(_step, delay);
+    } else {
+      opts.onProcess && opts.onProcess(1);
+      opts.onAnimationFinish && opts.onAnimationFinish();
+    }
+  };
+  _step = _step.bind(this);
+  animationFrame(_step, delay);
+}
+
+Animation.prototype.stop = function() {
+  this.isStop = true;
+};
+
+function drawCharts(type, opts, config, context) {
+  var _this = this;
+  var series = opts.series;
+  //兼容ECharts饼图类数据格式
+  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();
+  var seriesMA = null;
+  if (type == 'candle') {
+    let average = assign({}, opts.extra.candle.average);
+    if (average.show) {
+      seriesMA = calCandleMA(average.day, average.name, average.color, series[0].data);
+      seriesMA = fillSeries(seriesMA, opts, config);
+      opts.seriesMA = seriesMA;
+    } else if (opts.seriesMA) {
+      seriesMA = opts.seriesMA = fillSeries(opts.seriesMA, opts, config);
+    } else {
+      seriesMA = series;
+    }
+  } else {
+    seriesMA = series;
+  }
+  /* 过滤掉show=false的series */
+  opts._series_ = series = filterSeries(series);
+  //重新计算图表区域
+  opts.area = new Array(4);
+  //复位绘图区域
+  for (let j = 0; j < 4; j++) {
+    opts.area[j] = opts.padding[j] * opts.pix;
+  }
+  //通过计算三大区域:图例、X轴、Y轴的大小,确定绘图区域
+  var _calLegendData = calLegendData(seriesMA, opts, config, opts.chartData, context),
+    legendHeight = _calLegendData.area.wholeHeight,
+    legendWidth = _calLegendData.area.wholeWidth;
+
+  switch (opts.legend.position) {
+    case 'top':
+      opts.area[0] += legendHeight;
+      break;
+    case 'bottom':
+      opts.area[2] += legendHeight;
+      break;
+    case 'left':
+      opts.area[3] += legendWidth;
+      break;
+    case 'right':
+      opts.area[1] += legendWidth;
+      break;
+  }
+
+  let _calYAxisData = {},
+    yAxisWidth = 0;
+  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轴标题
+    if (opts.yAxis.showTitle) {
+      let maxTitleHeight = 0;
+      for (let i = 0; i < opts.yAxis.data.length; i++) {
+        maxTitleHeight = Math.max(maxTitleHeight, opts.yAxis.data[i].titleFontSize ? opts.yAxis.data[i].titleFontSize * opts.pix : config.fontSize)
+      }
+      opts.area[0] += maxTitleHeight;
+    }
+    let rightIndex = 0,
+      leftIndex = 0;
+    //计算主绘图区域左右位置
+    for (let i = 0; i < yAxisWidth.length; i++) {
+      if (yAxisWidth[i].position == 'left') {
+        if (leftIndex > 0) {
+          opts.area[3] += yAxisWidth[i].width + opts.yAxis.padding * opts.pix;
+        } else {
+          opts.area[3] += yAxisWidth[i].width;
+        }
+        leftIndex += 1;
+      } else if (yAxisWidth[i].position == 'right') {
+        if (rightIndex > 0) {
+          opts.area[1] += yAxisWidth[i].width + opts.yAxis.padding * opts.pix;
+        } else {
+          opts.area[1] += yAxisWidth[i].width;
+        }
+        rightIndex += 1;
+      }
+    }
+  } else {
+    config.yAxisWidth = yAxisWidth;
+  }
+  opts.chartData.yAxisData = _calYAxisData;
+
+  if (opts.categories && opts.categories.length && opts.type !== 'radar' && opts.type !== 'gauge' && opts.type !== 'bar') {
+    opts.chartData.xAxisData = getXAxisPoints(opts.categories, opts, config);
+    let _calCategoriesData = calCategoriesData(opts.categories, opts, config, opts.chartData.xAxisData.eachSpacing, context),
+      xAxisHeight = _calCategoriesData.xAxisHeight,
+      angle = _calCategoriesData.angle;
+    config.xAxisHeight = xAxisHeight;
+    config._xAxisTextAngle_ = angle;
+    opts.area[2] += xAxisHeight;
+    opts.chartData.categoriesData = _calCategoriesData;
+  } else {
+    if (opts.type === 'line' || opts.type === 'area' || opts.type === 'scatter' || opts.type === 'bubble' || opts.type === 'bar') {
+      opts.chartData.xAxisData = calXAxisData(series, opts, config, context);
+      categories = opts.chartData.xAxisData.rangesFormat;
+      let _calCategoriesData = calCategoriesData(categories, opts, config, opts.chartData.xAxisData.eachSpacing, context),
+        xAxisHeight = _calCategoriesData.xAxisHeight,
+        angle = _calCategoriesData.angle;
+      config.xAxisHeight = xAxisHeight;
+      config._xAxisTextAngle_ = angle;
+      opts.area[2] += xAxisHeight;
+      opts.chartData.categoriesData = _calCategoriesData;
+    } else {
+      opts.chartData.xAxisData = {
+        xAxisPoints: []
+      };
+    }
+  }
+
+  //计算右对齐偏移距离
+  if (opts.enableScroll && opts.xAxis.scrollAlign == 'right' && opts._scrollDistance_ === undefined) {
+    let offsetLeft = 0,
+      xAxisPoints = opts.chartData.xAxisData.xAxisPoints,
+      startX = opts.chartData.xAxisData.startX,
+      endX = opts.chartData.xAxisData.endX,
+      eachSpacing = opts.chartData.xAxisData.eachSpacing;
+    let totalWidth = eachSpacing * (xAxisPoints.length - 1);
+    let screenWidth = endX - startX;
+    offsetLeft = screenWidth - totalWidth;
+    _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({
+        timing: opts.timing,
+        duration: duration,
+        onProcess: function(process) {
+          context.clearRect(0, 0, opts.width, opts.height);
+          if (opts.rotate) {
+            contextRotate(context, opts);
+          }
+          drawWordCloudDataPoints(series, opts, config, context, process);
+          drawCanvas(opts, context);
+        },
+        onAnimationFinish: function onAnimationFinish() {
+          _this.uevent.trigger('renderComplete');
+        }
+      });
+      break;
+    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({
+        timing: opts.timing,
+        duration: duration,
+        onProcess: function(process) {
+          context.clearRect(0, 0, opts.width, opts.height);
+          if (opts.rotate) {
+            contextRotate(context, opts);
+          }
+          opts.chartData.funnelData = drawFunnelDataPoints(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 'line':
+      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 _drawLineDataPoints = drawLineDataPoints(series, opts, config, context, process),
+            xAxisPoints = _drawLineDataPoints.xAxisPoints,
+            calPoints = _drawLineDataPoints.calPoints,
+            eachSpacing = _drawLineDataPoints.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 'scatter':
+      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 _drawScatterDataPoints = drawScatterDataPoints(series, opts, config, context, process),
+            xAxisPoints = _drawScatterDataPoints.xAxisPoints,
+            calPoints = _drawScatterDataPoints.calPoints,
+            eachSpacing = _drawScatterDataPoints.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 'bubble':
+      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 _drawBubbleDataPoints = drawBubbleDataPoints(series, opts, config, context, process),
+            xAxisPoints = _drawBubbleDataPoints.xAxisPoints,
+            calPoints = _drawBubbleDataPoints.calPoints,
+            eachSpacing = _drawBubbleDataPoints.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 'mix':
+      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 _drawMixDataPoints = drawMixDataPoints(series, opts, config, context, process),
+            xAxisPoints = _drawMixDataPoints.xAxisPoints,
+            calPoints = _drawMixDataPoints.calPoints,
+            eachSpacing = _drawMixDataPoints.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 'column':
+      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 _drawColumnDataPoints = drawColumnDataPoints(series, opts, config, context, process),
+            xAxisPoints = _drawColumnDataPoints.xAxisPoints,
+            calPoints = _drawColumnDataPoints.calPoints,
+            eachSpacing = _drawColumnDataPoints.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 '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,
+        duration: duration,
+        onProcess: function onProcess(process) {
+          context.clearRect(0, 0, opts.width, opts.height);
+          if (opts.rotate) {
+            contextRotate(context, opts);
+          }
+          drawXAxis(categories, opts, config, context);
+          var _drawBarDataPoints = drawBarDataPoints(series, opts, config, context, process),
+            yAxisPoints = _drawBarDataPoints.yAxisPoints,
+            calPoints = _drawBarDataPoints.calPoints,
+            eachSpacing = _drawBarDataPoints.eachSpacing;
+          opts.chartData.yAxisPoints = yAxisPoints;
+          opts.chartData.xAxisPoints = opts.chartData.xAxisData.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, yAxisPoints);
+          drawCanvas(opts, context);
+        },
+        onAnimationFinish: function onAnimationFinish() {
+          _this.uevent.trigger('renderComplete');
+        }
+      });
+      break;
+    case 'area':
+      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 _drawAreaDataPoints = drawAreaDataPoints(series, opts, config, context, process),
+            xAxisPoints = _drawAreaDataPoints.xAxisPoints,
+            calPoints = _drawAreaDataPoints.calPoints,
+            eachSpacing = _drawAreaDataPoints.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 '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,
+        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 'rose':
+      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 = drawRoseDataPoints(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 'radar':
+      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.radarData = drawRadarDataPoints(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 'arcbar':
+      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.arcbarData = drawArcbarDataPoints(series, opts, config, context, process);
+          drawCanvas(opts, context);
+        },
+        onAnimationFinish: function onAnimationFinish() {
+          _this.uevent.trigger('renderComplete');
+        }
+      });
+      break;
+    case 'gauge':
+      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.gaugeData = drawGaugeDataPoints(categories, series, opts, config, context, process);
+          drawCanvas(opts, context);
+        },
+        onAnimationFinish: function onAnimationFinish() {
+          _this.uevent.trigger('renderComplete');
+        }
+      });
+      break;
+    case 'candle':
+      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 _drawCandleDataPoints = drawCandleDataPoints(series, seriesMA, opts, config, context, process),
+            xAxisPoints = _drawCandleDataPoints.xAxisPoints,
+            calPoints = _drawCandleDataPoints.calPoints,
+            eachSpacing = _drawCandleDataPoints.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);
+          }
+          if (seriesMA) {
+            drawLegend(seriesMA, opts, config, context, opts.chartData);
+          } else {
+            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;
+  }
+}
+
+function uChartsEvent() {
+  this.events = {};
+}
+
+uChartsEvent.prototype.addEventListener = function(type, listener) {
+  this.events[type] = this.events[type] || [];
+  this.events[type].push(listener);
+};
+
+uChartsEvent.prototype.delEventListener = function(type) {
+  this.events[type] = [];
+};
+
+uChartsEvent.prototype.trigger = function() {
+  for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+    args[_key] = arguments[_key];
+  }
+  var type = args[0];
+  var params = args.slice(1);
+  if (!!this.events[type]) {
+    this.events[type].forEach(function(listener) {
+      try {
+        listener.apply(null, params);
+      } catch (e) {
+          //console.log('[uCharts] '+e);
+      }
+    });
+  }
+};
+
+var uCharts = function uCharts(opts) {
+  opts.pix = opts.pixelRatio ? opts.pixelRatio : 1;
+  opts.fontSize = opts.fontSize ? opts.fontSize : 13;
+  opts.fontColor = opts.fontColor ? opts.fontColor : config.fontColor;
+  if (opts.background == "" || opts.background == "none") {
+    opts.background = "#FFFFFF"
+  }
+  opts.title = assign({}, opts.title);
+  opts.subtitle = assign({}, opts.subtitle);
+  opts.duration = opts.duration ? opts.duration : 1000;
+  opts.yAxis = assign({}, {
+    data: [],
+    showTitle: false,
+    disabled: false,
+    disableGrid: false,
+    gridSet: 'number',
+    splitNumber: 5,
+    gridType: 'solid',
+    dashLength: 4 * opts.pix,
+    gridColor: '#cccccc',
+    padding: 10,
+    fontColor: '#666666'
+  }, opts.yAxis);
+  opts.xAxis = assign({}, {
+    rotateLabel: false,
+    rotateAngle:45,
+    disabled: false,
+    disableGrid: false,
+    splitNumber: 5,
+    calibration:false,
+    fontColor: '#666666',
+    fontSize: 13,
+    lineHeight: 20,
+    marginTop: 0,
+    gridType: 'solid',
+    dashLength: 4,
+    scrollAlign: 'left',
+    boundaryGap: 'center',
+    axisLine: true,
+    axisLineColor: '#cccccc',
+    titleFontSize: 13,
+    titleOffsetY: 0,
+    titleOffsetX: 0,
+    titleFontColor: '#666666'
+  }, opts.xAxis);
+  opts.xAxis.scrollPosition = opts.xAxis.scrollAlign;
+  opts.legend = assign({}, {
+    show: true,
+    position: 'bottom',
+    float: 'center',
+    backgroundColor: 'rgba(0,0,0,0)',
+    borderColor: 'rgba(0,0,0,0)',
+    borderWidth: 0,
+    padding: 5,
+    margin: 5,
+    itemGap: 10,
+    fontSize: opts.fontSize,
+    lineHeight: opts.fontSize,
+    fontColor: opts.fontColor,
+    formatter: {},
+    hiddenColor: '#CECECE'
+  }, opts.legend);
+  opts.extra = assign({
+    tooltip:{
+      legendShape: 'auto'
+    }
+  }, opts.extra);
+  opts.rotate = opts.rotate ? true : false;
+  opts.animation = opts.animation ? true : false;
+  opts.rotate = opts.rotate ? true : false;
+  opts.canvas2d = opts.canvas2d ? true : false;
+  
+  let config$$1 = assign({}, config);
+  config$$1.color = opts.color ? opts.color : config$$1.color;
+  if (opts.type == 'pie') {
+    config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.pie.labelWidth * opts.pix || config$$1.pieChartLinePadding * opts.pix;
+  }
+  if (opts.type == 'ring') {
+    config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.ring.labelWidth * opts.pix || config$$1.pieChartLinePadding * opts.pix;
+  }
+  if (opts.type == 'rose') {
+    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.rotate = opts.rotate;
+  if (opts.rotate) {
+    let tempWidth = opts.width;
+    let tempHeight = opts.height;
+    opts.width = tempHeight;
+    opts.height = tempWidth;
+  }
+
+  //适配高分屏
+  opts.padding = opts.padding ? opts.padding : config$$1.padding;
+  config$$1.yAxisWidth = config.yAxisWidth * opts.pix;
+  config$$1.fontSize = opts.fontSize * opts.pix;
+  config$$1.titleFontSize = config.titleFontSize * opts.pix;
+  config$$1.subtitleFontSize = config.subtitleFontSize * opts.pix;
+  if(!opts.context){
+    throw new Error('[uCharts] 未获取到context!注意:v2.0版本后,需要自行获取canvas的绘图上下文并传入opts.context!');
+  }
+  this.context = opts.context;
+  if (!this.context.setTextAlign) {
+    this.context.setStrokeStyle = function(e) {
+      return this.strokeStyle = e;
+    }
+    this.context.setLineWidth = function(e) {
+      return this.lineWidth = e;
+    }
+    this.context.setLineCap = function(e) {
+      return this.lineCap = e;
+    }
+    this.context.setFontSize = function(e) {
+      return this.font = e + "px sans-serif";
+    }
+    this.context.setFillStyle = function(e) {
+      return this.fillStyle = e;
+    }
+    this.context.setTextAlign = function(e) {
+      return this.textAlign = e;
+    }
+    this.context.setTextBaseline = function(e) {
+      return this.textBaseline = e;
+    }
+    this.context.setShadow = function(offsetX,offsetY,blur,color) {
+      this.shadowColor = color;
+      this.shadowOffsetX = offsetX;
+      this.shadowOffsetY = offsetY;
+      this.shadowBlur = blur;
+    }
+    this.context.draw = function() {}
+  }
+  //兼容NVUEsetLineDash
+  if(!this.context.setLineDash){
+    this.context.setLineDash = function(e) {}
+  }
+  opts.chartData = {};
+  this.uevent = new uChartsEvent();
+  this.scrollOption = {
+    currentOffset: 0,
+    startTouchX: 0,
+    distance: 0,
+    lastMoveTime: 0
+  };
+  this.opts = opts;
+  this.config = config$$1;
+  drawCharts.call(this, opts.type, opts, config$$1, this.context);
+};
+
+uCharts.prototype.updateData = function() {
+  let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+  this.opts = assign({}, this.opts, data);
+  this.opts.updateData = true;
+  let scrollPosition = data.scrollPosition || 'current';
+  switch (scrollPosition) {
+    case 'current':
+      this.opts._scrollDistance_ = this.scrollOption.currentOffset;
+      break;
+    case 'left':
+      this.opts._scrollDistance_ = 0;
+      this.scrollOption = {
+        currentOffset: 0,
+        startTouchX: 0,
+        distance: 0,
+        lastMoveTime: 0
+      };
+      break;
+    case 'right':
+      let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config, this.context), yAxisWidth = _calYAxisData.yAxisWidth;
+      this.config.yAxisWidth = yAxisWidth;
+      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 totalWidth = eachSpacing * (xAxisPoints.length - 1);
+      let screenWidth = endX - startX;
+      offsetLeft = screenWidth - totalWidth;
+      this.scrollOption = {
+        currentOffset: offsetLeft,
+        startTouchX: offsetLeft,
+        distance: 0,
+        lastMoveTime: 0
+      };
+      this.opts._scrollDistance_ = offsetLeft;
+      break;
+  }
+  drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
+};
+
+uCharts.prototype.zoom = function() {
+  var val = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.opts.xAxis.itemCount;
+  if (this.opts.enableScroll !== true) {
+    console.log('[uCharts] 请启用滚动条后使用')
+    return;
+  }
+  //当前屏幕中间点
+  let centerPoint = Math.round(Math.abs(this.scrollOption.currentOffset) / this.opts.chartData.eachSpacing) + Math.round(this.opts.xAxis.itemCount / 2);
+  this.opts.animation = false;
+  this.opts.xAxis.itemCount = val.itemCount;
+  //重新计算x轴偏移距离
+  let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config, this.context),
+    yAxisWidth = _calYAxisData.yAxisWidth;
+  this.config.yAxisWidth = yAxisWidth;
+  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 centerLeft = eachSpacing * centerPoint;
+  let screenWidth = endX - startX;
+  let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1);
+  offsetLeft = screenWidth / 2 - centerLeft;
+  if (offsetLeft > 0) {
+    offsetLeft = 0;
+  }
+  if (offsetLeft < MaxLeft) {
+    offsetLeft = MaxLeft;
+  }
+  this.scrollOption = {
+    currentOffset: 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();
+};
+
+uCharts.prototype.addEventListener = function(type, listener) {
+  this.uevent.addEventListener(type, listener);
+};
+
+uCharts.prototype.delEventListener = function(type) {
+  this.uevent.delEventListener(type);
+};
+
+uCharts.prototype.getCurrentDataIndex = function(e) {
+  var touches = null;
+  if (e.changedTouches) {
+    touches = e.changedTouches[0];
+  } else {
+    touches = e.mp.changedTouches[0];
+  }
+  if (touches) {
+    let _touches$ = getTouches(touches, this.opts, e);
+    if (this.opts.type === 'pie' || this.opts.type === 'ring') {
+      return findPieChartCurrentIndex({
+        x: _touches$.x,
+        y: _touches$.y
+      }, this.opts.chartData.pieData, this.opts);
+    } else if (this.opts.type === 'rose') {
+      return findRoseChartCurrentIndex({
+        x: _touches$.x,
+        y: _touches$.y
+      }, this.opts.chartData.pieData, this.opts);
+    } else if (this.opts.type === 'radar') {
+      return findRadarChartCurrentIndex({
+        x: _touches$.x,
+        y: _touches$.y
+      }, this.opts.chartData.radarData, this.opts.categories.length);
+    } else if (this.opts.type === 'funnel') {
+      return findFunnelChartCurrentIndex({
+        x: _touches$.x,
+        y: _touches$.y
+      }, this.opts.chartData.funnelData);
+    } else if (this.opts.type === 'map') {
+      return findMapChartCurrentIndex({
+        x: _touches$.x,
+        y: _touches$.y
+      }, this.opts);
+    } else if (this.opts.type === 'word') {
+      return findWordChartCurrentIndex({
+        x: _touches$.x,
+        y: _touches$.y
+      }, this.opts.chartData.wordCloudData);
+    } else if (this.opts.type === 'bar') {
+      return findBarChartCurrentIndex({
+        x: _touches$.x,
+        y: _touches$.y
+      }, this.opts.chartData.calPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset));
+    } else {
+      return findCurrentIndex({
+        x: _touches$.x,
+        y: _touches$.y
+      }, this.opts.chartData.calPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset));
+    }
+  }
+  return -1;
+};
+
+uCharts.prototype.getLegendDataIndex = function(e) {
+  var touches = null;
+  if (e.changedTouches) {
+    touches = e.changedTouches[0];
+  } else {
+    touches = e.mp.changedTouches[0];
+  }
+  if (touches) {
+    let _touches$ = getTouches(touches, this.opts, e);
+    return findLegendIndex({
+      x: _touches$.x,
+      y: _touches$.y
+    }, this.opts.chartData.legendData);
+  }
+  return -1;
+};
+
+uCharts.prototype.touchLegend = function(e) {
+  var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+  var touches = null;
+  if (e.changedTouches) {
+    touches = e.changedTouches[0];
+  } else {
+    touches = e.mp.changedTouches[0];
+  }
+  if (touches) {
+    var _touches$ = getTouches(touches, this.opts, e);
+    var index = this.getLegendDataIndex(e);
+    if (index >= 0) {
+      if (this.opts.type == 'candle') {
+        this.opts.seriesMA[index].show = !this.opts.seriesMA[index].show;
+      } else {
+        this.opts.series[index].show = !this.opts.series[index].show;
+      }
+      this.opts.animation = option.animation ? true : false;
+      this.opts._scrollDistance_ = this.scrollOption.currentOffset;
+      drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
+    }
+  }
+
+};
+
+uCharts.prototype.showToolTip = function(e) {
+  var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+  var touches = null;
+  if (e.changedTouches) {
+    touches = e.changedTouches[0];
+  } else {
+    touches = e.mp.changedTouches[0];
+  }
+  if (!touches) {
+    console.log("[uCharts] 未获取到event坐标信息");
+  }
+  var _touches$ = getTouches(touches, this.opts, e);
+  var currentOffset = this.scrollOption.currentOffset;
+  var opts = assign({}, this.opts, {
+    _scrollDistance_: currentOffset,
+    animation: false
+  });
+  if (this.opts.type === 'line' || this.opts.type === 'area' || this.opts.type === 'column' || this.opts.type === 'scatter' || this.opts.type === 'bubble') {
+    var current = this.getCurrentDataIndex(e);
+    var index = option.index == undefined ? current.index : option.index;
+    if (index > -1 || index.length>0) {
+      var seriesData = getSeriesDataItem(this.opts.series, index, current.group);
+      if (seriesData.length !== 0) {
+        var _getToolTipData = getToolTipData(seriesData, this.opts, index, current.group, this.opts.categories, option),
+          textList = _getToolTipData.textList,
+          offset = _getToolTipData.offset;
+        offset.y = _touches$.y;
+        opts.tooltip = {
+          textList: option.textList !== undefined ? option.textList : textList,
+          offset: option.offset !== undefined ? option.offset : offset,
+          option: option,
+          index: index,
+          group: current.group
+        };
+      }
+    }
+    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,
+        legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape
+      }];
+      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') {
+    var current = this.getCurrentDataIndex(e);
+    var index = option.index == undefined ? current.index : option.index;
+    if (index > -1 || index.length>0) {
+      var seriesData = getSeriesDataItem(this.opts.series, index, current.group);
+      if (seriesData.length !== 0) {
+        var _getToolTipData = getToolTipData(seriesData, this.opts, index, current.group, this.opts.categories, option),
+          textList = _getToolTipData.textList,
+          offset = _getToolTipData.offset;
+        offset.x = _touches$.x;
+        opts.tooltip = {
+          textList: option.textList !== undefined ? 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 === 'mix') {
+    var current = this.getCurrentDataIndex(e);
+    var index = option.index == undefined ? current.index : option.index;
+    if (index > -1) {
+      var currentOffset = this.scrollOption.currentOffset;
+      var opts = assign({}, this.opts, {
+        _scrollDistance_: currentOffset,
+        animation: false
+      });
+      var seriesData = getSeriesDataItem(this.opts.series, index);
+      if (seriesData.length !== 0) {
+        var _getMixToolTipData = getMixToolTipData(seriesData, this.opts, index, this.opts.categories, option),
+          textList = _getMixToolTipData.textList,
+          offset = _getMixToolTipData.offset;
+        offset.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 === 'candle') {
+    var current = this.getCurrentDataIndex(e);
+    var index = option.index == undefined ? current.index : option.index;
+    if (index > -1) {
+      var currentOffset = this.scrollOption.currentOffset;
+      var opts = assign({}, this.opts, {
+        _scrollDistance_: currentOffset,
+        animation: false
+      });
+      var seriesData = getSeriesDataItem(this.opts.series, index);
+      if (seriesData.length !== 0) {
+        var _getToolTipData = getCandleToolTipData(this.opts.series[0].data, seriesData, this.opts, index, this.opts.categories, this.opts.extra.candle, option),
+          textList = _getToolTipData.textList,
+          offset = _getToolTipData.offset;
+        offset.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 === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose' || this.opts.type === 'funnel') {
+    var index = option.index == undefined ? this.getCurrentDataIndex(e) : 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,
+        legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape
+      }];
+      var offset = {
+        x: _touches$.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 === 'map') {
+    var index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index;
+    if (index > -1) {
+      var opts = assign({}, this.opts, {animation: false});
+      var seriesData = assign({}, this.opts.series[index]);
+      seriesData.name = seriesData.properties.name
+      var textList = [{
+        text: option.formatter ? option.formatter(seriesData, undefined, index, this.opts) : seriesData.name,
+        color: seriesData.color,
+        legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape
+      }];
+      var offset = {
+        x: _touches$.x,
+        y: _touches$.y
+      };
+      opts.tooltip = {
+        textList: option.textList ? option.textList : textList,
+        offset: option.offset !== undefined ? option.offset : offset,
+        option: option,
+        index: index
+      };
+    }
+    opts.updateData = false;
+    drawCharts.call(this, opts.type, opts, this.config, this.context);
+  }
+  if (this.opts.type === 'word') {
+    var index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index;
+    if (index > -1) {
+      var opts = assign({}, this.opts, {animation: false});
+      var seriesData = assign({}, this.opts.series[index]);
+      var textList = [{
+        text: option.formatter ? option.formatter(seriesData, undefined, index, this.opts) : seriesData.name,
+        color: seriesData.color,
+        legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape
+      }];
+      var offset = {
+        x: _touches$.x,
+        y: _touches$.y
+      };
+      opts.tooltip = {
+        textList: option.textList ? option.textList : textList,
+        offset: option.offset !== undefined ? option.offset : offset,
+        option: option,
+        index: index
+      };
+    }
+    opts.updateData = false;
+    drawCharts.call(this, opts.type, opts, this.config, this.context);
+  }
+  if (this.opts.type === 'radar') {
+    var index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index;
+    if (index > -1) {
+      var opts = assign({}, this.opts, {animation: false});
+      var seriesData = getSeriesDataItem(this.opts.series, index);
+      if (seriesData.length !== 0) {
+        var textList = seriesData.map((item) => {
+          return {
+            text: option.formatter ? option.formatter(item, this.opts.categories[index], index, this.opts) : item.name + ': ' + item.data,
+            color: item.color,
+            legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? item.legendShape : this.opts.extra.tooltip.legendShape
+          };
+        });
+        var offset = {
+          x: _touches$.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);
+  }
+};
+
+uCharts.prototype.translate = function(distance) {
+  this.scrollOption = {
+    currentOffset: distance,
+    startTouchX: distance,
+    distance: 0,
+    lastMoveTime: 0
+  };
+  let opts = assign({}, this.opts, {
+    _scrollDistance_: distance,
+    animation: false
+  });
+  drawCharts.call(this, this.opts.type, opts, this.config, this.context);
+};
+
+uCharts.prototype.scrollStart = function(e) {
+  var touches = null;
+  if (e.changedTouches) {
+    touches = e.changedTouches[0];
+  } else {
+    touches = e.mp.changedTouches[0];
+  }
+  var _touches$ = getTouches(touches, this.opts, e);
+  if (touches && this.opts.enableScroll === true) {
+    this.scrollOption.startTouchX = _touches$.x;
+  }
+};
+
+uCharts.prototype.scroll = function(e) {
+  if (this.scrollOption.lastMoveTime === 0) {
+    this.scrollOption.lastMoveTime = Date.now();
+  }
+  let Limit = this.opts.touchMoveLimit || 60;
+  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) {
+    touches = e.changedTouches[0];
+  } else {
+    touches = e.mp.changedTouches[0];
+  }
+  if (touches && this.opts.enableScroll === true) {
+    var _touches$ = getTouches(touches, this.opts, e);
+    var _distance;
+    _distance = _touches$.x - this.scrollOption.startTouchX;
+    var currentOffset = this.scrollOption.currentOffset;
+    var validDistance = calValidDistance(this, currentOffset + _distance, this.opts.chartData, this.config, this.opts);
+    this.scrollOption.distance = _distance = validDistance - currentOffset;
+    var opts = assign({}, this.opts, {
+      _scrollDistance_: currentOffset + _distance,
+      animation: false
+    });
+		this.opts = opts;
+    drawCharts.call(this, opts.type, opts, this.config, this.context);
+    return currentOffset + _distance;
+  }
+};
+
+uCharts.prototype.scrollEnd = function(e) {
+  if (this.opts.enableScroll === true) {
+    var _scrollOption = this.scrollOption,
+      currentOffset = _scrollOption.currentOffset,
+      distance = _scrollOption.distance;
+    this.scrollOption.currentOffset = currentOffset + distance;
+    this.scrollOption.distance = 0;
+    this.scrollOption.moveCount = 0;
+  }
+};
+
+export default uCharts;

Файловите разлики са ограничени, защото са твърде много
+ 17 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js


+ 201 - 0
uni_modules/qiun-data-charts/license.md

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 80 - 0
uni_modules/qiun-data-charts/package.json

@@ -0,0 +1,80 @@
+{
+  "id": "qiun-data-charts",
+  "displayName": "秋云 ucharts echarts 高性能跨全端图表组件",
+  "version": "2.5.0-20230101",
+  "description": "uCharts 新增正负柱状图!支持H5及APP用 ucharts echarts 渲染图表,uniapp可视化首选组件",
+  "keywords": [
+    "ucharts",
+    "echarts",
+    "f2",
+    "图表",
+    "可视化"
+],
+  "repository": "https://gitee.com/uCharts/uCharts",
+"engines": {
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": "474119"
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "插件不采集任何数据",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/~qiun",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 84 - 0
uni_modules/qiun-data-charts/readme.md

@@ -0,0 +1,84 @@
+![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)
+
+## 快速体验
+
+一套代码编到多个平台,依次扫描二维码,亲自体验uCharts图表跨平台效果!其他平台请自行编译。
+
+![](https://www.ucharts.cn/images/web/guide/qrcode20220224.png)
+
+![](https://img-blog.csdnimg.cn/7d0115593ff24ac39a224fb7c6ed72a4.png)
+
+## 致开发者
+
+感谢各位开发者`五年`来对秋云及uCharts的支持,uCharts的进步离不开各位开发者的鼓励与贡献。为更好的帮助各位开发者使用图表工具,我们推出了新版官网,增加了在线定制、问答社区、在线配置等一些增值服务,为确保您能更好的应用图表组件,建议您先`仔细阅读官网指南`以及`常见问题`,而不是下载下来`直接使用`。如仍然不能解决,请到`官网社区`或开通会员后加入`专属VIP会员群`提问将会很快得到回答。
+
+## 视频教程
+
+## [uCharts新手入门教程](https://www.bilibili.com/video/BV1qA411Q7se/?share_source=copy_web&vd_source=42a1242f9aaade6427736af69eb2e1d9)
+
+
+## 社群支持
+
+uCharts官方拥有5个2000人的QQ群及专属VIP会员群支持,庞大的用户量证明我们一直在努力,请各位放心使用!uCharts的开源图表组件的开发,团队付出了大量的时间与精力,经过四来的考验,不会有比较明显的bug,请各位放心使用。如果您有更好的想法,可以在`码云提交Pull Requests`以帮助更多开发者完成需求,再次感谢各位对uCharts的鼓励与支持!
+
+#### 官方交流群
+- 交流群1:371774600(已满)
+- 交流群2:619841586(已满)
+- 交流群3:955340127(已满)
+- 交流群4:641669795(已满)
+- 交流群5:236294809(只能扫码加入)
+
+![](https://www.ucharts.cn/images/web/qq5.jpg)
+
+- 口令`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)
+
+
+## 相关链接
+- [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)
+- [uCharts npm开源地址](https://www.ucharts.cn)
+- [ECharts官网](https://echarts.apache.org/zh/index.html)
+- [ECharts配置手册](https://echarts.apache.org/zh/option.html)
+- [图表组件在项目中的应用 ReportPlus数据报表](https://www.ucharts.cn/v2/#/layout/info?id=1) 

Файловите разлики са ограничени, защото са твърде много
+ 22 - 0
uni_modules/qiun-data-charts/static/app-plus/echarts.min.js


Файловите разлики са ограничени, защото са твърде много
+ 22 - 0
uni_modules/qiun-data-charts/static/h5/echarts.min.js


Някои файлове не бяха показани, защото твърде много файлове са промени