l-echart.uvue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. <template>
  2. <!-- #ifdef APP -->
  3. <web-view class="lime-echart" ref="chartRef" @load="loaded" :style="[customStyle]"
  4. :webview-styles="[webviewStyles]" src="/pagesStorage/components/lime-echart/static/uvue.html?v=10112">
  5. </web-view>
  6. <!-- #endif -->
  7. <!-- #ifdef H5 -->
  8. <div class="lime-echart" ref="chartRef"></div>
  9. <!-- #endif -->
  10. <!-- #ifndef H5 || APP-->
  11. <canvas class="lime-echart" :id="canvasid" :canvas-id="canvasid"
  12. @touchstart="touchstart"
  13. @touchmove="touchmove"
  14. @touchend="touchend">
  15. </canvas>
  16. <!-- #endif -->
  17. </template>
  18. <script lang="uts" setup>
  19. // @ts-nocheck
  20. import { getCurrentInstance, nextTick } from "vue";
  21. import { Echarts } from './uvue';
  22. // #ifdef WEB
  23. import { dispatch } from './canvas';
  24. // #endif
  25. // #ifndef APP || WEB
  26. import {Canvas, setCanvasCreator, dispatch} from './canvas';
  27. import {wrapTouch, convertTouchesToArray, devicePixelRatio ,sleep, canIUseCanvas2d, getRect} from './utils';
  28. // #endif
  29. type EchartsResolve = (value : Echarts) => void
  30. defineOptions({
  31. name: 'l-echart'
  32. })
  33. const emits = defineEmits(['finished'])
  34. const props = defineProps({
  35. // #ifdef APP
  36. webviewStyles: {
  37. type: Object
  38. },
  39. customStyle: {
  40. type: Object
  41. },
  42. // #endif
  43. // #ifndef APP
  44. webviewStyles: {
  45. type: Object
  46. },
  47. customStyle: {
  48. type: [String, Object]
  49. },
  50. // #endif
  51. isDisableScroll: {
  52. type: Boolean,
  53. default: false
  54. },
  55. isClickable: {
  56. type: Boolean,
  57. default: true
  58. },
  59. enableHover: {
  60. type: Boolean,
  61. default: false
  62. },
  63. beforeDelay: {
  64. type: Number,
  65. default: 30
  66. }
  67. })
  68. const instance = getCurrentInstance()!;
  69. const canvasid = `lime-echart-${instance.uid}`
  70. const finished = ref(false)
  71. const map = [] as EchartsResolve[]
  72. const callbackMap = [] as EchartsResolve[]
  73. // let context = null as UniWebViewElement | null
  74. let chart = null as Echarts | null
  75. let chartRef = ref<UniWebViewElement | null>(null)
  76. const trigger = () => {
  77. // #ifdef APP
  78. if (finished.value) {
  79. if (chart == null) {
  80. chart = new Echarts(chartRef.value!)
  81. }
  82. while (map.length > 0) {
  83. const resolve = map.pop() as EchartsResolve
  84. resolve(chart!)
  85. }
  86. }
  87. // #endif
  88. // #ifndef APP
  89. while (map.length > 0) {
  90. if(chart != null){
  91. const resolve = map.pop() as EchartsResolve
  92. resolve(chart!)
  93. }
  94. }
  95. // #endif
  96. if(chart != null){
  97. while(callbackMap.length > 0){
  98. const callback = callbackMap.pop() as EchartsResolve
  99. callback(chart!)
  100. }
  101. }
  102. }
  103. // #ifdef APP
  104. const loaded = (event : UniWebViewLoadEvent) => {
  105. event.stopPropagation()
  106. event.preventDefault()
  107. finished.value = true
  108. trigger()
  109. emits('finished')
  110. }
  111. // #endif
  112. const _next = () : boolean => {
  113. if (chart == null) {
  114. console.warn(`组件还未初始化,请先使用 init`)
  115. return true
  116. }
  117. return false
  118. }
  119. const setOption = (option : UTSJSONObject) => {
  120. if (_next()) return
  121. chart!.setOption(option);
  122. }
  123. const showLoading = () => {
  124. if (_next()) return
  125. chart!.showLoading();
  126. }
  127. const hideLoading = () => {
  128. if (_next()) return
  129. chart!.hideLoading();
  130. }
  131. const clear = () => {
  132. if (_next()) return
  133. chart!.clear();
  134. }
  135. const dispose = () => {
  136. if (_next()) return
  137. chart!.dispose();
  138. }
  139. const resize = (size : UTSJSONObject) => {
  140. if (_next()) return
  141. chart!.resize(size);
  142. }
  143. const canvasToTempFilePath = (opt : UTSJSONObject) => {
  144. if (_next()) return
  145. chart!.canvasToTempFilePath(opt);
  146. }
  147. // #ifdef APP
  148. function init(callback : ((chart : Echarts) => void) | null) : Promise<Echarts> {
  149. if(callback!=null){
  150. callbackMap.push(callback)
  151. }
  152. return new Promise<Echarts>((resolve) => {
  153. map.push(resolve)
  154. trigger()
  155. })
  156. }
  157. // #endif
  158. // #ifndef APP
  159. // #ifndef WEB
  160. let use2dCanvas = canIUseCanvas2d()
  161. const getContext = async () =>{
  162. return getRect(`#${canvasid}`, {context: instance.proxy!, type: use2dCanvas ? 'fields': 'boundingClientRect'}).then(res => {
  163. if(res) {
  164. let dpr = uni.getWindowInfo().pixelRatio
  165. let {width, height, node} = res
  166. let canvas;
  167. if(node) {
  168. const ctx = node.getContext('2d');
  169. canvas = new Canvas(ctx, instance.proxy, true, node);
  170. } else {
  171. const ctx = uni.createCanvasContext(canvasid, instance.proxy);
  172. canvas = new Canvas(ctx, instance.proxy, false);
  173. }
  174. return { canvas, width, height, devicePixelRatio: dpr, node };
  175. } else {
  176. return {}
  177. }
  178. })
  179. }
  180. // #endif
  181. const getTouch = (e) => {
  182. const touches = e.touches[0]
  183. // #ifdef WEB
  184. const rect = chart!.getZr().dom.getBoundingClientRect();
  185. const touch = {
  186. x: touches.clientX - rect.left,
  187. y: touches.clientY - rect.top
  188. }
  189. // #endif
  190. // #ifndef WEB
  191. const touch = {
  192. x: touches.x,
  193. y: touches.y
  194. }
  195. // #endif
  196. return touch
  197. }
  198. const touchstart = (e) => {
  199. if(chart == null) return
  200. const handler = chart.getZr().handler;
  201. const touch = getTouch(e)
  202. dispatch.call(handler, 'mousedown', touch)
  203. dispatch.call(handler, 'click', touch)
  204. }
  205. const touchmove = (e) => {
  206. if(chart == null) return
  207. const handler = chart.getZr().handler;
  208. const touch = getTouch(e)
  209. dispatch.call(handler, 'mousemove', touch)
  210. // const rect = chart.getZr().dom.getBoundingClientRect()
  211. // handler.dispatch('mousemove', {
  212. // zrX: e.touches[0].clientX - rect.left,
  213. // zrY: e.touches[0].clientY - rect.top
  214. // })
  215. }
  216. const touchend = (e) => {
  217. if(chart == null) return
  218. const handler = chart.getZr().handler;
  219. const touch = {
  220. x: 999999999,
  221. y: 999999999
  222. }
  223. dispatch.call(handler, 'mousemove', touch)
  224. dispatch.call(handler, 'touchend', touch)
  225. }
  226. async function init(echarts: any, ...args: any[]): Promise<Echarts>{
  227. if(echarts == null){
  228. console.error('请确保已经引入了 ECharts 库');
  229. return Promise.reject('请确保已经引入了 ECharts 库');
  230. }
  231. let theme:string|null=null
  232. let opts={}
  233. let callback:Function|null=null;
  234. args.forEach(item =>{
  235. if(typeof item === 'function') {
  236. callback = item
  237. } else if(['string'].includes(typeof item)){
  238. theme = item
  239. } else if(typeof item === 'object'){
  240. opts = item
  241. }
  242. })
  243. // #ifdef WEB
  244. chart = echarts.init(chartRef.value, theme, opts)
  245. window.addEventListener('touchstart', touchstart)
  246. window.addEventListener('touchmove', touchmove)
  247. window.addEventListener('touchend', touchend)
  248. // #endif
  249. // #ifndef WEB
  250. let config = await getContext();
  251. setCanvasCreator(echarts, config)
  252. chart = echarts.init(config.canvas, theme, Object.assign({}, config, opts))
  253. // #endif
  254. console.log('chart', chart)
  255. if(callback!=null && typeof callback == 'function'){
  256. callbackMap.push(callback)
  257. }
  258. return new Promise<Echarts>((resolve) => {
  259. map.push(resolve)
  260. trigger()
  261. })
  262. }
  263. onMounted(()=>{
  264. nextTick(()=>{
  265. finished.value = true
  266. trigger()
  267. emits('finished')
  268. })
  269. })
  270. onUnmounted(()=>{
  271. // #ifdef WEB
  272. window.removeEventListener('touchstart', touchstart)
  273. window.removeEventListener('touchmove', touchmove)
  274. window.removeEventListener('touchend', touchend)
  275. // #endif
  276. })
  277. // #endif
  278. defineExpose({
  279. init,
  280. setOption,
  281. showLoading,
  282. hideLoading,
  283. clear,
  284. dispose,
  285. resize,
  286. canvasToTempFilePath
  287. })
  288. </script>
  289. <style lang="scss">
  290. .lime-echart {
  291. flex: 1;
  292. width: 100%;
  293. }
  294. </style>