canvas.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. /**
  2. * 发现bug
  3. * android app上字体要大于等于20px才能画多个字体,不然要每次调用fillText时都要设置字体
  4. * android app上,重绘时会一直闪烁
  5. * */
  6. class canvasDraw {
  7. /*
  8. * @params{ DOM } canvasEl canvas元素节点
  9. * @params{ Object } option 统计图配置信息
  10. */
  11. constructor(el, option) {
  12. // canvas DOM;
  13. this.option = option;
  14. this.context = el.context;
  15. // canvas宽高
  16. this.width = el.width;
  17. this.height = el.height;
  18. // 预留XY文字间距
  19. this.reservedSpace = 55;
  20. this.textAndDotSpace = 10;
  21. // X点之间的间隔 宽高
  22. this.spaceX = 1;
  23. this.spaceY = 70;
  24. this.xWidth = 1;
  25. this.xHeight = 1;
  26. this.XList = [];
  27. this.YList = [];
  28. let yAxis = this.option.yAxis || {};
  29. this.xAxis = this.option.xAxis.map(e => {
  30. let date = new Date(e)
  31. return date.getFullYear() + '年' + (date.getMonth() + 1) + '月' + date.getDate() + '日';
  32. })
  33. let measure = this.context.measureText(this.xAxis[0]).width;
  34. this.xAxisLength = measure || (this.width - this.reservedSpace) / 2;
  35. this.drawDataList = this.option.data || [];
  36. this.xScaleListLength = this.drawDataList[0] && this.drawDataList[0].data.length || 0;
  37. // 刻度数量
  38. this.scale = yAxis.subsection ? yAxis.subsection + 1 : 5;
  39. this.xScaleSizeOriginal = 0;
  40. // XY文字颜色 X线条点颜色 数据线颜色
  41. this.XYTextColor = '#666666';
  42. this.XDotColor = '#666666';
  43. this.dataLineXColor = this.option.dataLineXColor || [];
  44. if (this.dataLineXColor.length < this.xScaleListLength) {
  45. this.dataLineXColor = this.dataLineXColor.concat(
  46. [...Array(this.xScaleListLength - this.dataLineXColor.length).keys()]
  47. .map(e => this.getColor16())
  48. )
  49. }
  50. this.dataDotSize = 5;
  51. this.dataLineSize = 0.5;
  52. let data = this.drawDataList.length > 1 ?
  53. this.drawDataList.map(e => e.data).reduce((a,b) => a.concat(b || []))
  54. : this.drawDataList[0].data;
  55. this.max = Math.max.apply(null, data);
  56. this.min = Math.min.apply(null, data);
  57. this.yScaleList = [];
  58. this.xScaleList = [];
  59. // 获取鼠标手势事件参数
  60. this.touchX = 0;
  61. this.touchY = 0;
  62. // 计数的做优化的值
  63. this.timeout = null;
  64. // 初始化
  65. this.init();
  66. // 绑定事件
  67. if(el.addEventListener){
  68. this.el.addEventListener('touchstart', touchstart, false);
  69. this.el.addEventListener('touchmove', touchmove, false);
  70. this.el.addEventListener('touchend', touchend, false);
  71. this.el.addEventListener('mouseout', mouseout, false);
  72. this.el.addEventListener('mousemove', mousemove, false);
  73. }
  74. }
  75. /**
  76. * 获取刻度数据
  77. * @return {Array} kedu
  78. */
  79. getDatas(){
  80. let max = this.max;
  81. let keduObject = this.keduObject = this.getMeanInfo();
  82. let kedu = [];
  83. if(keduObject.lose){
  84. for (let i = keduObject.lose; i > 0; i--) {
  85. if(keduObject.mean < 0){
  86. kedu.push(parseFloat((keduObject.mean * i).toFixed(2)));
  87. }else{
  88. kedu.push(parseFloat('-' + (keduObject.mean * i).toFixed(2)));
  89. }
  90. }
  91. }
  92. kedu.push(0)
  93. for (let i = 1, length = keduObject.just; i <= length; i++) {
  94. kedu.push(parseFloat((Math.abs(keduObject.mean) * i).toFixed(2)));
  95. }
  96. return kedu
  97. }
  98. /**
  99. * 刻度算法
  100. * @return {Number} 刻度大小
  101. */
  102. meanFun(max, num = 4, bool) {
  103. if(max == 0 || num == 0){
  104. return 0
  105. }
  106. if(max < 0){
  107. Math.abs(max)
  108. }
  109. if (bool) {
  110. max = max.toFixed(2) * 100;
  111. return ((max + max % num) / num) / 100;
  112. }
  113. return Math.ceil((max + max % num) / num);
  114. }
  115. /**
  116. * 计算刻度数据
  117. * @return {Object} .just 正刻度量 .lose 负刻度量 .mean刻度大小
  118. */
  119. getMeanInfo() {
  120. let max = this.max;
  121. let min = this.min;
  122. let subsection = this.scale - 1;
  123. let boolEan = Math.floor(max) === Math.floor(min);
  124. if (max > 0 && min < 0) {
  125. let copyMin = Math.abs(min);
  126. let mean = this.meanFun(copyMin + max, subsection, boolEan);
  127. let bool = copyMin > max;
  128. let num = Math.floor([bool ? copyMin : max][0] / mean);
  129. let nMean = this.meanFun([bool ? copyMin : max][0], num, boolEan);
  130. return {
  131. just: bool ? subsection - num : num,
  132. mean: nMean,
  133. lose: !bool ? subsection - num : num
  134. }
  135. } else if (max >= 0 && min >= 0) {
  136. return {
  137. just: subsection,
  138. mean: this.meanFun(max, subsection,boolEan),
  139. lose: 0
  140. }
  141. } else if (max <= 0 && min < 0) {
  142. this.isLose = true;
  143. return {
  144. just: 0,
  145. mean: this.meanFun(min, subsection,boolEan),
  146. lose: subsection
  147. }
  148. }
  149. }
  150. /**
  151. * 初始化统计图
  152. */
  153. init() {
  154. this.YText = this.getDatas().reverse();
  155. this.getYAxisList();
  156. this.getXAxisList();
  157. this.drawXYAxis();
  158. this.drawYText();
  159. this.drawXText();
  160. this.initData();
  161. }
  162. /**
  163. * 悬停线
  164. */
  165. drawMouseTooltipLine() {
  166. if (!this.isTouch()) return;
  167. this.dataLineSize = 1;
  168. // this.redraw();
  169. this.drawMouseTooltipLineContext();
  170. this.drawMouseTooltip();
  171. }
  172. /**
  173. * 绘制悬停线
  174. */
  175. drawMouseTooltipLineContext(){
  176. this.context.beginPath();
  177. this.context.strokeStyle = 'rgba(0,0,0,0.3)';
  178. this.context.lineTo(this.touchX, this.YList[0]);
  179. this.context.lineTo(this.touchX, this.YList[this.YList.length - 1]);
  180. this.context.stroke();
  181. }
  182. /**
  183. * 用于判断是否是在图指定区域里
  184. * @return {Boolean} true在指定区域里
  185. */
  186. isTouch() {
  187. let XList = this.XList;
  188. let YList = this.YList;
  189. let touchX = this.touchX;
  190. let touchY = this.touchY;
  191. let maxX = XList[XList.length - 1];
  192. let minX = XList[0];
  193. let maxY = YList[YList.length - 1];
  194. let minY = YList[0];
  195. return (
  196. touchX >= minX && touchX <= maxX &&
  197. touchY >= minY && touchY <= maxY
  198. )
  199. }
  200. /**
  201. * 绘制悬停圈
  202. * 绘制坐标点数据
  203. */
  204. drawMouseTooltip() {
  205. let XList = this.XList;
  206. let YList = this.YList;
  207. let touchX = this.touchX;
  208. let list = this.drawDataList;
  209. let fontTxtSize = this.fontTxtSize;
  210. let xScaleList = this.xScaleList;
  211. let yScaleList = this.yScaleList;
  212. let dataLineXColor = this.dataLineXColor;
  213. let lineHeight = this.lineHeight;
  214. let textIndent = this.textIndent;
  215. let minXValue = XList[0];
  216. let minYValue = YList[0];
  217. let xAxis = this.xAxis;
  218. let index = this.touchIndex = this.getBigValueMin(xScaleList, touchX);
  219. this.tooltipHeight = (fontTxtSize + lineHeight) * (list.length + 1) + lineHeight;
  220. list.forEach((e, i) => {
  221. this.context.beginPath();
  222. if(touchX > xScaleList[index] - 2 && touchX < xScaleList[index] + 2){
  223. this.context.fillStyle = dataLineXColor[i];
  224. this.context.globalAlpha=0.3;
  225. this.context.arc(touchX, yScaleList[i][index], fontTxtSize / 2, 0, 2 * Math.PI);
  226. this.context.fill();
  227. this.context.beginPath();
  228. this.context.globalAlpha= 1;
  229. this.context.fillStyle = '#FFFFFF';
  230. this.context.arc(touchX, yScaleList[i][index], fontTxtSize / 4 + 0.5, 0, 2 * Math.PI);
  231. this.context.fill();
  232. this.context.beginPath();
  233. this.context.globalAlpha= 1;
  234. this.context.fillStyle = dataLineXColor[i];
  235. this.context.arc(touchX, yScaleList[i][index], fontTxtSize / 4, 0, 2 * Math.PI);
  236. this.context.fill();
  237. }
  238. })
  239. // tip长度
  240. this.context.textAlign = 'start';
  241. this.context.textBaseline = 'middle';
  242. this.context.fillStyle = '#FFFFFF';
  243. let measure = this.context.measureText(xAxis[index]).width;
  244. this.tooltipWidth = measure ? measure + this.fontTxtSize * 2 : (this.width - this.reservedSpace) / 2;
  245. list.forEach((e, i) => {
  246. let dataTxt = e.data;
  247. let title = (e.title || '') + ':' + dataTxt[index];
  248. let measure = this.context.measureText(title).width;
  249. let tooltipWidth = measure ? measure + this.fontTxtSize * 2 : (this.width - this.reservedSpace) / 2;
  250. if(tooltipWidth > this.tooltipWidth){
  251. this.tooltipWidth = tooltipWidth;
  252. }
  253. })
  254. this.context.beginPath()
  255. this.context.fillStyle = 'rgba(255,255,255,1)';
  256. this.roundRect(minXValue, minYValue, this.tooltipWidth, this.tooltipHeight, 3);
  257. this.context.fill();
  258. this.context.beginPath()
  259. this.context.strokeStyle = 'rgba(220,65,55,1)';
  260. this.context.moveTo(minXValue, minYValue);
  261. this.context.lineTo(minXValue + this.tooltipWidth, minYValue);
  262. this.context.lineTo(minXValue + this.tooltipWidth, minYValue + this.tooltipHeight);
  263. this.context.lineTo(minXValue, minYValue + this.tooltipHeight);
  264. this.context.closePath()
  265. this.context.stroke();
  266. this.context.beginPath()
  267. this.context.fillStyle = '#333333';
  268. this.context.font = this.fontTxtSize + this.fontFamily;
  269. this.context.fillText(xAxis[index], minXValue + textIndent, minYValue + lineHeight + textIndent / 2, );
  270. let x = 0;
  271. let y = 0;
  272. list.forEach((e, i) => {
  273. this.context.beginPath();
  274. this.context.fillStyle = '#333333';
  275. let dataTxt = e.data;
  276. let title = (e.title || '') + ':' + dataTxt[index];
  277. x = minXValue + textIndent;
  278. y = minYValue + (fontTxtSize + lineHeight) * (i + 1) + textIndent / 2;
  279. this.context.font = this.fontTxtSize + this.fontFamily;
  280. this.context.fillText(title, x + textIndent * 2, y + lineHeight);
  281. this.context.beginPath();
  282. this.context.fillStyle = dataLineXColor[i];
  283. this.context.arc(x + textIndent / 2, y + lineHeight, fontTxtSize / 4, 0, 2 * Math.PI);
  284. this.context.fill();
  285. })
  286. // #ifdef H5
  287. setTimeout(() => {
  288. this.context.draw(true);
  289. },100)
  290. // #endif
  291. // #ifndef H5
  292. this.context.draw(true);
  293. // #endif
  294. }
  295. /**
  296. * 绘制圆角矩形
  297. */
  298. roundRect(x, y, w, h, r) {
  299. if (w < 2 * r) r = w / 2;
  300. if (h < 2 * r) r = h / 2;
  301. this.context.beginPath();
  302. this.context.moveTo(x + r, y);
  303. this.context.arcTo(x + w, y, x + w, y + h, r);
  304. this.context.arcTo(x + w, y + h, x, y + h, r);
  305. this.context.arcTo(x, y + h, x, y, r);
  306. this.context.arcTo(x, y, x + w, y, r);
  307. this.context.closePath();
  308. }
  309. /**
  310. * 获取数据点下标
  311. */
  312. getBigValueMin(array, x) {
  313. for (let i = 0, length = array.length; i < length; i++) {
  314. if (array[i] >= x) {
  315. return i;
  316. }
  317. }
  318. return array.length - 1;
  319. }
  320. /**
  321. * 获取数据对应坐标
  322. */
  323. initData() {
  324. let YList = this.YList;
  325. let XList = this.XList;
  326. let YText = this.YText;
  327. let reservedSpace = this.reservedSpace;
  328. let xAxisLength = this.xAxisLength;
  329. // 刻度最大值最小值
  330. let minData = YText[YText.length - 1];
  331. let maxScaleList = YText[0];
  332. // 0坐标到Y刻度总高度的距离
  333. let XYHeight = YList[YList.length - 1];
  334. // Y刻度总高度
  335. let yHeight = XYHeight - this.spaceY;
  336. // x总刻度
  337. let xScaleAll = XList[XList.length - 1];
  338. // X每刻度大小
  339. this.xScaleSizeOriginal = this.xScaleSize = parseFloat(((xScaleAll - reservedSpace) / (this.xScaleListLength - 1)).toFixed(
  340. 2));
  341. // y刻度每份大小
  342. let yScaleSize = this.yScaleSize = 0;
  343. // 当刻度最大值是0或者负数的时候
  344. if (YText[0] <= 0) {
  345. this.yScaleSize = yScaleSize = parseFloat((yHeight / (Math.abs(minData) - Math.abs(maxScaleList))).toFixed(8));
  346. this.drawDataList.forEach(data => {
  347. let list = data.data;
  348. this.yScaleList.push(list.map(e => Math.floor((Math.abs(e)) * yScaleSize + this.spaceY)));
  349. })
  350. } else {
  351. this.yScaleSize = yScaleSize = parseFloat((yHeight / (maxScaleList - minData)).toFixed(8));
  352. this.drawDataList.forEach(data => {
  353. let list = data.data;
  354. this.yScaleList.push(list.map(e => Math.floor((maxScaleList - e) * yScaleSize + this.spaceY)));
  355. })
  356. }
  357. this.drawDataLine();
  358. }
  359. /**
  360. * 重绘统计图 xy坐标轴 刻度文字 坐标线 统计线
  361. */
  362. redraw() {
  363. this.context.clearRect(0, 0, this.width, this.height);
  364. this.drawXYAxis();
  365. this.drawYText();
  366. this.drawDataLine();
  367. }
  368. /**
  369. * 调节X坐标间距
  370. * @param {String,Number} size = [1-10]
  371. */
  372. handleXScaleSize(size) {
  373. this.xScaleSize = this.xScaleSizeOriginal * size;
  374. this.redraw();
  375. }
  376. /**
  377. * 绘制统计线
  378. */
  379. drawDataLine() {
  380. let dataLineSize = this.dataLineSize;
  381. let dataDotSize = this.dataDotSize;
  382. let dataLineXColor = this.dataLineXColor;
  383. let reservedSpace = this.reservedSpace;
  384. let xScaleSize = this.xScaleSize;
  385. let YList = this.YList;
  386. let xScaleList = this.xScaleList = [...Array(this.xScaleListLength).keys()].map(i => Math.floor(i * xScaleSize + reservedSpace));
  387. this.context.lineJoin = 'round';
  388. let indexOf0 = this.YText.indexOf(0);
  389. let index0 = YList[indexOf0];
  390. let drawDataList = this.drawDataList;
  391. let gradient = this.context
  392. .createLinearGradient(this.xScaleList[0], YList[0], this.xScaleList[0], YList[YList.length - 1]);
  393. drawDataList.forEach((e, i) => {
  394. if(e.isBg){
  395. let bg = e.bgColor || [{ key:0, value: 'rgba(231, 0, 18, 0.5)' },{ key:1, value: 'rgba(231, 0, 18, 0.1)' }];
  396. if(typeof bg === 'string'){
  397. gradient = bg;
  398. }else{
  399. bg.forEach((ee,ii) => {
  400. gradient.addColorStop(ee.key, ee.value);
  401. })
  402. }
  403. }
  404. })
  405. this.context.fillStyle = gradient;
  406. this.yScaleList.forEach((yD, yI) => {
  407. for (var i = 1, length = xScaleList.length; i < length; i++) {
  408. let xx = this.xScaleList[i - 1];
  409. let xx1 = this.xScaleList[i];
  410. let yy = yD[i - 1];
  411. let yy1 = yD[i];
  412. let ax = (xx1 - xx) / 3;
  413. let bx = xx + ax;
  414. let bx1 = xx + ax * 2;
  415. this.context.beginPath();
  416. this.context.moveTo(xx, yy);
  417. this.context.bezierCurveTo(bx, yy, bx1, yy1, xx1, yy1);
  418. if(drawDataList[yI].isBg){
  419. this.context.lineTo(xx1, index0)
  420. this.context.lineTo(xx, index0)
  421. this.context.lineTo(xx, yy)
  422. this.context.fill();
  423. }
  424. }
  425. })
  426. this.context.lineWidth = this.dataLineSize;
  427. this.yScaleList.forEach((yD, yI) => {
  428. this.context.beginPath();
  429. this.context.strokeStyle = dataLineXColor[yI];
  430. for (var i = 1, length = xScaleList.length; i < length; i++) {
  431. let xx = this.xScaleList[i - 1];
  432. let xx1 = this.xScaleList[i];
  433. let yy = yD[i - 1];
  434. let yy1 = yD[i];
  435. let ax = (xx1 - xx) / 3;
  436. let bx = xx + ax;
  437. let bx1 = xx + ax * 2;
  438. this.context.moveTo(xx, yy);
  439. this.context.bezierCurveTo(bx, yy, bx1, yy1, xx1, yy1);
  440. }
  441. this.context.stroke();
  442. })
  443. // #ifdef H5
  444. setTimeout(() => {
  445. this.context.draw(true);
  446. },100)
  447. // #endif
  448. // #ifndef H5
  449. this.context.draw(true);
  450. // #endif
  451. }
  452. /**
  453. * 随机生成16位字符颜色
  454. */
  455. getColor16() {
  456. return '#' + Math.random().toString(16).slice(-6);
  457. }
  458. /**
  459. * 绘制Y刻度文字
  460. */
  461. drawYText() {
  462. let YText = this.YText;
  463. let YList = this.YList;
  464. let XYTextColor = this.XYTextColor;
  465. let reservedSpace = this.reservedSpace;
  466. let textAndDotSpace = this.textAndDotSpace;
  467. let x = reservedSpace - textAndDotSpace;
  468. this.context.fillStyle = XYTextColor;
  469. this.context.textAlign = 'end';
  470. this.context.textBaseline = 'middle';
  471. YList.forEach((y, i) => {
  472. this.context.font = this.fontTxtSize + this.fontFamily;
  473. this.context.fillText(this.YText[i], x, y, x);
  474. })
  475. this.drawXText();
  476. }
  477. /**
  478. * 绘制X刻度文字,由于时间问题,这里只绘制了起始和结束文字
  479. */
  480. drawXText() {
  481. let xAxis = this.xAxis;
  482. let YList = this.YList;
  483. let XList = this.XList;
  484. let xAxisLength = this.xAxisLength;
  485. let XYTextColor = this.XYTextColor;
  486. let reservedSpace = this.reservedSpace;
  487. this.context.fillStyle = XYTextColor;
  488. this.context.textAlign = 'start';
  489. this.context.textBaseline = 'middle';
  490. this.context.font = this.fontTxtSize + this.fontFamily;
  491. this.context.fillText(xAxis[0], XList[0],
  492. YList[YList.length - 1] + this.fontTxtSize,
  493. xAxisLength + this.fontTxtSize * 4);
  494. this.context.font = this.fontTxtSize + this.fontFamily;
  495. this.context.textAlign = 'end';
  496. this.context.fillText(xAxis[xAxis.length - 1],
  497. XList[XList.length - 1], YList[YList.length - 1] + this.fontTxtSize,
  498. xAxisLength + this.fontTxtSize * 4);
  499. // #ifdef H5
  500. setTimeout(() => {
  501. this.context.draw(true);
  502. },100)
  503. // #endif
  504. // #ifndef H5
  505. this.context.draw(true);
  506. // #endif
  507. }
  508. /**
  509. * 绘制XY统计图雏形
  510. */
  511. drawXYAxis() {
  512. let XList = this.XList;
  513. let YList = this.YList;
  514. let xWidth = this.xWidth;
  515. let xHeight = this.xHeight;
  516. let XDotColor = this.XDotColor;
  517. let reservedSpace = this.reservedSpace;
  518. this.context.fillStyle = XDotColor;
  519. YList.forEach((y, i) => {
  520. XList.forEach((x, j) => {
  521. this.context.fillRect(x, y, xWidth, xHeight);
  522. })
  523. })
  524. // #ifdef H5
  525. setTimeout(() => {
  526. this.context.draw(true);
  527. },100)
  528. // #endif
  529. // #ifndef H5
  530. this.context.draw(true);
  531. // #endif
  532. }
  533. /**
  534. * 获取X轴对应坐标点
  535. */
  536. getXAxisList() {
  537. let width = this.width;
  538. let spaceX = this.spaceX;
  539. let xWidth = this.xWidth;
  540. let xHeight = this.xHeight;
  541. let reservedSpace = this.reservedSpace;
  542. let length = (width - reservedSpace - this.fontTxtSize) / (xWidth + spaceX);
  543. for (let i = 0; i < length; i++) {
  544. this.XList.push(i * (spaceX + xWidth) + reservedSpace);
  545. }
  546. }
  547. /**
  548. * 获取y轴对应坐标点
  549. */
  550. getYAxisList() {
  551. let height = this.height;
  552. let scale = this.scale;
  553. let reservedSpace = this.reservedSpace;
  554. this.spaceY = Math.floor((height - reservedSpace) / scale);
  555. for (let i = 0; i < scale; i++) {
  556. this.YList.push(i * this.spaceY + this.spaceY);
  557. }
  558. this.setTextStyle();
  559. }
  560. /**
  561. * 设置字体类型,行高,字体大小,缩进
  562. */
  563. setTextStyle() {
  564. // 字体
  565. this.fontFamily = 'px 宋体';
  566. this.lineHeight = 10;
  567. this.textIndent = 10;
  568. this.fontTxtSize = this.spaceY / 5 < 14 ? 14 : this.spaceY / 5;
  569. }
  570. };
  571. let touchstart = function (e) {
  572. if (!e.touches[0]) return
  573. this.ctx.touchX = e.touches[0].x;
  574. this.ctx.touchY = e.touches[0].y;
  575. this.ctx.drawMouseTooltipLine()
  576. }
  577. let touchmove = function (e) {
  578. if (!e.touches[0]) return
  579. this.ctx.touchX = e.touches[0].x;
  580. this.ctx.touchY = e.touches[0].y;
  581. this.ctx.drawMouseTooltipLine()
  582. }
  583. let mousemove = function (e){
  584. if (e.pageX){
  585. this.ctx.touchX = e.x;
  586. this.ctx.touchY = e.y;
  587. this.ctx.drawMouseTooltipLine()
  588. }
  589. }
  590. let mouseout = function (e) {
  591. this.ctx.dataLineSize = 0.5;
  592. this.ctx.redraw()
  593. }
  594. let touchend = function (e) {
  595. this.ctx.dataLineSize = 0.5;
  596. this.ctx.redraw()
  597. }
  598. export default {
  599. canvasDraw,
  600. touchstart,
  601. touchmove,
  602. mousemove,
  603. mouseout,
  604. touchend
  605. }