From 423e8a3a2f35a48f77c0c117674eb6e84cbb86f5 Mon Sep 17 00:00:00 2001 From: Cxx0822 <1556464090@qq.com> Date: Sun, 6 Sep 2026 16:07:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=9D=E5=A7=8B=E5=8C=96=E5=B7=A5?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 21 + index.html | 20 + package.json | 77 + pnpm-lock.yaml | 9988 +++++++++++++++++ shims-uni.d.ts | 10 + src/App.vue | 13 + src/components/RecordPopup.vue | 176 + src/components/UserPopup.vue | 104 + src/env.d.ts | 8 + src/main.ts | 13 + src/manifest.json | 72 + src/pages.json | 44 + src/pages/index/index.vue | 219 + src/pages/user/index.vue | 63 + src/shime-uni.d.ts | 6 + src/static/logo.png | Bin 0 -> 8225 bytes src/static/tabs/home-active.png | Bin 0 -> 4860 bytes src/static/tabs/home.png | Bin 0 -> 4594 bytes src/static/tabs/user-active.png | Bin 0 -> 7563 bytes src/static/tabs/user.png | Bin 0 -> 7132 bytes src/store/app.ts | 12 + src/store/record.ts | 100 + src/store/user.ts | 69 + src/types/family.ts | 36 + src/uni.scss | 76 + .../liu-drag-button_1.0.5/changelog.md | 12 + .../liu-drag-button/liu-drag-button.vue | 143 + .../liu-drag-button_1.0.5/license.md | 6 + .../liu-drag-button_1.0.5/package.json | 85 + .../liu-drag-button_1.0.5/readme.md | 36 + .../changelog.md | 320 + .../qiun-data-charts/qiun-data-charts.vue | 1618 +++ .../components/qiun-error/qiun-error.vue | 46 + .../components/qiun-loading/loading1.vue | 162 + .../components/qiun-loading/loading2.vue | 170 + .../components/qiun-loading/loading3.vue | 173 + .../components/qiun-loading/loading4.vue | 222 + .../components/qiun-loading/loading5.vue | 229 + .../components/qiun-loading/qiun-loading.vue | 36 + .../js_sdk/u-charts/config-echarts.js | 422 + .../js_sdk/u-charts/config-ucharts.js | 606 + .../js_sdk/u-charts/readme.md | 5 + .../js_sdk/u-charts/u-charts.js | 7706 +++++++++++++ .../js_sdk/u-charts/u-charts.min.js | 18 + .../license.md | 201 + .../package.json | 80 + .../qiun-data-charts_2.5.0-20230101/readme.md | 84 + .../static/app-plus/echarts.min.js | 23 + .../static/h5/echarts.min.js | 23 + .../wu-calendar_1.5.6/changelog.md | 145 + .../wu-calendar_1.5.6/components/i18n/en.json | 14 + .../components/i18n/index.js | 8 + .../components/i18n/zh-Hans.json | 14 + .../components/i18n/zh-Hant.json | 14 + .../components/wu-calendar-block/props.js | 73 + .../wu-calendar-block/wu-calendar-block.vue | 111 + .../components/wu-calendar-item/props.js | 55 + .../wu-calendar-item/wu-calendar-item.vue | 252 + .../components/wu-calendar/calendar.js | 664 ++ .../components/wu-calendar/props.js | 166 + .../components/wu-calendar/util.js | 552 + .../components/wu-calendar/wu-calendar.vue | 1069 ++ .../wu-calendar_1.5.6/package.json | 91 + src/uni_modules/wu-calendar_1.5.6/readme.md | 16 + src/uni_modules/wu-ui-tools/changelog.md | 22 + .../components/wu-ui-tools/wu-ui-tools.vue | 6 + src/uni_modules/wu-ui-tools/index.js | 73 + src/uni_modules/wu-ui-tools/index.scss | 7 + .../wu-ui-tools/libs/config/config.js | 34 + .../wu-ui-tools/libs/css/color.scss | 32 + .../wu-ui-tools/libs/css/common.scss | 100 + .../wu-ui-tools/libs/css/components.scss | 23 + .../wu-ui-tools/libs/css/variable.scss | 111 + src/uni_modules/wu-ui-tools/libs/css/vue.scss | 40 + .../function/color/color-convert/CHANGELOG.md | 54 + .../libs/function/color/color-convert/LICENSE | 21 + .../function/color/color-convert/README.md | 68 + .../color/color-convert/conversions.js | 839 ++ .../function/color/color-convert/index.js | 81 + .../function/color/color-convert/package.json | 48 + .../function/color/color-convert/route.js | 97 + .../libs/function/color/color-name/LICENSE | 8 + .../libs/function/color/color-name/README.md | 11 + .../libs/function/color/color-name/index.js | 152 + .../function/color/color-name/package.json | 28 + .../libs/function/color/color-string/LICENSE | 21 + .../function/color/color-string/README.md | 62 + .../libs/function/color/color-string/index.js | 244 + .../function/color/color-string/package.json | 39 + .../wu-ui-tools/libs/function/color/color.js | 496 + .../wu-ui-tools/libs/function/color/index.js | 158 + .../libs/function/color/is-arrayish/LICENSE | 21 + .../libs/function/color/is-arrayish/README.md | 16 + .../libs/function/color/is-arrayish/index.js | 9 + .../function/color/is-arrayish/package.json | 45 + .../function/color/simple-swizzle/LICENSE | 21 + .../function/color/simple-swizzle/README.md | 39 + .../function/color/simple-swizzle/index.js | 29 + .../color/simple-swizzle/package.json | 36 + .../wu-ui-tools/libs/function/debounce.js | 29 + .../wu-ui-tools/libs/function/digit.js | 167 + .../wu-ui-tools/libs/function/index.js | 738 ++ .../wu-ui-tools/libs/function/platform.js | 75 + .../wu-ui-tools/libs/function/test.js | 287 + .../wu-ui-tools/libs/function/throttle.js | 30 + .../libs/luch-request/adapters/index.js | 97 + .../luch-request/core/InterceptorManager.js | 50 + .../libs/luch-request/core/Request.js | 198 + .../libs/luch-request/core/buildFullPath.js | 20 + .../libs/luch-request/core/defaults.js | 29 + .../libs/luch-request/core/dispatchRequest.js | 3 + .../libs/luch-request/core/mergeConfig.js | 103 + .../libs/luch-request/core/settle.js | 16 + .../libs/luch-request/helpers/buildURL.js | 69 + .../libs/luch-request/helpers/combineURLs.js | 14 + .../luch-request/helpers/isAbsoluteURL.js | 14 + .../wu-ui-tools/libs/luch-request/index.d.ts | 116 + .../wu-ui-tools/libs/luch-request/index.js | 3 + .../wu-ui-tools/libs/luch-request/utils.js | 131 + .../libs/luch-request/utils/clone.js | 264 + .../wu-ui-tools/libs/mixin/button.js | 13 + .../wu-ui-tools/libs/mixin/mixin.js | 188 + .../wu-ui-tools/libs/mixin/mpMixin.js | 8 + .../wu-ui-tools/libs/mixin/mpShare.js | 13 + .../wu-ui-tools/libs/mixin/openType.js | 44 + .../wu-ui-tools/libs/mixin/touch.js | 59 + .../wu-ui-tools/libs/util/async-validator.js | 1343 +++ .../wu-ui-tools/libs/util/dayjs.js | 218 + .../wu-ui-tools/libs/util/route.js | 124 + src/uni_modules/wu-ui-tools/package.json | 86 + src/uni_modules/wu-ui-tools/readme.md | 18 + src/uni_modules/wu-ui-tools/theme.scss | 43 + src/utils/index.ts | 3 + tsconfig.json | 13 + unocss.config.ts | 20 + vite.config.ts | 12 + 136 files changed, 34546 insertions(+) create mode 100644 .gitignore create mode 100644 index.html create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 shims-uni.d.ts create mode 100644 src/App.vue create mode 100644 src/components/RecordPopup.vue create mode 100644 src/components/UserPopup.vue create mode 100644 src/env.d.ts create mode 100644 src/main.ts create mode 100644 src/manifest.json create mode 100644 src/pages.json create mode 100644 src/pages/index/index.vue create mode 100644 src/pages/user/index.vue create mode 100644 src/shime-uni.d.ts create mode 100644 src/static/logo.png create mode 100644 src/static/tabs/home-active.png create mode 100644 src/static/tabs/home.png create mode 100644 src/static/tabs/user-active.png create mode 100644 src/static/tabs/user.png create mode 100644 src/store/app.ts create mode 100644 src/store/record.ts create mode 100644 src/store/user.ts create mode 100644 src/types/family.ts create mode 100644 src/uni.scss create mode 100644 src/uni_modules/liu-drag-button_1.0.5/changelog.md create mode 100644 src/uni_modules/liu-drag-button_1.0.5/components/liu-drag-button/liu-drag-button.vue create mode 100644 src/uni_modules/liu-drag-button_1.0.5/license.md create mode 100644 src/uni_modules/liu-drag-button_1.0.5/package.json create mode 100644 src/uni_modules/liu-drag-button_1.0.5/readme.md create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/changelog.md create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-data-charts/qiun-data-charts.vue create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-error/qiun-error.vue create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading1.vue create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading2.vue create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading3.vue create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading4.vue create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading5.vue create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/qiun-loading.vue create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/config-echarts.js create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/config-ucharts.js create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/readme.md create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/u-charts.js create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/u-charts.min.js create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/license.md create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/package.json create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/readme.md create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/static/app-plus/echarts.min.js create mode 100644 src/uni_modules/qiun-data-charts_2.5.0-20230101/static/h5/echarts.min.js create mode 100644 src/uni_modules/wu-calendar_1.5.6/changelog.md create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/i18n/en.json create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/i18n/index.js create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/i18n/zh-Hans.json create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/i18n/zh-Hant.json create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/wu-calendar-block/props.js create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/wu-calendar-block/wu-calendar-block.vue create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/wu-calendar-item/props.js create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/wu-calendar-item/wu-calendar-item.vue create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/wu-calendar/calendar.js create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/wu-calendar/props.js create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/wu-calendar/util.js create mode 100644 src/uni_modules/wu-calendar_1.5.6/components/wu-calendar/wu-calendar.vue create mode 100644 src/uni_modules/wu-calendar_1.5.6/package.json create mode 100644 src/uni_modules/wu-calendar_1.5.6/readme.md create mode 100644 src/uni_modules/wu-ui-tools/changelog.md create mode 100644 src/uni_modules/wu-ui-tools/components/wu-ui-tools/wu-ui-tools.vue create mode 100644 src/uni_modules/wu-ui-tools/index.js create mode 100644 src/uni_modules/wu-ui-tools/index.scss create mode 100644 src/uni_modules/wu-ui-tools/libs/config/config.js create mode 100644 src/uni_modules/wu-ui-tools/libs/css/color.scss create mode 100644 src/uni_modules/wu-ui-tools/libs/css/common.scss create mode 100644 src/uni_modules/wu-ui-tools/libs/css/components.scss create mode 100644 src/uni_modules/wu-ui-tools/libs/css/variable.scss create mode 100644 src/uni_modules/wu-ui-tools/libs/css/vue.scss create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-convert/CHANGELOG.md create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-convert/LICENSE create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-convert/README.md create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-convert/conversions.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-convert/index.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-convert/package.json create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-convert/route.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-name/LICENSE create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-name/README.md create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-name/index.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-name/package.json create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-string/LICENSE create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-string/README.md create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-string/index.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color-string/package.json create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/color.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/index.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/is-arrayish/LICENSE create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/is-arrayish/README.md create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/is-arrayish/index.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/is-arrayish/package.json create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/simple-swizzle/LICENSE create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/simple-swizzle/README.md create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/simple-swizzle/index.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/color/simple-swizzle/package.json create mode 100644 src/uni_modules/wu-ui-tools/libs/function/debounce.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/digit.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/index.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/platform.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/test.js create mode 100644 src/uni_modules/wu-ui-tools/libs/function/throttle.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/adapters/index.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/core/InterceptorManager.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/core/Request.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/core/buildFullPath.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/core/defaults.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/core/dispatchRequest.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/core/mergeConfig.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/core/settle.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/helpers/buildURL.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/helpers/combineURLs.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/helpers/isAbsoluteURL.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/index.d.ts create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/index.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/utils.js create mode 100644 src/uni_modules/wu-ui-tools/libs/luch-request/utils/clone.js create mode 100644 src/uni_modules/wu-ui-tools/libs/mixin/button.js create mode 100644 src/uni_modules/wu-ui-tools/libs/mixin/mixin.js create mode 100644 src/uni_modules/wu-ui-tools/libs/mixin/mpMixin.js create mode 100644 src/uni_modules/wu-ui-tools/libs/mixin/mpShare.js create mode 100644 src/uni_modules/wu-ui-tools/libs/mixin/openType.js create mode 100644 src/uni_modules/wu-ui-tools/libs/mixin/touch.js create mode 100644 src/uni_modules/wu-ui-tools/libs/util/async-validator.js create mode 100644 src/uni_modules/wu-ui-tools/libs/util/dayjs.js create mode 100644 src/uni_modules/wu-ui-tools/libs/util/route.js create mode 100644 src/uni_modules/wu-ui-tools/package.json create mode 100644 src/uni_modules/wu-ui-tools/readme.md create mode 100644 src/uni_modules/wu-ui-tools/theme.scss create mode 100644 src/utils/index.ts create mode 100644 tsconfig.json create mode 100644 unocss.config.ts create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7ce6e50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +*.local + +# Editor directories and files +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..f8a54cb --- /dev/null +++ b/index.html @@ -0,0 +1,20 @@ + + +
+ + +mLJ59k z6&7`hR}PjhaW$3uo_GI^73Dw3SwMhr-aE$IV;}hI7$0klUW<5lXPQYe(D^6qd)5E# z9`W&wSU0Gz#Rnn3Lp`Im?A@7DJ4d7bMCdgJYZuhI3XPSgJsiX5hWe-X#S3JvoTO&! zKt-2W0AzJjQHTVP zd(*9QRGt@uoZ|^}JD}LG2GP*e^cYWN0fpEm_7 U*M7_rj{-cuRG&wcV_a6g+PspM)(7`IhM*{v*(xW4+iFD~a$yA=++F zhra|m%J96=ax|NqN^X;PT)lU00hN9UO2qygJG=TZvhSoDntf%|HE8+t_PBi5)Rn6F zl#wpWZ|>ZW+b&8&M`2UZRX^XE(5I6WJ0HvXWCJJs5=o_(ool?I*}y-hof(33K&+dj ztx~U>lxkn6o2D<4-y>%6fsm*uRgl*_qvAtUe6uYtHufAi-s7Py5z#I!rfW 4hNr1=j={m@#rMDy#GuZ|<`Pd< zRo|U+(92a}DH40eknMg}79T$UC+PdyEAB&-*sHAri<_2h?jd!ks^hbvP=xl@8wrSv zV-WNoC3O}w&I*bs-nm^L*Q_c=pH5Rc5{CmDf}|}9sEITPez{Gm0GFSJOT^F3E9m1; z6mULeG)VUmD8gLr<=2u~pd6JmQS8zYqq7D8LK9k}c^`%AIT?Juaqw=}r?-xW%%9m| zcKT^MjOINb+mh=Mm|3%Ad3YyOO$O9uari@jun=I`a($-38@lB)svm;zh>ul;B06>+ zVu{6xK@n#laDAKRogg@Hzhj#rpcsI3H#k{CAkc!%e*v(pSq((sG(!8RD9HRE2rD2F zxtEav!pgAv@OB3Xi~Rs^KLtwaDQ?~xKkS_yeLA?vU~VC5 l!fbDW=F0>*Q#`W1Hp0=v7;x z+YxYER49Pi)u@Q^VQm#tfaP8UGzGfAEpGd|ZILC;9|aaFiAj|a=h>lzb^>~2eQ1dO zT@4Py9{+uDLdU`tQA28b>nV)c`^jV_RSI?jUNtiJMt4_Qu~8^cTM577wn{fa!1J2# zEm?YtXuk(iD-NgtbgzP!A9~G=5%A1d)-ttdS8b`TJP@GJmG*&qo2>s5Z;U{3#? QnoOIm@#3jLrj*4 zvL`#4CR>(D5+PeEOQhcNJHG$^{+Q)+&U4?-{ap8TJ?FU&-NwpnkC==Y1OnMZAro!E z-&f$LM|3y%oip6h0)ZeP6yizy5a{O|cp~6%;Q58d;OnoEXQiODAexnQ0L=z@lGgNf zp)+HDl0sJe+oNXvT}p--8JvaVCg&63T0nQFeusisd`OjSRPj<&V_C60BT7v4(9^Qd zvVU48Dk#C$hp#n#9Vt7#-Fw4sWW?d?k7t`%n~T@1FXhK=X9Jbtzc#ELRPSw>7p>Z8 z^!4}kSxtR7qb#1iW Kt46DacA|Z+aO>)VU2fmrzLfG=NWXg$ z0cFhCc*GMeEG*V=EYTQC!R39x)4v{HGk7q2$EesW0<%z+#J-wCyb#lXxIZLYvE`Ey z7<$(j$|&rw_xlTR-tH10hGhcrw35>mZQ*DylziF!5k*P9>X#8t7qj??lmzwJWBC qB!pxR4NLJdp+|X!Rhe=i3cUoTZ9xFJfV=+c?izWmqYdi6j7r&EnWY%GbTTga zrnMx@1-fau>Wuahg9_GFB>6gnM;25l_PtUVsVhS>mDG{*VO!A{=YJh7>5HWb_}(eg zcY8 b-$wqy>>iE+@Cbeg7#>m@}lEvDfLJ8LiBs9nO}UkP2r4$ zA TNqp-aL`R2w(2v0{u@uW7tVb$>LHOQwITX?cUBN5L4>$B?#w zBoU%SfC|f<%gXjZQJ6qQxdy>TDc@b+7U&?z-NO~nj*Us5{cu=za#RA!@Qn4)m3odX zO+#*4_#tOaU0&E@&wmmj;X4NBQNec14R`bF&O=p&ny=|Q)rC{gAHSQ4+7v3vqJG=U z(r-E7B+WfMJnUrf3YJ>~X?U#fZ$)W4@b>xbVYaB;GaWqsv8&hvU?^-x>x8zpDM$Ef z6q$)?wPVkx&rjk}zZ;uF&fwjLv&!sMzn1qW{2Bz4`!qTBIkM-a=iih8Vt7Z^!bP&{ zAN>?Ol$cFmw$uFdEi5qVka0CdBrmY#Vo&A59Uj#wBE;J6`ppAT5Rw?Q eT7S+bD;P$m5i|OhNl5e5)Kn(Wt~ u;V-QGR~@2agk123YX>sYZj} z&(g)`Lt&C7rb2#{n7#&)w`odBN{Qr{>e7>@N{N|f3NPYn*(K%;-}f?xGZQ`q&uu(( zesYQzxLL siBv($ zSBpuO&>0296Qm35h3rz|$!j{ECS&~swsPaScnwoI=o8EcHoNPrCEXKHO&8p* qc=(W^c@#6xvA5#a*3Q$i>PTq#g z^>Vl>Xs71)9EPuCp+#nc6nxL471uJ+FHeaDQ&UrMGk5%G7D|cDtAu;wFW45$YM^~} zBc~pj9&p7_g(hFaqV}8o4pg)ILInE(d+)5iZ&uS~TQ Z7Pto3axiV0L;r4bSHe{I234W>Je==u&n=Kj~6mnEXt-==w>;lhhM)QN;bEYe_U zSzKJasI9HdtTJy4Bn{WzYpgl^mrK>xYv0a*vwX|i&|7D`DoQ`Mc!yYQq3gqs8KivS zG^O!fz_pn?s4su?$ofz2{G*YHxwm_ LH*g4~K(+KRyT(E&k+1F5IRsr#;R*~90!EDQgnyUM37Yc7KDqo!tqMUjfbI}|S z7Y}9P5LR|d>V$0Rndy$vgG{iCBwip$^yHrdle8r+Hg#Nk3rLm5sF<&tl7a1-7alZ2 zuJxQ6KPd6$V2y1_Q ej-3w$-0pl{LKA8NiZ0b5J~^ z@A%zV?_%UY3Y>B{AtRK7R|5 MtJ?i2A9o7`M=R7-1xIOpFPd?zA}S|7l=IFW@-R_~(H3vq+Ndk-1m zTnXW?%%?+H^jIolL4T5;P30gd78srJ-V9qdkH^Cy!!8f+DEXUFCza2J@31K@>ewTf zx(Xd*<3H9qvZhqn8T?dwHi!=TiIbyd;5iU=!j@sYkW1~qThg@>aJWxTjBC(yj}^1r z`Nbxx)lS!M4ZV*!#S*#qpP~Eq)a*53P-8A~t~kjVdPP8~;6=mP3#9+CbNIuD7IVzp z8KwKXUZucsxyiUqYTt{Q!X0vIH79-W7m{|pxpKR*pGzdz@p24 ng`*XjH$A3q? XgdS3TH^eY@d$UJ#1Vk+L>~a!jpC{RTf8#dOcR%Ax 6PhI<})e# zuP_R5ss9}xTKdRVS=3#`T%^P>&IQg7 Ku-?c=p3hsE%j5 z<^ 2#F?BZSShZrQT4NiTtv+?l~Nt5~O`ntn?`~ft4mz}fIJmZdX2nCY! z>~z(6OsbL1tS)c$C Ufo z**-;k>hBX LlX`xE=jVyCfEJSR>3yOJ6WfBXB ztuH4HBc1Sf_RW6Sv1p^Oj4_+AUkRg%6FteECu>>uz260dv57I4w^+AjCPA&AYCq zex*N1wZLdlmrXrODj=%;+u*?@yil~Q;UO06MK$)?hmyV%;ttD!_vCt3%9{}Sdxnfc zx#nh^F$TCVID}q=j%pi26NM>%?7f5k%XT>zDs#7Qd8}q>_D!vX#*Q$(Z_8b|Ent0< zhYusk1~sN9o<2O%(D{`7HE3&KpEyFp>kJm${fqgpySuxMV=w&$E6ZRL+L0w9;g-|M zLe^#tp3w96sC#y3lvVra?%lh$j8y(Pmv ACr6nIR)4#kjiMSfPxI z8%)>A`4wcE^dm~x1a(xarmWwb!m~u2`@-qNaa-4VDt)DDdF@gu^B6n&0ZJU*lL0X( zu0pC5*B4L&aRK=;i5m);Vy;odEK6*6&?*JeGU<@}mMcGGOtx1|OicWoE~k?Y=QNAb zjiamgljV`nb;`7&t&My%-T_-`0MJhdi_y(^nuLOW^RPr9g&i>(FUb}}P}NYB%n=8} zw-gN8Sh-Oab%`0YpVBG}?M15KTwxp;fVJ*OWJzD~Y!CZ+ ZV6ewK;}Tb`tm-LF38cdMf{UPKG&SBaCG?0(ogD%CpmSK%}E5W?@{N7wGkO9#fc# zt^`-F87RsbGY1x`B`Fj00Gby#l+l+Y2u%dICtF8{E1Eycc`o9Zg@cYj=#zWYl=-!u z%eE620H_A6)~t|wX#QRAP*VkpU(<`>SH->ohUQWRM`O_-xRRoUT9{oUgu{D1K|Ar! zYX{(Ol@$0U@!gEBBK(IH!Lz;CiPe0VSCLO-#k4Eo=I|_nEo{Ei_rt%UF15ID<7%?I z_FO377DdRkd#XSCfPAHRMdlhzOp)cwQDLc`Q#zCmF)OT}36X<)W`O@Bj^*}~=7#&` zM!nuYL{1L($@qG+!(q#Qt;mw&2b)b{`S8m`u_T5vE8>K3{hLW^moNvk)pC=sm7|gd zEPJeol)IIwFiBRGWy)R@-KY3YSRdo{^tV%(ndoKW)j|a)2~;H|qU^ffMeRoe!umDh zV5(Sb%JVh-8i7aIlfG^+J^n5m&WiXY9Fjb9>tI#P0eJ!wKR{M5_$7?9ZPNSb01OZ! zFuIeI;;4Agh;>bOmyx-khw^Q0lLipU5EA2g(rG3^2%1dvEtYmoiEw~{zRTbHlNxC1 z`~;8BIl^s#vU(2ZkuZ++NJ9|jjOD7aMoQ #TJ7|9z}v5l$yyuAEAt!_Wm zy284M+~9x9aY7PwD-2+WuM1_cmp)yX^+5YHreJiTQx>RrQ?Qi$Za*@Y4weFIPX`cj zU@4|auTuzUC}UVSM)QeHCeI-u>+ zS@@L~?C(ov7U+KW&(5ujSJe(uBrqG1rO!_2>FMbj7=+!LIA8vAJV*h&3i & zlJwj{GK32dTr$mP `?X^w`C-@k)%GRS9sSwA )^VM*HZsB z6MmRrkCQwkK)O2W%E6M~^^G=?1p-0xn+jk}APv 7QUN^+R@rkI`--A-8&=MRcRSbBzeM)m@s(5OJ%D~sx*Ms6N@9~#=XuVYER1yyy z5ZoTWv;00@0u*0sTUS?C0u_){P8ue%+CSDkf4iS^=wA3K6xoF9q@Ejn ff^rrp5k192)n*|#$(m{jgW3_3nSo zPGHVQ9+mdVosJ>fo`f{OR;Zs{ Sff^mfUA*MAVwor>{@K7S!TP w9uDNombGs~A&~9uL+Mao@XgKcoi+(Ug6F+DJ$@|h2d_XVBr9TtiCfhF0YLgM-2eap literal 0 HcmV?d00001 diff --git a/src/static/tabs/user-active.png b/src/static/tabs/user-active.png new file mode 100644 index 0000000000000000000000000000000000000000..0a8082288c16e15b052b378f17b3d74520869e4a GIT binary patch literal 7563 zcmX|GcQ~8h`%VZ#s}g&QP *Y%wDx}W=gPNJc{1| 4V#f1Vyu>n9X6O;NSlqIYOqFzJh}J z_+FP)tFGbXVD v=$KM>ilp^NHx>|hyHCn zYX{>yh=g}}KyAcR9W0MGj#f2yNOIU#|7q|Vg|#V}eh9i)H1=Nh$fIz1%1HF6Pg2IX zAuZr+f}d?PW!^WVyaVI3Ds?#8y`~ T)xzp*xQ YQX}K?tO?H(OmIAGA=as+TOTLMp;1GIUfH!) zFAzGesh#$Rx5r(XZ+&F*_*HDr(&GZgVeD-(SkIqC;)3Mf_%9EuovkeXNK6Gz{Pm5* z`7f1^^#1*}m>Zw(4HhTwA2TTrhQ5nH0vdVwXLItw+gZ@l6j3#f&pCG_N1jw`oiv$B z3A&gxy_t}bFUg-j#M~#7oKgg|)hU@$Gce C4?hjshgAN^<{W->{$S*jgm7>3hoAQ2?U~CbpVoBdsQxYuyDYeZjn%Bt#IR>d zH !U11u{a0NvIwEmPSS$7&3x^kF zbJ;VFN6aCpKfLj$DzRkwbS$8aV;1W*AP@QBWIA-Q^PPsILq`Kf!pnnnqSAHoTpuHc z?BH`aa^8F<3aLQ*kWU &Oi0Nhy2Pm4-04%Rm{>;o_;$y%*PjGk z#gGvPnY@X%DYBeJ`YTmCju7h~!aFsBK74+Da|a%+t}&RjcDJ0>i>(h;Q*N4TIEf`Z zk*JTCCVXEDH`0rtH2SWtt*V0-c+j=bX1 SvlE2I+ahp$r7&-%IVH~!x{ F+! zeg<$2Nr=^bE;oEt*u>IlJ3n|iuYPT6&{49v)33i&!t(@7hk!c?JLm=|STz?PZ*E7d zO~waYijyzIrg#+m<7BwyovnDlO=htCGjfGNRTVu|`3Tzd;T{rM?IAN8I!iTmCNmS8 z();LfW9qE#ig2fp={L0(b%B#mW)z@DMtKNn3(riOm@CHS%Bp+1EST;hqio_wtgzTh zn+;V2q-!;RVw=$rxXLZJ+}Un}>Zrw(wwP?(TBxhPQ7Y^T+h1uo8Ebxn LzE{5OlUdXKGj>6` zQl3Q0R{1TNZ+4mX2u~9WFg^1($Z|B=WPi&)Ra2VrlEn%fr9EL8SIj^ziI@qc5=zQX z+N$ZFgGHHu46WPF8&U2<&L%M$g2R7pB_}~gV1tJ*@pp5>_Bhqpy6Eh-0~OZOpXVk; z)1!l$)YRhYor!hO9wkBd;C}>)ZiI4P)El9_Z%s`X9_cVu4mqW4vIov4y;sWyzIU$n zO0u>mci`mP|N6mwx>f(Ll}X8DulD8Tq{*(@Hk-5YfTbMZ8!c%DEWFWfkH?UlS&@XX z+mdBe(Jafi!`u18wbeIW;~vZQ*$OZL)G+QP_OH8l9payY=~FR*ue{QJSMyBd+4k@E zacO@C=rDnx447uwv*q=pUiPWUKkSYv{F%GZWvTb!dy$=f6RO$AogvlkmKVy@Ajk$e zs>zo1m5eaaHFg^q?6>{-H|{$7HV*=@Nv`r;;hNISQCKx;k=HJUE`uG(&S|G9@<#5Q zQ+mUuz 6U5BFSsoT5&OCEJlpaoB4emai5)8gW~B(}87z5{ s_MZ!}P3qJSifm9Rzm8w-l|= zPvov$)`8`LNDRUu5f2OA3GH+;0GUw_4MDIh#eTSu&X9dgh|;GR6||8qbR!fJi+j+| ztOkv;N9Mt}zH7Rg>cI$M!RFAN^gHBSa-{GQ<^ov4up*Xt#Ufwo^$H7JG+guj9_286 zOnFa8kVXDM2Jdjz9aTuTG+02REM^@VhOdv1S`bODc|JOuXj|!j+iBOMjP>9?OI6qV zcDJAJ{Cya~pJN{Osqrnx(Ar*A`-|Gvem9fwV(7wYjJy^uXLmzEdO;u~@hZJIqfcB=S_6)4C^R#P8KJA8)Sb!!yNhzSL(D8eK-hxZGdp1LRL9)eZ0m%_Hm#ZljV zr-dg>dTraksZ)@q!oo<@AB(Dgx~s{>C0NBmp8AS5?lDe!boA0x#0SKGhdx4pQo83Q zEKQ;l z30uM41%|;a-e7Ko07qw!UWRXQt43B%)=7%_Rs1B=$=FM+$wA$&zZ#A=C`l@A1Tv~^ z?55?lj&q4gW0gvgl5mTZ$oS$ktD?7D*lxgy5DotMPyS_n0%<_%U!q`ZQ#4gU=25FV zYVz6NiAO=ss*tKjvns_Of7UG%MZ*%a=#Z1UWl64D WXy=--gQqr~zhbWLOS%Rf(=Gd@hj5$iz+^@=>| zH*Xq<16IAR4&I)bTD8$p{yV$#on-)eXd4>v@2__actxd%T%1|7EMI*Krv#QLaB{=c zwApQ5(%c;+Ni%Fp3*dWt_Wb++oY1l@s6h)VIj7z)7sKqEBgB|EWDW=O>e 2bMGz z{7A?kOR*GNY5IHZc%HualJ69G=CpX<@tc4_o|!iv7{0 mWlv(~B8 lccWvg}2TVaE5Ow6(F5H12*|dAKTO)xyrg+ay_$RCLi@; zaM^Op5>@aksX8WLwAt-w5`ygKZMho=ee+I sDvn|#r>10w<+8;eibCMrTVxw>&4t3H^O>?)T)1FM|x8h z-D_M`@2u6_F=WQlmc%$eM z?%#85^K{+zXCj?rT67{Sszn+AAH{79JC3w8`2_2MlOFl0q6LXIec_rIr6ima;M`?= z%C6iFOSMUJ$&9PF4VuP>`tKBKPHY~_9L&GrD=_*^$^q>4CNc~w!DZ~;px7~;K9o7! zn+ujgO(2VVvUueSf3F!zMgbb7-Ys4;gGBT0t^8#72ckX%wI0x%C1!koWbOHjc)19T z1T!(Q)0y&{+K|!2KR<(Dc9r4PZ`N;a2_rzPEenmn;;@(IUP$#Q#${{yoMVcv{(qso zM(1&vLYUoxhXoBnMm53Q8i)iB+`H~={sO0?>*CenWIE%hAib7KXp5PDPAG|b_NLEu zd>#zGkxgp2Pd7$6k? Li*UZjb4co(Sp#DL~Ak)oHu>j&-5^fJGh1~gI?ZNQxXh2!}tnI z4?~;^00}zy7M6U i!md+b7o_SSo9ar~|$~6?Fg`Yux@^T^iZs*Fds8 z1q8L>?o83sm(NA5i1UU1l^B^At@#-N{P<9Uh!9To#07EWVLX^pxbIi;FFip7(4^?K z<#=n)s^ex$kLsgwEx~fkB+cC4{0^hYz7UbWA_FvEJHtyt3A{9K=>JAnF+#-dNl+l` z=TBH>C|CsX6r`-t;NP{yzmO7{d^`k5JUHKN#}j%4lK=GriYGtSoEa44XG qR1M{s|?55Q6g^b2) %r@KwSHw|s+ip*Eoh0SD$m$*Bl?be+`PFz8Cao(sVSStB{^!E5zFjP7CaQJe`A zL=GR182%6R;{QP@5<^dN{#%4pii?Js5L<=j>H6E-M8!PA|MA8)x6DLM*rOt!>`b8~ z=ogM%gKX&&-lPcv!!Tf+-0)iT1AKeHkLA%qfBC}b6y-+N91ECYdQItcr6*_^MC zhGUapYaOg#ogP>9A%~y!LEg{-5*7_gIf{BD?!R?Fo)9NK@m86q1U?5{*?AD%=+ZJM zQrN{!c+5o?FcHhgsEZ}Oj7Ub>Z$7+dC2(&;yjUxm2Yf(6wP!%bkl^iof24PrlZeVM zrVU*xm$|ig9z0U^3vM`|Z68>SH?-%!$2K5sbRW`ET^xRkAQa{b)lDul%RvW65%|!a zp#*yp;73wC8(udLf@cF&l+MGG`fwcJk0hsg0*5Ji1ZzIfP5J9nXv?vkXpS@#JqG3& z`dan_=2L*Twik7PIZPEiWwFy)pyAHvV_$qDuxKdqN(Q*{9&pGx&eKc^9AuxMYk-JB z8{ATuE}wc@p@ekqgym3`da1>dB_2A3qZ##NA^(j-#i$#miyP@=zoo*)eq@C-j`W@h zzl-RP!VG`qj^y$wNytvfO|a>#XlV~yfNcD(H>u1Nu(7xB=dd$<(DenMd%3Hs+^^fO z-*4EDQ{0)&_PT{SOk5UIt S)%}0 zlL6jrco^S6nE9xbiBYTHjy4w50N0T!` h6yzEk>c&T~dv#2Od&-=Ss|YbOys-pCQ}*6vMW+yG z#>I3&rSWHe6T2N@ot#2YtSWEw!(cA2ADtVun&0K!DfS$;9LZ9osasuDfBdLh#srYu z;WvXqNWujh_!OJ%Z+SdxxT~AD!^ZeE+0kG647*0^>8P;Ta_<`tvz3nCH!FPzuSHlo zV!4{feUqYAt?08{(QY4;j5IIipeuMvuVD+X8^HMvHh1AJ$I!7zpopB21u8UE+ p}kj~}3(h{ph7kG`PK#KAsyL;RzD4W=4&9A)3K{wFx+OlY!=k37Gr z$0XYdg*+a^^_zTlmwL-)Fp&C1TKs!UMU6WXqTjtR<NJzlHBlVfb{#}Xq z607#vM2sO<;`G~=-xUlrqRp|e4`yv|Ac4f4pGj9TwN-C-7R_QkU-GT>m1q{7bR?G4 zCP)(tzs}P~UppNIp8D~)dTLptHapGhKk;UN%VJhD1}9J@-+9%*KyIeR|JwYCOY<*X z>k^< CUsp-x3V?DJq+Y`S?7Qpmz{vrT& zATtjlRac}%Jw~9kgan-6rxwoL!zJKZ-H o21fNsZZAy6{B^%38L*i3MILq17qn zNxj8dvGtZ5+ag40In2^bR$&JniS5R`z=(JaWmd~yH9zj3=K9@{0xck9*9Ys(6n%ML zPrVV4-Z0dWL!3|kGzS^WlCLZDQk^Rf1^ AzQ&ILcf6 z0 &H}5zisJkeP5hS*pokQb*sk(o0)ORpQ~jf zx$5znEnGwd+1NuYYcLR~B7c$bH8S!=QmUtOGc_pjAyZg$xQ_oxi+bM8s 2H)nh748yl?Wq3{=XuHoOvBa=PrHQ{f&e~-n3XPr+HUr$G?Mk!ZOCSd+FS5DDR zN?PRoiE^z9M@3E8h|my|Y~zNu-3&nD7xS%Oe;@ef=(bJl4wSUmB5xtoyJNNgsA;8{ z- &QA~t>J#nA8T9u;;Cn}Q1kIh?Y%h_bn#>PoPd42g#c%eS;2c!va;9|!xe~T zed=` aC>2x3k|6bl2_f7{Pk}DogUt&oXL#hRg#y2g zb_vjwMe4hmwWxe!1Q`>dcBT2FzzI;dhapgIv{$B8UzILI+29X5#!9f(@#`P rZr5I$NE;sTL{O zA6=N89pt1#sqIp+R+HdZ3gC_ri?H(M!I-p*K^mEDg|US;|f@{)JK1@-Qh!bgz4T z9dYayw}Jw4um7&I#y}R>fpe7LGYVV1W{8d*|2qxoYCaGpD)z9-g$J%>zFpquxr+is zdoW1fn_ks=j#)Svr3KRxY4R;SdKkDyMDXShJL+~+5|I%OJHnrBbI=m-U(r#I1Y40U z@`Ds(1-k|y?Y>2A8mAzq(MsiKYl3#&S+r6PoXDbfiEx$ale7m_3~L!Um>vY4#g1W9 z$ciYlm^I>>`vHcGP{(?IInh)KgzKRboD=1?jo-c!4l>l91jo?>RWiIJ*r&eZ@LDvn z2~MHtZcJwKwbraX7lS?s;#OL-^~B=S0Rp0&1N#wRdC#O1yeB( `=e~!@vy2dgBt6KWZ^q%J{{5=Ja z&0)&M5lL!6&zGc3NzR>gMn|x1xp6GOofbc3gZddRBV!O#1I6?kuL|*}f4R-t7PR>~ zBeiCC$BmnULBJ% z$$j`MKsevUu={JDwbSg-8}( 6&Q&sMeAfTJC(NA2b^ zAFmoZNiw`!y#8vA3(}9Z!DmT=J(2;vHVbv%_9K~cvBqvFLdCv4dqlC7M@{toKaoH8 zaGq8itQ!@DNlr`)m^~gn6|EMhc~TJ8EQyG<+=o8Bydw)&%ndAkaVz(-G5sF+109ec ztPAGk`+`Gva-V+vm7VX?L5-l_a!k`tR;z^fn9|G~3PE_L-)}3@c*s;!5*dSi`j% k}&JlZIyU=Z$;{GqQjH$Utu$0eue;N zTp(yKY!5fizli~ib}oJ&r?n7D4sgg%rN|~1cZp?G_cyBB6>+J}v{>pCz@*(Qj(4`+ zYgzh8NtB|zQj;HIi(4wBT>M@~|KGIspVR6P8&W0(QlJti#0z!KPd!L)M=*kGWA7MC z|Dg!l-46bE@9-``yLa7A78@1)PvGCB9=!7(Xu9YfV{?!4$_)?zxVdR{{Ow3MQYHP* bKM?~W^9y+u-xX>Tz5uk;^pSNc_Ne~>3O)jE literal 0 HcmV?d00001 diff --git a/src/static/tabs/user.png b/src/static/tabs/user.png new file mode 100644 index 0000000000000000000000000000000000000000..6993189dbb4f1f1faca0548042dd01431e93e49e GIT binary patch literal 7132 zcmZ`;cUTk6*9{>+5X2<(YJgCrBho<$HMFSo2ucT$-UOrwq4!Wj2L+@`2kAvHfKpUC zDm5ro1S!(Ly#N2ceV*C9b9Z)TpV`@a&bbr&0IhZX8rwAh0B~I!rEWmF4*gfal%(@p zvzh_`00PifM;iH)ZRgYY8&72ns<~mMA9w~Gvor3L=bt`ftPW2C8`sC3CYFAV_PP52 zLh(U+WQ$<^vr =Q6!tYDmEolFvMV%&;Oj? Vy@!jM=v~}2}A&4Q&4f+7 tg_MFxb*lgBe^TJeO_i3nfKa3gH7rG?BKL%3q~84AJQV{k0u8GbIgI8U>JzCB z4-XxuXJ)RNYHHkU)YQ~izulg6BEnjd)ik+zakjt4@;ltQEcAoYbRdO>p?3G!+CmY9 z$x7JHA7%FolT#Ka4laiBBO@c@Tikvq Ph#B``wg8)lJr}ikWFW{DLyN5B zp0wrT<70RF uya4>hyLa#IB@KJofg0FX{8&}Ui*YAI z@gqX<@Qsb2=@kGOUkpWzNIqQ@gQ@#MX8@-|jTTyCA9G}7k`30zug*vfMV|QZ)42*G zX 7Y{HDo(y3oDrycZe@vlFOmKTE^dDh>E!cf~b`R@p)Z_K=dx8>gN(Q+G?P>_QE( z2QZ z+Hs#y#n9 z#lFF??WO7I>F7C;K{lgUK~ptY+q1%$u@@U9uoC)5&CSjIa${zMH}udMzU?DocdfCt z-|eSY>2S U6anDH zDWE*q59v32PDl0lC%PNS4a?9M*j>wCXBmu)jPLf_l1{Z|=dQCReh(e%h_TdgfVFWh zil3#_<(gsbhCP!lAKEna6e5@mH~_36N#9LOOpac;2F{*<+Ss#uN4x=`dsRh6DsE-( zq<>^wW{)6rJ5G6SeS>L3+QyJJqC7*3NDKTRobXihtPy1+P_jOTbSRkK+}u3Ne$4NH zw+VrS+(Bed<=^mJEI?sB^3{O9PmO+0jIi|}F!#e)!YmDk#6D;u(I>7$I)kz1)Y>7N zvkr(6z9cy41xJc!0Q3)ij3@ViTo`86#N}7B%2?nZdpWe8`dy?&2FA*-T-f$ueVQP4 za%w6#xp!zAX>ZB$*3#O^n{EJiQ+JNt=P6mL2-D(#mX^bstoT@+H!*G30j2?|@wK3P zUGw|xqqeP@4lYq$c9*Dz821(4v25|S2fvNRT%SJ8n%vl(eW^!_%u*)GxVIH7@s#Vb zyo&x*Va7~2Z{ofiSKCw%suvqUNn72zkyO{hNI@RUjk30Wbq@Tjz@K-akQ~A8?kZ?S zzS8*bchMYqUjrd5AC)DT5P{D`dwIx{(NFihUbQ;^m1ok$X`Ujoq8R+Ip8S_U*an7f zJ7Phd2dv5 M~h3x8Abc{f 6*MW*0gHaM@|VpUL``g3r JeaVH$4cjE01q}CWM!(eduHrr h25f%iIGoJJ1i%R*w$HxT>JayjN;P*!E9Ej;Jej0Fx?sjkp z;n?w&b3#{beuD&;A~rPgA&y0UQFnj;+V>X5F$d+ko$$Gri_(TPwI&?YHVg>Oo_i6p zdSQVreRUeeeZzHcRVIOaD7dnapu{y8=mZYGdi^ ~Z^@xLx;c8UA`6@Qk?5 zdIdP+-Fuku(edN8IB XHg1AKAc4!$bfrt4Dj% zHjGAB#xWvESoT~>18 yKk;kS%22rl%d0!i%bOt6c?|80z$H^MeP)JM2aWUXyx_i;GLJ Co^f{SV~V{;_R+d zCA&k{EL6Rh-;4l4UfCg1BDZdmEI)k?WIP`doH_bbM(E7ttsJ4_+g(q}T? (~ zY$-=JWk=y_%e8OcD#w6&MhG+S-@pIndeC3P?u<1uHT~r6;7Z4JLr_SlU2+?F=TJOD zM^yb-a6osXbGMj;jK|LxAn(TO`C~xwm?i!SQ9JM_+?mLMTE$0gaG!ldqW8#Mn|^}& zy07hhh-RxI_pned3J2!ZE;n~^iO|N|R^7QwP;>dXD}U5FN>E|&AvL20QvbFoVW-j7 z`S2v2!i(0SH*2HlMm*;%xGPp25+U^{UOVpUIV6!Ew#`8GeBXvAZTNtSiur#1OLd7+ zT>+rm9ViH@m#y)vw1pA24RuI;+0snk6!Q4-4{8$Elj)gTT=ohK?AQ}7_G8)DSNkW! z9|ceFzu(G3ZQYrjtv L-6g#UJa+#zsa)Q=@)gW?k0pd8m2Jw0pI; zO^J h55+ZdaF2*gb`<+;`)v^5;&c&jiA1o-4Sp|iY^+sUho;i8o)QvKoeHjQOva4| zK(e)?KL38I{`;`<4OcuEdYPo~$25nU2}|uN&`ngusfP|IobhSXDmb6|_#5$BK4GK< z#Sa}1Jfup8=ZB^bz>&l@Gx6v1dFjdbzZ}1W(WZV~wm7W-%~A7d<46?S+iX{{1KnUq zZ+-rkEy)|5)*bz&E$Fm_M7V?HDMmgFe8CN@F&>LO`gryx(O;rKm}r>xB0v1{*eo5c z+)J)aWC{qFx7sdvgnqZX!f*^8N@@M3wH`ReHx3$}8}Hmf0Y!faHRst^+Gw8WE^v5G zN|a?;7T^3eQ7ft4vG*CI%7>yWx4)gu1gk6{(N(Y1K=|}vqY;p;_h2n{bMWD(w1pe57uY>7 z2>g0cZ%~UR$zM%38V?>Xw8^n5F@a^UP&+7Wc nN|=va|z~cK1x`;RnB2g#t?nPmo0T-)cg0U+=M$o->j=TCz{9H@LApo1QU#& zI8bvG|FvZZ7Ll@fhe+2O0!z`_df-G21;Ww<_%w%{xc5J$38(Oat!_Blwc}GZxrvSi zFRB!&l0pZ-0Vo^(`oEhh-N(taND^myM^nbKhG|SD%TeNu)6tE9-~`Zj`6biMG(YU3 zAQ9o+DTOaDPge76I(dY8D+?d `s9*+*Zgu~B*8^CD@1~iU3bj1?ny|+vUJ8Ux zHPao*$Bc|VKnF%9!Sy=46#GT}dzfGIv4Xch)DMfo&gy(+jX-2Y9c1N{!@At4-7kM0 zp>^+~f|*|~swhXFer%<_NR`6=Engen?|Bu%kTN55o}pl=;fBcI7&1Mxbe6pXTIM)e z^_RUyU8$t6HbMF=qYQ8EU%w=Ul^sJ2M!x*@>lLj@+kb&TUshj!H`N~Ejv=13iq>B0 z1q<=i8qXG!Am{hKvPir>=f7$VtWa@78^kD3xrP23R>He;s9d>8>;6tpI)3JRpPqzR zh7Kp{c3!BSZrOxzg=L|F? H`@+(QGVlYB~@f zGe?#8k+l33#mu82FCb(nzw Je?E-!%?0R71qv1ua|1HBVzrNAKZ`F0LJrDlRH2 zYE^r^>czo8KR)zHf7r6zm|idusqZ&R4jlPC4io1dPOQnnTcqZB+1CmvhCx7~5gdHV z@+-@VZSNm%S-<=tJq}h$y`QBo2ES3`L)4*eL6mW1Z!IM3g2FZ?o`!%{UMG;PcUZ6( zu=nu-9^OW@2&X0t{miW8+{=I`CMI5i;pnU}jUL`~j_#kTa6%+PBt^{UOBRs{!MgI^ z#7`!O4;2^~*xnJ< da=+kQjUeu!Oi^ndp|0`DYI`T?Pn_-0!@pYsp;3mXP3XJ?P|#hIFQBp$%B^@8o}%-<}?ee=YMY z9zeCzLcVgTp`p>zcHHbH#|JL^9)hCz#Y2cJHD(;-e0fKvC@w`^g>Ifxq c$CEvT8 zm0|X~vmF87=Qq;4D%`Hyyy$Naxj3Cm;#e?G#A*VA?XvB1X-o$D^11y~aYjOXWzW~T zeDhrcPl86%ZyDY_d|h-#U?xL Z)YL@VPd%}iBTfoa zH8&+PaZTE2Sy}f5k?``3#`OCi=~f7#7-)ovzT*uenvzw6DnZ~69^9~9&dJw1rg8QV zt;JT7*q-ZudTmwduuP;jp$xscP-%mJE?NDMGyUAmIzW>^otocHnGL6_FQ}@hIO$b4 z_2mf*H5ACEDCo0dUulzIF<1UModq{ A8xD|F^PCQevRqgw;KV@(2izb1*FtZL{akK=l)ZMH znYr+efl=uIk4iV|FFjI@75b)k4l>|F8PL<-etQ26UDcD@&`>x*9Ht@rk2T`fcno}f zW85h%d)1_iOU`5I)3@vXSA}^rA(VakyjYL<(bnRo3cgq11Xd}{F`MkmBC%Ok#912Q zg4VWFDu&ym(!?r9kt&f(S-~D#_(c-s?fv%&e_|}%M81=N#$&!d@GNm`sV_XyE%r7K z*t9Rv@`s+l } zR2H2H13AIzczn+|UzDlB RJe;!CC=H%?GnAM~8 zeqLvDulg(`G)+sgYeSKWOg%mjH1xL3;_+hicXsrGJ~U;#LBHGk%WG+*LLP1~Mm3$v z%9Z>OHpX^NCLrq ({ + version: '1.0.0.20260905', + baseUrl: 'https://cxx0822.s.3q.hair', + showFab: true, + }), + actions: { + + }, +}) diff --git a/src/store/record.ts b/src/store/record.ts new file mode 100644 index 0000000..c9a8578 --- /dev/null +++ b/src/store/record.ts @@ -0,0 +1,100 @@ +import { defineStore } from 'pinia' +import type { IRecord, IRecordForm } from "@/types/family"; +import type {UploadFile} from "@wot-ui/ui/components/wd-upload/types"; + +export const useRecordStore = defineStore('record', { + state: () => ({ + baseUrl: 'https://cxx0822.s.3q.hair', + recordList: [] as IRecord[], + recordForm: { + user_id: 0, + content: '', + image_list: [], + video_list: [] + } as IRecordForm, + currentRecordId: 0, + showRecordPopup: false, + recordApiType: 'ADD' as 'ADD' | 'UPDATE', + imageFileList: [] as UploadFile[], + videoFileList: [] as UploadFile[], + }), + actions: { + async handleRecordApi() { + if (this.recordApiType === 'ADD') { + await this.addRecordApi() + } else if (this.recordApiType === 'UPDATE') { + await this.updateRecordApi() + } + + await this.refreshRecord() + }, + async refreshRecord() { + this.recordList = await this.getRecordListApi() + }, + getEmptyForm(): IRecordForm { + return { + user_id: 0, + content: '', + image_list: [], + video_list: [] + } + }, + async getRecordListApi() { + return new Promise((resolve, reject) => { + wx.request({ + url: `${this.baseUrl}/family-api/records`, + method: 'GET', + header: { 'Content-Type': 'application/json' }, + data: { + skip: 0, + limit: 20 + }, + success: (res) => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(res.data) + } else { + reject({ status: res.statusCode, data: res.data }) + } + }, + fail: (err) => reject(err), + }) + }) + }, + async addRecordApi() { + return new Promise((resolve, reject) => { + wx.request({ + url: `${this.baseUrl}/family-api/records`, + method: 'POST', + header: { 'Content-Type': 'application/json' }, + data: this.recordForm, + success: (res) => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(res.data) + } else { + reject({ status: res.statusCode, data: res.data }) + } + }, + fail: (err) => reject(err), + }) + }) + }, + async updateRecordApi() { + return new Promise((resolve, reject) => { + wx.request({ + url: `${this.baseUrl}/family-api/records/${this.currentRecordId}`, + method: 'PUT', + header: { 'Content-Type': 'application/json' }, + data: this.recordForm, + success: (res) => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(res.data) + } else { + reject({ status: res.statusCode, data: res.data }) + } + }, + fail: (err) => reject(err), + }) + }) + } + }, +}) diff --git a/src/store/user.ts b/src/store/user.ts new file mode 100644 index 0000000..feb9138 --- /dev/null +++ b/src/store/user.ts @@ -0,0 +1,69 @@ +import { defineStore } from 'pinia' +import type { IUser } from "@/types/family"; +import type { UploadFile } from "@wot-ui/ui/components/wd-upload/types"; + +export const useUserStore = defineStore('user', { + state: () => ({ + baseUrl: 'https://cxx0822.s.3q.hair', + showUserPopup: false, + userForm: { + id: 0, + name: '', + avatar: '', + create_time: '', + update_time: '', + } as IUser, + imageFileList: [] as UploadFile[], + currentUser: {} as IUser, + userApiType: 'ADD' as 'ADD' | 'UPDATE', + isRefresh: false, + }), + actions: { + async handleUserApi() { + if (this.userApiType === 'ADD') { + this.currentUser = await this.addUserApi() + } else if (this.userApiType === 'UPDATE') { + this.currentUser = await this.updateUserApi() + } + + wx.setStorageSync('USER', this.currentUser) + this.isRefresh = !this.isRefresh + }, + async addUserApi() { + return new Promise((resolve, reject) => { + wx.request({ + url: `${this.baseUrl}/family-api/users`, + method: 'POST', + header: { 'Content-Type': 'application/json' }, + data: this.userForm, + success: (res) => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(res.data) + } else { + reject({ status: res.statusCode, data: res.data }) + } + }, + fail: (err) => reject(err), + }) + }) + }, + async updateUserApi() { + return new Promise((resolve, reject) => { + wx.request({ + url: `${this.baseUrl}/family-api/users/${this.currentUser.id}`, + method: 'PUT', + header: { 'Content-Type': 'application/json' }, + data: this.userForm, + success: (res) => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(res.data) + } else { + reject({ status: res.statusCode, data: res.data }) + } + }, + fail: (err) => reject(err), + }) + }) + } + }, +}) diff --git a/src/types/family.ts b/src/types/family.ts new file mode 100644 index 0000000..b0b9a43 --- /dev/null +++ b/src/types/family.ts @@ -0,0 +1,36 @@ +export interface IUser { + id: number + name: string + avatar: string + create_time: string + update_time: string +} + +export interface IComment { + id: number + record_id: number + user: IUser, + content: string + create_time: string + update_time: string +} + +export interface IRecord { + id: number + user: IUser, + content: string + image_list: string[] + video_list: string[] + like_count: number + comment_count: number + comments: IComment[] + create_time: string + update_time: string +} + +export interface IRecordForm { + user_id: number + content: string, + image_list: string[], + video_list: string[] +} \ No newline at end of file diff --git a/src/uni.scss b/src/uni.scss new file mode 100644 index 0000000..288300d --- /dev/null +++ b/src/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color: #333; // 基本色 +$uni-text-color-inverse: #fff; // 反色 +$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable: #c0c0c0; + +/* 背景颜色 */ +$uni-bg-color: #fff; +$uni-bg-color-grey: #f8f8f8; +$uni-bg-color-hover: #f1f1f1; // 点击状态颜色 +$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色 + +/* 边框颜色 */ +$uni-border-color: #c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm: 12px; +$uni-font-size-base: 14px; +$uni-font-size-lg: 16; + +/* 图片尺寸 */ +$uni-img-size-sm: 20px; +$uni-img-size-base: 26px; +$uni-img-size-lg: 40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2c405a; // 文章标题颜色 +$uni-font-size-title: 20px; +$uni-color-subtitle: #555; // 二级标题颜色 +$uni-font-size-subtitle: 18px; +$uni-color-paragraph: #3f536e; // 文章段落颜色 +$uni-font-size-paragraph: 15px; \ No newline at end of file diff --git a/src/uni_modules/liu-drag-button_1.0.5/changelog.md b/src/uni_modules/liu-drag-button_1.0.5/changelog.md new file mode 100644 index 0000000..f04925b --- /dev/null +++ b/src/uni_modules/liu-drag-button_1.0.5/changelog.md @@ -0,0 +1,12 @@ +## 1.0.5(2023-07-13) +优化 +## 1.0.4(2023-06-08) +增加预览二维码 +## 1.0.3(2023-05-31) +增加license +## 1.0.2(2023-04-28) +优化 +## 1.0.1(2023-04-26) +增加示例 +## 1.0.0(2023-04-26) +初始化发布 diff --git a/src/uni_modules/liu-drag-button_1.0.5/components/liu-drag-button/liu-drag-button.vue b/src/uni_modules/liu-drag-button_1.0.5/components/liu-drag-button/liu-drag-button.vue new file mode 100644 index 0000000..8b10e7c --- /dev/null +++ b/src/uni_modules/liu-drag-button_1.0.5/components/liu-drag-button/liu-drag-button.vue @@ -0,0 +1,143 @@ + + + + + + + + diff --git a/src/uni_modules/liu-drag-button_1.0.5/license.md b/src/uni_modules/liu-drag-button_1.0.5/license.md new file mode 100644 index 0000000..029bf39 --- /dev/null +++ b/src/uni_modules/liu-drag-button_1.0.5/license.md @@ -0,0 +1,6 @@ +### 1、本插件可免费下载使用; +### 2、未经许可,严禁复制本插件派生同类插件上传插件市场; +### 3、未经许可,严禁在插件市场恶意复制抄袭本插件进行违规获利; +### 4、对本软件的任何使用都必须遵守这些条款,违反这些条款的个人或组织将面临法律追究。 + + diff --git a/src/uni_modules/liu-drag-button_1.0.5/package.json b/src/uni_modules/liu-drag-button_1.0.5/package.json new file mode 100644 index 0000000..61a3c70 --- /dev/null +++ b/src/uni_modules/liu-drag-button_1.0.5/package.json @@ -0,0 +1,85 @@ +{ + "id": "liu-drag-button", + "displayName": "可拖动悬浮按钮", + "version": "1.0.5", + "description": "可拖动的悬浮按钮,兼容小程序、H5,支持自动停靠,支持自定义样式,使用相当简单,源码简单易修改。", + "keywords": [ + "悬浮按钮", + "拖拽按钮", + "拖动", + "按钮", + "拖拽" + ], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "type": "component-vue", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "u" + }, + "App": { + "app-vue": "u", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "y", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} diff --git a/src/uni_modules/liu-drag-button_1.0.5/readme.md b/src/uni_modules/liu-drag-button_1.0.5/readme.md new file mode 100644 index 0000000..848af4d --- /dev/null +++ b/src/uni_modules/liu-drag-button_1.0.5/readme.md @@ -0,0 +1,36 @@ +# liu-drag-button适用于uni-app项目的可拖动悬浮按钮组件 +### 本组件目前兼容微信小程序、H5 +### 本组件是可拖动的悬浮按钮,兼容小程序、H5,支持自动停靠,支持自定义样式,源码简单易修改 +# --- 扫码预览、关注我们 --- + +## 扫码关注公众号,查看更多插件信息,预览插件效果! + + + +### 使用方式 +``` html ++ ++ ++ 按钮 +``` +``` javascript +export default { + data() { + return { + + }; + }, + methods: { + //点击按钮 + clickBtn(){ + console.log('按钮被点击了') + }, + } +} +``` + +### 属性说明 +| 名称 | 类型 | 默认值 | 描述 | +| ----------------------------|--------------- | ------------------ | ---------------| +| disabled | Boolean | false | 是否禁用拖动 +| canDocking | Boolean | true | 是否自动停靠 +| bottomPx | Number | 30 | 按钮默认位置离底部距离(px) +| rightPx | Number | 0 | 按钮默认位置离右边距离(px) diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/changelog.md b/src/uni_modules/qiun-data-charts_2.5.0-20230101/changelog.md new file mode 100644 index 0000000..4d470a4 --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/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导入示例项目】。 +## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,如仍不好用,请重启电脑; +## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。 +## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。 +## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn) +## 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! +## [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导入示例项目】。 +## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,如仍不好用,请重启电脑; +## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。 +## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。 +## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn) +## 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! +## [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导入示例项目】。 +## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,如仍不好用,请重启电脑; +## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。 +## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。 +## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn) +## 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! +## [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导入示例项目】。 +## 初次使用如果提示未注册<qiun-data-charts>组件,请重启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导入示例项目】。 +## 初次使用如果提示未注册组件,请重启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帮助页 diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-data-charts/qiun-data-charts.vue b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-data-charts/qiun-data-charts.vue new file mode 100644 index 0000000..5678f7d --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-data-charts/qiun-data-charts.vue @@ -0,0 +1,1618 @@ + + + + + + + + + + + + + diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-error/qiun-error.vue b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-error/qiun-error.vue new file mode 100644 index 0000000..b15b19f --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-error/qiun-error.vue @@ -0,0 +1,46 @@ + ++ + ++ + + + + ++ + ++ + + + + ++ + ++ + ++ + + + + ++ ++ + ++ + ++ + ++ + ++ + ++ + + + + + diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading1.vue b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading1.vue new file mode 100644 index 0000000..b701394 --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading1.vue @@ -0,0 +1,162 @@ + ++ {{errorMessage==null?'请点击重试':errorMessage}} ++ + + + + + diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading2.vue b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading2.vue new file mode 100644 index 0000000..7541b31 --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading2.vue @@ -0,0 +1,170 @@ + ++ + + + + + + + + + diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading3.vue b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading3.vue new file mode 100644 index 0000000..8e14db3 --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading3.vue @@ -0,0 +1,173 @@ + ++ + + + + + + + + + diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading4.vue b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading4.vue new file mode 100644 index 0000000..77c55b7 --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading4.vue @@ -0,0 +1,222 @@ + ++ + + + + + + + + + diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading5.vue b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading5.vue new file mode 100644 index 0000000..cb93a55 --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/loading5.vue @@ -0,0 +1,229 @@ + ++ + + + + + + + + diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/qiun-loading.vue b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/qiun-loading.vue new file mode 100644 index 0000000..7789060 --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/components/qiun-loading/qiun-loading.vue @@ -0,0 +1,36 @@ + ++ + + + + + + + + + diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/config-echarts.js b/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/config-echarts.js new file mode 100644 index 0000000..7b8168f --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/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 += '+ + + + +
' + 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}
{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; \ No newline at end of file diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/config-ucharts.js b/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/config-ucharts.js new file mode 100644 index 0000000..17b28b3 --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/config-ucharts.js @@ -0,0 +1,606 @@ +/* + * 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')}, + "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; \ No newline at end of file diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/readme.md b/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/readme.md new file mode 100644 index 0000000..d307ba3 --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/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`文件,以免被强制覆盖。 \ No newline at end of file diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/u-charts.js b/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/u-charts.js new file mode 100644 index 0000000..f78bde5 --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/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; \ No newline at end of file diff --git a/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/u-charts.min.js b/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/u-charts.min.js new file mode 100644 index 0000000..0902ecd --- /dev/null +++ b/src/uni_modules/qiun-data-charts_2.5.0-20230101/js_sdk/u-charts/u-charts.min.js @@ -0,0 +1,18 @@ +/* + * uCharts (R) + * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360/快手)、Vue、Taro等支持canvas的框架平台 + * Copyright (C) 2021 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(e,...t){if(e==null){throw new TypeError("[uCharts] Cannot convert undefined or null to object")}if(!t||t.length<=0){return e}function i(e,a){for(let t in a){e[t]=e[t]&&e[t].toString()==="[object Object]"?i(e[t],a[t]):e[t]=a[t]}return e}t.forEach(t=>{e=i(e,t)});return e};var util={toFixed:function t(e,a){a=a||2;if(this.isFloat(e)){e=e.toFixed(a)}return e},isFloat:function t(e){return e%1!==0},approximatelyEqual:function t(e,a){return Math.abs(e-a)<1e-10},isSameSign:function t(e,a){return Math.abs(e)===e&&Math.abs(a)===a||Math.abs(e)!==e&&Math.abs(a)!==a},isSameXCoordinateArea:function t(e,a){return this.isSameSign(e.x,a.x)},isCollision:function t(e,a){e.end={};e.end.x=e.start.x+e.width;e.end.y=e.start.y-e.height;a.end={};a.end.x=a.start.x+a.width;a.end.y=a.start.y-a.height;var i=a.start.x>e.end.x||a.end.xe.start.y||a.start.y 1){if(r.extra.mount.widthRatio>2)r.extra.mount.widthRatio=2;n+=(r.extra.mount.widthRatio-1)*a.eachSpacing}var l=e;if(e>=0){l=0;t.uevent.trigger("scrollLeft");t.scrollOption.position="left";r.xAxis.scrollPosition="left"}else if(Math.abs(e)>=n-o){l=o-n;t.uevent.trigger("scrollRight");t.scrollOption.position="right";r.xAxis.scrollPosition="right"}else{t.scrollOption.position=e;r.xAxis.scrollPosition=e}return l}function isInAngleRange(t,e,a){function i(t){while(t<0){t+=2*Math.PI}while(t>2*Math.PI){t-=2*Math.PI}return t}t=i(t);e=i(e);a=i(a);if(e>a){a+=2*Math.PI;if(t =e&&t<=a}function createCurveControlPoints(t,e){function a(t,e){if(t[e-1]&&t[e+1]){return t[e].y>=Math.max(t[e-1].y,t[e+1].y)||t[e].y<=Math.min(t[e-1].y,t[e+1].y)}else{return false}}function c(t,e){if(t[e-1]&&t[e+1]){return t[e].x>=Math.max(t[e-1].x,t[e+1].x)||t[e].x<=Math.min(t[e-1].x,t[e+1].x)}else{return false}}var i=.2;var r=.2;var o=null;var n=null;var l=null;var s=null;if(e<1){o=t[0].x+(t[1].x-t[0].x)*i;n=t[0].y+(t[1].y-t[0].y)*i}else{o=t[e].x+(t[e+1].x-t[e-1].x)*i;n=t[e].y+(t[e+1].y-t[e-1].y)*i}if(e>t.length-3){var h=t.length-1;l=t[h].x-(t[h].x-t[h-1].x)*r;s=t[h].y-(t[h].y-t[h-1].y)*r}else{l=t[e+1].x-(t[e+2].x-t[e].x)*r;s=t[e+1].y-(t[e+2].y-t[e].y)*r}if(a(t,e+1)){s=t[e+1].y}if(a(t,e)){n=t[e].y}if(c(t,e+1)){l=t[e+1].x}if(c(t,e)){o=t[e].x}if(n>=Math.max(t[e].y,t[e+1].y)||n<=Math.min(t[e].y,t[e+1].y)){n=t[e].y}if(s>=Math.max(t[e].y,t[e+1].y)||s<=Math.min(t[e].y,t[e+1].y)){s=t[e+1].y}if(o>=Math.max(t[e].x,t[e+1].x)||o<=Math.min(t[e].x,t[e+1].x)){o=t[e].x}if(l>=Math.max(t[e].x,t[e+1].x)||l<=Math.min(t[e].x,t[e+1].x)){l=t[e+1].x}return{ctrA:{x:o,y:n},ctrB:{x:l,y:s}}}function convertCoordinateOrigin(t,e,a){return{x:a.x+t,y:a.y-e}}function avoidCollision(t,e){if(e){while(util.isCollision(t,e)){if(t.start.x>0){t.start.y--}else if(t.start.x<0){t.start.y++}else{if(t.start.y>0){t.start.y++}else{t.start.y--}}}}return t}function fixPieSeries(e,a,t){let i=[];if(e.length>0&&e[0].data.constructor.toString().indexOf("Array")>-1){a._pieSeries_=e;let t=e[0].data;for(var r=0;r =1e4){a=1e3}else if(i>=1e3){a=100}else if(i>=100){a=10}else if(i>=10){a=5}else if(i>=1){a=1}else if(i>=.1){a=.1}else if(i>=.01){a=.01}else if(i>=.001){a=.001}else if(i>=1e-4){a=1e-4}else if(i>=1e-5){a=1e-5}else{a=1e-6}return{minRange:findRange(t,"lower",a),maxRange:findRange(e,"upper",a)}}function measureText(a,t,e){var i=0;a=String(a);e=false;if(e!==false&&e!==undefined&&e.setFontSize&&e.measureText){e.setFontSize(t);return e.measureText(a).width}else{var a=a.split("");for(let e=0;e -1;if(n){let t=filterSeries(e);for(var l=0;l 5&&arguments[5]!==undefined?arguments[5]:{};var l=a.chartData.calPoints?a.chartData.calPoints:[];let s={};if(r.length>0){let e=[];for(let t=0;t 0){e=o[i]}return{text:n.formatter?n.formatter(t,e,i,a):t.name+": "+t.data,color:t.color,legendShape:a.extra.tooltip.legendShape=="auto"?t.legendShape:a.extra.tooltip.legendShape}});var h={x:Math.round(s.x),y:Math.round(s.y)};return{textList:e,offset:h}}function getMixToolTipData(t,e,a,i){var r=arguments.length>4&&arguments[4]!==undefined?arguments[4]:{};var o=e.chartData.xAxisPoints[a]+e.chartData.eachSpacing/2;var n=t.map(function(t){return{text:r.formatter?r.formatter(t,i[a],a,e):t.name+": "+t.data,color:t.color,disableLegend:t.disableLegend?true:false,legendShape:e.extra.tooltip.legendShape=="auto"?t.legendShape:e.extra.tooltip.legendShape}});n=n.filter(function(t){if(t.disableLegend!==true){return t}});var l={x:Math.round(o),y:0};return{textList:n,offset:l}}function getCandleToolTipData(o,e,n,l,i,t){var r=arguments.length>6&&arguments[6]!==undefined?arguments[6]:{};var a=n.chartData.calPoints;let s=t.color.upFill;let h=t.color.downFill;let c=[s,s,h,s];var d=[];e.map(function(t){if(l==0){if(t.data[1]-t.data[0]<0){c[1]=h}else{c[1]=s}}else{if(t.data[0] o[l-1][1]){c[2]=s}if(t.data[3] 4&&arguments[4]!==undefined?arguments[4]:0;var l={index:-1,group:[]};var i=e.chartData.eachSpacing/2;let r=[];if(n&&n.length>0){if(!e.categories){i=0}else{for(let t=1;t t){l.index=e}})}}}return l}function findBarChartCurrentIndex(a,t,e,i){var r=arguments.length>4&&arguments[4]!==undefined?arguments[4]:0;var o={index:-1,group:[]};var n=e.chartData.eachSpacing/2;let l=e.chartData.yAxisPoints;if(t&&t.length>0){if(isInExactChartArea(a,e,i)){l.forEach(function(t,e){if(a.y+r+n>t){o.index=e}})}}return o}function findLegendIndex(o,t,e){let n=-1;let l=0;if(isInExactLegendArea(o,t.area)){let i=t.points;let r=-1;for(let t=0,e=i.length;t t[0]-l&&o.x t[1]-l&&o.y e.start.x&&t.x e.start.y&&t.y =e.area[3]-10&&t.y>=e.area[0]&&t.y<=e.height-e.area[2]}function findRadarChartCurrentIndex(t,e,a){var r=2*Math.PI/a;var o=-1;if(isInExactPieChartArea(t,e.center,e.radius)){var n=function t(e){if(e<0){e+=2*Math.PI}if(e>2*Math.PI){e-=2*Math.PI}return e};var l=Math.atan2(e.center.y-t.y,t.x-e.center.x);l=-1*l;if(l<0){l+=2*Math.PI}var i=e.angleList.map(function(t){t=n(-1*t);return t});i.forEach(function(t,e){var a=n(t-r/2);var i=n(t+r/2);if(i=a&&l<=i||l+2*Math.PI>=a&&l+2*Math.PI<=i){o=e}})}return o}function findFunnelChartCurrentIndex(t,e){var a=-1;for(var i=0,r=e.series.length;i o.funnelArea[0]&&t.x o.funnelArea[1]&&t.y o.area[0]&&t.x o.area[1]&&t.y s.width-s.area[1]-s.area[3]){i.push(n);o.push(r-s.legend.itemGap*s.pix);r=e;n=[t]}else{r+=e;n.push(t)}}if(n.length){i.push(n);o.push(r-s.legend.itemGap*s.pix);c.widthArr=o;let t=Math.max.apply(null,o);switch(s.legend.float){case"left":c.area.start.x=s.area[3];c.area.end.x=s.area[3]+t+2*d;break;case"right":c.area.start.x=s.width-s.area[1]-t-2*d;c.area.end.x=s.width-s.area[1];break;default:c.area.start.x=(s.width-t)/2-d;c.area.end.x=(s.width+t)/2+d}c.area.width=t+2*d;c.area.wholeWidth=t+2*d;c.area.height=i.length*u+2*d;c.area.wholeHeight=i.length*u+2*d+2*x;c.points=i}}else{let t=l.length;let e=s.height-s.area[0]-s.area[2]-2*x-2*d;let a=Math.min(Math.floor(e/u),t);c.area.height=a*u+d*2;c.area.wholeHeight=a*u+d*2;switch(s.legend.float){case"top":c.area.start.y=s.area[0]+x;c.area.end.y=s.area[0]+x+c.area.height;break;case"bottom":c.area.start.y=s.height-s.area[2]-x-c.area.height;c.area.end.y=s.height-s.area[2]-x;break;default:c.area.start.y=(s.height-c.area.height)/2;c.area.end.y=(s.height+c.area.height)/2}let i=t%a===0?t/a:Math.floor(t/a+1);let r=[];for(let e=0;ei){i=t}}c.widthArr.push(i);c.heightArr.push(a.length*u+d*2)}let e=0;for(let t=0;t 4&&arguments[4]!==undefined?arguments[4]:-1;var i;if(c=="stack"){i=dataCombineStack(t,e.categories.length)}else{i=dataCombine(t)}var r=[];i=i.filter(function(t){if(typeof t==="object"&&t!==null){if(t.constructor.toString().indexOf("Array")>-1){return t!==null}else{return t.value!==null}}else{return t!==null}});i.map(function(t){if(typeof t==="object"){if(t.constructor.toString().indexOf("Array")>-1){if(e.type=="candle"){t.map(function(t){r.push(t)})}else{r.push(t[0])}}else{r.push(t.value)}}else{r.push(t)}});var o=0;var n=0;if(r.length>0){o=Math.min.apply(this,r);n=Math.max.apply(this,r)}if(a>-1){if(typeof e.xAxis.data[a].min==="number"){o=Math.min(e.xAxis.data[a].min,o)}if(typeof e.xAxis.data[a].max==="number"){n=Math.max(e.xAxis.data[a].max,n)}}else{if(typeof e.xAxis.min==="number"){o=Math.min(e.xAxis.min,o)}if(typeof e.xAxis.max==="number"){n=Math.max(e.xAxis.max,n)}}if(o===n){var d=n||10;n+=d}var l=o;var x=n;var f=[];var p=(x-l)/e.xAxis.splitNumber;for(var s=0;s<=e.xAxis.splitNumber;s++){f.push(l+p*s)}return f}function calXAxisData(t,e,a,i){var r=assign({},{type:""},e.extra.bar);var o={angle:0,xAxisHeight:e.xAxis.lineHeight*e.pix+e.xAxis.marginTop*e.pix};o.ranges=getXAxisTextList(t,e,a,r.type);o.rangesFormat=o.ranges.map(function(t){t=util.toFixed(t,2);return t});var n=o.ranges.map(function(t){t=util.toFixed(t,2);return t});o=Object.assign(o,getXAxisPoints(n,e,a));var l=o.eachSpacing;var s=n.map(function(t){return measureText(t,e.xAxis.fontSize*e.pix,i)});if(e.xAxis.disabled===true){o.xAxisHeight=0}return o}function getRadarDataPoints(r,o,n,a,t){var l=arguments.length>5&&arguments[5]!==undefined?arguments[5]:1;var e=t.extra.radar||{};e.max=e.max||0;var s=Math.max(e.max,Math.max.apply(null,dataCombine(a)));var h=[];for(let e=0;e 2&&arguments[2]!==undefined?arguments[2]:1;var o=0;var n=0;for(let e=0;e 4&&arguments[4]!==undefined?arguments[4]:1;for(let t=0;t 4&&arguments[4]!==undefined?arguments[4]:1;var l=0;var s=0;var h=[];for(let e=0;e 2&&arguments[2]!==undefined?arguments[2]:1;if(o==1){o=.999999}for(let a=0;a =2){t._proportion_=t._proportion_%2}}return i}function getGaugeArcbarDataPoints(i,r){var o=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;if(o==1){o=.999999}for(let a=0;a =2){t._proportion_=t._proportion_%2}}return i}function getGaugeAxisPoints(e,a,t){let i;if(t=2){e[t]._endAngle_=e[t]._endAngle_%2}r=e[t]._endAngle_}return e}function getGaugeDataPoints(i,r,o){let n=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;for(let a=0;a =o.oldData){e._proportion_=(e._endAngle_-e._oldAngle_)*n+o.oldAngle}else{e._proportion_=e._oldAngle_-(e._oldAngle_-e._endAngle_)*n}if(e._proportion_>=2){e._proportion_=e._proportion_%2}}return i}function getPieTextMaxLength(i,r,o,n){i=getPieDataPoints(i);let l=0;for(let a=0;a 0){t.width=Math.min(t.width,+n.extra.mix.column.width*n.pix)}if(n.extra.column&&n.extra.column.width&&+n.extra.column.width>0){t.width=Math.min(t.width,+n.extra.column.width*n.pix)}if(t.width<=0){t.width=1}t.x+=(o+.5-r/2)*(t.width+e);return t})}function fixBarData(t,i,r,o,e,n){return t.map(function(t){if(t===null){return null}var e=0;var a=0;e=n.extra.bar.seriesGap*n.pix||0;a=n.extra.bar.categoryGap*n.pix||0;e=Math.min(e,i/r);a=Math.min(a,i/r);t.width=Math.ceil((i-2*a-e*(r-1))/r);if(n.extra.bar&&n.extra.bar.width&&+n.extra.bar.width>0){t.width=Math.min(t.width,+n.extra.bar.width*n.pix)}if(t.width<=0){t.width=1}t.y+=(o+.5-r/2)*(t.width+e);return t})}function fixColumeMeterData(t,e,a,i,r,o,n){var l=o.extra.column.categoryGap*o.pix||0;return t.map(function(t){if(t===null){return null}t.width=e-2*l;if(o.extra.column&&o.extra.column.width&&+o.extra.column.width>0){t.width=Math.min(t.width,+o.extra.column.width*o.pix)}if(i>0){t.width-=n}return t})}function fixColumeStackData(t,a,e,i,r,o,n){var l=o.extra.column.categoryGap*o.pix||0;return t.map(function(t,e){if(t===null){return null}t.width=Math.ceil(a-2*l);if(o.extra.column&&o.extra.column.width&&+o.extra.column.width>0){t.width=Math.min(t.width,+o.extra.column.width*o.pix)}if(t.width<=0){t.width=1}return t})}function fixBarStackData(t,a,e,i,r,o,n){var l=o.extra.bar.categoryGap*o.pix||0;return t.map(function(t,e){if(t===null){return null}t.width=Math.ceil(a-2*l);if(o.extra.bar&&o.extra.bar.width&&+o.extra.bar.width>0){t.width=Math.min(t.width,+o.extra.bar.width*o.pix)}if(t.width<=0){t.width=1}return t})}function getXAxisPoints(t,e,h){var a=e.width-e.area[1]-e.area[3];var i=e.enableScroll?Math.min(e.xAxis.itemCount,t.length):t.length;if((e.type=="line"||e.type=="area"||e.type=="scatter"||e.type=="bubble"||e.type=="bar")&&i>1&&e.xAxis.boundaryGap=="justify"){i-=1}var r=0;if(e.type=="mount"&&e.extra&&e.extra.mount&&e.extra.mount.widthRatio&&e.extra.mount.widthRatio>1){if(e.extra.mount.widthRatio>2)e.extra.mount.widthRatio=2;r=e.extra.mount.widthRatio-1;i+=r}var o=a/i;var n=[];var l=e.area[3];var s=e.width-e.area[1];t.forEach(function(t,e){n.push(l+r/2*o+e*o)});if(e.xAxis.boundaryGap!=="justify"){if(e.enableScroll===true){n.push(l+r*o+t.length*o)}else{n.push(s)}}return{xAxisPoints:n,startX:l,endX:s,eachSpacing:o}}function getCandleDataPoints(t,l,s,h,c,d,a){var x=arguments.length>7&&arguments[7]!==undefined?arguments[7]:1;var e=[];var f=d.height-d.area[0]-d.area[2];t.forEach(function(t,o){if(t===null){e.push(null)}else{var n=[];t.forEach(function(t,e){var a={};a.x=h[o]+Math.round(c/2);var i=t.value||t;var r=f*(i-l)/(s-l);r*=x;a.y=d.height-Math.round(r)-d.area[2];n.push(a)});e.push(n)}});return e}function getDataPoints(t,a,n,l,s,h,e){var c=arguments.length>7&&arguments[7]!==undefined?arguments[7]:1;var d="center";if(h.type=="line"||h.type=="area"||h.type=="scatter"||h.type=="bubble"){d=h.xAxis.boundaryGap}var x=[];var f=h.height-h.area[0]-h.area[2];var p=h.width-h.area[1]-h.area[3];t.forEach(function(i,t){if(i===null){x.push(null)}else{var r={};r.color=i.color;r.x=l[t];var o=i;if(typeof i==="object"&&i!==null){if(i.constructor.toString().indexOf("Array")>-1){let t,e,a;t=[].concat(h.chartData.xAxisData.ranges);e=t.shift();a=t.pop();o=i[1];r.x=h.area[3]+p*(i[0]-e)/(a-e);if(h.type=="bubble"){r.r=i[2];r.t=i[3]}}else{o=i.value}}if(d=="center"){r.x+=s/2}var e=f*(o-a)/(n-a);e*=c;r.y=h.height-e-h.area[2];x.push(r)}});return x}function getLineDataPoints(t,a,n,l,s,h,e,p,c){var c=arguments.length>8&&arguments[8]!==undefined?arguments[8]:1;var d=h.xAxis.boundaryGap;var x=[];var f=h.height-h.area[0]-h.area[2];var u=h.width-h.area[1]-h.area[3];t.forEach(function(i,t){if(i===null){x.push(null)}else{var r={};r.color=i.color;if(p.animation=="vertical"){r.x=l[t];var o=i;if(typeof i==="object"&&i!==null){if(i.constructor.toString().indexOf("Array")>-1){let t,e,a;t=[].concat(h.chartData.xAxisData.ranges);e=t.shift();a=t.pop();o=i[1];r.x=h.area[3]+u*(i[0]-e)/(a-e)}else{o=i.value}}if(d=="center"){r.x+=s/2}var e=f*(o-a)/(n-a);e*=c;r.y=h.height-e-h.area[2];x.push(r)}else{r.x=l[0]+s*t*c;var o=i;if(d=="center"){r.x+=s/2}var e=f*(o-a)/(n-a);r.y=h.height-e-h.area[2];x.push(r)}}});return x}function getColumnDataPoints(t,a,n,l,s,h,e,i,c){var c=arguments.length>8&&arguments[8]!==undefined?arguments[8]:1;var d=[];var x=h.height-h.area[0]-h.area[2];var f=h.width-h.area[1]-h.area[3];t.forEach(function(i,t){if(i===null){d.push(null)}else{var r={};r.color=i.color;r.x=l[t];var o=i;if(typeof i==="object"&&i!==null){if(i.constructor.toString().indexOf("Array")>-1){let t,e,a;t=[].concat(h.chartData.xAxisData.ranges);e=t.shift();a=t.pop();o=i[1];r.x=h.area[3]+f*(i[0]-e)/(a-e)}else{o=i.value}}r.x+=s/2;var e=x*(o*c-a)/(n-a);r.y=h.height-e-h.area[2];d.push(r)}});return d}function getMountDataPoints(t,o,n,l,s,h,e,a){var c=arguments.length>8&&arguments[8]!==undefined?arguments[8]:1;var d=[];var x=h.height-h.area[0]-h.area[2];var i=h.width-h.area[1]-h.area[3];var f=s*e.widthRatio;t.forEach(function(t,e){if(t===null){d.push(null)}else{var a={};a.color=t.color;a.x=l[e];a.x+=s/2;var i=t.data;var r=x*(i*c-o)/(n-o);a.y=h.height-r-h.area[2];a.value=i;a.width=f;d.push(a)}});return d}function getBarDataPoints(t,o,n,l,e,s,a){var h=arguments.length>7&&arguments[7]!==undefined?arguments[7]:1;var c=[];var i=s.height-s.area[0]-s.area[2];var d=s.width-s.area[1]-s.area[3];t.forEach(function(t,e){if(t===null){c.push(null)}else{var a={};a.color=t.color;a.y=l[e];var i=t;if(typeof t==="object"&&t!==null){i=t.value}var r=d*(i-o)/(n-o);r*=h;a.height=r;a.value=i;a.x=r+s.area[3];c.push(a)}});return c}function getStackDataPoints(t,s,h,c,g,d,e,x,y){var f=arguments.length>9&&arguments[9]!==undefined?arguments[9]:1;var p=[];var u=d.height-d.area[0]-d.area[2];t.forEach(function(t,e){if(t===null){p.push(null)}else{var a={};a.color=t.color;a.x=c[e]+Math.round(g/2);if(x>0){var i=0;for(let t=0;t<=x;t++){i+=y[t].data[e]}var r=i-t;var o=u*(i-s)/(h-s);var n=u*(r-s)/(h-s)}else{var i=t;if(typeof t==="object"&&t!==null){i=t.value}var o=u*(i-s)/(h-s);var n=0}var l=n;o*=f;l*=f;a.y=d.height-Math.round(o)-d.area[2];a.y0=d.height-Math.round(l)-d.area[2];p.push(a)}});return p}function getBarStackDataPoints(t,s,h,c,e,d,a,x,g){var f=arguments.length>9&&arguments[9]!==undefined?arguments[9]:1;var p=[];var u=d.width-d.area[1]-d.area[3];t.forEach(function(t,e){if(t===null){p.push(null)}else{var a={};a.color=t.color;a.y=c[e];if(x>0){var i=0;for(let t=0;t<=x;t++){i+=g[t].data[e]}var r=i-t;var o=u*(i-s)/(h-s);var n=u*(r-s)/(h-s)}else{var i=t;if(typeof t==="object"&&t!==null){i=t.value}var o=u*(i-s)/(h-s);var n=0}var l=n;o*=f;l*=f;a.height=o-l;a.x=d.area[3]+o;a.x0=d.area[3]+l;p.push(a)}});return p}function getYAxisTextList(t,e,h,c,a){var d=arguments.length>5&&arguments[5]!==undefined?arguments[5]:-1;var i;if(c=="stack"){i=dataCombineStack(t,e.categories.length)}else{i=dataCombine(t)}var r=[];i=i.filter(function(t){if(typeof t==="object"&&t!==null){if(t.constructor.toString().indexOf("Array")>-1){return t!==null}else{return t.value!==null}}else{return t!==null}});i.map(function(t){if(typeof t==="object"){if(t.constructor.toString().indexOf("Array")>-1){if(e.type=="candle"){t.map(function(t){r.push(t)})}else{r.push(t[1])}}else{r.push(t.value)}}else{r.push(t)}});var o=a.min||0;var n=a.max||0;if(r.length>0){o=Math.min.apply(this,r);n=Math.max.apply(this,r)}if(o===n){if(n==0){n=10}else{o=0}}var l=getDataRange(o,n);var x=a.min===undefined||a.min===null?l.minRange:a.min;var f=a.max===undefined||a.max===null?l.maxRange:a.max;var p=(f-x)/e.yAxis.splitNumber;var u=[];for(var s=0;s<=e.yAxis.splitNumber;s++){u.push(x+p*s)}return u.reverse()}function calYAxisData(a,o,e,n){var l=assign({},{type:""},o.extra.column);var t=o.yAxis.data.length;var s=new Array(t);if(t>0){for(let e=0;e {return t+(i.unit||"")}}i.categories=i.categories||o.categories;h[r]=i.categories}else{if(!i.formatter){i.formatter=(t,e,a)=>{return util.toFixed(t,i.tofix||0)+(i.unit||"")}}h[r]=getYAxisTextList(s[r],o,e,l.type,i,r)}let a=i.fontSize*o.pix||e.fontSize;d[r]={position:i.position?i.position:"left",width:0};c[r]=h[r].map(function(t,e){t=i.formatter(t,e,o);d[r].width=Math.max(d[r].width,measureText(t,a,n)+5);return t});let t=i.calibration?4*o.pix:0;d[r].width+=t+3*o.pix;if(i.disabled===true){d[r].width=0}}}else{var h=new Array(1);var c=new Array(1);var d=new Array(1);if(o.type==="bar"){h[0]=o.categories;if(!o.yAxis.formatter){o.yAxis.formatter=(t,e,a)=>{return t+(a.yAxis.unit||"")}}}else{if(!o.yAxis.formatter){o.yAxis.formatter=(t,e,a)=>{return t.toFixed(a.yAxis.tofix)+(a.yAxis.unit||"")}}h[0]=getYAxisTextList(a,o,e,l.type,{})}d[0]={position:"left",width:0};var i=o.yAxis.fontSize*o.pix||e.fontSize;c[0]=h[0].map(function(t,e){t=o.yAxis.formatter(t,e,o);d[0].width=Math.max(d[0].width,measureText(t,i,n)+5);return t});d[0].width+=3*o.pix;if(o.yAxis.disabled===true){d[0]={position:"left",width:0};o.yAxis.data[0]={disabled:true}}else{o.yAxis.data[0]={disabled:false,position:"left",max:o.yAxis.max,min:o.yAxis.min,formatter:o.yAxis.formatter};if(o.type==="bar"){o.yAxis.data[0].categories=o.categories;o.yAxis.data[0].type="categories"}}}return{rangesFormat:c,ranges:h,yAxisWidth:d}}function calTooltipYAxisData(r,t,o,e,a){let n=[].concat(o.chartData.yAxisData.ranges);let l=o.height-o.area[0]-o.area[2];let s=o.area[0];let h=[];for(let i=0;i 0&&r.tooltip.group.includes(n)==false){return}var l=typeof r.tooltip.index==="number"?r.tooltip.index:r.tooltip.index[r.tooltip.group.indexOf(n)];i.beginPath();if(o.activeType=="hollow"){i.setStrokeStyle(e);i.setFillStyle(r.background);i.setLineWidth(2*r.pix)}else{i.setStrokeStyle("#ffffff");i.setFillStyle(e);i.setLineWidth(1*r.pix)}if(a==="diamond"){t.forEach(function(t,e){if(t!==null&&l==e){i.moveTo(t.x,t.y-4.5);i.lineTo(t.x-4.5,t.y);i.lineTo(t.x,t.y+4.5);i.lineTo(t.x+4.5,t.y);i.lineTo(t.x,t.y-4.5)}})}else if(a==="circle"){t.forEach(function(t,e){if(t!==null&&l==e){i.moveTo(t.x+2.5*r.pix,t.y);i.arc(t.x,t.y,3*r.pix,0,2*Math.PI,false)}})}else if(a==="square"){t.forEach(function(t,e){if(t!==null&&l==e){i.moveTo(t.x-3.5,t.y-3.5);i.rect(t.x-3.5,t.y-3.5,7,7)}})}else if(a==="triangle"){t.forEach(function(t,e){if(t!==null&&l==e){i.moveTo(t.x,t.y-4.5);i.lineTo(t.x-4.5,t.y+4.5);i.lineTo(t.x+4.5,t.y+4.5);i.lineTo(t.x,t.y-4.5)}})}else if(a==="none"){return}i.closePath();i.fill();i.stroke()}function drawRingTitle(t,e,a,i){var r=t.title.fontSize||e.titleFontSize;var o=t.subtitle.fontSize||e.subtitleFontSize;var n=t.title.name||"";var l=t.subtitle.name||"";var c=t.title.color||t.fontColor;var d=t.subtitle.color||t.fontColor;var x=n?r:0;var f=l?o:0;var s=5;if(l){var p=measureText(l,o*t.pix,a);var u=i.x-p/2+(t.subtitle.offsetX||0)*t.pix;var h=i.y+o*t.pix/2+(t.subtitle.offsetY||0)*t.pix;if(n){h+=(x*t.pix+s)/2}a.beginPath();a.setFontSize(o*t.pix);a.setFillStyle(d);a.fillText(l,u,h);a.closePath();a.stroke()}if(n){var g=measureText(n,r*t.pix,a);var y=i.x-g/2+(t.title.offsetX||0);var v=i.y+r*t.pix/2+(t.title.offsetY||0)*t.pix;if(l){v-=(f*t.pix+s)/2}a.beginPath();a.setFontSize(r*t.pix);a.setFillStyle(c);a.fillText(n,y,v);a.closePath();a.stroke()}}function drawPointText(t,o,n,l,s){var h=o.data;var c=o.textOffset?o.textOffset:0;t.forEach(function(t,e){if(t!==null){l.beginPath();var a=o.textSize?o.textSize*s.pix:n.fontSize;l.setFontSize(a);l.setFillStyle(o.textColor||s.fontColor);var i=h[e];if(typeof h[e]==="object"&&h[e]!==null){if(h[e].constructor.toString().indexOf("Array")>-1){i=h[e][1]}else{i=h[e].value}}var r=o.formatter?o.formatter(i,e,o,s):i;l.setTextAlign("center");l.fillText(String(r),t.x,t.y-4+c*s.pix);l.closePath();l.stroke();l.setTextAlign("left")}})}function drawColumePointText(t,n,l,s,h){var c=n.data;var d=n.textOffset?n.textOffset:0;var x=h.extra.column.labelPosition;t.forEach(function(t,e){if(t!==null){s.beginPath();var a=n.textSize?n.textSize*h.pix:l.fontSize;s.setFontSize(a);s.setFillStyle(n.textColor||h.fontColor);var i=c[e];if(typeof c[e]==="object"&&c[e]!==null){if(c[e].constructor.toString().indexOf("Array")>-1){i=c[e][1]}else{i=c[e].value}}var r=n.formatter?n.formatter(i,e,n,h):i;s.setTextAlign("center");var o=t.y-4*h.pix+d*h.pix;if(t.y>n.zeroPoints){o=t.y+d*h.pix+a}if(x=="insideTop"){o=t.y+a+d*h.pix;if(t.y>n.zeroPoints){o=t.y-d*h.pix-4*h.pix}}if(x=="center"){o=t.y+d*h.pix+(h.height-h.area[2]-t.y+a)/2;if(n.zeroPoints n.zeroPoints){o=t.y-d*h.pix-(t.y-n.zeroPoints-a)/2}if(h.extra.column.type=="stack"){o=t.y+d*h.pix+(t.y0-t.y+a)/2}}if(x=="bottom"){o=h.height-h.area[2]+d*h.pix-4*h.pix;if(n.zeroPoints n.zeroPoints){o=n.zeroPoints-d*h.pix+a+2*h.pix}if(h.extra.column.type=="stack"){o=t.y0+d*h.pix-4*h.pix}}s.fillText(String(r),t.x,o);s.closePath();s.stroke();s.setTextAlign("left")}})}function drawMountPointText(t,n,l,s,h,c){var e=n.data;var d=n.textOffset?n.textOffset:0;var a=h.extra.mount.labelPosition;t.forEach(function(t,e){if(t!==null){s.beginPath();var a=n[e].textSize?n[e].textSize*h.pix:l.fontSize;s.setFontSize(a);s.setFillStyle(n[e].textColor||h.fontColor);var i=t.value;var r=n[e].formatter?n[e].formatter(i,e,n,h):i;s.setTextAlign("center");var o=t.y-4*h.pix+d*h.pix;if(t.y>c){o=t.y+d*h.pix+a}s.fillText(String(r),t.x,o);s.closePath();s.stroke();s.setTextAlign("left")}})}function drawBarPointText(t,o,n,l,s){var h=o.data;var e=o.textOffset?o.textOffset:0;t.forEach(function(t,e){if(t!==null){l.beginPath();var a=o.textSize?o.textSize*s.pix:n.fontSize;l.setFontSize(a);l.setFillStyle(o.textColor||s.fontColor);var i=h[e];if(typeof h[e]==="object"&&h[e]!==null){i=h[e].value}var r=o.formatter?o.formatter(i,e,o,s):i;l.setTextAlign("left");l.fillText(String(r),t.x+4*s.pix,t.y+a/2-3);l.closePath();l.stroke()}})}function drawGaugeLabel(e,a,i,r,o,n){a-=e.width/2+e.labelOffset*r.pix;a=a<10?10:a;let t;if(e.endAngle =2){l=l%2}s+=x}}function drawRadarLabel(t,s,h,c,d,x){var f=c.extra.radar||{};t.forEach(function(t,e){if(f.labelPointShow===true&&c.categories[e]!==""){var a={x:s*Math.cos(t),y:s*Math.sin(t)};var i=convertCoordinateOrigin(a.x,a.y,h);x.setFillStyle(f.labelPointColor);x.beginPath();x.arc(i.x,i.y,f.labelPointRadius*c.pix,0,2*Math.PI,false);x.closePath();x.fill()}if(f.labelShow===true){var r={x:(s+d.radarLabelTextMargin*c.pix)*Math.cos(t),y:(s+d.radarLabelTextMargin*c.pix)*Math.sin(t)};var o=convertCoordinateOrigin(r.x,r.y,h);var n=o.x;var l=o.y;if(util.approximatelyEqual(r.x,0)){n-=measureText(c.categories[e]||"",d.fontSize,x)/2}else if(r.x<0){n-=measureText(c.categories[e]||"",d.fontSize,x)}x.beginPath();x.setFontSize(d.fontSize);x.setFillStyle(f.labelColor||c.fontColor);x.fillText(c.categories[e]||"",n,l+d.fontSize/2);x.closePath();x.stroke()}})}function drawPieText(n,d,x,f,t,l){var p=x.pieChartLinePadding;var u=[];var g=null;var y=n.map(function(t,e){var a=t.formatter?t.formatter(t,e,n,d):util.toFixed(t._proportion_.toFixed(4)*100)+"%";a=t.labelText?t.labelText:a;var i=2*Math.PI-(t._start_+2*Math.PI*t._proportion_/2);if(t._rose_proportion_){i=2*Math.PI-(t._start_+2*Math.PI*t._rose_proportion_/2)}var r=t.color;var o=t._radius_;return{arc:i,text:a,color:r,radius:o,textColor:t.textColor,textSize:t.textSize,labelShow:t.labelShow}});for(let c=0;c =0?e+x.pieChartTextPadding:e-x.pieChartTextPadding;let n=a;let l=measureText(t.text,t.textSize*d.pix||x.fontSize,f);let s=n;if(g&&util.isSameXCoordinateArea(g.start,{x:o})){if(o>0){s=Math.min(n,g.start.y)}else if(e<0){s=Math.max(n,g.start.y)}else{if(n>0){s=Math.max(n,g.start.y)}else{s=Math.min(n,g.start.y)}}}if(o<0){o-=l}let h={lineStart:{x:i,y:r},lineEnd:{x:e,y:a},start:{x:o,y:s},width:l,height:x.fontSize,text:t.text,color:t.color,textColor:t.textColor,textSize:t.textSize};g=avoidCollision(h,g);u.push(g)}for(let n=0;n r?r:o.activeWidth;var n=e.area[0];var l=e.height-e.area[2];i.beginPath();i.setFillStyle(hexToRgb(o.activeBgColor,o.activeBgOpacity));i.rect(t-o.activeWidth/2,n,o.activeWidth,l-n);i.closePath();i.fill();i.setFillStyle("#FFFFFF")}function drawBarToolTipSplitArea(t,e,a,i,r){var o=assign({},{activeBgColor:"#000000",activeBgOpacity:.08},e.extra.bar);var n=e.area[3];var l=e.width-e.area[1];i.beginPath();i.setFillStyle(hexToRgb(o.activeBgColor,o.activeBgOpacity));i.rect(n,t-r/2,l-n,r);i.closePath();i.fill();i.setFillStyle("#FFFFFF")}function drawToolTip(e,r,o,a,n,i,f){var l=assign({},{showBox:true,showArrow:true,showCategory:false,bgColor:"#000000",bgOpacity:.7,borderColor:"#000000",borderWidth:0,borderRadius:0,borderOpacity:.7,boxPadding:3,fontColor:"#FFFFFF",fontSize:13,lineHeight:20,legendShow:true,legendShape:"auto",splitLine:true},o.extra.tooltip);if(l.showCategory==true&&o.categories){e.unshift({text:o.categories[o.tooltip.index],color:null})}var s=l.fontSize*o.pix;var p=l.lineHeight*o.pix;var h=l.boxPadding*o.pix;var c=s;var u=5*o.pix;if(l.legendShow==false){c=0;u=0}var d=l.showArrow?8*o.pix:0;var g=false;if(o.type=="line"||o.type=="mount"||o.type=="area"||o.type=="candle"||o.type=="mix"){if(l.splitLine==true){drawToolTipSplitLine(o.tooltip.offset.x,o,a,n)}}r=assign({x:0,y:0},r);r.y-=8*o.pix;var y=e.map(function(t){return measureText(t.text,s,n)});var x=c+u+4*h+Math.max.apply(null,y);var v=2*h+e.length*p;if(l.showBox==false){return}if(r.x-Math.abs(o._scrollDistance_||0)+d+x>o.width){g=true}if(v+r.y>o.height){r.y=o.height-v}n.beginPath();n.setFillStyle(hexToRgb(l.bgColor,l.bgOpacity));n.setLineWidth(l.borderWidth*o.pix);n.setStrokeStyle(hexToRgb(l.borderColor,l.borderOpacity));var t=l.borderRadius;if(g){if(x+d>o.width){r.x=o.width+Math.abs(o._scrollDistance_||0)+d+(x-o.width)}if(x>r.x){r.x=o.width+Math.abs(o._scrollDistance_||0)+d+(x-o.width)}if(l.showArrow){n.moveTo(r.x,r.y+10*o.pix);n.lineTo(r.x-d,r.y+10*o.pix+5*o.pix)}n.arc(r.x-d-t,r.y+v-t,t,0,Math.PI/2,false);n.arc(r.x-d-Math.round(x)+t,r.y+v-t,t,Math.PI/2,Math.PI,false);n.arc(r.x-d-Math.round(x)+t,r.y+t,t,-Math.PI,-Math.PI/2,false);n.arc(r.x-d-t,r.y+t,t,-Math.PI/2,0,false);if(l.showArrow){n.lineTo(r.x-d,r.y+10*o.pix-5*o.pix);n.lineTo(r.x,r.y+10*o.pix)}}else{if(l.showArrow){n.moveTo(r.x,r.y+10*o.pix);n.lineTo(r.x+d,r.y+10*o.pix-5*o.pix)}n.arc(r.x+d+t,r.y+t,t,-Math.PI,-Math.PI/2,false);n.arc(r.x+d+Math.round(x)-t,r.y+t,t,-Math.PI/2,0,false);n.arc(r.x+d+Math.round(x)-t,r.y+v-t,t,0,Math.PI/2,false);n.arc(r.x+d+t,r.y+v-t,t,Math.PI/2,Math.PI,false);if(l.showArrow){n.lineTo(r.x+d,r.y+10*o.pix+5*o.pix);n.lineTo(r.x,r.y+10*o.pix)}}n.closePath();n.fill();if(l.borderWidth>0){n.stroke()}if(l.legendShow){e.forEach(function(t,e){if(t.color!==null){n.beginPath();n.setFillStyle(t.color);var a=r.x+d+2*h;var i=r.y+(p-s)/2+p*e+h+1;if(g){a=r.x-x-d+2*h}switch(t.legendShape){case"line":n.moveTo(a,i+.5*c-2*o.pix);n.fillRect(a,i+.5*c-2*o.pix,c,4*o.pix);break;case"triangle":n.moveTo(a+7.5*o.pix,i+.5*c-5*o.pix);n.lineTo(a+2.5*o.pix,i+.5*c+5*o.pix);n.lineTo(a+12.5*o.pix,i+.5*c+5*o.pix);n.lineTo(a+7.5*o.pix,i+.5*c-5*o.pix);break;case"diamond":n.moveTo(a+7.5*o.pix,i+.5*c-5*o.pix);n.lineTo(a+2.5*o.pix,i+.5*c);n.lineTo(a+7.5*o.pix,i+.5*c+5*o.pix);n.lineTo(a+12.5*o.pix,i+.5*c);n.lineTo(a+7.5*o.pix,i+.5*c-5*o.pix);break;case"circle":n.moveTo(a+7.5*o.pix,i+.5*c);n.arc(a+7.5*o.pix,i+.5*c,5*o.pix,0,2*Math.PI);break;case"rect":n.moveTo(a,i+.5*c-5*o.pix);n.fillRect(a,i+.5*c-5*o.pix,15*o.pix,10*o.pix);break;case"square":n.moveTo(a+2*o.pix,i+.5*c-5*o.pix);n.fillRect(a+2*o.pix,i+.5*c-5*o.pix,10*o.pix,10*o.pix);break;default:n.moveTo(a,i+.5*c-5*o.pix);n.fillRect(a,i+.5*c-5*o.pix,15*o.pix,10*o.pix)}n.closePath();n.fill()}})}e.forEach(function(t,e){var a=r.x+d+2*h+c+u;if(g){a=r.x-x-d+2*h+c+u}var i=r.y+p*e+(p-s)/2-1+h+s;n.beginPath();n.setFontSize(s);n.setTextBaseline("normal");n.setFillStyle(l.fontColor);n.fillText(t.text,a,i);n.closePath();n.stroke()})}function drawColumnDataPoints(T,b,S,w){let A=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;let t=b.chartData.xAxisData,P=t.xAxisPoints,C=t.eachSpacing;let D=assign({},{type:"group",width:C/2,meterBorder:4,meterFillColor:"#FFFFFF",barBorderCircle:false,barBorderRadius:[],seriesGap:2,linearType:"none",linearOpacity:1,customColor:[],colorStop:0,labelPosition:"outside"},b.extra.column);let M=[];w.save();let L=-2;let F=P.length+2;if(b._scrollDistance_&&b._scrollDistance_!==0&&b.enableScroll===true){w.translate(b._scrollDistance_,0);L=Math.floor(-b._scrollDistance_/C)-2;F=L+b.xAxis.itemCount+4}if(b.tooltip&&b.tooltip.textList&&b.tooltip.textList.length&&A===1){drawToolTipSplitArea(b.tooltip.offset.x,b,S,w,C)}D.customColor=fillCustomColor(D.linearType,D.customColor,T,S);T.forEach(function(a,i){let e,t,o;e=[].concat(b.chartData.yAxisData.ranges[a.index]);t=e.pop();o=e.shift();let x=b.height-b.area[0]-b.area[2];let f=x*(0-t)/(o-t);let n=b.height-Math.round(f)-b.area[2];a.zeroPoints=n;var p=a.data;switch(D.type){case"group":var r=getColumnDataPoints(p,t,o,P,C,b,S,n,A);var u=getStackDataPoints(p,t,o,P,C,b,S,i,T,A);M.push(u);r=fixColumeData(r,C,T.length,i,S,b);for(let t=0;t L&&t n?n:o.y;const d=o.width;const s=Math.abs(n-o.y);if(D.barBorderCircle){D.barBorderRadius=[d/2,d/2,0,0]}if(o.y>n){D.barBorderRadius=[0,0,d/2,d/2]}let[t,e,a,i]=D.barBorderRadius;let r=Math.min(d/2,s/2);t=t>r?r:t;e=e>r?r:e;a=a>r?r:a;i=i>r?r:i;t=t<0?0:t;e=e<0?0:e;a=a<0?0:a;i=i<0?0:i;w.arc(h+t,c+t,t,-Math.PI,-Math.PI/2);w.arc(h+d-e,c+e,e,-Math.PI/2,0);w.arc(h+d-a,c+s-a,a,0,Math.PI/2);w.arc(h+i,c+s-i,i,Math.PI/2,Math.PI)}else{w.moveTo(l,o.y);w.lineTo(l+o.width,o.y);w.lineTo(l+o.width,n);w.lineTo(l,n);w.lineTo(l,o.y);w.setLineWidth(1);w.setStrokeStyle(y)}w.setFillStyle(g);w.closePath();w.fill()}};break;case"stack":var r=getStackDataPoints(p,t,o,P,C,b,S,i,T,A);M.push(r);r=fixColumeStackData(r,C,T.length,i,S,b,T);for(let e=0;e L&&e 0){s-=m}w.setFillStyle(g);w.moveTo(l,t.y);w.fillRect(l,t.y,t.width,s);w.closePath();w.fill()}};break;case"meter":var r=getDataPoints(p,t,o,P,C,b,S,A);M.push(r);r=fixColumeMeterData(r,C,T.length,i,S,b,D.meterBorder);for(let t=0;t L&&t 0){w.setStrokeStyle(a.color);w.setLineWidth(D.meterBorder*b.pix)}if(i==0){w.setFillStyle(D.meterFillColor)}else{w.setFillStyle(o.color||a.color)}var l=o.x-o.width/2;var s=b.height-o.y-b.area[2];if(D.barBorderRadius&&D.barBorderRadius.length===4||D.barBorderCircle===true){const h=l;const c=o.y;const d=o.width;const s=n-o.y;if(D.barBorderCircle){D.barBorderRadius=[d/2,d/2,0,0]}let[t,e,a,i]=D.barBorderRadius;let r=Math.min(d/2,s/2);t=t>r?r:t;e=e>r?r:e;a=a>r?r:a;i=i>r?r:i;t=t<0?0:t;e=e<0?0:e;a=a<0?0:a;i=i<0?0:i;w.arc(h+t,c+t,t,-Math.PI,-Math.PI/2);w.arc(h+d-e,c+e,e,-Math.PI/2,0);w.arc(h+d-a,c+s-a,a,0,Math.PI/2);w.arc(h+i,c+s-i,i,Math.PI/2,Math.PI);w.fill()}else{w.moveTo(l,o.y);w.lineTo(l+o.width,o.y);w.lineTo(l+o.width,n);w.lineTo(l,n);w.lineTo(l,o.y);w.fill()}if(i==0&&D.meterBorder>0){w.closePath();w.stroke()}}}break}});if(b.dataLabel!==false&&A===1){T.forEach(function(t,e){let a,i,r;a=[].concat(b.chartData.yAxisData.ranges[t.index]);i=a.pop();r=a.shift();var o=t.data;switch(D.type){case"group":var n=getColumnDataPoints(o,i,r,P,C,b,S,A);n=fixColumeData(n,C,T.length,e,S,b);drawColumePointText(n,t,S,w,b);break;case"stack":var n=getStackDataPoints(o,i,r,P,C,b,S,e,T,A);drawColumePointText(n,t,S,w,b);break;case"meter":var n=getDataPoints(o,i,r,P,C,b,S,A);drawColumePointText(n,t,S,w,b);break}})}w.restore();return{xAxisPoints:P,calPoints:M,eachSpacing:C}}function drawMountDataPoints(i,r,o,n){let f=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;let t=r.chartData.xAxisData,p=t.xAxisPoints,l=t.eachSpacing;let s=assign({},{type:"mount",widthRatio:1,borderWidth:1,barBorderCircle:false,barBorderRadius:[],linearType:"none",linearOpacity:1,customColor:[],colorStop:0},r.extra.mount);s.widthRatio=s.widthRatio<=0?0:s.widthRatio;s.widthRatio=s.widthRatio>=2?2:s.widthRatio;let e=[];n.save();let u=-2;let g=p.length+2;if(r._scrollDistance_&&r._scrollDistance_!==0&&r.enableScroll===true){n.translate(r._scrollDistance_,0);u=Math.floor(-r._scrollDistance_/l)-2;g=u+r.xAxis.itemCount+4}s.customColor=fillCustomColor(s.linearType,s.customColor,i,o);let y,v,m;y=[].concat(r.chartData.yAxisData.ranges[0]);v=y.pop();m=y.shift();let T=r.height-r.area[0]-r.area[2];let b=T*(0-v)/(m-v);let h=r.height-Math.round(b)-r.area[2];var c=getMountDataPoints(i,v,m,p,l,r,s,h,f);switch(s.type){case"bar":for(let t=0;t u&&t h?h:o.y;const C=o.width;const S=Math.abs(h-o.y);if(s.barBorderCircle){s.barBorderRadius=[C/2,C/2,0,0]}if(o.y>h){s.barBorderRadius=[0,0,C/2,C/2]}let[t,e,a,i]=s.barBorderRadius;let r=Math.min(C/2,S/2);t=t>r?r:t;e=e>r?r:e;a=a>r?r:a;i=i>r?r:i;t=t<0?0:t;e=e<0?0:e;a=a<0?0:a;i=i<0?0:i;n.arc(A+t,P+t,t,-Math.PI,-Math.PI/2);n.arc(A+C-e,P+e,e,-Math.PI/2,0);n.arc(A+C-a,P+S-a,a,0,Math.PI/2);n.arc(A+i,P+S-i,i,Math.PI/2,Math.PI)}else{n.moveTo(d,o.y);n.lineTo(d+o.width,o.y);n.lineTo(d+o.width,h);n.lineTo(d,h);n.lineTo(d,o.y)}n.setStrokeStyle(w);n.setFillStyle(a);if(s.borderWidth>0){n.setLineWidth(s.borderWidth*r.pix);n.closePath();n.stroke()}n.fill()}};break;case"triangle":for(let e=0;e u&&e 0){n.setLineWidth(s.borderWidth*r.pix);n.stroke()}n.fill()}};break;case"mount":for(let e=0;e u&&e 0){n.setLineWidth(s.borderWidth*r.pix);n.stroke()}n.fill()}};break;case"sharp":for(let e=0;e u&&e 0){n.setLineWidth(s.borderWidth*r.pix);n.stroke()}n.fill()}};break}if(r.dataLabel!==false&&f===1){let t,e,a;t=[].concat(r.chartData.yAxisData.ranges[0]);e=t.pop();a=t.shift();var c=getMountDataPoints(i,e,a,p,l,r,s,h,f);drawMountPointText(c,i,o,n,r,h)}n.restore();return{xAxisPoints:p,calPoints:c,eachSpacing:l}}function drawBarDataPoints(y,v,m,T){let b=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;let S=[];let w=(v.height-v.area[0]-v.area[2])/v.categories.length;for(let t=0;t C&&t r?r:t;e=e>r?r:e;a=a>r?r:a;i=i>r?r:i;t=t<0?0:t;e=e<0?0:e;a=a<0?0:a;i=i<0?0:i;T.arc(g+i,c+i,i,-Math.PI,-Math.PI/2);T.arc(o.x-t,c+t,t,-Math.PI/2,0);T.arc(o.x-e,c+h-e,e,0,Math.PI/2);T.arc(g+a,c+h-a,a,Math.PI/2,Math.PI)}else{T.moveTo(n,r);T.lineTo(o.x,r);T.lineTo(o.x,r+o.width);T.lineTo(n,r+o.width);T.lineTo(n,r);T.setLineWidth(1);T.setStrokeStyle(u)}T.setFillStyle(l);T.closePath();T.fill()}};break;case"stack":var i=getBarStackDataPoints(x,e,d,S,w,v,m,t,y,b);P.push(i);i=fixBarStackData(i,w,y.length,t,m,v,y);for(let e=0;e C&&e 5&&arguments[5]!==undefined?arguments[5]:1;var s=assign({},{color:{},average:{}},h.extra.candle);s.color=assign({},{upLine:"#f04864",upFill:"#f04864",downLine:"#2fc25b",downFill:"#2fc25b"},s.color);s.average=assign({},{show:false,name:[],day:[],color:c.color},s.average);h.extra.candle=s;let a=h.chartData.xAxisData,x=a.xAxisPoints,f=a.eachSpacing;let y=[];d.save();let p=-2;let v=x.length+2;let u=0;let m=h.width+f;if(h._scrollDistance_&&h._scrollDistance_!==0&&h.enableScroll===true){d.translate(h._scrollDistance_,0);p=Math.floor(-h._scrollDistance_/f)-2;v=p+h.xAxis.itemCount+4;u=-h._scrollDistance_-f*2+h.area[3];m=u+(h.xAxis.itemCount+4)*f}if(s.average.show||t){t.forEach(function(e,t){let a,i,r;a=[].concat(h.chartData.yAxisData.ranges[e.index]);i=a.pop();r=a.shift();var o=e.data;var n=getDataPoints(o,i,r,x,f,h,c,g);var l=splitPoints(n,e);for(let t=0;t u){d.moveTo(t.x,t.y);a=1}if(e>0&&t.x>u&&t.x p&&e 0){d.setStrokeStyle(s.color.upLine);d.setFillStyle(s.color.upFill);d.setLineWidth(1*h.pix);d.moveTo(t[3].x,t[3].y);d.lineTo(t[1].x,t[1].y);d.lineTo(t[1].x-f/4,t[1].y);d.lineTo(t[0].x-f/4,t[0].y);d.lineTo(t[0].x,t[0].y);d.lineTo(t[2].x,t[2].y);d.lineTo(t[0].x,t[0].y);d.lineTo(t[0].x+f/4,t[0].y);d.lineTo(t[1].x+f/4,t[1].y);d.lineTo(t[1].x,t[1].y);d.moveTo(t[3].x,t[3].y)}else{d.setStrokeStyle(s.color.downLine);d.setFillStyle(s.color.downFill);d.setLineWidth(1*h.pix);d.moveTo(t[3].x,t[3].y);d.lineTo(t[0].x,t[0].y);d.lineTo(t[0].x-f/4,t[0].y);d.lineTo(t[1].x-f/4,t[1].y);d.lineTo(t[1].x,t[1].y);d.lineTo(t[2].x,t[2].y);d.lineTo(t[1].x,t[1].y);d.lineTo(t[1].x+f/4,t[1].y);d.lineTo(t[0].x+f/4,t[0].y);d.lineTo(t[0].x,t[0].y);d.moveTo(t[3].x,t[3].y)}d.closePath();d.fill();d.stroke()}}});d.restore();return{xAxisPoints:x,calPoints:y,eachSpacing:f}}function drawAreaDataPoints(t,s,h,c){var d=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;var x=assign({},{type:"straight",opacity:.2,addLine:false,width:2,gradient:false,activeType:"none"},s.extra.area);let e=s.chartData.xAxisData,f=e.xAxisPoints,p=e.eachSpacing;let y=s.height-s.area[2];let v=[];c.save();let u=0;let g=s.width+p;if(s._scrollDistance_&&s._scrollDistance_!==0&&s.enableScroll===true){c.translate(s._scrollDistance_,0);u=-s._scrollDistance_-p*2+s.area[3];g=u+(s.xAxis.itemCount+4)*p}t.forEach(function(e,t){let a,i,r;a=[].concat(s.chartData.yAxisData.ranges[e.index]);i=a.pop();r=a.shift();let o=e.data;let n=getDataPoints(o,i,r,f,p,s,h,d);v.push(n);let l=splitPoints(n,e);for(let t=0;t 1){let t=r[0];let e=r[r.length-1];c.moveTo(t.x,t.y);let i=0;if(x.type==="curve"){for(let a=0;a u){c.moveTo(e.x,e.y);i=1}if(a>0&&e.x>u&&e.x