增加音乐,摇一摇,服务等页面
This commit is contained in:
@@ -0,0 +1,399 @@
|
||||
import {getDeviceInfo} from './utils';
|
||||
|
||||
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 || APP
|
||||
'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 || APP
|
||||
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 || getDeviceInfo().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}) {
|
||||
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
|
||||
}
|
||||
})
|
||||
} else if(echarts.setCanvasCreator) {
|
||||
echarts.setCanvasCreator(() => {
|
||||
return canvas;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
<template>
|
||||
<!-- #ifdef APP -->
|
||||
<web-view class="lime-echart" ref="chartRef" @load="loaded" :style="[lStyle]" :webview-styles="[webviewStyles]"
|
||||
src="/uni_modules/lime-echart/static/app/uvue.html?v=10112">
|
||||
</web-view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef WEB -->
|
||||
<div class="lime-echart" ref="chartRef"></div>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef WEB || APP-->
|
||||
<view class="lime-echart">
|
||||
<canvas style="width:100%; height:100%" v-if="canvasid" :id="canvasid" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"></canvas>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script lang="uts" setup>
|
||||
// @ts-nocheck
|
||||
import { echartsProps } from './type';
|
||||
import { Echarts } from './uvue';
|
||||
// #ifdef WEB
|
||||
import { dispatch } from './canvas';
|
||||
import * as echartsLibrary from '@/uni_modules/lime-echart/static/web/echarts.esm.min.js';
|
||||
// #endif
|
||||
// #ifndef APP || WEB
|
||||
import { Canvas, setCanvasCreator, dispatch } from './canvas';
|
||||
import { wrapTouch, convertTouchesToArray, devicePixelRatio, sleep, canIUseCanvas2d, getRect } from './utils';
|
||||
// #endif
|
||||
type EChartsResolveCallback = (value : Echarts) => void
|
||||
|
||||
const emits = defineEmits(['finished'])
|
||||
const props = withDefaults(defineProps<echartsProps>(), {
|
||||
isDisableScroll: false,
|
||||
isClickable: true,
|
||||
autoHideTooltip: false,
|
||||
enableHover: false,
|
||||
landscape: false,
|
||||
beforeDelay: 30,
|
||||
})
|
||||
const instance = getCurrentInstance()!;
|
||||
const canvasid = `lime-echart-${instance.uid}`
|
||||
const finished = ref(false)
|
||||
const initializationQueue = [] as EChartsResolveCallback[]
|
||||
const callbackQueue = [] as EChartsResolveCallback[]
|
||||
// let context = null as UniWebViewElement | null
|
||||
let chartInstance = null as Echarts | null
|
||||
let chartRef = ref<UniWebViewElement | null>(null)
|
||||
let canvasNode:any|null = null
|
||||
const processInitializationQueue = () => {
|
||||
// #ifdef APP
|
||||
if (finished.value) {
|
||||
if (chartInstance == null) {
|
||||
chartInstance = new Echarts(chartRef.value!)
|
||||
}
|
||||
while (initializationQueue.length > 0) {
|
||||
const resolve = initializationQueue.pop() as EChartsResolveCallback
|
||||
resolve(chartInstance!)
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
// #ifndef APP
|
||||
while (initializationQueue.length > 0) {
|
||||
if (chartInstance != null) {
|
||||
const resolve = initializationQueue.pop() as EChartsResolveCallback
|
||||
resolve(chartInstance!)
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
|
||||
if (chartInstance != null) {
|
||||
while (callbackQueue.length > 0) {
|
||||
const callback = callbackQueue.pop() as EChartsResolveCallback
|
||||
callback(chartInstance!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef APP
|
||||
const loaded = (event : UniWebViewLoadEvent) => {
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
nextTick(()=> {
|
||||
chartRef.value?.getBoundingClientRectAsync()?.then(res => {
|
||||
if(res.width > 0 && res.height > 0) {
|
||||
finished.value = true
|
||||
processInitializationQueue()
|
||||
emits('finished')
|
||||
} else {
|
||||
console.warn('【lime-echart】获取尺寸失败,请检查代码样式')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
|
||||
|
||||
const checkInitialization = () : boolean => {
|
||||
if (chartInstance == null) {
|
||||
console.warn(`组件还未初始化,请先使用 init`)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
const setOption = (option : UTSJSONObject) => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.setOption(option);
|
||||
}
|
||||
const showLoading = () => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.showLoading();
|
||||
}
|
||||
const hideLoading = () => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.hideLoading();
|
||||
}
|
||||
const clear = () => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.clear();
|
||||
}
|
||||
const dispose = () => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.dispose();
|
||||
}
|
||||
const resize = (size : UTSJSONObject) => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.resize(size);
|
||||
}
|
||||
const canvasToTempFilePath = (opt : UTSJSONObject) => {
|
||||
if (checkInitialization()) return
|
||||
// #ifdef APP
|
||||
chartInstance!.canvasToTempFilePath(opt);
|
||||
// #endif
|
||||
// #ifdef WEB
|
||||
opt.success?.({
|
||||
// @ts-ignore
|
||||
tempFilePath: chartInstance!._api.getDataURL()
|
||||
})
|
||||
// #endif
|
||||
// #ifndef WEB || APP
|
||||
if(canvasNode) {
|
||||
opt.success?.({
|
||||
tempFilePath: canvasNode.toDataURL()
|
||||
})
|
||||
} else {
|
||||
uni.canvasToTempFilePath({
|
||||
...opt,
|
||||
canvasId
|
||||
}, instance.proxy);
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
|
||||
// #ifdef APP
|
||||
function init(callback : ((chartInstance : Echarts) => void) | null) : Promise<Echarts> {
|
||||
if (callback != null) {
|
||||
callbackQueue.push(callback)
|
||||
}
|
||||
return new Promise<Echarts>((resolve) => {
|
||||
initializationQueue.push(resolve)
|
||||
processInitializationQueue()
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
// #ifndef APP
|
||||
// #ifndef WEB
|
||||
let use2dCanvas = canIUseCanvas2d()
|
||||
const getContext = async () => {
|
||||
return new Promise((resolve, reject)=>{
|
||||
uni.createCanvasContextAsync({
|
||||
id: canvasid,
|
||||
component: instance.proxy!,
|
||||
success: (context : CanvasContext) => {
|
||||
canvasNode = context
|
||||
const canvasContext = context.getContext('2d')!;
|
||||
const canvas = canvasContext.canvas;
|
||||
let uniCanvas;
|
||||
const width = canvas.offsetWidth
|
||||
const height = canvas.offsetHeight
|
||||
// 处理高清屏逻辑
|
||||
const dpr = devicePixelRatio//uni.getDeviceInfo().devicePixelRatio ?? 1;
|
||||
canvas.width = canvas.offsetWidth * dpr;
|
||||
canvas.height = canvas.offsetHeight * dpr;
|
||||
canvasContext.scale(dpr, dpr); // 仅需调用一次,当调用 reset 方法后需要再次 scale
|
||||
if(use2dCanvas) {
|
||||
uniCanvas = new Canvas(canvasContext, instance.proxy, true, context);
|
||||
} else {
|
||||
uniCanvas = new Canvas(canvasContext, instance.proxy, false);
|
||||
}
|
||||
resolve({ canvas: uniCanvas, width, height, devicePixelRatio: dpr, node: context});
|
||||
},
|
||||
fail(err) {
|
||||
reject(err)
|
||||
console.log('err', err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
const getTouch = (e) => {
|
||||
const touches = e.touches[0]
|
||||
// #ifdef WEB
|
||||
// @ts-ignore
|
||||
const rect = chart!.getZr().dom.getBoundingClientRect();
|
||||
const touch = {
|
||||
x: touches.clientX - rect.left,
|
||||
y: touches.clientY - rect.top
|
||||
}
|
||||
// #endif
|
||||
// #ifndef WEB
|
||||
const touch = {
|
||||
x: touches.x,
|
||||
y: touches.y
|
||||
}
|
||||
// #endif
|
||||
return touch
|
||||
}
|
||||
const handleTouchStart = (e) => {
|
||||
if (chartInstance == null) return
|
||||
const handler = chartInstance.getZr().handler;
|
||||
const touch = getTouch(e)
|
||||
dispatch.call(handler, 'mousedown', touch)
|
||||
dispatch.call(handler, 'mousemove', touch)
|
||||
handler.processGesture(wrapTouch(e), 'start');
|
||||
}
|
||||
const handleTouchMove = (e) => {
|
||||
if (chartInstance == null) return
|
||||
const handler = chartInstance.getZr().handler;
|
||||
const touch = getTouch(e)
|
||||
dispatch.call(handler, 'mousemove', touch)
|
||||
handler.processGesture(wrapTouch(e), 'change');
|
||||
}
|
||||
const handleTouchEnd = (e) => {
|
||||
if (chartInstance == null) return
|
||||
const handler = chartInstance.getZr().handler;
|
||||
const touch = e.changedTouches ? e.changedTouches[0] : {}
|
||||
handler.processGesture(wrapTouch(e), 'end');
|
||||
dispatch.call(handler, 'mouseup', touch)
|
||||
dispatch.call(handler, 'click', touch)
|
||||
}
|
||||
async function init(echarts : any, ...args : any[]) : Promise<Echarts> {
|
||||
const library = echarts || echartsLibrary
|
||||
if (library == null) {
|
||||
console.error('请确保已经引入了 ECharts 库');
|
||||
return Promise.reject('请确保已经引入了 ECharts 库');
|
||||
}
|
||||
let theme : string | null = null
|
||||
let opts = {}
|
||||
let callback : Function | null = null;
|
||||
|
||||
args.forEach(item => {
|
||||
if (typeof item === 'function') {
|
||||
callback = item
|
||||
} else if (['string'].includes(typeof item)) {
|
||||
theme = item
|
||||
} else if (typeof item === 'object') {
|
||||
opts = item
|
||||
}
|
||||
})
|
||||
|
||||
// #ifdef WEB
|
||||
library.env.domSupported = true
|
||||
library.env.hasGlobalWindow = true
|
||||
library.env.node = false
|
||||
library.env.pointerEventsSupported = false
|
||||
library.env.svgSupported = true
|
||||
library.env.touchEventsSupported = true
|
||||
library.env.transform3dSupported = true
|
||||
library.env.transformSupported = true
|
||||
library.env.worker = false
|
||||
library.env.wxa = false
|
||||
chartInstance = library.init(chartRef.value, theme, opts)
|
||||
// window.addEventListener('touchstart', touchstart)
|
||||
// window.addEventListener('touchmove', touchmove)
|
||||
// window.addEventListener('touchend', touchend)
|
||||
// #endif
|
||||
|
||||
// #ifndef WEB
|
||||
let config = await getContext();
|
||||
setCanvasCreator(library, config)
|
||||
chartInstance = library.init(config.canvas, theme, Object.assign({}, config, opts))
|
||||
// #endif
|
||||
if (callback != null && typeof callback == 'function') {
|
||||
callbackQueue.push(callback)
|
||||
}
|
||||
return new Promise<Echarts>((resolve) => {
|
||||
initializationQueue.push(resolve)
|
||||
processInitializationQueue()
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
finished.value = true
|
||||
processInitializationQueue()
|
||||
emits('finished')
|
||||
})
|
||||
})
|
||||
onUnmounted(() => {
|
||||
// #ifdef WEB
|
||||
// window.removeEventListener('touchstart', touchstart)
|
||||
// window.removeEventListener('touchmove', touchmove)
|
||||
// window.removeEventListener('touchend', touchend)
|
||||
// #endif
|
||||
})
|
||||
// #endif
|
||||
|
||||
defineExpose({
|
||||
init,
|
||||
setOption,
|
||||
showLoading,
|
||||
hideLoading,
|
||||
clear,
|
||||
dispose,
|
||||
resize,
|
||||
canvasToTempFilePath
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.lime-echart {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,484 @@
|
||||
<template>
|
||||
<!-- #ifndef APP-NVUE || WEB -->
|
||||
<view class="lime-echart"
|
||||
:style="[lStyle]"
|
||||
v-if="canvasId"
|
||||
ref="chartContainer"
|
||||
:aria-label="'图表'">
|
||||
<canvas class="lime-echart__canvas"
|
||||
type="2d"
|
||||
:style="[styles]"
|
||||
:id="canvasId"
|
||||
:disable-scroll="isDisableScroll"
|
||||
:canvas-id="canvasId"
|
||||
@touchstart="handleTouchStart"
|
||||
@touchmove="handleTouchMove"
|
||||
@touchend="handleTouchEnd">
|
||||
</canvas>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef WEB -->
|
||||
<div class="lime-echart" ref="chartContainer" :style="[styles, lStyle]"></div>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view class="lime-echart" :style="[lStyle]">
|
||||
<web-view class="lime-echart__canvas"
|
||||
:webview-styles="webviewStyles"
|
||||
:style="[styles]"
|
||||
ref="chartContainer"
|
||||
src="/uni_modules/lime-echart/static/app/uvue.html?v=1"
|
||||
@pagefinish="isInitialized = true"
|
||||
@onPostMessage="handleWebviewMessage"></web-view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
// @ts-nocheck
|
||||
import { defineComponent, getCurrentInstance, ref, onMounted, nextTick, onBeforeUnmount, watch, computed } from './vue'
|
||||
import echartProps from './props'
|
||||
|
||||
// #ifndef APP-NVUE || WEB
|
||||
import { Canvas, setCanvasCreator, dispatch } from './canvas';
|
||||
import { wrapTouch, convertTouchesToArray, devicePixelRatio ,sleep, canIUseCanvas2d, getRect, getDeviceInfo } from './utils';
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
import { base64ToPath, sleep } from './utils';
|
||||
import { Echarts } from './nvue'
|
||||
// #endif
|
||||
// #ifdef WEB
|
||||
import * as echartsLibrary from '@/uni_modules/lime-echart/static/web/echarts.esm.min.js';
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-VUE
|
||||
// #ifdef VUE3
|
||||
import '@/uni_modules/lime-echart/static/app/echarts.min.js';
|
||||
const echartsLibrary = globalThis.echarts
|
||||
// #endif
|
||||
// #ifdef VUE2
|
||||
import * as echartsLibrary from '@/uni_modules/lime-echart/static/web/echarts.esm.min.js';
|
||||
// #endif
|
||||
// #endif
|
||||
export default defineComponent({
|
||||
props: echartProps,
|
||||
emits: ['finished'],
|
||||
setup(props, { emit, expose }) {
|
||||
// #ifndef APP-NVUE || WEB || APP-VUE
|
||||
let echartsLibrary = null
|
||||
// #endif
|
||||
|
||||
const instance = getCurrentInstance()!;
|
||||
const canvasId = `lime-echart-${instance.uid}`
|
||||
const isInitialized = ref(false)
|
||||
const chartContainer = ref(null)
|
||||
|
||||
type ChartOptions = Record<string, any>
|
||||
type EChartsInstance = typeof echartsLibrary
|
||||
type EChartsResolveCallback = (value: EChartsInstance) => void
|
||||
|
||||
const initializationQueue = [] as EChartsResolveCallback[]
|
||||
const callbackQueue = [] as EChartsResolveCallback[]
|
||||
|
||||
let chartInstance: null | EChartsInstance = null
|
||||
|
||||
const styles = computed(()=> {
|
||||
if(props.landscape) {
|
||||
return {
|
||||
transform: 'translate(-50%,-50%) rotate(90deg)',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
}
|
||||
}
|
||||
return {}
|
||||
})
|
||||
|
||||
const checkInitialization = (): boolean => {
|
||||
if(chartInstance) return false
|
||||
console.warn(`组件还未初始化,请先使用 init`)
|
||||
return true
|
||||
}
|
||||
|
||||
const setOption = (options: ChartOptions) => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.setOption(options);
|
||||
}
|
||||
|
||||
const hideLoading = () => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.showLoading();
|
||||
}
|
||||
|
||||
const showLoading = () => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.hideLoading();
|
||||
}
|
||||
|
||||
const clear = () => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.clear();
|
||||
}
|
||||
|
||||
const dispose = () => {
|
||||
if (checkInitialization()) return
|
||||
chartInstance!.dispose();
|
||||
}
|
||||
const processInitializationQueue = () => {
|
||||
while (initializationQueue.length > 0) {
|
||||
if (chartInstance != null) {
|
||||
const resolve = initializationQueue.pop() as EChartsResolveCallback
|
||||
resolve(chartInstance!)
|
||||
}
|
||||
}
|
||||
|
||||
if (chartInstance != null) {
|
||||
while (callbackQueue.length > 0) {
|
||||
const callback = callbackQueue.pop() as EChartsResolveCallback
|
||||
callback(chartInstance!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const resize = (dimensions?: { width?: number; height?: number }) => {
|
||||
if (checkInitialization()) return
|
||||
// #ifdef APP-NVUE || WEB
|
||||
chartInstance!.resize(dimensions);
|
||||
// #endif
|
||||
// #ifndef APP-NVUE || WEB
|
||||
getRect(`#${canvasId}`, instance.proxy).then(res => {
|
||||
chartInstance!.resize({width: res.width, height: res.height});
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
let chartFile = ref(null);
|
||||
const handleWebviewMessage = (e) => {
|
||||
const detail = e?.detail?.data[0] || null;
|
||||
const data = detail?.data
|
||||
const key = detail?.event
|
||||
const options = data?.options
|
||||
const event = data?.event
|
||||
const file = detail?.file
|
||||
if (key == 'log' && data) {
|
||||
console.log(data)
|
||||
}
|
||||
if(event) {
|
||||
chartInstance.dispatchAction(event.replace(/"/g,''), options)
|
||||
}
|
||||
if(file) {
|
||||
chartFile.value = file
|
||||
}
|
||||
}
|
||||
|
||||
const canvasToTempFilePath = (options: ChartOptions) => {
|
||||
if (checkInitialization()) return
|
||||
chartContainer.value.evalJs(`canvasToTempFilePath()`);
|
||||
watch(chartFile, async (file) =>{
|
||||
if(!file) return
|
||||
const tempFilePath = await base64ToPath(file)
|
||||
options.success({tempFilePath})
|
||||
})
|
||||
}
|
||||
|
||||
const getContext = () => {
|
||||
if(isInitialized.value) {
|
||||
return Promise.resolve(isInitialized.value)
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
watch(isInitialized, (val) =>{
|
||||
if(!val) return
|
||||
resolve(val)
|
||||
})
|
||||
})
|
||||
}
|
||||
const init = async (echarts, ...args) => {
|
||||
let theme: string | null = null
|
||||
let config:Record<string, any> = {}
|
||||
let callback: Function | null = null;
|
||||
|
||||
args.forEach(item => {
|
||||
if (typeof item === 'function') {
|
||||
callback = item
|
||||
} else if (typeof item === 'string') {
|
||||
theme = item
|
||||
} else if (typeof item === 'object') {
|
||||
config = item
|
||||
}
|
||||
})
|
||||
if(props.beforeDelay) {
|
||||
await sleep(props.beforeDelay)
|
||||
}
|
||||
await getContext();
|
||||
chartInstance = new Echarts(chartContainer.value)
|
||||
chartContainer.value.evalJs(`init(null, null, ${JSON.stringify(config)}, ${theme})`)
|
||||
if (callback && typeof callback === 'function') {
|
||||
callbackQueue.push(callback)
|
||||
}
|
||||
|
||||
return new Promise<EChartsInstance>((resolve) => {
|
||||
nextTick(()=>{
|
||||
initializationQueue.push(resolve)
|
||||
processInitializationQueue()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
|
||||
// #ifndef APP-NVUE || WEB
|
||||
let canvasNode;
|
||||
const canvasToTempFilePath = (options: ChartOptions) => {
|
||||
if (checkInitialization()) return
|
||||
if(canvasNode) {
|
||||
options.success?.({
|
||||
tempFilePath: canvasNode.toDataURL()
|
||||
})
|
||||
} else {
|
||||
uni.canvasToTempFilePath({
|
||||
...options,
|
||||
canvasId
|
||||
}, instance.proxy);
|
||||
}
|
||||
}
|
||||
|
||||
const getContext = () => {
|
||||
return getRect(`#${canvasId}`, instance.proxy).then(res => {
|
||||
let dpr = devicePixelRatio
|
||||
let {width, height, node} = res
|
||||
let canvas: Canvas | null = null;
|
||||
if(!(width || height)) {
|
||||
return Promise.reject('no rect')
|
||||
}
|
||||
if(node && node.getContext) {
|
||||
const ctx = node.getContext('2d');
|
||||
canvas = new Canvas(ctx, instance.proxy, true, node);
|
||||
canvasNode = node
|
||||
} else {
|
||||
dpr = 1
|
||||
const ctx = uni.createCanvasContext(canvasId, instance.proxy);
|
||||
canvas = new Canvas(ctx, instance.proxy, false);
|
||||
}
|
||||
return { canvas, width, height, devicePixelRatio: dpr, node }
|
||||
})
|
||||
}
|
||||
const getTouch = (e) => {
|
||||
const touches = e.touches[0]
|
||||
const touch = props.landscape
|
||||
? {
|
||||
x: touches.y,
|
||||
y: touches.x
|
||||
}
|
||||
: {
|
||||
x: touches.x,
|
||||
y: touches.y
|
||||
}
|
||||
return touch
|
||||
}
|
||||
const handleTouchStart = (e) => {
|
||||
if (chartInstance == null) return
|
||||
const handler = chartInstance.getZr().handler;
|
||||
const touch = getTouch(e)
|
||||
dispatch.call(handler, 'mousedown', touch)
|
||||
dispatch.call(handler, 'mousemove', touch)
|
||||
handler.processGesture(wrapTouch(e), 'start');
|
||||
}
|
||||
const handleTouchMove = (e) => {
|
||||
if (chartInstance == null) return
|
||||
const handler = chartInstance.getZr().handler;
|
||||
const touch = getTouch(e)
|
||||
dispatch.call(handler, 'mousemove', touch)
|
||||
handler.processGesture(wrapTouch(e), 'change');
|
||||
}
|
||||
const handleTouchEnd = (e) => {
|
||||
if (chartInstance == null) return
|
||||
const handler = chartInstance.getZr().handler;
|
||||
const touch = e.changedTouches ? e.changedTouches[0] : {}
|
||||
handler.processGesture(wrapTouch(e), 'end');
|
||||
dispatch.call(handler, 'mouseup', touch)
|
||||
dispatch.call(handler, 'click', touch)
|
||||
}
|
||||
const init = async (echartsLib: EChartsInstance = echartsLibrary, ...args: any[]): Promise<EChartsInstance> => {
|
||||
const library = echartsLib || echartsLibrary
|
||||
if (!library) {
|
||||
console.error('ECharts library is required');
|
||||
return Promise.reject('ECharts library is required');
|
||||
}
|
||||
let theme: string | null = null
|
||||
let config:Record<string, any> = {}
|
||||
let callback: Function | null = null;
|
||||
|
||||
args.forEach(item => {
|
||||
if (typeof item === 'function') {
|
||||
callback = item
|
||||
} else if (typeof item === 'string') {
|
||||
theme = item
|
||||
} else if (typeof item === 'object') {
|
||||
config = item
|
||||
}
|
||||
})
|
||||
if(props.beforeDelay) {
|
||||
await sleep(props.beforeDelay)
|
||||
}
|
||||
let options = await getContext();
|
||||
setCanvasCreator(library, options)
|
||||
chartInstance = library.init(options.canvas, theme, Object.assign({}, options, config))
|
||||
if (callback && typeof callback === 'function') {
|
||||
callbackQueue.push(callback)
|
||||
}
|
||||
return new Promise<EChartsInstance>((resolve) => {
|
||||
initializationQueue.push(resolve)
|
||||
processInitializationQueue()
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
|
||||
// #ifdef WEB
|
||||
const canvasToTempFilePath = (options: ChartOptions) => {
|
||||
if (checkInitialization()) return
|
||||
options.success?.({
|
||||
tempFilePath: chartInstance._api.getDataURL()
|
||||
})
|
||||
}
|
||||
|
||||
const init = async (echarts: EChartsInstance = echartsLibrary, ...args: any[]): Promise<EChartsInstance> => {
|
||||
const library = echarts || echartsLibrary
|
||||
if (!library) {
|
||||
console.error('ECharts library is required');
|
||||
return Promise.reject('ECharts library is required');
|
||||
}
|
||||
|
||||
let theme: string | null = null
|
||||
let config = {}
|
||||
let callback: Function | null = null;
|
||||
|
||||
args.forEach(item => {
|
||||
if (typeof item === 'function') {
|
||||
callback = item
|
||||
} else if (typeof item === 'string') {
|
||||
theme = item
|
||||
} else if (typeof item === 'object') {
|
||||
config = item
|
||||
}
|
||||
})
|
||||
|
||||
// Configure ECharts environment
|
||||
library.env.domSupported = true
|
||||
library.env.hasGlobalWindow = true
|
||||
library.env.node = false
|
||||
library.env.pointerEventsSupported = false
|
||||
library.env.svgSupported = true
|
||||
library.env.touchEventsSupported = true
|
||||
library.env.transform3dSupported = true
|
||||
library.env.transformSupported = true
|
||||
library.env.worker = false
|
||||
library.env.wxa = false
|
||||
|
||||
chartInstance = library.init(chartContainer.value, theme, config)
|
||||
|
||||
if (callback != null && typeof callback === 'function') {
|
||||
callbackQueue.push(callback)
|
||||
}
|
||||
|
||||
return new Promise<EChartsInstance>((resolve) => {
|
||||
initializationQueue.push(resolve)
|
||||
processInitializationQueue()
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
|
||||
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
// #ifndef APP-NVUE
|
||||
isInitialized.value = true
|
||||
// #endif
|
||||
emit('finished')
|
||||
processInitializationQueue()
|
||||
})
|
||||
})
|
||||
onBeforeUnmount(()=> {
|
||||
clear()
|
||||
dispose()
|
||||
})
|
||||
|
||||
// #ifdef VUE3
|
||||
expose({
|
||||
init,
|
||||
setOption,
|
||||
hideLoading,
|
||||
showLoading,
|
||||
clear,
|
||||
dispose,
|
||||
resize,
|
||||
canvasToTempFilePath
|
||||
})
|
||||
// #endif
|
||||
|
||||
return {
|
||||
canvasId,
|
||||
chartContainer,
|
||||
styles,
|
||||
// #ifndef WEB || APP-NVUE
|
||||
handleTouchStart,
|
||||
handleTouchMove,
|
||||
handleTouchEnd,
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
handleWebviewMessage,
|
||||
isInitialized,
|
||||
// #endif
|
||||
|
||||
// #ifdef VUE2
|
||||
init,
|
||||
setOption,
|
||||
hideLoading,
|
||||
showLoading,
|
||||
clear,
|
||||
dispose,
|
||||
resize,
|
||||
canvasToTempFilePath,
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.lime-echart {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.lime-echart__canvas {
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.lime-echart__mask {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
@@ -0,0 +1,56 @@
|
||||
export class Echarts {
|
||||
eventMap = new Map()
|
||||
constructor(webview) {
|
||||
this.webview = webview
|
||||
this.options = null
|
||||
}
|
||||
setOption() {
|
||||
this.options = arguments
|
||||
console.log('setOption1')
|
||||
this.webview.evalJs(`setOption(${JSON.stringify(arguments)})`);
|
||||
}
|
||||
getOption() {
|
||||
return this.options
|
||||
}
|
||||
showLoading() {
|
||||
this.webview.evalJs(`showLoading(${JSON.stringify(arguments)})`);
|
||||
}
|
||||
hideLoading() {
|
||||
this.webview.evalJs(`hideLoading()`);
|
||||
}
|
||||
clear() {
|
||||
this.webview.evalJs(`clear()`);
|
||||
}
|
||||
dispose() {
|
||||
this.webview.evalJs(`dispose()`);
|
||||
}
|
||||
resize(size) {
|
||||
if(size) {
|
||||
this.webview.evalJs(`resize(${JSON.stringify(size)})`);
|
||||
} else {
|
||||
this.webview.evalJs(`resize()`);
|
||||
}
|
||||
}
|
||||
on(type, ...args) {
|
||||
const query = args[0]
|
||||
const useQuery = query && typeof query != 'function'
|
||||
const param = useQuery ? [type, query] : [type]
|
||||
const key = `${type}${useQuery ? JSON.stringify(query): '' }`
|
||||
const callback = useQuery ? args[1]: args[0]
|
||||
if(typeof callback == 'function'){
|
||||
this.eventMap.set(key, callback)
|
||||
}
|
||||
this.webview.evalJs(`on(${JSON.stringify(param)})`);
|
||||
console.warn('nvue 暂不支持事件')
|
||||
}
|
||||
dispatchAction(type, options){
|
||||
const handler = this.eventMap.get(type)
|
||||
if(handler){
|
||||
handler(options)
|
||||
}
|
||||
}
|
||||
// 不让报错 无实际作用
|
||||
isDisposed() {
|
||||
return !!this.webview
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
export default {
|
||||
// #ifdef MP-WEIXIN || MP-TOUTIAO
|
||||
type: {
|
||||
type: String,
|
||||
default: '2d'
|
||||
},
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
webviewStyles: Object,
|
||||
// #endif
|
||||
lStyle: String,
|
||||
isDisableScroll: Boolean,
|
||||
isClickable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
enableHover: Boolean,
|
||||
beforeDelay: {
|
||||
type: Number,
|
||||
default: 30
|
||||
},
|
||||
landscape: Boolean,
|
||||
autoHideTooltip: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// @ts-nocheck
|
||||
export interface echartsProps {
|
||||
webviewStyles?: UTSJSONObject,
|
||||
lStyle?: string | UTSJSONObject
|
||||
isDisableScroll: boolean;
|
||||
isClickable: boolean;
|
||||
enableHover: boolean;
|
||||
beforeDelay: number;
|
||||
landscape: boolean;
|
||||
autoHideTooltip: boolean;
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 获取设备基础信息
|
||||
*
|
||||
* @see [uni.getDeviceInfo](https://uniapp.dcloud.net.cn/api/system/getDeviceInfo.html)
|
||||
*/
|
||||
export function getDeviceInfo() {
|
||||
if (uni.getDeviceInfo || uni.canIUse('getDeviceInfo')) {
|
||||
return uni.getDeviceInfo();
|
||||
} else {
|
||||
return uni.getSystemInfoSync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取窗口信息
|
||||
*
|
||||
* @see [uni.getWindowInfo](https://uniapp.dcloud.net.cn/api/system/getWindowInfo.html)
|
||||
*/
|
||||
export function getWindowInfo() {
|
||||
if (uni.getWindowInfo || uni.canIUse('getWindowInfo')) {
|
||||
return uni.getWindowInfo();
|
||||
} else {
|
||||
return uni.getSystemInfoSync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取APP基础信息
|
||||
*
|
||||
* @see [uni.getAppBaseInfo](https://uniapp.dcloud.net.cn/api/system/getAppBaseInfo.html)
|
||||
*/
|
||||
export function getAppBaseInfo() {
|
||||
if (uni.getAppBaseInfo || uni.canIUse('getAppBaseInfo')) {
|
||||
return uni.getAppBaseInfo();
|
||||
} else {
|
||||
return uni.getSystemInfoSync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
// 计算版本
|
||||
export function compareVersion(v1, v2) {
|
||||
v1 = v1.split('.')
|
||||
v2 = v2.split('.')
|
||||
const len = Math.max(v1.length, v2.length)
|
||||
while (v1.length < len) {
|
||||
v1.push('0')
|
||||
}
|
||||
while (v2.length < len) {
|
||||
v2.push('0')
|
||||
}
|
||||
for (let i = 0; i < len; i++) {
|
||||
const num1 = parseInt(v1[i], 10)
|
||||
const num2 = parseInt(v2[i], 10)
|
||||
|
||||
if (num1 > num2) {
|
||||
return 1
|
||||
} else if (num1 < num2) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
// const systemInfo = uni.getSystemInfoSync();
|
||||
|
||||
function gte(version) {
|
||||
// 截止 2023-03-22 mac pc小程序不支持 canvas 2d
|
||||
// let {
|
||||
// SDKVersion,
|
||||
// platform
|
||||
// } = systemInfo;
|
||||
const { platform } = getDeviceInfo();
|
||||
let { SDKVersion } = getAppBaseInfo();
|
||||
// #ifdef MP-ALIPAY
|
||||
SDKVersion = my.SDKVersion
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
return platform !== 'mac' && compareVersion(SDKVersion, version) >= 0;
|
||||
// #endif
|
||||
return compareVersion(SDKVersion, version) >= 0;
|
||||
}
|
||||
|
||||
|
||||
export function canIUseCanvas2d() {
|
||||
// #ifdef MP-WEIXIN
|
||||
return gte('2.9.0');
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
return gte('2.7.0');
|
||||
// #endif
|
||||
// #ifdef MP-TOUTIAO
|
||||
return gte('1.78.0');
|
||||
// #endif
|
||||
return false
|
||||
}
|
||||
|
||||
export function convertTouchesToArray(touches) {
|
||||
// 如果 touches 是一个数组,则直接返回它
|
||||
if (Array.isArray(touches)) {
|
||||
return touches;
|
||||
}
|
||||
// 如果touches是一个对象,则转换为数组
|
||||
if (typeof touches === 'object' && touches !== null) {
|
||||
return Object.values(touches);
|
||||
}
|
||||
// 对于其他类型,直接返回它
|
||||
return touches;
|
||||
}
|
||||
|
||||
export function wrapTouch(event) {
|
||||
event.touches = convertTouchesToArray(event.touches)
|
||||
for (let i = 0; i < event.touches.length; ++i) {
|
||||
const touch = event.touches[i];
|
||||
touch.offsetX = touch.x;
|
||||
touch.offsetY = touch.y;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
// export const devicePixelRatio = uni.getSystemInfoSync().pixelRatio
|
||||
export const devicePixelRatio = getWindowInfo().pixelRatio;
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
export function base64ToPath(base64) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || [];
|
||||
const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
|
||||
bitmap.loadBase64Data(base64, () => {
|
||||
if (!format) {
|
||||
reject(new Error('ERROR_BASE64SRC_PARSE'))
|
||||
}
|
||||
const time = new Date().getTime();
|
||||
const filePath = `_doc/uniapp_temp/${time}.${format}`
|
||||
|
||||
bitmap.save(filePath, {},
|
||||
() => {
|
||||
bitmap.clear()
|
||||
resolve(filePath)
|
||||
},
|
||||
(error) => {
|
||||
bitmap.clear()
|
||||
console.error(`${JSON.stringify(error)}`)
|
||||
reject(error)
|
||||
})
|
||||
}, (error) => {
|
||||
bitmap.clear()
|
||||
console.error(`${JSON.stringify(error)}`)
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
|
||||
|
||||
export function sleep(time) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(true)
|
||||
}, time)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function getRect(selector, context) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const dom = uni.createSelectorQuery().in(context).select(selector);
|
||||
const result = (rect) => {
|
||||
if (rect) {
|
||||
resolve(rect)
|
||||
} else {
|
||||
reject()
|
||||
}
|
||||
}
|
||||
dom.fields({
|
||||
node: true,
|
||||
size: true,
|
||||
rect: true
|
||||
}, result).exec()
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,136 @@
|
||||
// @ts-nocheck
|
||||
// #ifdef APP
|
||||
type EchartsEventHandler = (event: UTSJSONObject)=>void
|
||||
// type EchartsTempResolve = (obj : UTSJSONObject) => void
|
||||
// type EchartsTempOptions = UTSJSONObject
|
||||
export class Echarts {
|
||||
options: UTSJSONObject = {} as UTSJSONObject
|
||||
context: UniWebViewElement
|
||||
eventMap: Map<string, EchartsEventHandler> = new Map()
|
||||
private temp: UTSJSONObject[] = []
|
||||
constructor(context: UniWebViewElement){
|
||||
this.context = context
|
||||
this.init()
|
||||
}
|
||||
init(){
|
||||
this.context.evalJS(`init(null, null, ${JSON.stringify({})})`)
|
||||
|
||||
this.context.addEventListener('message', (e : UniWebViewMessageEvent) => {
|
||||
// event.stopPropagation()
|
||||
// event.preventDefault()
|
||||
|
||||
const detail = e.detail.data[0]
|
||||
const file = detail.getString('file')
|
||||
const data = detail.get('data')
|
||||
const key = detail.getString('event')
|
||||
const options = typeof data == 'object' ? (data as UTSJSONObject).getJSON('options'): null
|
||||
const event = typeof data == 'object' ? (data as UTSJSONObject).getString('event'): null
|
||||
if (key == 'log' && data != null) {
|
||||
console.log(data)
|
||||
}
|
||||
if (event != null && options != null) {
|
||||
this.dispatchAction(event.replace(/"/g,''), options)
|
||||
}
|
||||
if(file != null){
|
||||
while (this.temp.length > 0) {
|
||||
const opt = this.temp.pop()
|
||||
const success = opt?.get('success')
|
||||
if(typeof success == 'function'){
|
||||
success as (res: UTSJSONObject) => void
|
||||
success({tempFilePath: file})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
setOption(option: UTSJSONObject){
|
||||
this.options = option;
|
||||
this.context.evalJS(`setOption(${JSON.stringify([option])})`)
|
||||
}
|
||||
setOption(option: UTSJSONObject, notMerge: boolean = false, lazyUpdate: boolean = false){
|
||||
this.options = option;
|
||||
this.context.evalJS(`setOption(${JSON.stringify([option, notMerge, lazyUpdate])})`)
|
||||
}
|
||||
setOption(option: UTSJSONObject, notMerge: UTSJSONObject){
|
||||
this.options = option;
|
||||
this.context.evalJS(`setOption(${JSON.stringify([option, notMerge])})`)
|
||||
}
|
||||
getOption(): UTSJSONObject {
|
||||
return this.options
|
||||
}
|
||||
showLoading(){
|
||||
this.context.evalJS(`showLoading(${JSON.stringify([] as any[])})`);
|
||||
}
|
||||
showLoading(type: string, opts: UTSJSONObject){
|
||||
this.context.evalJS(`showLoading(${JSON.stringify([type, opts])})`);
|
||||
}
|
||||
hideLoading(){
|
||||
this.context.evalJS(`hideLoading()`);
|
||||
}
|
||||
clear(){
|
||||
this.context.evalJS(`clear()`);
|
||||
}
|
||||
dispose(){
|
||||
this.context.evalJS(`dispose()`);
|
||||
}
|
||||
resize(size:UTSJSONObject){
|
||||
setTimeout(()=>{
|
||||
this.context.evalJS(`resize(${JSON.stringify(size)})`);
|
||||
},0)
|
||||
}
|
||||
resize(){
|
||||
setTimeout(()=>{
|
||||
this.context.evalJS(`resize()`);
|
||||
},10)
|
||||
|
||||
}
|
||||
on(type:string, query: any, callback: EchartsEventHandler) {
|
||||
const key = `${type}${JSON.stringify(query)}`
|
||||
if(typeof callback == 'function'){
|
||||
this.eventMap.set(key, callback)
|
||||
}
|
||||
this.context.evalJS(`on(${JSON.stringify([type, query])})`);
|
||||
console.warn('uvue 暂不支持事件')
|
||||
}
|
||||
on(type:string, callback: EchartsEventHandler) {
|
||||
const key = `${type}`
|
||||
if(typeof callback == 'function'){
|
||||
this.eventMap.set(key, callback)
|
||||
}
|
||||
this.context.evalJS(`on(${JSON.stringify([type])})`);
|
||||
console.warn('uvue 暂不支持事件')
|
||||
}
|
||||
dispatchAction(type:string, options: UTSJSONObject){
|
||||
const handler = this.eventMap.get(type)
|
||||
if(handler!=null){
|
||||
handler(options)
|
||||
}
|
||||
}
|
||||
canvasToTempFilePath(opt: UTSJSONObject){
|
||||
// this.context.evalJS(`on(${JSON.stringify(opt)})`);
|
||||
this.context.evalJS(`canvasToTempFilePath(${JSON.stringify(opt)})`);
|
||||
this.temp.push(opt)
|
||||
}
|
||||
isDisposed():boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// #endif
|
||||
// #ifndef APP
|
||||
export class Echarts {
|
||||
constructor() {}
|
||||
setOption(option: UTSJSONObject): void
|
||||
isDisposed(): boolean;
|
||||
clear(): void;
|
||||
resize(size:UTSJSONObject): void;
|
||||
resize(): void;
|
||||
canvasToTempFilePath(opt : UTSJSONObject): void;
|
||||
dispose(): void;
|
||||
showLoading(cfg?: UTSJSONObject): void;
|
||||
showLoading(name?: string, cfg?: UTSJSONObject): void;
|
||||
hideLoading(): void;
|
||||
getZr(): any
|
||||
}
|
||||
// #endif
|
||||
@@ -0,0 +1,16 @@
|
||||
// @ts-nocheck
|
||||
|
||||
// #ifdef VUE3
|
||||
export * from 'vue';
|
||||
// #endif
|
||||
|
||||
// #ifndef VUE3
|
||||
export * from '@vue/composition-api';
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
import Vue from 'vue'
|
||||
import VueCompositionAPI from '@vue/composition-api'
|
||||
Vue.use(VueCompositionAPI)
|
||||
// #endif
|
||||
|
||||
// #endif
|
||||
Reference in New Issue
Block a user