From d72334e80bee2b410bf970a2dc9bd2f3b38f408d Mon Sep 17 00:00:00 2001
From: unanmed <1319491857@qq.com>
Date: Sun, 25 May 2025 17:11:18 +0800
Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=8A=8A=E6=A0=B7=E6=9D=BF?=
 =?UTF-8?q?=E6=89=80=E9=9C=80=E7=9A=84=E6=A0=87=E7=AD=BE=E5=AE=9A=E4=B9=89?=
 =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E8=87=B3=20client-modules?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../src/render/elements}/animate.ts           |   0
 .../src/render/elements}/block.ts             |   0
 .../src/render/elements}/cache.ts             |   2 +-
 .../src/render/elements}/camera.ts            |   0
 .../src/render/elements}/frame.ts             |   0
 .../src/render/elements}/hero.ts              |   2 +-
 .../src/render/elements/index.ts              |  77 ++++
 .../src/render/elements}/layer.ts             |   0
 .../src/render/elements/misc.ts               | 331 ++++++++++++++++++
 .../src/render/elements}/viewport.ts          |   0
 .../client-modules/src/render/index.tsx       |   3 +
 packages/render-elements/src/misc.ts          | 324 -----------------
 packages/render-vue/src/map.ts                |  58 +--
 13 files changed, 415 insertions(+), 382 deletions(-)
 rename {packages/render-elements/src => packages-user/client-modules/src/render/elements}/animate.ts (100%)
 rename {packages/render-elements/src => packages-user/client-modules/src/render/elements}/block.ts (100%)
 rename {packages/render-elements/src => packages-user/client-modules/src/render/elements}/cache.ts (99%)
 rename {packages/render-elements/src => packages-user/client-modules/src/render/elements}/camera.ts (100%)
 rename {packages/render-elements/src => packages-user/client-modules/src/render/elements}/frame.ts (100%)
 rename {packages/render-elements/src => packages-user/client-modules/src/render/elements}/hero.ts (99%)
 create mode 100644 packages-user/client-modules/src/render/elements/index.ts
 rename {packages/render-elements/src => packages-user/client-modules/src/render/elements}/layer.ts (100%)
 create mode 100644 packages-user/client-modules/src/render/elements/misc.ts
 rename {packages/render-elements/src => packages-user/client-modules/src/render/elements}/viewport.ts (100%)

diff --git a/packages/render-elements/src/animate.ts b/packages-user/client-modules/src/render/elements/animate.ts
similarity index 100%
rename from packages/render-elements/src/animate.ts
rename to packages-user/client-modules/src/render/elements/animate.ts
diff --git a/packages/render-elements/src/block.ts b/packages-user/client-modules/src/render/elements/block.ts
similarity index 100%
rename from packages/render-elements/src/block.ts
rename to packages-user/client-modules/src/render/elements/block.ts
diff --git a/packages/render-elements/src/cache.ts b/packages-user/client-modules/src/render/elements/cache.ts
similarity index 99%
rename from packages/render-elements/src/cache.ts
rename to packages-user/client-modules/src/render/elements/cache.ts
index cdb2092..187b699 100644
--- a/packages/render-elements/src/cache.ts
+++ b/packages-user/client-modules/src/render/elements/cache.ts
@@ -1,6 +1,6 @@
 import { logger } from '@motajs/common';
 import { MotaOffscreenCanvas2D } from '@motajs/render-core';
-import { SizedCanvasImageSource } from './types';
+import { SizedCanvasImageSource } from '@motajs/render-elements';
 
 // 经过测试(https://www.measurethat.net/Benchmarks/Show/30741/1/drawimage-img-vs-canvas-vs-bitmap-cropping-fix-loading)
 // 得出结论,ImageBitmap和Canvas的绘制性能不如Image,于是直接画Image就行,所以缓存基本上就是存Image
diff --git a/packages/render-elements/src/camera.ts b/packages-user/client-modules/src/render/elements/camera.ts
similarity index 100%
rename from packages/render-elements/src/camera.ts
rename to packages-user/client-modules/src/render/elements/camera.ts
diff --git a/packages/render-elements/src/frame.ts b/packages-user/client-modules/src/render/elements/frame.ts
similarity index 100%
rename from packages/render-elements/src/frame.ts
rename to packages-user/client-modules/src/render/elements/frame.ts
diff --git a/packages/render-elements/src/hero.ts b/packages-user/client-modules/src/render/elements/hero.ts
similarity index 99%
rename from packages/render-elements/src/hero.ts
rename to packages-user/client-modules/src/render/elements/hero.ts
index fe21508..0149573 100644
--- a/packages/render-elements/src/hero.ts
+++ b/packages-user/client-modules/src/render/elements/hero.ts
@@ -1,7 +1,7 @@
 import { RenderAdapter } from '@motajs/render-core';
 import { logger } from '@motajs/common';
 import { ILayerRenderExtends, Layer, LayerMovingRenderable } from './layer';
-import { SizedCanvasImageSource } from './types';
+import { SizedCanvasImageSource } from '@motajs/render-elements';
 import EventEmitter from 'eventemitter3';
 import { texture } from './cache';
 import { TimingFn } from 'mutate-animate';
diff --git a/packages-user/client-modules/src/render/elements/index.ts b/packages-user/client-modules/src/render/elements/index.ts
new file mode 100644
index 0000000..ac1be29
--- /dev/null
+++ b/packages-user/client-modules/src/render/elements/index.ts
@@ -0,0 +1,77 @@
+import { standardElementNoCache, tagMap } from '@motajs/render-vue';
+import { createCache } from './cache';
+import { createFrame } from './frame';
+import { createLayer, Layer, LayerGroup } from './layer';
+import { createViewport } from './viewport';
+import { Icon, Winskin } from './misc';
+import { Animate } from './animate';
+
+export function createElements() {
+    createCache();
+    createFrame();
+    createLayer();
+    createViewport();
+
+    // ----- 注册标签
+
+    tagMap.register('winskin', (_0, _1, props) => {
+        if (!props)
+            return new Winskin(core.material.images.images['winskin.png']);
+        else {
+            const {
+                image = core.material.images.images['winskin.png'],
+                type = 'static'
+            } = props;
+            return new Winskin(image, type);
+        }
+    });
+    tagMap.register('layer', (_0, _1, props) => {
+        if (!props) return new Layer();
+        else {
+            const { ex } = props;
+            const l = new Layer();
+
+            if (ex) {
+                (ex as any[]).forEach(v => {
+                    l.extends(v);
+                });
+            }
+
+            return l;
+        }
+    });
+    tagMap.register('layer-group', (_0, _1, props) => {
+        if (!props) return new LayerGroup();
+        else {
+            const { ex, layers } = props;
+            const l = new LayerGroup();
+
+            if (ex) {
+                (ex as any[]).forEach(v => {
+                    l.extends(v);
+                });
+            }
+            if (layers) {
+                (layers as any[]).forEach(v => {
+                    l.addLayer(v);
+                });
+            }
+
+            return l;
+        }
+    });
+    tagMap.register('animation', (_0, _1, _props) => {
+        return new Animate();
+    });
+    tagMap.register('icon', standardElementNoCache(Icon));
+}
+
+export * from './animate';
+export * from './block';
+export * from './cache';
+export * from './camera';
+export * from './frame';
+export * from './hero';
+export * from './layer';
+export * from './misc';
+export * from './viewport';
diff --git a/packages/render-elements/src/layer.ts b/packages-user/client-modules/src/render/elements/layer.ts
similarity index 100%
rename from packages/render-elements/src/layer.ts
rename to packages-user/client-modules/src/render/elements/layer.ts
diff --git a/packages-user/client-modules/src/render/elements/misc.ts b/packages-user/client-modules/src/render/elements/misc.ts
new file mode 100644
index 0000000..17c8a6e
--- /dev/null
+++ b/packages-user/client-modules/src/render/elements/misc.ts
@@ -0,0 +1,331 @@
+import { logger } from '@motajs/common';
+import {
+    ERenderItemEvent,
+    RenderItem,
+    RenderItemPosition,
+    MotaOffscreenCanvas2D,
+    Transform
+} from '@motajs/render-core';
+import { SizedCanvasImageSource } from '@motajs/render-elements';
+import { isNil } from 'lodash-es';
+import { RenderableData, AutotileRenderable, texture } from './cache';
+import { IAnimateFrame, renderEmits } from './frame';
+
+export interface EIconEvent extends ERenderItemEvent {}
+
+export class Icon extends RenderItem<EIconEvent> implements IAnimateFrame {
+    /** 图标id */
+    icon: AllNumbers = 0;
+    /** 帧数 */
+    frame: number = 0;
+    /** 是否启用动画 */
+    animate: boolean = false;
+    /** 图标的渲染信息 */
+    private renderable?: RenderableData | AutotileRenderable;
+
+    private pendingIcon?: AllNumbers;
+
+    constructor(type: RenderItemPosition, cache?: boolean, fall?: boolean) {
+        super(type, cache, fall);
+        this.setAntiAliasing(false);
+        this.setHD(false);
+    }
+
+    protected render(
+        canvas: MotaOffscreenCanvas2D,
+        _transform: Transform
+    ): void {
+        const ctx = canvas.ctx;
+        const renderable = this.renderable;
+        if (!renderable) return;
+        const [x, y, w, h] = renderable.render[0];
+        const cw = this.width;
+        const ch = this.height;
+        const frame = this.animate
+            ? RenderItem.animatedFrame % renderable.frame
+            : this.frame;
+
+        if (!this.animate) {
+            if (renderable.autotile) {
+                ctx.drawImage(renderable.image[0], x, y, w, h, 0, 0, cw, ch);
+            } else {
+                ctx.drawImage(renderable.image, x, y, w, h, 0, 0, cw, ch);
+            }
+        } else {
+            const [x1, y1, w1, h1] = renderable.render[frame];
+            if (renderable.autotile) {
+                const img = renderable.image[0];
+                ctx.drawImage(img, x1, y1, w1, h1, 0, 0, cw, ch);
+            } else {
+                ctx.drawImage(renderable.image, x1, y1, w1, h1, 0, 0, cw, ch);
+            }
+        }
+    }
+
+    /**
+     * 设置图标
+     * @param id 图标id
+     */
+    setIcon(id: AllIds | AllNumbers) {
+        if (id === 0) {
+            this.renderable = void 0;
+            return;
+        }
+        const num = typeof id === 'number' ? id : texture.idNumberMap[id];
+
+        const { loading } = Mota.require('@user/data-base');
+        if (loading.loaded) {
+            this.setIconRenderable(num);
+        } else {
+            if (isNil(this.pendingIcon)) {
+                loading.once('loaded', () => {
+                    this.setIconRenderable(this.pendingIcon ?? 0);
+                    delete this.pendingIcon;
+                });
+            }
+            this.pendingIcon = num;
+        }
+    }
+
+    private setIconRenderable(num: AllNumbers) {
+        const renderable = texture.getRenderable(num);
+
+        if (!renderable) {
+            logger.warn(43, num.toString());
+            return;
+        } else {
+            this.icon = num;
+            this.renderable = renderable;
+            this.frame = renderable.frame;
+        }
+        this.update();
+    }
+
+    /**
+     * 更新动画帧
+     */
+    updateFrameAnimate(): void {
+        if (this.animate) this.update(this);
+    }
+
+    destroy(): void {
+        renderEmits.removeFramer(this);
+        super.destroy();
+    }
+
+    protected handleProps(
+        key: string,
+        _prevValue: any,
+        nextValue: any
+    ): boolean {
+        switch (key) {
+            case 'icon':
+                this.setIcon(nextValue);
+                return true;
+            case 'animate':
+                if (!this.assertType(nextValue, 'boolean', key)) return false;
+                this.animate = nextValue;
+                if (nextValue) renderEmits.addFramer(this);
+                else renderEmits.removeFramer(this);
+                this.update();
+                return true;
+            case 'frame':
+                if (!this.assertType(nextValue, 'number', key)) return false;
+                this.frame = nextValue;
+                this.update();
+                return true;
+        }
+        return false;
+    }
+}
+
+interface WinskinPatterns {
+    top: CanvasPattern;
+    left: CanvasPattern;
+    bottom: CanvasPattern;
+    right: CanvasPattern;
+}
+
+export interface EWinskinEvent extends ERenderItemEvent {}
+
+export class Winskin extends RenderItem<EWinskinEvent> {
+    image: SizedCanvasImageSource;
+    /** 边框宽度,32表示原始宽度 */
+    borderSize: number = 32;
+    /** 图片名称 */
+    imageName?: string;
+
+    private pendingImage?: ImageIds;
+    private patternCache?: WinskinPatterns;
+    private patternTransform: DOMMatrix;
+
+    private static patternMap: Map<string, WinskinPatterns> = new Map();
+
+    constructor(
+        image: SizedCanvasImageSource,
+        type: RenderItemPosition = 'static'
+    ) {
+        super(type, false, false);
+        this.image = image;
+        this.setAntiAliasing(false);
+
+        if (window.DOMMatrix) {
+            this.patternTransform = new DOMMatrix();
+        } else if (window.WebKitCSSMatrix) {
+            this.patternTransform = new WebKitCSSMatrix();
+        } else {
+            this.patternTransform = new SVGMatrix();
+        }
+    }
+
+    private generatePattern() {
+        const pattern = this.requireCanvas();
+        const img = this.image;
+        pattern.size(32, 16);
+        pattern.withGameScale(false);
+        pattern.setHD(false);
+        pattern.setAntiAliasing(false);
+        const ctx = pattern.ctx;
+        ctx.drawImage(img, 144, 0, 32, 16, 0, 0, 32, 16);
+        const topPattern = ctx.createPattern(pattern.canvas, 'repeat');
+        ctx.clearRect(0, 0, 32, 16);
+        ctx.drawImage(img, 144, 48, 32, 16, 0, 0, 32, 16);
+        const bottomPattern = ctx.createPattern(pattern.canvas, 'repeat');
+        ctx.clearRect(0, 0, 32, 16);
+        pattern.size(16, 32);
+        ctx.drawImage(img, 128, 16, 16, 32, 0, 0, 16, 32);
+        const leftPattern = ctx.createPattern(pattern.canvas, 'repeat');
+        ctx.clearRect(0, 0, 16, 32);
+        ctx.drawImage(img, 176, 16, 16, 32, 0, 0, 16, 32);
+        const rightPattern = ctx.createPattern(pattern.canvas, 'repeat');
+        if (!topPattern || !bottomPattern || !leftPattern || !rightPattern) {
+            return null;
+        }
+        const winskinPattern: WinskinPatterns = {
+            top: topPattern,
+            bottom: bottomPattern,
+            left: leftPattern,
+            right: rightPattern
+        };
+        if (this.imageName) {
+            Winskin.patternMap.set(this.imageName, winskinPattern);
+        }
+        this.patternCache = winskinPattern;
+        this.deleteCanvas(pattern);
+        return winskinPattern;
+    }
+
+    private getPattern() {
+        if (!this.imageName) {
+            if (this.patternCache) return this.patternCache;
+            return this.generatePattern();
+        } else {
+            const pattern = Winskin.patternMap.get(this.imageName);
+            if (pattern) return pattern;
+            return this.generatePattern();
+        }
+    }
+
+    protected render(
+        canvas: MotaOffscreenCanvas2D,
+        _transform: Transform
+    ): void {
+        const ctx = canvas.ctx;
+        const img = this.image;
+        const w = this.width;
+        const h = this.height;
+        const pad = this.borderSize / 2;
+        // 背景
+        ctx.drawImage(img, 0, 0, 128, 128, 2, 2, w - 4, h - 4);
+        const pattern = this.getPattern();
+        if (!pattern) return;
+        const { top, left, right, bottom } = pattern;
+        top.setTransform(this.patternTransform);
+        left.setTransform(this.patternTransform);
+        right.setTransform(this.patternTransform);
+        bottom.setTransform(this.patternTransform);
+        // 上下左右边框
+        ctx.save();
+        ctx.fillStyle = top;
+        ctx.translate(pad, 0);
+        ctx.fillRect(0, 0, w - pad * 2, pad);
+        ctx.fillStyle = bottom;
+        ctx.translate(0, h - pad);
+        ctx.fillRect(0, 0, w - pad * 2, pad);
+        ctx.fillStyle = left;
+        ctx.translate(-pad, pad * 2 - h);
+        ctx.fillRect(0, 0, pad, h - pad * 2);
+        ctx.fillStyle = right;
+        ctx.translate(w - pad, 0);
+        ctx.fillRect(0, 0, pad, h - pad * 2);
+        ctx.restore();
+        // 四个角的边框
+        ctx.drawImage(img, 128, 0, 16, 16, 0, 0, pad, pad);
+        ctx.drawImage(img, 176, 0, 16, 16, w - pad, 0, pad, pad);
+        ctx.drawImage(img, 128, 48, 16, 16, 0, h - pad, pad, pad);
+        ctx.drawImage(img, 176, 48, 16, 16, w - pad, h - pad, pad, pad);
+    }
+
+    /**
+     * 设置winskin图片
+     * @param image winskin图片
+     */
+    setImage(image: SizedCanvasImageSource) {
+        this.image = image;
+        this.patternCache = void 0;
+        this.update();
+    }
+
+    /**
+     * 通过图片名称设置winskin
+     * @param name 图片名称
+     */
+    setImageByName(name: ImageIds) {
+        const { loading } = Mota.require('@user/data-base');
+        if (loading.loaded) {
+            const image = core.material.images.images[name];
+            this.setImage(image);
+        } else {
+            if (isNil(this.pendingImage)) {
+                loading.once('loaded', () => {
+                    const id = this.pendingImage;
+                    if (!id) return;
+                    const image = core.material.images.images[id];
+                    this.setImage(image);
+                    delete this.pendingImage;
+                });
+            }
+            this.pendingImage = name;
+        }
+        this.imageName = name;
+    }
+
+    /**
+     * 设置边框大小
+     * @param size 边框大小
+     */
+    setBorderSize(size: number) {
+        this.borderSize = size;
+        this.patternTransform.a = size / 32;
+        this.patternTransform.d = size / 32;
+        this.update();
+    }
+
+    protected handleProps(
+        key: string,
+        _prevValue: any,
+        nextValue: any
+    ): boolean {
+        switch (key) {
+            case 'image':
+                if (!this.assertType(nextValue, 'string', key)) return false;
+                this.setImageByName(nextValue);
+                return true;
+            case 'borderSize':
+                if (!this.assertType(nextValue, 'number', key)) return false;
+                this.setBorderSize(nextValue);
+                return true;
+        }
+        return false;
+    }
+}
diff --git a/packages/render-elements/src/viewport.ts b/packages-user/client-modules/src/render/elements/viewport.ts
similarity index 100%
rename from packages/render-elements/src/viewport.ts
rename to packages-user/client-modules/src/render/elements/viewport.ts
diff --git a/packages-user/client-modules/src/render/index.tsx b/packages-user/client-modules/src/render/index.tsx
index 460022e..774fbbe 100644
--- a/packages-user/client-modules/src/render/index.tsx
+++ b/packages-user/client-modules/src/render/index.tsx
@@ -7,6 +7,7 @@ import { hook } from '@user/data-base';
 import { createItemDetail } from './itemDetail';
 import { createLoopMap } from './loopMap';
 import { createGameCanvas } from './legacy/gameCanvas';
+import { createElements } from './elements';
 
 export function createGameRenderer() {
     const main = new MotaRenderer();
@@ -41,8 +42,10 @@ export function createRender() {
     createGameCanvas();
     createItemDetail();
     createLoopMap();
+    createElements();
 }
 
 export * from './components';
 export * from './ui';
 export * from './use';
+export * from './elements';
diff --git a/packages/render-elements/src/misc.ts b/packages/render-elements/src/misc.ts
index 7c8b5bc..fe52c4a 100644
--- a/packages/render-elements/src/misc.ts
+++ b/packages/render-elements/src/misc.ts
@@ -6,11 +6,6 @@ import {
     MotaOffscreenCanvas2D
 } from '@motajs/render-core';
 import { Font } from '@motajs/render-style';
-import { logger } from '@motajs/common';
-import { isNil } from 'lodash-es';
-import { IAnimateFrame, renderEmits } from './frame';
-import { AutotileRenderable, RenderableData, texture } from './cache';
-import { SizedCanvasImageSource } from './types';
 
 /** 文字的安全填充,会填充在文字的上侧和下侧,防止削顶和削底 */
 const SAFE_PAD = 1;
@@ -229,322 +224,3 @@ export class Comment extends RenderItem {
         return false;
     }
 }
-
-export interface EIconEvent extends ERenderItemEvent {}
-
-export class Icon extends RenderItem<EIconEvent> implements IAnimateFrame {
-    /** 图标id */
-    icon: AllNumbers = 0;
-    /** 帧数 */
-    frame: number = 0;
-    /** 是否启用动画 */
-    animate: boolean = false;
-    /** 图标的渲染信息 */
-    private renderable?: RenderableData | AutotileRenderable;
-
-    private pendingIcon?: AllNumbers;
-
-    constructor(type: RenderItemPosition, cache?: boolean, fall?: boolean) {
-        super(type, cache, fall);
-        this.setAntiAliasing(false);
-        this.setHD(false);
-    }
-
-    protected render(
-        canvas: MotaOffscreenCanvas2D,
-        _transform: Transform
-    ): void {
-        const ctx = canvas.ctx;
-        const renderable = this.renderable;
-        if (!renderable) return;
-        const [x, y, w, h] = renderable.render[0];
-        const cw = this.width;
-        const ch = this.height;
-        const frame = this.animate
-            ? RenderItem.animatedFrame % renderable.frame
-            : this.frame;
-
-        if (!this.animate) {
-            if (renderable.autotile) {
-                ctx.drawImage(renderable.image[0], x, y, w, h, 0, 0, cw, ch);
-            } else {
-                ctx.drawImage(renderable.image, x, y, w, h, 0, 0, cw, ch);
-            }
-        } else {
-            const [x1, y1, w1, h1] = renderable.render[frame];
-            if (renderable.autotile) {
-                const img = renderable.image[0];
-                ctx.drawImage(img, x1, y1, w1, h1, 0, 0, cw, ch);
-            } else {
-                ctx.drawImage(renderable.image, x1, y1, w1, h1, 0, 0, cw, ch);
-            }
-        }
-    }
-
-    /**
-     * 设置图标
-     * @param id 图标id
-     */
-    setIcon(id: AllIds | AllNumbers) {
-        if (id === 0) {
-            this.renderable = void 0;
-            return;
-        }
-        const num = typeof id === 'number' ? id : texture.idNumberMap[id];
-
-        const { loading } = Mota.require('@user/data-base');
-        if (loading.loaded) {
-            this.setIconRenderable(num);
-        } else {
-            if (isNil(this.pendingIcon)) {
-                loading.once('loaded', () => {
-                    this.setIconRenderable(this.pendingIcon ?? 0);
-                    delete this.pendingIcon;
-                });
-            }
-            this.pendingIcon = num;
-        }
-    }
-
-    private setIconRenderable(num: AllNumbers) {
-        const renderable = texture.getRenderable(num);
-
-        if (!renderable) {
-            logger.warn(43, num.toString());
-            return;
-        } else {
-            this.icon = num;
-            this.renderable = renderable;
-            this.frame = renderable.frame;
-        }
-        this.update();
-    }
-
-    /**
-     * 更新动画帧
-     */
-    updateFrameAnimate(): void {
-        if (this.animate) this.update(this);
-    }
-
-    destroy(): void {
-        renderEmits.removeFramer(this);
-        super.destroy();
-    }
-
-    protected handleProps(
-        key: string,
-        _prevValue: any,
-        nextValue: any
-    ): boolean {
-        switch (key) {
-            case 'icon':
-                this.setIcon(nextValue);
-                return true;
-            case 'animate':
-                if (!this.assertType(nextValue, 'boolean', key)) return false;
-                this.animate = nextValue;
-                if (nextValue) renderEmits.addFramer(this);
-                else renderEmits.removeFramer(this);
-                this.update();
-                return true;
-            case 'frame':
-                if (!this.assertType(nextValue, 'number', key)) return false;
-                this.frame = nextValue;
-                this.update();
-                return true;
-        }
-        return false;
-    }
-}
-
-interface WinskinPatterns {
-    top: CanvasPattern;
-    left: CanvasPattern;
-    bottom: CanvasPattern;
-    right: CanvasPattern;
-}
-
-export interface EWinskinEvent extends ERenderItemEvent {}
-
-export class Winskin extends RenderItem<EWinskinEvent> {
-    image: SizedCanvasImageSource;
-    /** 边框宽度,32表示原始宽度 */
-    borderSize: number = 32;
-    /** 图片名称 */
-    imageName?: string;
-
-    private pendingImage?: ImageIds;
-    private patternCache?: WinskinPatterns;
-    private patternTransform: DOMMatrix;
-
-    private static patternMap: Map<string, WinskinPatterns> = new Map();
-
-    constructor(
-        image: SizedCanvasImageSource,
-        type: RenderItemPosition = 'static'
-    ) {
-        super(type, false, false);
-        this.image = image;
-        this.setAntiAliasing(false);
-
-        if (window.DOMMatrix) {
-            this.patternTransform = new DOMMatrix();
-        } else if (window.WebKitCSSMatrix) {
-            this.patternTransform = new WebKitCSSMatrix();
-        } else {
-            this.patternTransform = new SVGMatrix();
-        }
-    }
-
-    private generatePattern() {
-        const pattern = this.requireCanvas();
-        const img = this.image;
-        pattern.size(32, 16);
-        pattern.withGameScale(false);
-        pattern.setHD(false);
-        pattern.setAntiAliasing(false);
-        const ctx = pattern.ctx;
-        ctx.drawImage(img, 144, 0, 32, 16, 0, 0, 32, 16);
-        const topPattern = ctx.createPattern(pattern.canvas, 'repeat');
-        ctx.clearRect(0, 0, 32, 16);
-        ctx.drawImage(img, 144, 48, 32, 16, 0, 0, 32, 16);
-        const bottomPattern = ctx.createPattern(pattern.canvas, 'repeat');
-        ctx.clearRect(0, 0, 32, 16);
-        pattern.size(16, 32);
-        ctx.drawImage(img, 128, 16, 16, 32, 0, 0, 16, 32);
-        const leftPattern = ctx.createPattern(pattern.canvas, 'repeat');
-        ctx.clearRect(0, 0, 16, 32);
-        ctx.drawImage(img, 176, 16, 16, 32, 0, 0, 16, 32);
-        const rightPattern = ctx.createPattern(pattern.canvas, 'repeat');
-        if (!topPattern || !bottomPattern || !leftPattern || !rightPattern) {
-            return null;
-        }
-        const winskinPattern: WinskinPatterns = {
-            top: topPattern,
-            bottom: bottomPattern,
-            left: leftPattern,
-            right: rightPattern
-        };
-        if (this.imageName) {
-            Winskin.patternMap.set(this.imageName, winskinPattern);
-        }
-        this.patternCache = winskinPattern;
-        this.deleteCanvas(pattern);
-        return winskinPattern;
-    }
-
-    private getPattern() {
-        if (!this.imageName) {
-            if (this.patternCache) return this.patternCache;
-            return this.generatePattern();
-        } else {
-            const pattern = Winskin.patternMap.get(this.imageName);
-            if (pattern) return pattern;
-            return this.generatePattern();
-        }
-    }
-
-    protected render(
-        canvas: MotaOffscreenCanvas2D,
-        _transform: Transform
-    ): void {
-        const ctx = canvas.ctx;
-        const img = this.image;
-        const w = this.width;
-        const h = this.height;
-        const pad = this.borderSize / 2;
-        // 背景
-        ctx.drawImage(img, 0, 0, 128, 128, 2, 2, w - 4, h - 4);
-        const pattern = this.getPattern();
-        if (!pattern) return;
-        const { top, left, right, bottom } = pattern;
-        top.setTransform(this.patternTransform);
-        left.setTransform(this.patternTransform);
-        right.setTransform(this.patternTransform);
-        bottom.setTransform(this.patternTransform);
-        // 上下左右边框
-        ctx.save();
-        ctx.fillStyle = top;
-        ctx.translate(pad, 0);
-        ctx.fillRect(0, 0, w - pad * 2, pad);
-        ctx.fillStyle = bottom;
-        ctx.translate(0, h - pad);
-        ctx.fillRect(0, 0, w - pad * 2, pad);
-        ctx.fillStyle = left;
-        ctx.translate(-pad, pad * 2 - h);
-        ctx.fillRect(0, 0, pad, h - pad * 2);
-        ctx.fillStyle = right;
-        ctx.translate(w - pad, 0);
-        ctx.fillRect(0, 0, pad, h - pad * 2);
-        ctx.restore();
-        // 四个角的边框
-        ctx.drawImage(img, 128, 0, 16, 16, 0, 0, pad, pad);
-        ctx.drawImage(img, 176, 0, 16, 16, w - pad, 0, pad, pad);
-        ctx.drawImage(img, 128, 48, 16, 16, 0, h - pad, pad, pad);
-        ctx.drawImage(img, 176, 48, 16, 16, w - pad, h - pad, pad, pad);
-    }
-
-    /**
-     * 设置winskin图片
-     * @param image winskin图片
-     */
-    setImage(image: SizedCanvasImageSource) {
-        this.image = image;
-        this.patternCache = void 0;
-        this.update();
-    }
-
-    /**
-     * 通过图片名称设置winskin
-     * @param name 图片名称
-     */
-    setImageByName(name: ImageIds) {
-        const { loading } = Mota.require('@user/data-base');
-        if (loading.loaded) {
-            const image = core.material.images.images[name];
-            this.setImage(image);
-        } else {
-            if (isNil(this.pendingImage)) {
-                loading.once('loaded', () => {
-                    const id = this.pendingImage;
-                    if (!id) return;
-                    const image = core.material.images.images[id];
-                    this.setImage(image);
-                    delete this.pendingImage;
-                });
-            }
-            this.pendingImage = name;
-        }
-        this.imageName = name;
-    }
-
-    /**
-     * 设置边框大小
-     * @param size 边框大小
-     */
-    setBorderSize(size: number) {
-        this.borderSize = size;
-        this.patternTransform.a = size / 32;
-        this.patternTransform.d = size / 32;
-        this.update();
-    }
-
-    protected handleProps(
-        key: string,
-        _prevValue: any,
-        nextValue: any
-    ): boolean {
-        switch (key) {
-            case 'image':
-                if (!this.assertType(nextValue, 'string', key)) return false;
-                this.setImageByName(nextValue);
-                return true;
-            case 'borderSize':
-                if (!this.assertType(nextValue, 'number', key)) return false;
-                this.setBorderSize(nextValue);
-                return true;
-        }
-        return false;
-    }
-}
diff --git a/packages/render-vue/src/map.ts b/packages/render-vue/src/map.ts
index a1f8e6d..fce54a3 100644
--- a/packages/render-vue/src/map.ts
+++ b/packages/render-vue/src/map.ts
@@ -12,13 +12,8 @@ import {
 import {
     Comment,
     ETextEvent,
-    Icon,
     Image,
     Text,
-    Winskin,
-    Animate,
-    Layer,
-    LayerGroup,
     BezierCurve,
     Circle,
     Ellipse,
@@ -70,7 +65,7 @@ class RenderTagMap {
 
 export const tagMap = new RenderTagMap();
 
-const standardElement = (
+export const standardElement = (
     Item: new (
         type: RenderItemPosition,
         cache?: boolean,
@@ -91,7 +86,7 @@ const standardElement = (
     };
 };
 
-const standardElementNoCache = (
+export const standardElementNoCache = (
     Item: new (
         type: RenderItemPosition,
         cache?: boolean,
@@ -199,44 +194,6 @@ tagMap.register('custom', (_0, _1, props) => {
         return item(props);
     }
 });
-tagMap.register('layer', (_0, _1, props) => {
-    if (!props) return new Layer();
-    else {
-        const { ex } = props;
-        const l = new Layer();
-
-        if (ex) {
-            (ex as any[]).forEach(v => {
-                l.extends(v);
-            });
-        }
-
-        return l;
-    }
-});
-tagMap.register('layer-group', (_0, _1, props) => {
-    if (!props) return new LayerGroup();
-    else {
-        const { ex, layers } = props;
-        const l = new LayerGroup();
-
-        if (ex) {
-            (ex as any[]).forEach(v => {
-                l.extends(v);
-            });
-        }
-        if (layers) {
-            (layers as any[]).forEach(v => {
-                l.addLayer(v);
-            });
-        }
-
-        return l;
-    }
-});
-tagMap.register('animation', (_0, _1, _props) => {
-    return new Animate();
-});
 tagMap.register('g-rect', standardElementNoCache(Rect));
 tagMap.register('g-circle', standardElementNoCache(Circle));
 tagMap.register('g-ellipse', standardElementNoCache(Ellipse));
@@ -245,14 +202,3 @@ tagMap.register('g-bezier', standardElementNoCache(BezierCurve));
 tagMap.register('g-quad', standardElementNoCache(QuadraticCurve));
 tagMap.register('g-path', standardElementNoCache(Path));
 tagMap.register('g-rectr', standardElementNoCache(RectR));
-tagMap.register('icon', standardElementNoCache(Icon));
-tagMap.register('winskin', (_0, _1, props) => {
-    if (!props) return new Winskin(core.material.images.images['winskin.png']);
-    else {
-        const {
-            image = core.material.images.images['winskin.png'],
-            type = 'static'
-        } = props;
-        return new Winskin(image, type);
-    }
-});