@cataract6545/tmui
Version:
tm-vuetify是一个新势力由主题驱动的UI组件库,相比其它优势大,组件全,设计趋势紧跟未来。具有主题生成,主题实时切换,暗黑实时切换,lottie动画,图表等新颖功能,tmui TMUI
249 lines (224 loc) • 6.39 kB
text/typescript
import { tmRoundRect } from './shape/roundRect';
// @ts-expect-error
import * as TWEEN from "@/tmui/tool/lib/tween.min.js";
import { getCanvas } from "@/tmui/tool/function/getCanvas";
// #ifdef APP-NVUE
import { enable, WeexBridge } from "@/tmui/tool/gcanvas/index.js";
const dom = uni.requireNativePlugin("dom");
// #endif
import { ComponentPublicInstance } from "vue"
import { Shape } from "./shape";
export interface tmCvOptsType {
left?: number,
top?: number,
width: number,
height: number,
dpr?: number,
platform?: 'uni' | 'web'
}
var requestAnimationFrameId:IdleRequestCallback|any = 0;
let stopDrawer = false;
let tween:TWEEN|null = null;
/**
* tmCv
* 协议:MIT
* 功能特色:
* 1/图形为插件式类对象,分模块加载,大小可控,对小程序非常有效
* 2/保留了高效的内部动画,动画简单有趣,使用超级简单
* @description tmCv是tmui作者专为uniapp开发轻量级的canvas绘制插件
* @copyright tmui保留版权,不可随意拿来更改公开发布为自己的产品。不接受二次开发并公布为二次产品。
* @author tmui3.0附带库
* @default 2023年3月29日
*/
export class tmCv {
private requestIdleCallback: Function | null = null
private requestAnimationFrame: Function | null = null
/**onFramdi,关闭时需要注销 */
private timid: any = null;
ctx: UniApp.CanvasContext | null = null;
render: HTMLCanvasElement | null = null;
private canvasId: string = ""
private proxy: ComponentPublicInstance | null = null;
graphs: Array<Shape> = [];
opts: tmCvOptsType = {
left: 0,
top: 0,
width: 0,
height: 0,
dpr: 1,
platform: 'uni'
}
constructor(proxy: ComponentPublicInstance, domId: string, opts?: tmCvOptsType) {
this.canvasId = domId;
this.proxy = proxy;
if (typeof opts !== 'undefined') {
this.opts = { ...this.opts, ...opts }
}
}
init(): Promise<tmCv> {
return this._getNodes(this.proxy)
}
add(graph: any | any[]) {
if (Array.isArray(graph)) {
this.graphs.push(...graph)
return
}
this.graphs.push(graph)
}
draw() {
if (!this.ctx) return;
this.ctx.clearRect(0, 0, this.opts.width, this.opts.height)
for (const rect of this.graphs) {
rect.draw()
}
if (this.ctx.draw) {
this.ctx.draw()
}
}
public animation(arg: { duration?: number, repeat?: number, yoyo?: boolean } = { duration: 500, repeat: 0, yoyo: false },
onUpdate: (progress: number) => void, onStart?: (progress: number) => void): Promise<{ [key: string]: any }> {
return new Promise((res, rej) => {
tween = new TWEEN.Tween({ progress: 0 })
.easing(TWEEN.Easing.Linear.None) // 缓动函数
.to({ progress: 1 }, arg?.duration ?? 0)
.onUpdate((e: any) => {
onUpdate(e.progress)
})
.onStart((e: any) => {
if (onStart) {
onStart(e.progress)
}
})
.onComplete((e: any) => {
res(e)
})
.delay(0)
.repeat(arg?.repeat ?? 0)
.yoyo(arg?.yoyo ?? false)
.start();
})
}
private _getNodes(proxy: ComponentPublicInstance | null): Promise<tmCv> {
let t = this;
let sys = uni.getSystemInfoSync()
function initOpts(node: any) {
try {
if (typeof window !== 'undefined') {
t.requestIdleCallback = window.requestIdleCallback;
t.requestAnimationFrame = window.requestAnimationFrame;
}
// @ts-expect-error
if (node && node !== null && typeof node != 'undefined' && node?.requestAnimationFrame && t.requestAnimationFrame == null) {
t.requestAnimationFrame = node.requestAnimationFrame
t.requestIdleCallback = node.cancelAnimationFrame
t.render = node;
}
if (t.requestAnimationFrame == null) {
t.requestAnimationFrame = uni.$tm.u.requestAnimationFrame;
t.requestIdleCallback = uni.$tm.u.cancelAnimationFrame
}
} catch (error) {
console.error("tmCv:", error)
}
}
return new Promise((res, rej) => {
if (!this.proxy) {
res(this)
return;
}
let delay = 10
// #ifdef APP-NVUE
let isAndroid = sys.osName == "android";
if (isAndroid) {
delay = 250
} else {
delay = 100
}
// #endif
// #ifdef MP
delay = 60
// #endif
// #ifdef APP-VUE
delay = 30
// #endif
// #ifdef APP-NVUE
setTimeout(() => {
/*获取元素引用*/
let domId = t.canvasId.replace(/[\.|#]/g, "")
var ganvas: any = proxy?.$refs[domId] ?? null;
dom?.getComponentRect(ganvas, function (res: any) {
t.opts.left = res?.size?.left ?? 0;
t.opts.top = res?.size?.top ?? 0;
t.opts.dpr = sys.pixelRatio;
// @ts-ignore
getCanvas(t.proxy, domId, t.opts.width, t.opts.height).then((e) => {
t.ctx = e.ctx
initOpts(e.node)
res(t)
}).catch(error => {
console.error(error)
})
});
}, delay);
// #endif
// #ifndef APP-NVUE
setTimeout(() => {
uni
.createSelectorQuery()
.in(proxy)
.select(".canvas")
.boundingClientRect()
.exec(((resNodes) => {
const result = resNodes[0]
// @ts-ignore
this.opts.left = result?.left ?? 0;
// @ts-ignore
this.opts.top = result?.top ?? 0;
this.opts.dpr = sys.pixelRatio;
// @ts-ignore
getCanvas(proxy, this.canvasId, this.opts.width, this.opts.height).then((e) => {
initOpts(e.node)
this.ctx = e.ctx
stopDrawer = false;
animate(this.requestAnimationFrame)
res(this)
}).catch(error => {
})
}));
}, delay);
// #endif
})
}
/**注销tmCv */
destory() {
if (!this.requestIdleCallback) return;
stopDrawer = true;
try{
this.requestIdleCallback(requestAnimationFrameId);
requestIdleCallback(requestAnimationFrameId)
}catch(e){
//TODO handle the exception
}
}
}
function animate(requestAnimationFrames: any) {
if (!requestAnimationFrames) return;
function animateVC() {
if(stopDrawer){
try{
tween.stop();
}catch(e){
//TODO handle the exception
}
tween = null;
clearTimeout(requestAnimationFrameId)
return;
}
requestAnimationFrameId = requestAnimationFrames(animateVC);
TWEEN.update();
}
animateVC()
}
export {
Shape
}