const cacheChart = {} class Image { constructor() { // __zr.dom this.currentSrc = null this.naturalHeight = 0 this.naturalWidth = 0 this.width = 0 this.height = 0 this.tagName = 'IMG' } set src(src) { this.currentSrc = src uni.getImageInfo({ src, success: (res) => { this.naturalWidth = this.width = res.width this.naturalHeight = this.height = res.height this.onload() }, fail: () => { this.onerror() } }) } get src() { return this.currentSrc } } export default class Canvas { constructor(ctx, canvasId, isNew, canvasNode) { cacheChart[canvasId] = {ctx} this.canvasId = canvasId; this.chart = null; this.isNew = isNew if (isNew) { this.canvasNode = canvasNode; } else { this.canvasNode = { createImage: () => { return new Image() } }; this._initStyle(ctx); } this._initEvent(); } getContext(contextType) { if (contextType === '2d') { return this.ctx; } } setChart(chart) { this.chart = chart; } attachEvent(e) {} detachEvent() {} addEventListener() {} removeEventListener() {} _initCanvas(zrender, ctx) { zrender.util.getContext = function() { return ctx; }; zrender.util.$override('measureText', function(text, font) { ctx.font = font || '12px sans-serif'; return ctx.measureText(text, font); }); } strLen(str) { let len = 0; for (let i = 0; i < str.length; i++) { if (str.charCodeAt(i) > 0 && str.charCodeAt(i) < 128) { len++; } else { len += 2; } } return len; } _initStyle(ctx) { var styles = [ 'fillStyle', 'strokeStyle', 'fontSize', 'globalAlpha', 'opacity', 'textAlign', 'textBaseline', 'shadow', 'lineWidth', 'lineCap', 'lineJoin', 'lineDash', 'miterLimit', // #ifdef MP-TOUTIAO 'font' // #endif ]; const fontSizeReg = /([\d\.]+)px/; const colorReg = /#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])\b/g; styles.forEach(style => { Object.defineProperty(ctx, style, { set: value => { if (style === 'font' && fontSizeReg.test(value)) { const match = fontSizeReg.exec(value); ctx.setFontSize(match[1]); return; } if (style === 'opacity') { ctx.setGlobalAlpha(value) return; } if (style !== 'fillStyle' && style !== 'strokeStyle' || value !== 'none' && value !== null) { // #ifdef H5 || APP-PLUS || MP-BAIDU if(typeof value == 'object') { if (value.hasOwnProperty('colorStop') || value.hasOwnProperty('colors')) { ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value); } return } // #endif // #ifdef MP-TOUTIAO if(colorReg.test(value)) { value = value.replace(colorReg, '#$1$1$2$2$3$3') } // #endif ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value); } } }); }); if(!this.isNew) { ctx.uniDrawImage = ctx.drawImage ctx.drawImage = (...a) => { a[0] = a[0].src ctx.uniDrawImage(...a) } } if(!ctx.createRadialGradient) { ctx.createRadialGradient = function() { return ctx.createCircularGradient(...[...arguments].slice(-3)) }; } // 字节不支持 if (!ctx.strokeText) { ctx.strokeText = (...a) => { ctx.fillText(...a) } } // 钉钉不支持 if (!ctx.measureText) { ctx.measureText = (text, font) => { let fontSize = 12; if (font) { fontSize = parseInt(font.match(/([\d\.]+)px/)[1]) } fontSize /= 2; return { width: this.strLen(text) * fontSize }; } } } _initEvent() { this.event = {}; const eventNames = [{ wxName: 'touchStart', ecName: 'mousedown' }, { wxName: 'touchMove', ecName: 'mousemove' }, { wxName: 'touchEnd', ecName: 'mouseup' }, { wxName: 'touchEnd', ecName: 'click' }]; eventNames.forEach(name => { this.event[name.wxName] = e => { const touch = e.touches[0]; this.chart.getZr().handler.dispatch(name.ecName, { zrX: name.wxName === 'tap' ? touch.clientX : touch.x, zrY: name.wxName === 'tap' ? touch.clientY : touch.y }); }; }); } set width(w) { if (this.canvasNode) this.canvasNode.width = w } set height(h) { if (this.canvasNode) this.canvasNode.height = h } get width() { if (this.canvasNode) return this.canvasNode.width return 0 } get height() { if (this.canvasNode) return this.canvasNode.height return 0 } get ctx() { return cacheChart[this.canvasId]['ctx'] || null } set chart(chart) { cacheChart[this.canvasId]['chart'] = chart } get chart() { return cacheChart[this.canvasId]['chart'] || null } }