店播抖音版小程序

echarts.vue 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <template>
  2. <canvas
  3. v-if="canvasId"
  4. :type="forceUseOldCanvas?'':'2d'"
  5. class="ec-canvas"
  6. :id="canvasId"
  7. :canvasId="canvasId"
  8. @touchstart="touchStart"
  9. @touchmove="touchMove"
  10. @touchend="touchEnd">
  11. </canvas>
  12. </template>
  13. <script>
  14. import WxCanvas2 from './wx-canvas2';
  15. import WxCanvas from './wx-canvas';
  16. import * as echarts from './echarts.min'; /*chart.min.js为在线定制*/
  17. function compareVersion(v1s, v2s) {
  18. const v1 = v1s.split('.');
  19. const v2 = v2s.split('.');
  20. const len = Math.max(v1.length, v2.length);
  21. while (v1.length < len) {
  22. v1.push('0');
  23. }
  24. while (v2.length < len) {
  25. v2.push('0');
  26. }
  27. for (let i = 0; i < len; i += 1) {
  28. const num1 = parseInt(v1[i]);
  29. const num2 = parseInt(v2[i]);
  30. if (num1 > num2) {
  31. return 1;
  32. } else if (num1 < num2) {
  33. return -1;
  34. }
  35. }
  36. return 0;
  37. }
  38. function wrapTouch(e) {
  39. for (let i = 0; i < e.mp.touches.length; i += 1) {
  40. const touch = e.mp.touches[i];
  41. touch.offsetX = touch.x;
  42. touch.offsetY = touch.y;
  43. }
  44. return e;
  45. }
  46. export default {
  47. props: {
  48. // echarts: {
  49. // required: true,
  50. // type: Object,
  51. // default() {
  52. // return null;
  53. // },
  54. // },
  55. forceUseOldCanvas: {
  56. type: Boolean,
  57. default: false,
  58. },
  59. canvasId: {
  60. type: String,
  61. default: 'ec-canvas',
  62. },
  63. onInit: {
  64. type: Function,
  65. default: null,
  66. },
  67. lazyLoad: {
  68. type: Boolean,
  69. default: false,
  70. },
  71. disableTouch: {
  72. type: Boolean,
  73. default: false,
  74. },
  75. throttleTouch: {
  76. type: Boolean,
  77. default: false,
  78. },
  79. },
  80. onReady() {
  81. if (!echarts) {
  82. console.warn('组件需绑定 echarts 变量,例:<ec-canvas id="mychart-dom-bar" '
  83. + 'canvas-id="mychart-bar" :echarts="echarts"></ec-canvas>');
  84. return;
  85. }
  86. if (!this.lazyLoad) {
  87. this.init();
  88. }
  89. },
  90. methods: {
  91. init(callback) {
  92. const version = wx.getSystemInfoSync().SDKVersion;
  93. const canUseNewCanvas = compareVersion(version, '2.9.0') >= 0;
  94. this.isUseNewCanvas = canUseNewCanvas && !this.forceUseOldCanvas;
  95. if (this.forceUseOldCanvas && canUseNewCanvas) {
  96. console.warn('开发者强制使用旧canvas,建议关闭');
  97. }
  98. if (this.isUseNewCanvas) {
  99. this.initByNewWay(callback);
  100. } else {
  101. const isValid = compareVersion(version, '1.9.91') >= 0;
  102. if (!isValid) {
  103. console.error('微信基础库版本过低,需大于等于 1.9.91。'
  104. + '参见:https://github.com/ecomfe/echarts-for-weixin'
  105. + '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82');
  106. } else {
  107. console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能');
  108. this.initByOldWay(callback);
  109. }
  110. }
  111. },
  112. initByNewWay(callback) {
  113. // version >= 2.9.0:使用新的方式初始化
  114. const { canvasId } = this;
  115. const query = wx.createSelectorQuery().in(this);
  116. query
  117. .select(`#${canvasId}`)
  118. .fields({ node: true, size: true })
  119. .exec((res) => {
  120. const canvasNode = res[0].node;
  121. this.canvasNode = canvasNode;
  122. const canvasDpr = wx.getSystemInfoSync().pixelRatio;
  123. const canvasWidth = res[0].width;
  124. const canvasHeight = res[0].height;
  125. const ctx = canvasNode.getContext('2d');
  126. const canvas = new WxCanvas2(ctx, canvasId, true, canvasNode);
  127. echarts.setCanvasCreator(() => canvas);
  128. if (typeof callback === 'function') {
  129. this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr);
  130. } else if (typeof this.onInit === 'function') {
  131. this.chart = this.onInit(canvas, canvasWidth, canvasHeight, canvasDpr);
  132. } else {
  133. this.triggerEvent('init', {
  134. canvas,
  135. width: canvasWidth,
  136. height: canvasHeight,
  137. dpr: canvasDpr,
  138. });
  139. }
  140. });
  141. },
  142. initByOldWay(callback) {
  143. // 1.9.91 <= version < 2.9.0:原来的方式初始化
  144. const { canvasId } = this;
  145. this.ctx = wx.createCanvasContext(canvasId);
  146. const canvas = new WxCanvas(this.ctx, canvasId);
  147. echarts.setCanvasCreator(() => canvas);
  148. // const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
  149. const canvasDpr = 1;
  150. const query = wx.createSelectorQuery();
  151. query.select(`#${canvasId}`).boundingClientRect((res) => {
  152. if (!res) {
  153. setTimeout(() => this.init(), 50);
  154. return;
  155. }
  156. const { width, height } = res;
  157. if (typeof callback === 'function') {
  158. this.chart = callback(canvas, width, height, canvasDpr);
  159. } else if (typeof this.onInit === 'function') {
  160. this.chart = this.onInit(canvas, width, height, canvasDpr);
  161. } else {
  162. this.triggerEvent('init', {
  163. canvas,
  164. width,
  165. height,
  166. dpr: canvasDpr,
  167. });
  168. }
  169. }).exec();
  170. },
  171. canvasToTempFilePath(opt) {
  172. const { canvasId } = this;
  173. if (this.isUseNewCanvas) {
  174. // 新版
  175. const query = wx.createSelectorQuery();
  176. query
  177. .select(`#${canvasId}`)
  178. .fields({ node: true, size: true })
  179. .exec((res) => {
  180. const canvasNode = res[0].node;
  181. Object.assign(opt, { canvas: canvasNode });
  182. wx.canvasToTempFilePath(opt);
  183. });
  184. } else {
  185. // 旧的
  186. this.ctx.draw(true, () => {
  187. wx.canvasToTempFilePath({
  188. canvasId,
  189. ...opt,
  190. });
  191. });
  192. }
  193. },
  194. touchStart(e) {
  195. const { disableTouch, chart } = this;
  196. if (disableTouch || !chart || !e.mp.touches.length) return;
  197. const touch = e.mp.touches[0];
  198. const { handler } = chart.getZr();
  199. handler.dispatch('mousedown', {
  200. zrX: touch.x,
  201. zrY: touch.y,
  202. });
  203. handler.dispatch('mousemove', {
  204. zrX: touch.x,
  205. zrY: touch.y,
  206. });
  207. handler.processGesture(wrapTouch(e), 'start');
  208. },
  209. touchMove(e) {
  210. const {
  211. disableTouch, throttleTouch, chart, lastMoveTime,
  212. } = this;
  213. if (disableTouch || !chart || !e.mp.touches.length) return;
  214. if (throttleTouch) {
  215. const currMoveTime = Date.now();
  216. if (currMoveTime - lastMoveTime < 240) return;
  217. this.lastMoveTime = currMoveTime;
  218. }
  219. const touch = e.mp.touches[0];
  220. const { handler } = chart.getZr();
  221. handler.dispatch('mousemove', {
  222. zrX: touch.x,
  223. zrY: touch.y,
  224. });
  225. handler.processGesture(wrapTouch(e), 'change');
  226. },
  227. touchEnd(e) {
  228. const { disableTouch, chart } = this;
  229. if (disableTouch || !chart) return;
  230. const touch = e.mp.changedTouches ? e.mp.changedTouches[0] : {};
  231. const { handler } = chart.getZr();
  232. handler.dispatch('mouseup', {
  233. zrX: touch.x,
  234. zrY: touch.y,
  235. });
  236. handler.dispatch('click', {
  237. zrX: touch.x,
  238. zrY: touch.y,
  239. });
  240. handler.processGesture(wrapTouch(e), 'end');
  241. },
  242. },
  243. };
  244. </script>
  245. <style scoped>
  246. .ec-canvas {
  247. width: 100%;
  248. height: 100%;
  249. }
  250. </style>