qiun-data-charts.vue 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544
  1. <!--
  2. * qiun-data-charts 秋云高性能跨全端图表组件 v2.3.3-20210706
  3. * Copyright (c) 2021 QIUN® 秋云 https://www.ucharts.cn All rights reserved.
  4. * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  5. * 复制使用请保留本段注释,感谢支持开源!
  6. * 为方便更多开发者使用,如有更好的建议请提交码云 Pull Requests !
  7. *
  8. * uCharts®官方网站
  9. * https://www.uCharts.cn
  10. *
  11. * 开源地址:
  12. * https://gitee.com/uCharts/uCharts
  13. *
  14. * uni-app插件市场地址:
  15. * http://ext.dcloud.net.cn/plugin?id=271
  16. *
  17. -->
  18. <template>
  19. <view class="chartsview" :id="'ChartBoxId'+cid">
  20. <view v-if="mixinDatacomLoading">
  21. <!-- 自定义加载状态,请改这里 -->
  22. <qiun-loading :loadingType="loadingType" />
  23. </view>
  24. <view v-if="mixinDatacomErrorMessage && errorShow" @tap="reloading">
  25. <!-- 自定义错误提示,请改这里 -->
  26. <qiun-error :errorMessage="errorMessage" />
  27. </view>
  28. <!-- APP和H5采用renderjs渲染图表 -->
  29. <!-- #ifdef APP-VUE || H5 -->
  30. <block v-if="echarts">
  31. <view
  32. :style="{ background: background }"
  33. style="width: 100%;height: 100%;"
  34. :data-directory="directory"
  35. :id="'EC'+cid"
  36. :prop="echartsOpts"
  37. :change:prop="rdcharts.ecinit"
  38. :resize="echartsResize"
  39. :change:resize="rdcharts.ecresize"
  40. v-show="showchart"
  41. />
  42. </block>
  43. <block v-else>
  44. <view
  45. @tap="rdcharts.tap"
  46. @mousemove="rdcharts.mouseMove"
  47. @mousedown="rdcharts.mouseDown"
  48. @mouseup="rdcharts.mouseUp"
  49. @touchstart="rdcharts.touchStart"
  50. @touchmove="rdcharts.touchMove"
  51. @touchend="rdcharts.touchEnd"
  52. :id="'UC'+cid"
  53. :prop="uchartsOpts"
  54. :change:prop="rdcharts.ucinit"
  55. >
  56. <canvas
  57. :id="cid"
  58. :canvasId="cid"
  59. :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
  60. :disable-scroll="disableScroll"
  61. @error="_error"
  62. v-show="showchart"
  63. />
  64. </view>
  65. </block>
  66. <!-- #endif -->
  67. <!-- 支付宝小程序 -->
  68. <!-- #ifdef MP-ALIPAY -->
  69. <block v-if="ontouch">
  70. <canvas
  71. :id="cid"
  72. :canvasId="cid"
  73. :width="cWidth * pixel"
  74. :height="cHeight * pixel"
  75. :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
  76. :disable-scroll="disScroll"
  77. @tap="_tap"
  78. @touchstart="_touchStart"
  79. @touchmove="_touchMove"
  80. @touchend="_touchEnd"
  81. @error="_error"
  82. v-show="showchart"
  83. />
  84. </block>
  85. <block v-if="!ontouch">
  86. <canvas
  87. :id="cid"
  88. :canvasId="cid"
  89. :width="cWidth * pixel"
  90. :height="cHeight * pixel"
  91. :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
  92. :disable-scroll="disScroll"
  93. @tap="_tap"
  94. @error="_error"
  95. v-show="showchart"
  96. />
  97. </block>
  98. <!-- #endif -->
  99. <!-- 其他小程序通过vue渲染图表 -->
  100. <!-- #ifdef MP-360 || MP-BAIDU || MP-QQ || MP-TOUTIAO || MP-WEIXIN -->
  101. <block v-if="type2d">
  102. <view v-if="ontouch" @tap="_tap">
  103. <canvas
  104. :id="cid"
  105. :canvasId="cid"
  106. :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
  107. type="2d"
  108. :disable-scroll="disScroll"
  109. @touchstart="_touchStart"
  110. @touchmove="_touchMove"
  111. @touchend="_touchEnd"
  112. @error="_error"
  113. v-show="showchart"
  114. />
  115. </view>
  116. <view v-if="!ontouch" @tap="_tap">
  117. <canvas
  118. :id="cid"
  119. :canvasId="cid"
  120. :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
  121. type="2d"
  122. :disable-scroll="disScroll"
  123. @error="_error"
  124. v-show="showchart"
  125. />
  126. </view>
  127. </block>
  128. <block v-if="!type2d">
  129. <view v-if="ontouch" @tap="_tap">
  130. <canvas
  131. :id="cid"
  132. :canvasId="cid"
  133. :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
  134. @touchstart="_touchStart"
  135. @touchmove="_touchMove"
  136. @touchend="_touchEnd"
  137. :disable-scroll="disScroll"
  138. @error="_error"
  139. v-if="showchart"
  140. />
  141. </view>
  142. <view v-if="!ontouch" >
  143. <canvas
  144. :id="cid"
  145. :canvasId="cid"
  146. :style="{ width: cWidth + 'px', height: cHeight + 'px', background: background }"
  147. :disable-scroll="disScroll"
  148. @tap="_tap"
  149. @error="_error"
  150. v-if="showchart"
  151. />
  152. </view>
  153. </block>
  154. <!-- #endif -->
  155. </view>
  156. </template>
  157. <script>
  158. import qiunError from "../qiun-error/qiun-error.vue"
  159. import uChartsMp from '../u-charts/u-charts.js';
  160. import cfu from '../u-charts/config-ucharts.js';
  161. // #ifdef APP-VUE || H5
  162. import cfe from '../u-charts/config-echarts.js';
  163. // #endif
  164. function deepCloneAssign(origin = {}, ...args) {
  165. for (let i in args) {
  166. for (let key in args[i]) {
  167. if (args[i].hasOwnProperty(key)) {
  168. origin[key] = args[i][key] && typeof args[i][key] === 'object' ? deepCloneAssign(Array.isArray(args[i][key]) ? [] : {}, origin[key], args[i][key]) : args[i][key];
  169. }
  170. }
  171. }
  172. return origin;
  173. }
  174. function formatterAssign(args,formatter) {
  175. for (let key in args) {
  176. if(args[key] !== null && typeof args[key] === 'object'){
  177. formatterAssign(args[key],formatter)
  178. }else if(key === 'format' && typeof args[key] === 'string'){
  179. args['formatter'] = formatter[args[key]] ? formatter[args[key]] : undefined;
  180. }
  181. }
  182. return args;
  183. }
  184. // 时间转换函数,为了匹配uniClinetDB读取出的时间与categories不同
  185. function getFormatDate(date) {
  186. var seperator = "-";
  187. var year = date.getFullYear();
  188. var month = date.getMonth() + 1;
  189. var strDate = date.getDate();
  190. if (month >= 1 && month <= 9) {
  191. month = "0" + month;
  192. }
  193. if (strDate >= 0 && strDate <= 9) {
  194. strDate = "0" + strDate;
  195. }
  196. var currentdate = year + seperator + month + seperator + strDate;
  197. return currentdate;
  198. }
  199. var lastMoveTime = null;
  200. /**
  201. * 防抖
  202. *
  203. * @param { Function } fn 要执行的方法
  204. * @param { Number } wait 防抖多少毫秒
  205. *
  206. * 在 vue 中使用(注意:不能使用箭头函数,否则this指向不对,并且不能再次封装如:
  207. * move(){ // 错误调用方式
  208. * debounce(function () {
  209. * console.log(this.title);
  210. * }, 1000)});
  211. * 应该直接使用:// 正确调用方式
  212. * move: debounce(function () {
  213. * console.log(this.title);
  214. * }, 1000)
  215. */
  216. function debounce(fn, wait) {
  217. let timer = false;
  218. return function() {
  219. clearTimeout(timer);
  220. timer && clearTimeout(timer);
  221. timer = setTimeout(() => {
  222. timer = false;
  223. fn.apply(this, arguments); // 把参数传进去
  224. }, wait);
  225. };
  226. }
  227. export default {
  228. name: 'qiun-data-charts',
  229. components:{
  230. qiunError
  231. },
  232. props: {
  233. type: {
  234. type: String,
  235. default: null
  236. },
  237. canvasId: {
  238. type: String,
  239. default: 'uchartsid'
  240. },
  241. canvas2d: {
  242. type: Boolean,
  243. default: false
  244. },
  245. background: {
  246. type: String,
  247. default: 'none'
  248. },
  249. animation: {
  250. type: Boolean,
  251. default: true
  252. },
  253. chartData: {
  254. type: Object,
  255. default() {
  256. return {
  257. categories: [],
  258. series: []
  259. };
  260. }
  261. },
  262. opts: {
  263. type: Object,
  264. default() {
  265. return {};
  266. }
  267. },
  268. eopts: {
  269. type: Object,
  270. default() {
  271. return {};
  272. }
  273. },
  274. loadingType: {
  275. type: Number,
  276. default: 2
  277. },
  278. errorShow: {
  279. type: Boolean,
  280. default: true
  281. },
  282. errorReload: {
  283. type: Boolean,
  284. default: true
  285. },
  286. errorMessage: {
  287. type: String,
  288. default: null
  289. },
  290. inScrollView: {
  291. type: Boolean,
  292. default: false
  293. },
  294. reshow: {
  295. type: Boolean,
  296. default: false
  297. },
  298. reload: {
  299. type: Boolean,
  300. default: false
  301. },
  302. disableScroll: {
  303. type: Boolean,
  304. default: false
  305. },
  306. ontap: {
  307. type: Boolean,
  308. default: true
  309. },
  310. ontouch: {
  311. type: Boolean,
  312. default: false
  313. },
  314. onmouse: {
  315. type: Boolean,
  316. default: true
  317. },
  318. onmovetip: {
  319. type: Boolean,
  320. default: false
  321. },
  322. echartsH5: {
  323. type: Boolean,
  324. default: false
  325. },
  326. echartsApp: {
  327. type: Boolean,
  328. default: false
  329. },
  330. tooltipShow: {
  331. type: Boolean,
  332. default: true
  333. },
  334. tooltipFormat: {
  335. type: String,
  336. default: undefined
  337. },
  338. tooltipCustom: {
  339. type: Object,
  340. default: undefined
  341. },
  342. startDate: {
  343. type: String,
  344. default: undefined
  345. },
  346. endDate: {
  347. type: String,
  348. default: undefined
  349. },
  350. textEnum: {
  351. type: Array,
  352. default () {
  353. return []
  354. }
  355. },
  356. groupEnum: {
  357. type: Array,
  358. default () {
  359. return []
  360. }
  361. },
  362. pageScrollTop: {
  363. type: Number,
  364. default: 0
  365. },
  366. directory: {
  367. type: String,
  368. default: '/'
  369. },
  370. tapLegend: {
  371. type: Boolean,
  372. default: true
  373. }
  374. },
  375. data() {
  376. return {
  377. cid: 'uchartsid',
  378. inWx: false,
  379. inAli: false,
  380. inTt: false,
  381. inBd: false,
  382. inH5: false,
  383. inApp: false,
  384. inWin: false,
  385. type2d: true,
  386. disScroll: false,
  387. openmouse: false,
  388. pixel: 1,
  389. cWidth: 375,
  390. cHeight: 250,
  391. showchart: false,
  392. echarts: false,
  393. echartsResize:false,
  394. uchartsOpts: {},
  395. echartsOpts: {},
  396. drawData:{},
  397. lastDrawTime:null,
  398. };
  399. },
  400. created(){
  401. this.cid = this.canvasId
  402. if (this.canvasId == 'uchartsid' || this.canvasId == '') {
  403. let t = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  404. let len = t.length
  405. let id = ''
  406. for (let i = 0; i < 32; i++) {
  407. id += t.charAt(Math.floor(Math.random() * len))
  408. }
  409. this.cid = id
  410. }
  411. const systemInfo = uni.getSystemInfoSync()
  412. if(systemInfo.platform === 'windows'){
  413. this.inWin = true;
  414. }
  415. // #ifdef MP-WEIXIN
  416. this.inWx = true;
  417. if (this.canvas2d === false || systemInfo.platform === 'windows') {
  418. this.type2d = false;
  419. }else{
  420. this.pixel = systemInfo.pixelRatio;
  421. if (this.canvasId === 'uchartsid' || this.canvasId == '') {
  422. console.log('[uCharts]:开启canvas2d模式,必须指定canvasId,否则会出现偶尔获取不到dom节点的问题!');
  423. }
  424. }
  425. // #endif
  426. //非微信小程序端强制关闭canvas2d模式
  427. // #ifndef MP-WEIXIN
  428. this.type2d = false;
  429. // #endif
  430. // #ifdef MP-ALIPAY
  431. this.inAli = true;
  432. this.pixel = systemInfo.pixelRatio;
  433. // #endif
  434. // #ifdef MP-BAIDU
  435. this.inBd = true;
  436. // #endif
  437. // #ifdef MP-TOUTIAO
  438. this.inTt = true;
  439. // #endif
  440. this.disScroll = this.disableScroll;
  441. },
  442. mounted() {
  443. // #ifdef APP-VUE
  444. this.inApp = true;
  445. if (this.echartsApp === true) {
  446. this.echarts = true;
  447. this.openmouse = false;
  448. }
  449. // #endif
  450. // #ifdef APP-NVUE
  451. this.inApp = true;
  452. this.mixinDatacomLoading = false
  453. this.mixinDatacomErrorMessage = "暂不支持NVUE"
  454. // #endif
  455. // #ifdef H5
  456. this.inH5 = true;
  457. if(this.inWin === true){
  458. this.openmouse = this.onmouse;
  459. }
  460. if (this.echartsH5 === true) {
  461. this.echarts = true;
  462. }
  463. // #endif
  464. this.$nextTick(()=>{
  465. this.beforeInit();
  466. })
  467. // #ifndef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || APP-VUE
  468. const time = this.inH5 ? 500 : 200;
  469. const _this = this;
  470. uni.onWindowResize(
  471. debounce(function(res) {
  472. if (_this.mixinDatacomLoading == true) {
  473. return;
  474. }
  475. let errmsg = _this.mixinDatacomErrorMessage;
  476. if (errmsg !== null && errmsg !== 'null' && errmsg !== '') {
  477. return;
  478. }
  479. if (_this.echarts) {
  480. _this.echartsResize = !_this.echartsResize;
  481. } else {
  482. _this.resizeHandler();
  483. }
  484. }, time)
  485. );
  486. // #endif
  487. },
  488. destroyed(){
  489. if(this.echarts === true){
  490. delete cfe.option[this.cid]
  491. delete cfe.instance[this.cid]
  492. }else{
  493. delete cfu.option[this.cid]
  494. delete cfu.instance[this.cid]
  495. }
  496. // #ifndef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO
  497. uni.offWindowResize(()=>{})
  498. // #endif
  499. },
  500. watch: {
  501. chartDataProps: {
  502. handler(val, oldval) {
  503. if (typeof val === 'object') {
  504. if (JSON.stringify(val) !== JSON.stringify(oldval)) {
  505. if (val.series && val.series.length > 0) {
  506. this.beforeInit();
  507. }else{
  508. this.mixinDatacomLoading = true;
  509. this._clearChart();
  510. this.showchart = false;
  511. this.mixinDatacomErrorMessage = null;
  512. }
  513. }
  514. } else {
  515. this.mixinDatacomLoading = false;
  516. this._clearChart();
  517. this.showchart = false;
  518. this.mixinDatacomErrorMessage = '参数错误:chartData数据类型错误';
  519. }
  520. },
  521. immediate: false,
  522. deep: true
  523. },
  524. localdata:{
  525. handler(val, oldval) {
  526. if (JSON.stringify(val) !== JSON.stringify(oldval)) {
  527. if (val.length > 0) {
  528. this.beforeInit();
  529. }else{
  530. this.mixinDatacomLoading = true;
  531. this._clearChart();
  532. this.showchart = false;
  533. this.mixinDatacomErrorMessage = null;
  534. }
  535. }
  536. },
  537. immediate: false,
  538. deep: true
  539. },
  540. optsProps: {
  541. handler(val, oldval) {
  542. if (typeof val === 'object') {
  543. if (JSON.stringify(val) !== JSON.stringify(oldval) && this.echarts === false) {
  544. this.checkData(this.drawData);
  545. }
  546. } else {
  547. this.mixinDatacomLoading = false;
  548. this._clearChart();
  549. this.showchart = false;
  550. this.mixinDatacomErrorMessage = '参数错误:opts数据类型错误';
  551. }
  552. },
  553. immediate: false,
  554. deep: true
  555. },
  556. eoptsProps: {
  557. handler(val, oldval) {
  558. if (typeof val === 'object') {
  559. if (JSON.stringify(val) !== JSON.stringify(oldval) && this.echarts === true) {
  560. this.checkData(this.drawData);
  561. }
  562. } else {
  563. this.mixinDatacomLoading = false;
  564. this.showchart = false;
  565. this.mixinDatacomErrorMessage = '参数错误:eopts数据类型错误';
  566. }
  567. },
  568. immediate: false,
  569. deep: true
  570. },
  571. reshow(val, oldval) {
  572. if (val === true && this.mixinDatacomLoading === false) {
  573. setTimeout(() => {
  574. this.mixinDatacomErrorMessage = null;
  575. this.echartsResize = !this.echartsResize;
  576. this.checkData(this.drawData);
  577. }, 200);
  578. }
  579. },
  580. reload(val, oldval) {
  581. if (val === true) {
  582. this.showchart = false;
  583. this.mixinDatacomErrorMessage = null;
  584. this.reloading();
  585. }
  586. },
  587. mixinDatacomErrorMessage(val, oldval) {
  588. if (val) {
  589. this.emitMsg({name: 'error', params: {type:"error", errorShow: this.errorShow, msg: val, id: this.cid}});
  590. if(this.errorShow){
  591. console.log('[秋云图表组件]' + val);
  592. }
  593. }
  594. },
  595. errorMessage(val, oldval) {
  596. if (val && this.errorShow && val !== null && val !== 'null' && val !== '') {
  597. this.showchart = false;
  598. this.mixinDatacomLoading = false;
  599. this.mixinDatacomErrorMessage = val;
  600. } else {
  601. this.showchart = false;
  602. this.mixinDatacomErrorMessage = null;
  603. this.reloading();
  604. }
  605. }
  606. },
  607. computed: {
  608. optsProps() {
  609. return JSON.parse(JSON.stringify(this.opts));
  610. },
  611. eoptsProps() {
  612. return JSON.parse(JSON.stringify(this.eopts));
  613. },
  614. chartDataProps() {
  615. return JSON.parse(JSON.stringify(this.chartData));
  616. },
  617. },
  618. methods: {
  619. beforeInit(){
  620. this.mixinDatacomErrorMessage = null;
  621. if (typeof this.chartData === 'object' && this.chartData != null && this.chartData.series !== undefined && this.chartData.series.length > 0) {
  622. //拷贝一下chartData,为了opts变更后统一数据来源
  623. this.drawData = deepCloneAssign({}, this.chartData);
  624. this.mixinDatacomLoading = false;
  625. this.showchart = true;
  626. this.checkData(this.chartData);
  627. }else if(this.localdata.length>0){
  628. this.mixinDatacomLoading = false;
  629. this.showchart = true;
  630. this.localdataInit(this.localdata);
  631. }else if(this.collection !== ''){
  632. this.mixinDatacomLoading = false;
  633. this.getCloudData();
  634. }else{
  635. this.mixinDatacomLoading = true;
  636. }
  637. },
  638. localdataInit(resdata){
  639. //替换enum类型为正确的描述
  640. if(this.groupEnum.length>0){
  641. for (let i = 0; i < resdata.length; i++) {
  642. for (let j = 0; j < this.groupEnum.length; j++) {
  643. if(resdata[i].group === this.groupEnum[j].value){
  644. resdata[i].group = this.groupEnum[j].text
  645. }
  646. }
  647. }
  648. }
  649. if(this.textEnum.length>0){
  650. for (let i = 0; i < resdata.length; i++) {
  651. for (let j = 0; j < this.textEnum.length; j++) {
  652. if(resdata[i].text === this.textEnum[j].value){
  653. resdata[i].text = this.textEnum[j].text
  654. }
  655. }
  656. }
  657. }
  658. let needCategories = false;
  659. let tmpData = {categories:[], series:[]}
  660. let tmpcategories = []
  661. let tmpseries = [];
  662. //拼接categories
  663. if(this.echarts === true){
  664. needCategories = cfe.categories.includes(this.type)
  665. }else{
  666. needCategories = cfu.categories.includes(this.type)
  667. }
  668. if(needCategories === true){
  669. //如果props中的chartData带有categories,则优先使用chartData的categories
  670. if(this.chartData && this.chartData.categories && this.chartData.categories.length>0){
  671. tmpcategories = this.chartData.categories
  672. }else{
  673. //如果是日期类型的数据,不管是本地数据还是云数据,都按起止日期自动拼接categories
  674. if(this.startDate && this.endDate){
  675. let idate = new Date(this.startDate)
  676. let edate = new Date(this.endDate)
  677. while (idate <= edate) {
  678. tmpcategories.push(getFormatDate(idate))
  679. idate = idate.setDate(idate.getDate() + 1)
  680. idate = new Date(idate)
  681. }
  682. //否则从结果中去重并拼接categories
  683. }else{
  684. let tempckey = {};
  685. resdata.map(function(item, index) {
  686. if (item.text != undefined && !tempckey[item.text]) {
  687. tmpcategories.push(item.text)
  688. tempckey[item.text] = true
  689. }
  690. });
  691. }
  692. }
  693. tmpData.categories = tmpcategories
  694. }
  695. //拼接series
  696. let tempskey = {};
  697. resdata.map(function(item, index) {
  698. if (item.group != undefined && !tempskey[item.group]) {
  699. tmpseries.push({ name: item.group, data: [] });
  700. tempskey[item.group] = true;
  701. }
  702. });
  703. //如果没有获取到分组名称(可能是带categories的数据,也可能是不带的饼图类)
  704. if (tmpseries.length == 0) {
  705. tmpseries = [{ name: '默认分组', data: [] }];
  706. //如果是需要categories的图表类型
  707. if(needCategories === true){
  708. for (let j = 0; j < tmpcategories.length; j++) {
  709. let seriesdata = 0;
  710. for (let i = 0; i < resdata.length; i++) {
  711. if (resdata[i].text == tmpcategories[j]) {
  712. seriesdata = resdata[i].value;
  713. }
  714. }
  715. tmpseries[0].data.push(seriesdata);
  716. }
  717. //如果是饼图类的图表类型
  718. }else{
  719. for (let i = 0; i < resdata.length; i++) {
  720. tmpseries[0].data.push({"name": resdata[i].text,"value": resdata[i].value});
  721. }
  722. }
  723. //如果有分组名
  724. } else {
  725. for (let k = 0; k < tmpseries.length; k++) {
  726. //如果有categories
  727. if (tmpcategories.length > 0) {
  728. for (let j = 0; j < tmpcategories.length; j++) {
  729. let seriesdata = 0;
  730. for (let i = 0; i < resdata.length; i++) {
  731. if (tmpseries[k].name == resdata[i].group && resdata[i].text == tmpcategories[j]) {
  732. seriesdata = resdata[i].value;
  733. }
  734. }
  735. tmpseries[k].data.push(seriesdata);
  736. }
  737. //如果传了group而没有传text,即没有categories(正常情况下这种数据是不符合数据要求规范的)
  738. } else {
  739. for (let i = 0; i < resdata.length; i++) {
  740. if (tmpseries[k].name == resdata[i].group) {
  741. tmpseries[k].data.push(resdata[i].value);
  742. }
  743. }
  744. }
  745. }
  746. }
  747. tmpData.series = tmpseries
  748. //拷贝一下chartData,为了opts变更后统一数据来源
  749. this.drawData = deepCloneAssign({}, tmpData);
  750. this.checkData(tmpData)
  751. },
  752. reloading() {
  753. if(this.errorReload === false){
  754. return;
  755. }
  756. this.showchart = false;
  757. this.mixinDatacomErrorMessage = null;
  758. if (this.collection !== '') {
  759. this.mixinDatacomLoading = false;
  760. this.onMixinDatacomPropsChange(true);
  761. } else {
  762. this.beforeInit();
  763. }
  764. },
  765. checkData(anyData) {
  766. let cid = this.cid
  767. //复位opts或eopts
  768. if(this.echarts === true){
  769. cfe.option[cid] = deepCloneAssign({}, this.eopts);
  770. cfe.option[cid].id = cid;
  771. cfe.option[cid].type = this.type;
  772. }else{
  773. if (this.type && cfu.type.includes(this.type)) {
  774. cfu.option[cid] = deepCloneAssign({}, cfu[this.type], this.opts);
  775. cfu.option[cid].canvasId = cid;
  776. } else {
  777. this.mixinDatacomLoading = false;
  778. this.showchart = false;
  779. this.mixinDatacomErrorMessage = '参数错误:props参数中type类型不正确';
  780. }
  781. }
  782. //挂载categories和series
  783. let newData = deepCloneAssign({}, anyData);
  784. if (newData.series !== undefined && newData.series.length > 0) {
  785. this.mixinDatacomErrorMessage = null;
  786. if (this.echarts === true) {
  787. cfe.option[cid].chartData = newData;
  788. this.$nextTick(()=>{
  789. this.init()
  790. })
  791. }else{
  792. cfu.option[cid].categories = newData.categories;
  793. cfu.option[cid].series = newData.series;
  794. this.$nextTick(()=>{
  795. this.init()
  796. })
  797. }
  798. }
  799. },
  800. resizeHandler() {
  801. //渲染防抖
  802. let currTime = Date.now();
  803. let lastDrawTime = this.lastDrawTime?this.lastDrawTime:currTime-3000;
  804. let duration = currTime - lastDrawTime;
  805. if (duration < 1000) return;
  806. let chartdom = uni
  807. .createSelectorQuery()
  808. // #ifndef MP-ALIPAY
  809. .in(this)
  810. // #endif
  811. .select('#ChartBoxId'+this.cid)
  812. .boundingClientRect(data => {
  813. this.showchart = true;
  814. if (data.width > 0 && data.height > 0) {
  815. if (data.width !== this.cWidth || data.height !== this.cHeight) {
  816. this.checkData(this.drawData)
  817. }
  818. }
  819. })
  820. .exec();
  821. },
  822. getCloudData() {
  823. if (this.mixinDatacomLoading == true) {
  824. return;
  825. }
  826. this.mixinDatacomLoading = true;
  827. this.mixinDatacomGet()
  828. .then(res => {
  829. this.mixinDatacomResData = res.result.data;
  830. this.localdataInit(this.mixinDatacomResData);
  831. })
  832. .catch(err => {
  833. this.mixinDatacomLoading = false;
  834. this.showchart = false;
  835. this.mixinDatacomErrorMessage = '请求错误:' + err;
  836. });
  837. },
  838. onMixinDatacomPropsChange(needReset, changed) {
  839. if (needReset == true && this.collection !== '') {
  840. this.showchart = false;
  841. this.mixinDatacomErrorMessage = null;
  842. this._clearChart();
  843. this.getCloudData();
  844. }
  845. },
  846. _clearChart() {
  847. let cid = this.cid
  848. if (this.echrts !== true) {
  849. const ctx = uni.createCanvasContext(cid, this);
  850. ctx.clearRect(0, 0, this.cWidth, this.cHeight);
  851. ctx.draw();
  852. }
  853. },
  854. init() {
  855. let cid = this.cid
  856. let chartdom = uni
  857. .createSelectorQuery()
  858. // #ifndef MP-ALIPAY
  859. .in(this)
  860. // #endif
  861. .select('#ChartBoxId'+cid)
  862. .boundingClientRect(data => {
  863. if (data.width > 0 && data.height > 0) {
  864. this.mixinDatacomLoading = false;
  865. this.showchart = true;
  866. this.lastDrawTime = Date.now();
  867. this.cWidth = data.width;
  868. this.cHeight = data.height;
  869. if(this.echarts !== true){
  870. cfu.option[cid].background = this.background == 'none' ? '#FFFFFF' : this.background;
  871. cfu.option[cid].canvas2d = this.type2d;
  872. cfu.option[cid].pixelRatio = this.pixel;
  873. cfu.option[cid].animation = this.animation;
  874. cfu.option[cid].width = data.width * this.pixel;
  875. cfu.option[cid].height = data.height * this.pixel;
  876. cfu.option[cid].ontap = this.ontap;
  877. cfu.option[cid].ontouch = this.ontouch;
  878. cfu.option[cid].onmouse = this.openmouse;
  879. cfu.option[cid].onmovetip = this.onmovetip;
  880. cfu.option[cid].tooltipShow = this.tooltipShow;
  881. cfu.option[cid].tooltipFormat = this.tooltipFormat;
  882. cfu.option[cid].tooltipCustom = this.tooltipCustom;
  883. cfu.option[cid].inScrollView = this.inScrollView;
  884. cfu.option[cid].lastDrawTime = this.lastDrawTime;
  885. cfu.option[cid].tapLegend = this.tapLegend;
  886. }
  887. //如果是H5或者App端,采用renderjs渲染图表
  888. if (this.inH5 || this.inApp) {
  889. if (this.echarts == true) {
  890. cfe.option[cid].ontap = this.ontap;
  891. cfe.option[cid].onmouse = this.openmouse;
  892. cfe.option[cid].tooltipShow = this.tooltipShow;
  893. cfe.option[cid].tooltipFormat = this.tooltipFormat;
  894. cfe.option[cid].tooltipCustom = this.tooltipCustom;
  895. cfe.option[cid].lastDrawTime = this.lastDrawTime;
  896. this.echartsOpts = deepCloneAssign({}, cfe.option[cid]);
  897. } else {
  898. cfu.option[cid].rotateLock = cfu.option[cid].rotate;
  899. this.uchartsOpts = deepCloneAssign({}, cfu.option[cid]);
  900. }
  901. //如果是小程序端,采用uCharts渲染
  902. } else {
  903. cfu.option[cid] = formatterAssign(cfu.option[cid],cfu.formatter)
  904. this.mixinDatacomErrorMessage = null;
  905. this.mixinDatacomLoading = false;
  906. this.showchart = true;
  907. this.$nextTick(()=>{
  908. if (this.type2d === true) {
  909. const query = uni.createSelectorQuery().in(this)
  910. query
  911. .select('#' + cid)
  912. .fields({ node: true, size: true })
  913. .exec(res => {
  914. if (res[0]) {
  915. const canvas = res[0].node;
  916. const ctx = canvas.getContext('2d');
  917. cfu.option[cid].context = ctx;
  918. canvas.width = data.width * this.pixel;
  919. canvas.height = data.height * this.pixel;
  920. canvas._width = data.width * this.pixel;
  921. canvas._height = data.height * this.pixel;
  922. cfu.option[cid].rotateLock = cfu.option[cid].rotate;
  923. if(cfu.instance[cid] && cfu.option[cid] && cfu.option[cid].update === true){
  924. this._updataUChart(cid)
  925. }else{
  926. setTimeout(()=>{
  927. cfu.option[cid].context.restore();
  928. cfu.option[cid].context.save();
  929. this._newChart(cid)
  930. },100)
  931. }
  932. } else {
  933. this.showchart = false;
  934. this.mixinDatacomErrorMessage = '参数错误:开启2d模式后,未获取到dom节点,canvas-id:' + cid;
  935. }
  936. });
  937. } else {
  938. if(this.inAli){
  939. cfu.option[cid].rotateLock = cfu.option[cid].rotate;
  940. }
  941. cfu.option[cid].context = uni.createCanvasContext(cid, this);
  942. if(cfu.instance[cid] && cfu.option[cid] && cfu.option[cid].update === true){
  943. this._updataUChart(cid)
  944. }else{
  945. setTimeout(()=>{
  946. cfu.option[cid].context.restore();
  947. cfu.option[cid].context.save();
  948. this._newChart(cid)
  949. },100)
  950. }
  951. }
  952. })
  953. }
  954. } else {
  955. this.mixinDatacomLoading = false;
  956. this.showchart = false;
  957. if (this.reshow == true) {
  958. this.mixinDatacomErrorMessage = '布局错误:未获取到父元素宽高尺寸!canvas-id:' + cid;
  959. }
  960. }
  961. })
  962. .exec();
  963. },
  964. saveImage(){
  965. uni.canvasToTempFilePath({
  966. canvasId: this.cid,
  967. success: res=>{
  968. //#ifdef H5
  969. var a = document.createElement("a");
  970. a.href = res.tempFilePath;
  971. a.download = this.cid;
  972. a.target = '_blank'
  973. a.click();
  974. //#endif
  975. //#ifndef H5
  976. uni.saveImageToPhotosAlbum({
  977. filePath: res.tempFilePath,
  978. success: function () {
  979. uni.showToast({
  980. title: '保存成功',
  981. duration: 2000
  982. });
  983. }
  984. });
  985. //#endif
  986. }
  987. },this);
  988. },
  989. // #ifndef APP-VUE || H5
  990. _newChart(cid) {
  991. if (this.mixinDatacomLoading == true) {
  992. return;
  993. }
  994. this.showchart = true;
  995. cfu.instance[cid] = new uChartsMp(cfu.option[cid]);
  996. cfu.instance[cid].addEventListener('renderComplete', () => {
  997. this.emitMsg({name: 'complete', params: {type:"complete", complete: true, id: cid}});
  998. cfu.instance[cid].delEventListener('renderComplete')
  999. });
  1000. cfu.instance[cid].addEventListener('scrollLeft', () => {
  1001. this.emitMsg({name: 'scrollLeft', params: {type:"scrollLeft", scrollLeft: true, id: cid}});
  1002. });
  1003. cfu.instance[cid].addEventListener('scrollRight', () => {
  1004. this.emitMsg({name: 'scrollRight', params: {type:"scrollRight", scrollRight: true, id: cid}});
  1005. });
  1006. },
  1007. _updataUChart(cid) {
  1008. cfu.instance[cid].updateData(cfu.option[cid])
  1009. },
  1010. _tooltipDefault(item, category, index, opts) {
  1011. if (category) {
  1012. let data = item.data
  1013. if(typeof item.data === "object"){
  1014. data = item.data.value
  1015. }
  1016. return category + ' ' + item.name + ':' + data;
  1017. } else {
  1018. if (item.properties && item.properties.name) {
  1019. return item.properties.name;
  1020. } else {
  1021. return item.name + ':' + item.data;
  1022. }
  1023. }
  1024. },
  1025. _showTooltip(e) {
  1026. let cid = this.cid
  1027. let tc = cfu.option[cid].tooltipCustom
  1028. if (tc && tc !== undefined && tc !== null) {
  1029. let offset = undefined;
  1030. if (tc.x >= 0 && tc.y >= 0) {
  1031. offset = { x: tc.x, y: tc.y + 10 };
  1032. }
  1033. cfu.instance[cid].showToolTip(e, {
  1034. index: tc.index,
  1035. offset: offset,
  1036. textList: tc.textList,
  1037. formatter: (item, category, index, opts) => {
  1038. if (typeof cfu.option[cid].tooltipFormat === 'string' && cfu.formatter[cfu.option[cid].tooltipFormat]) {
  1039. return cfu.formatter[cfu.option[cid].tooltipFormat](item, category, index, opts);
  1040. } else {
  1041. return this._tooltipDefault(item, category, index, opts);
  1042. }
  1043. }
  1044. });
  1045. } else {
  1046. cfu.instance[cid].showToolTip(e, {
  1047. formatter: (item, category, index, opts) => {
  1048. if (typeof cfu.option[cid].tooltipFormat === 'string' && cfu.formatter[cfu.option[cid].tooltipFormat]) {
  1049. return cfu.formatter[cfu.option[cid].tooltipFormat](item, category, index, opts);
  1050. } else {
  1051. return this._tooltipDefault(item, category, index, opts);
  1052. }
  1053. }
  1054. });
  1055. }
  1056. },
  1057. _tap(e,move) {
  1058. let cid = this.cid
  1059. let currentIndex = null;
  1060. let legendIndex = null;
  1061. if (this.inScrollView === true || this.inAli) {
  1062. let chartdom = uni
  1063. .createSelectorQuery()
  1064. // #ifndef MP-ALIPAY
  1065. .in(this)
  1066. .select('#ChartBoxId'+cid)
  1067. // #endif
  1068. // #ifdef MP-ALIPAY
  1069. .select('#'+this.cid)
  1070. // #endif
  1071. .boundingClientRect(data => {
  1072. e.changedTouches=[];
  1073. if (this.inAli) {
  1074. e.changedTouches.unshift({ x: e.detail.clientX - data.left, y: e.detail.clientY - data.top});
  1075. }else{
  1076. e.changedTouches.unshift({ x: e.detail.x - data.left, y: e.detail.y - data.top - this.pageScrollTop});
  1077. }
  1078. if(move){
  1079. if (this.tooltipShow === true) {
  1080. this._showTooltip(e);
  1081. }
  1082. }else{
  1083. currentIndex = cfu.instance[cid].getCurrentDataIndex(e);
  1084. legendIndex = cfu.instance[cid].getLegendDataIndex(e);
  1085. if(this.tapLegend === true){
  1086. cfu.instance[cid].touchLegend(e);
  1087. }
  1088. if (this.tooltipShow === true) {
  1089. this._showTooltip(e);
  1090. }
  1091. this.emitMsg({name: 'getIndex', params: { type:"getIndex", event:{ x: e.detail.x - data.left, y: e.detail.y - data.top }, currentIndex: currentIndex, legendIndex: legendIndex, id: cid, opts: cfu.instance[cid].opts}});
  1092. }
  1093. })
  1094. .exec();
  1095. } else {
  1096. if(move){
  1097. if (this.tooltipShow === true) {
  1098. this._showTooltip(e);
  1099. }
  1100. }else{
  1101. e.changedTouches=[];
  1102. e.changedTouches.unshift({ x: e.detail.x - e.currentTarget.offsetLeft, y: e.detail.y - e.currentTarget.offsetTop });
  1103. currentIndex = cfu.instance[cid].getCurrentDataIndex(e);
  1104. legendIndex = cfu.instance[cid].getLegendDataIndex(e);
  1105. if(this.tapLegend === true){
  1106. cfu.instance[cid].touchLegend(e);
  1107. }
  1108. if (this.tooltipShow === true) {
  1109. this._showTooltip(e);
  1110. }
  1111. this.emitMsg({name: 'getIndex', params: {type:"getIndex", event:{ x: e.detail.x, y: e.detail.y - e.currentTarget.offsetTop }, currentIndex: currentIndex, legendIndex: legendIndex, id: cid, opts: cfu.instance[cid].opts}});
  1112. }
  1113. }
  1114. },
  1115. _touchStart(e) {
  1116. let cid = this.cid
  1117. lastMoveTime=Date.now();
  1118. if(cfu.option[cid].enableScroll === true){
  1119. cfu.instance[cid].scrollStart(e);
  1120. }
  1121. this.emitMsg({name:'getTouchStart', params:{type:"touchStart", event:e.changedTouches[0], id:cid}});
  1122. },
  1123. _touchMove(e) {
  1124. let cid = this.cid
  1125. let currMoveTime = Date.now();
  1126. let duration = currMoveTime - lastMoveTime;
  1127. if (duration < Math.floor(1000 / 60)) return;//每秒60帧
  1128. lastMoveTime = currMoveTime;
  1129. if(cfu.option[cid].enableScroll === true){
  1130. cfu.instance[cid].scroll(e);
  1131. }
  1132. this.emitMsg({name: 'getTouchMove', params: {type:"touchMove", event:e.changedTouches[0], id: cid}});
  1133. if(this.ontap === true && cfu.option[cid].enableScroll === false && this.onmovetip === true){
  1134. this._tap(e,true)
  1135. }
  1136. },
  1137. _touchEnd(e) {
  1138. let cid = this.cid
  1139. if(cfu.option[cid].enableScroll === true){
  1140. cfu.instance[cid].scrollEnd(e);
  1141. }
  1142. this.emitMsg({name:'getTouchEnd', params:{type:"touchEnd", event:e.changedTouches[0], id:cid}});
  1143. if(this.ontap === true && cfu.option[cid].enableScroll === false && this.onmovetip === true){
  1144. this._tap(e,true)
  1145. }
  1146. },
  1147. // #endif
  1148. _error(e) {
  1149. this.mixinDatacomErrorMessage = e.detail.errMsg;
  1150. },
  1151. emitMsg(msg) {
  1152. this.$emit(msg.name, msg.params);
  1153. },
  1154. getRenderType() {
  1155. //防止如果开启echarts且父元素为v-if的情况renderjs监听不到prop变化的问题
  1156. if(this.echarts===true && this.mixinDatacomLoading===false){
  1157. this.beforeInit()
  1158. }
  1159. },
  1160. toJSON(){
  1161. return this
  1162. }
  1163. }
  1164. };
  1165. </script>
  1166. <!-- #ifdef APP-VUE || H5 -->
  1167. <script module="rdcharts" lang="renderjs">
  1168. import uChartsRD from '../u-charts/u-charts.js';
  1169. import cfu from '../u-charts/config-ucharts.js';
  1170. import cfe from '../u-charts/config-echarts.js';
  1171. var that = {};
  1172. var rootdom = null;
  1173. function rddeepCloneAssign(origin = {}, ...args) {
  1174. for (let i in args) {
  1175. for (let key in args[i]) {
  1176. if (args[i].hasOwnProperty(key)) {
  1177. origin[key] = args[i][key] && typeof args[i][key] === 'object' ? rddeepCloneAssign(Array.isArray(args[i][key]) ? [] : {}, origin[key], args[i][key]) : args[i][key];
  1178. }
  1179. }
  1180. }
  1181. return origin;
  1182. }
  1183. function rdformatterAssign(args,formatter) {
  1184. for (let key in args) {
  1185. if(args[key] !== null && typeof args[key] === 'object'){
  1186. rdformatterAssign(args[key],formatter)
  1187. }else if(key === 'format' && typeof args[key] === 'string'){
  1188. args['formatter'] = formatter[args[key]] ? formatter[args[key]] : undefined;
  1189. }
  1190. }
  1191. return args;
  1192. }
  1193. export default {
  1194. data() {
  1195. return {
  1196. rid:null
  1197. }
  1198. },
  1199. mounted() {
  1200. rootdom = {top:0,left:0}
  1201. // #ifdef H5
  1202. let dm = document.querySelectorAll('uni-main')[0]
  1203. if(dm === undefined){
  1204. dm = document.querySelectorAll('uni-page-wrapper')[0]
  1205. }
  1206. rootdom = {top:dm.offsetTop,left:dm.offsetLeft}
  1207. // #endif
  1208. setTimeout(()=>{
  1209. if(this.rid === null){
  1210. this.$ownerInstance.callMethod('getRenderType')
  1211. }
  1212. },200)
  1213. },
  1214. destroyed(){
  1215. delete cfu.option[this.rid]
  1216. delete cfu.instance[this.rid]
  1217. delete cfe.option[this.rid]
  1218. delete cfe.instance[this.rid]
  1219. },
  1220. methods: {
  1221. //==============以下是ECharts的方法====================
  1222. ecinit(newVal, oldVal, owner, instance){
  1223. let cid = JSON.stringify(newVal.id)
  1224. this.rid = cid
  1225. that[cid] = this.$ownerInstance
  1226. let eopts = JSON.parse(JSON.stringify(newVal))
  1227. let type = eopts.type;
  1228. //载入并覆盖默认配置
  1229. if (type && cfe.type.includes(type)) {
  1230. cfe.option[cid] = rddeepCloneAssign({}, cfe[type], eopts);
  1231. }else{
  1232. cfe.option[cid] = rddeepCloneAssign({}, eopts);
  1233. }
  1234. let newData = eopts.chartData;
  1235. //挂载categories和series
  1236. if(cfe.option[cid].xAxis && cfe.option[cid].xAxis.type && cfe.option[cid].xAxis.type === 'category'){
  1237. cfe.option[cid].xAxis.data = newData.categories
  1238. }
  1239. if(cfe.option[cid].yAxis && cfe.option[cid].yAxis.type && cfe.option[cid].yAxis.type === 'category'){
  1240. cfe.option[cid].yAxis.data = newData.categories
  1241. }
  1242. cfe.option[cid].series = []
  1243. for (var i = 0; i < newData.series.length; i++) {
  1244. cfe.option[cid].seriesTemplate = cfe.option[cid].seriesTemplate ? cfe.option[cid].seriesTemplate : {}
  1245. let Template = rddeepCloneAssign({},cfe.option[cid].seriesTemplate,newData.series[i])
  1246. cfe.option[cid].series.push(Template)
  1247. }
  1248. if (typeof window.echarts === 'object') {
  1249. this.newEChart()
  1250. }else{
  1251. const script = document.createElement('script')
  1252. // #ifdef APP-VUE
  1253. script.src = './uni_modules/qiun-data-charts/static/app-plus/echarts.min.js'
  1254. // #endif
  1255. // #ifdef H5
  1256. const rooturl = window.location.origin
  1257. const directory = instance.getDataset().directory
  1258. script.src = rooturl + directory + 'uni_modules/qiun-data-charts/static/h5/echarts.min.js'
  1259. // #endif
  1260. script.onload = this.newEChart
  1261. document.head.appendChild(script)
  1262. }
  1263. },
  1264. ecresize(newVal, oldVal, owner, instance){
  1265. if(cfe.instance[this.rid]){
  1266. cfe.instance[this.rid].resize()
  1267. }
  1268. },
  1269. newEChart(){
  1270. let cid = this.rid
  1271. if(cfe.instance[cid] === undefined){
  1272. cfe.instance[cid] = echarts.init(that[cid].$el.children[0])
  1273. //ontap开启后才触发click事件
  1274. if(cfe.option[cid].ontap === true){
  1275. cfe.instance[cid].on('click', resdata => {
  1276. let event = JSON.parse(JSON.stringify({
  1277. x:resdata.event.offsetX,y:resdata.event.offsetY
  1278. }))
  1279. that[cid].callMethod('emitMsg',{name:"getIndex", params:{type:"getIndex", event:event, currentIndex:resdata.dataIndex, value:resdata.data, seriesName: resdata.seriesName,id:cid}})
  1280. })
  1281. }
  1282. this.updataEChart(cid,cfe.option[cid])
  1283. }else{
  1284. this.updataEChart(cid,cfe.option[cid])
  1285. }
  1286. },
  1287. updataEChart(cid,option){
  1288. //替换option内format属性为formatter的预定义方法
  1289. option = rdformatterAssign(option,cfe.formatter)
  1290. if(option.tooltip){
  1291. option.tooltip.show = option.tooltipShow?true:false;
  1292. option.tooltip.position = this.tooltipPosition()
  1293. //tooltipFormat方法,替换组件的tooltipFormat为config-echarts.js内对应的方法
  1294. if (typeof option.tooltipFormat === 'string' && cfe.formatter[option.tooltipFormat]) {
  1295. option.tooltip.formatter = option.tooltip.formatter ? option.tooltip.formatter : cfe.formatter[option.tooltipFormat]
  1296. }
  1297. }
  1298. // 颜色渐变添加的方法
  1299. if (option.series) {
  1300. for (let i in option.series) {
  1301. let linearGradient = option.series[i].linearGradient
  1302. if (linearGradient) {
  1303. option.series[i].color = new echarts.graphic.LinearGradient(linearGradient[0],linearGradient[1],linearGradient[2],linearGradient[3],linearGradient[4])
  1304. }
  1305. }
  1306. }
  1307. cfe.instance[cid].setOption(option, option.notMerge)
  1308. cfe.instance[cid].on('finished', function(){
  1309. that[cid].callMethod('emitMsg',{name:"complete",params:{type:"complete",complete:true,id:cid}})
  1310. if(cfe.instance[cid]){
  1311. cfe.instance[cid].off('finished')
  1312. }
  1313. })
  1314. },
  1315. tooltipPosition(){
  1316. return (point, params, dom, rect, size) => {
  1317. let x = point[0]
  1318. let y = point[1]
  1319. let viewWidth = size.viewSize[0]
  1320. let viewHeight = size.viewSize[1]
  1321. let boxWidth = size.contentSize[0]
  1322. let boxHeight = size.contentSize[1]
  1323. let posX = x + 30
  1324. let posY = y + 30
  1325. if (posX + boxWidth > viewWidth) {
  1326. posX = x - boxWidth - 30
  1327. }
  1328. if (posY + boxHeight > viewHeight) {
  1329. posY = y - boxHeight - 30
  1330. }
  1331. return [posX, posY]
  1332. }
  1333. },
  1334. //==============以下是uCharts的方法====================
  1335. ucinit(newVal, oldVal, owner, instance){
  1336. if(JSON.stringify(newVal) == JSON.stringify(oldVal)){
  1337. return;
  1338. }
  1339. let cid = JSON.parse(JSON.stringify(newVal.canvasId))
  1340. this.rid = cid
  1341. that[cid] = this.$ownerInstance
  1342. cfu.option[cid] = JSON.parse(JSON.stringify(newVal))
  1343. cfu.option[cid] = rdformatterAssign(cfu.option[cid],cfu.formatter)
  1344. let canvasdom = document.getElementById(cid)
  1345. if(canvasdom && canvasdom.children[0]){
  1346. cfu.option[cid].context = canvasdom.children[0].getContext("2d")
  1347. if(cfu.instance[cid] && cfu.option[cid] && cfu.option[cid].update === true){
  1348. this.updataUChart()
  1349. }else{
  1350. setTimeout(()=>{
  1351. cfu.option[cid].context.restore();
  1352. cfu.option[cid].context.save();
  1353. this.newUChart()
  1354. },100)
  1355. }
  1356. }
  1357. },
  1358. newUChart() {
  1359. let cid = this.rid
  1360. cfu.instance[cid] = new uChartsRD(cfu.option[cid])
  1361. cfu.instance[cid].addEventListener('renderComplete', () => {
  1362. that[cid].callMethod('emitMsg',{name:"complete",params:{type:"complete",complete:true,id:cid}})
  1363. cfu.instance[cid].delEventListener('renderComplete')
  1364. });
  1365. cfu.instance[cid].addEventListener('scrollLeft', () => {
  1366. that[cid].callMethod('emitMsg',{name:"scrollLeft",params:{type:"scrollLeft",scrollLeft:true,id:cid}})
  1367. });
  1368. cfu.instance[cid].addEventListener('scrollRight', () => {
  1369. that[cid].callMethod('emitMsg',{name:"scrollRight",params:{type:"scrollRight",scrollRight:true,id:cid}})
  1370. });
  1371. },
  1372. updataUChart() {
  1373. let cid = this.rid
  1374. cfu.instance[cid].updateData(cfu.option[cid])
  1375. },
  1376. tooltipDefault(item, category, index, opts) {
  1377. if (category) {
  1378. let data = item.data
  1379. if(typeof item.data === "object"){
  1380. data = item.data.value
  1381. }
  1382. return category + ' ' + item.name + ':' + data;
  1383. } else {
  1384. if (item.properties && item.properties.name) {
  1385. return item.properties.name ;
  1386. } else {
  1387. return item.name + ':' + item.data;
  1388. }
  1389. }
  1390. },
  1391. showTooltip(e,cid) {
  1392. let tc = cfu.option[cid].tooltipCustom
  1393. if (tc && tc !== undefined && tc !== null) {
  1394. let offset = undefined;
  1395. if (tc.x >= 0 && tc.y >= 0) {
  1396. offset = { x: tc.x, y: tc.y + 10 };
  1397. }
  1398. cfu.instance[cid].showToolTip(e, {
  1399. index: tc.index,
  1400. offset: offset,
  1401. textList: tc.textList,
  1402. formatter: (item, category, index, opts) => {
  1403. if (typeof cfu.option[cid].tooltipFormat === 'string' && cfu.formatter[cfu.option[cid].tooltipFormat]) {
  1404. return cfu.formatter[cfu.option[cid].tooltipFormat](item, category, index, opts);
  1405. } else {
  1406. return this.tooltipDefault(item, category, index, opts);
  1407. }
  1408. }
  1409. });
  1410. } else {
  1411. cfu.instance[cid].showToolTip(e, {
  1412. formatter: (item, category, index, opts) => {
  1413. if (typeof cfu.option[cid].tooltipFormat === 'string' && cfu.formatter[cfu.option[cid].tooltipFormat]) {
  1414. return cfu.formatter[cfu.option[cid].tooltipFormat](item, category, index, opts);
  1415. } else {
  1416. return this.tooltipDefault(item, category, index, opts);
  1417. }
  1418. }
  1419. });
  1420. }
  1421. },
  1422. tap(e) {
  1423. let cid = this.rid
  1424. let ontap = cfu.option[cid].ontap
  1425. let tooltipShow = cfu.option[cid].tooltipShow
  1426. let tapLegend = cfu.option[cid].tapLegend
  1427. if(ontap == false) return;
  1428. let currentIndex=null
  1429. let legendIndex=null
  1430. let rchartdom = document.getElementById('UC'+cid).getBoundingClientRect()
  1431. let tmpe = {}
  1432. if(e.detail.x){//tap或者click的事件
  1433. tmpe = { x: e.detail.x - rchartdom.left, y:e.detail.y - rchartdom.top + rootdom.top}
  1434. }else{//mouse的事件
  1435. tmpe = { x: e.clientX - rchartdom.left, y:e.clientY - rchartdom.top + rootdom.top}
  1436. }
  1437. e.changedTouches.unshift(tmpe)
  1438. currentIndex=cfu.instance[cid].getCurrentDataIndex(e)
  1439. legendIndex=cfu.instance[cid].getLegendDataIndex(e)
  1440. if(tapLegend === true){
  1441. cfu.instance[cid].touchLegend(e);
  1442. }
  1443. if(tooltipShow==true){
  1444. this.showTooltip(e,cid)
  1445. }
  1446. that[cid].callMethod('emitMsg',{name:"getIndex",params:{type:"getIndex",event:tmpe,currentIndex:currentIndex,legendIndex:legendIndex,id:cid, opts: cfu.instance[cid].opts}})
  1447. },
  1448. touchStart(e) {
  1449. let cid = this.rid
  1450. let ontouch = cfu.option[cid].ontouch
  1451. if(ontouch == false) return;
  1452. cfu.instance[cid].scrollStart(e)
  1453. that[cid].callMethod('emitMsg',{name:"getTouchStart",params:{type:"touchStart",event:e.changedTouches[0],id:cid}})
  1454. },
  1455. touchMove(e) {
  1456. let cid = this.rid
  1457. let ontouch = cfu.option[cid].ontouch
  1458. if(ontouch == false) return;
  1459. cfu.instance[cid].scroll(e)
  1460. that[cid].callMethod('emitMsg',{name:"getTouchMove",params:{type:"touchMove",event:e.changedTouches[0],id:cid}})
  1461. if(cfu.option[cid].ontap === true && cfu.option[cid].enableScroll === false && cfu.option[cid].onmovetip === true){
  1462. let rchartdom = document.getElementById('UC'+cid).getBoundingClientRect()
  1463. let tmpe = { x: e.changedTouches[0].clientX - rchartdom.left, y:e.changedTouches[0].clientY - rchartdom.top + rootdom.top}
  1464. e.changedTouches.unshift(tmpe)
  1465. if(cfu.option[cid].tooltipShow === true){
  1466. this.showTooltip(e,cid)
  1467. }
  1468. }
  1469. },
  1470. touchEnd(e) {
  1471. let cid = this.rid
  1472. let ontouch = cfu.option[cid].ontouch
  1473. if(ontouch == false) return;
  1474. cfu.instance[cid].scrollEnd(e)
  1475. that[cid].callMethod('emitMsg',{name:"getTouchEnd",params:{type:"touchEnd",event:e.changedTouches[0],id:cid}})
  1476. },
  1477. mouseDown(e) {
  1478. let cid = this.rid
  1479. let onmouse = cfu.option[cid].onmouse
  1480. if(onmouse == false) return;
  1481. let rchartdom = document.getElementById('UC'+cid).getBoundingClientRect()
  1482. let tmpe = {}
  1483. tmpe = { x: e.clientX - rchartdom.left, y:e.clientY - rchartdom.top + rootdom.top}
  1484. e.changedTouches.unshift(tmpe)
  1485. cfu.instance[cid].scrollStart(e)
  1486. cfu.option[cid].mousedown=true;
  1487. that[cid].callMethod('emitMsg',{name:"getTouchStart",params:{type:"mouseDown",event:tmpe,id:cid}})
  1488. },
  1489. mouseMove(e) {
  1490. let cid = this.rid
  1491. let onmouse = cfu.option[cid].onmouse
  1492. let tooltipShow = cfu.option[cid].tooltipShow
  1493. if(onmouse == false) return;
  1494. let rchartdom = document.getElementById('UC'+cid).getBoundingClientRect()
  1495. let tmpe = {}
  1496. tmpe = { x: e.clientX - rchartdom.left, y:e.clientY - rchartdom.top + rootdom.top}
  1497. e.changedTouches.unshift(tmpe)
  1498. if(cfu.option[cid].mousedown){
  1499. cfu.instance[cid].scroll(e)
  1500. that[cid].callMethod('emitMsg',{name:"getTouchMove",params:{type:"mouseMove",event:tmpe,id:cid}})
  1501. }else if(cfu.instance[cid]){
  1502. if(tooltipShow==true){
  1503. this.showTooltip(e,cid)
  1504. }
  1505. }
  1506. },
  1507. mouseUp(e) {
  1508. let cid = this.rid
  1509. let onmouse = cfu.option[cid].onmouse
  1510. if(onmouse == false) return;
  1511. let rchartdom = document.getElementById('UC'+cid).getBoundingClientRect()
  1512. let tmpe = {}
  1513. tmpe = { x: e.clientX - rchartdom.left, y:e.clientY - rchartdom.top + rootdom.top}
  1514. e.changedTouches.unshift(tmpe)
  1515. cfu.instance[cid].scrollEnd(e)
  1516. cfu.option[cid].mousedown=false;
  1517. that[cid].callMethod('emitMsg',{name:"getTouchEnd",params:{type:"mouseUp",event:tmpe,id:cid}})
  1518. },
  1519. }
  1520. }
  1521. </script>
  1522. <!-- #endif -->
  1523. <style scoped>
  1524. .chartsview {
  1525. width: 100%;
  1526. height: 100%;
  1527. display: flex;
  1528. flex: 1;
  1529. justify-content: center;
  1530. align-items: center;
  1531. }
  1532. </style>