123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- const cacheChart = {}
- const fontSizeReg = /([\d\.]+)px/;
- class EventEmit {
- constructor() {
- this.__events = {};
- }
- on(type, listener) {
- if (!type || !listener) {
- return;
- }
- const events = this.__events[type] || [];
- events.push(listener);
- this.__events[type] = events;
- }
- emit(type, e) {
- if (type.constructor === Object) {
- e = type;
- type = e && e.type;
- }
- if (!type) {
- return;
- }
- const events = this.__events[type];
- if (!events || !events.length) {
- return;
- }
- events.forEach((listener) => {
- listener.call(this, e);
- });
- }
- off(type, listener) {
- const __events = this.__events;
- const events = __events[type];
- if (!events || !events.length) {
- return;
- }
- if (!listener) {
- delete __events[type];
- return;
- }
- for (let i = 0, len = events.length; i < len; i++) {
- if (events[i] === listener) {
- events.splice(i, 1);
- i--;
- }
- }
- }
- }
- class Image {
- constructor() {
- 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
- }
- }
- class OffscreenCanvas {
- constructor(ctx, com, canvasId) {
- this.tagName = 'canvas'
- this.com = com
- this.canvasId = canvasId
- this.ctx = ctx
- }
- set width(w) {
- this.com.offscreenWidth = w
- }
- set height(h) {
- this.com.offscreenHeight = h
- }
- get width() {
- return this.com.offscreenWidth || 0
- }
- get height() {
- return this.com.offscreenHeight || 0
- }
- getContext(type) {
- return this.ctx
- }
- getImageData() {
- return new Promise((resolve, reject) => {
- this.com.$nextTick(() => {
- uni.canvasGetImageData({
- x:0,
- y:0,
- width: this.com.offscreenWidth,
- height: this.com.offscreenHeight,
- canvasId: this.canvasId,
- success: (res) => {
- resolve(res)
- },
- fail: (err) => {
- reject(err)
- },
- }, this.com)
- })
- })
- }
- }
- export class Canvas {
- constructor(ctx, com, isNew, canvasNode={}) {
- cacheChart[com.canvasId] = {ctx}
- this.canvasId = com.canvasId;
- this.chart = null;
- this.isNew = isNew
- this.tagName = 'canvas'
- this.canvasNode = canvasNode;
- this.com = com;
- if (!isNew) {
- this._initStyle(ctx)
- }
- this._initEvent();
- this._ee = new EventEmit()
- }
- getContext(type) {
- if (type === '2d') {
- return this.ctx;
- }
- }
- setAttribute(key, value) {
- if(key === 'aria-label') {
- this.com['ariaLabel'] = value
- }
- }
- setChart(chart) {
- this.chart = chart;
- }
- createOffscreenCanvas(param){
- if(!this.children) {
- this.com.isOffscreenCanvas = true
- this.com.offscreenWidth = param.width||300
- this.com.offscreenHeight = param.height||300
- const com = this.com
- const canvasId = this.com.offscreenCanvasId
- const context = uni.createCanvasContext(canvasId, this.com)
- this._initStyle(context)
- this.children = new OffscreenCanvas(context, com, canvasId)
- }
- return this.children
- }
- appendChild(child) {
- console.log('child', child)
- }
- dispatchEvent(type, e) {
- if(typeof type == 'object') {
- this._ee.emit(type.type, type);
- } else {
- this._ee.emit(type, e);
- }
- return true
- }
- attachEvent() {
- }
- detachEvent() {
- }
- addEventListener(type, listener) {
- this._ee.on(type, listener)
- }
- removeEventListener(type, listener) {
- this._ee.off(type, listener)
- }
- _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);
- // });
- }
- _initStyle(ctx, child) {
- const styles = [
- 'fillStyle',
- 'strokeStyle',
- 'fontSize',
- 'globalAlpha',
- 'opacity',
- 'textAlign',
- 'textBaseline',
- 'shadow',
- 'lineWidth',
- 'lineCap',
- 'lineJoin',
- 'lineDash',
- 'miterLimit',
- // #ifdef H5
- 'font',
- // #endif
- ];
- 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 => {
- // #ifdef H5
- if (style === 'font' && fontSizeReg.test(value)) {
- const match = fontSizeReg.exec(value);
- ctx.setFontSize(match[1]);
- return;
- }
- // #endif
-
- 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 && !child) {
- 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 || uni.getSystemInfoSync().osName == 'harmonyos') {
- ctx._measureText = ctx.measureText
- const 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;
- }
- ctx.measureText = (text, font) => {
- let fontSize = ctx?.state?.fontSize || 12;
- if (font) {
- fontSize = parseInt(font.match(/([\d\.]+)px/)[1])
- }
- fontSize /= 2;
- let isBold = fontSize >= 16;
- const widthFactor = isBold ? 1.3 : 1;
- // ctx._measureText(text, (res) => {})
- return {
- width: strLen(text) * fontSize * widthFactor
- };
- }
- }
- }
- _initEvent(e) {
- 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) {
- this.canvasNode.width = w
- }
- set height(h) {
- this.canvasNode.height = h
- }
- get width() {
- return this.canvasNode.width || 0
- }
- get height() {
- return this.canvasNode.height || 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
- }
- }
- export function dispatch(name, {x,y, wheelDelta}) {
- this.dispatch(name, {
- zrX: x,
- zrY: y,
- zrDelta: wheelDelta,
- preventDefault: () => {},
- stopPropagation: () =>{}
- });
- }
- export function setCanvasCreator(echarts, {canvas, node}) {
- // echarts.setCanvasCreator(() => canvas);
- if(echarts && !echarts.registerPreprocessor) {
- return console.warn('echarts 版本不对或未传入echarts,vue3请使用esm格式')
- }
- echarts.registerPreprocessor(option => {
- if (option && option.series) {
- if (option.series.length > 0) {
- option.series.forEach(series => {
- series.progressive = 0;
- });
- } else if (typeof option.series === 'object') {
- option.series.progressive = 0;
- }
- }
- });
- function loadImage(src, onload, onerror) {
- let img = null
- if(node && node.createImage) {
- img = node.createImage()
- img.onload = onload.bind(img);
- img.onerror = onerror.bind(img);
- img.src = src;
- return img
- } else {
- img = new Image()
- img.onload = onload.bind(img)
- img.onerror = onerror.bind(img);
- img.src = src
- return img
- }
- }
- if(echarts.setPlatformAPI) {
- echarts.setPlatformAPI({
- loadImage: canvas.setChart ? loadImage : null,
- createCanvas(){
- const key = 'createOffscreenCanvas'
- return uni.canIUse(key) && uni[key] ? uni[key]({type: '2d'}) : canvas
- }
- })
- }
- }
|