mirage-engine 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/Mirage.d.ts +8 -0
- package/dist/core/Syncer.d.ts +18 -0
- package/dist/dom/Extractor.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/mirage-engine.js +176 -0
- package/dist/mirage-engine.umd.js +1 -0
- package/dist/renderer/DomProjector.d.ts +4 -0
- package/dist/renderer/Renderer.d.ts +16 -0
- package/dist/types/index.d.ts +17 -0
- package/package.json +36 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Renderer } from '../renderer/Renderer';
|
|
2
|
+
export declare class Syncer {
|
|
3
|
+
private target;
|
|
4
|
+
private renderer;
|
|
5
|
+
private observer;
|
|
6
|
+
private isDomDirty;
|
|
7
|
+
private isRunning;
|
|
8
|
+
private mutationTimer;
|
|
9
|
+
private cssTimer;
|
|
10
|
+
constructor(target: HTMLElement, renderer: Renderer);
|
|
11
|
+
start(): void;
|
|
12
|
+
stop(): void;
|
|
13
|
+
private clearTimers;
|
|
14
|
+
private onTransitionFinished;
|
|
15
|
+
private onWindowResize;
|
|
16
|
+
private forceUpdateScene;
|
|
17
|
+
private renderLoop;
|
|
18
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Mirage } from './core/Mirage';
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
var p = Object.defineProperty;
|
|
2
|
+
var v = (r, e, t) => e in r ? p(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
|
|
3
|
+
var i = (r, e, t) => (v(r, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
|
+
import * as h from "three";
|
|
5
|
+
class S {
|
|
6
|
+
constructor() {
|
|
7
|
+
i(this, "canvas");
|
|
8
|
+
i(this, "scene");
|
|
9
|
+
i(this, "camera");
|
|
10
|
+
i(this, "renderer");
|
|
11
|
+
i(this, "renderOrder", 0);
|
|
12
|
+
this.canvas = document.createElement("canvas"), this.scene = new h.Scene();
|
|
13
|
+
const e = window.innerWidth, t = window.innerHeight;
|
|
14
|
+
this.camera = new h.OrthographicCamera(
|
|
15
|
+
e / -2,
|
|
16
|
+
e / 2,
|
|
17
|
+
t / 2,
|
|
18
|
+
t / -2,
|
|
19
|
+
1,
|
|
20
|
+
1e3
|
|
21
|
+
), this.camera.position.z = 100, this.renderer = new h.WebGLRenderer({
|
|
22
|
+
canvas: this.canvas,
|
|
23
|
+
alpha: !0
|
|
24
|
+
}), this.renderer.setSize(e, t);
|
|
25
|
+
}
|
|
26
|
+
mount(e) {
|
|
27
|
+
e.appendChild(this.canvas);
|
|
28
|
+
}
|
|
29
|
+
dispose() {
|
|
30
|
+
try {
|
|
31
|
+
this.renderer.dispose();
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
this.canvas.parentElement && this.canvas.parentElement.removeChild(this.canvas);
|
|
35
|
+
}
|
|
36
|
+
setSize(e, t) {
|
|
37
|
+
this.renderer.setSize(e, t), this.camera.left = e / -2, this.camera.right = e / 2, this.camera.top = t / 2, this.camera.bottom = t / -2, this.camera.updateProjectionMatrix();
|
|
38
|
+
}
|
|
39
|
+
clearScene() {
|
|
40
|
+
for (; this.scene.children.length > 0; )
|
|
41
|
+
this.scene.remove(this.scene.children[0]);
|
|
42
|
+
}
|
|
43
|
+
buildScene(e) {
|
|
44
|
+
if (e.type === "BOX") {
|
|
45
|
+
const t = new h.PlaneGeometry(
|
|
46
|
+
e.rect.width,
|
|
47
|
+
e.rect.height
|
|
48
|
+
), s = e.styles.backgroundColor;
|
|
49
|
+
let o = s, n = 1;
|
|
50
|
+
if (s === "transparent" || s === "rgba(0, 0, 0, 0)")
|
|
51
|
+
o = "#ffffff", n = 0;
|
|
52
|
+
else if (s.startsWith("rgba")) {
|
|
53
|
+
const a = s.match(/[\d.]+/g);
|
|
54
|
+
if (a && a.length >= 4) {
|
|
55
|
+
const g = a[0], y = a[1], T = a[2];
|
|
56
|
+
n = parseFloat(a[3]), o = `rgb(${g}, ${y}, ${T})`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const c = e.styles.opacity * n, d = new h.MeshBasicMaterial({
|
|
60
|
+
color: o,
|
|
61
|
+
opacity: c,
|
|
62
|
+
transparent: c < 1
|
|
63
|
+
}), l = new h.Mesh(t, d), u = this.renderer.domElement.width, f = this.renderer.domElement.height, w = 1e-3;
|
|
64
|
+
this.renderOrder++, l.position.set(
|
|
65
|
+
e.rect.x - u / 2 + e.rect.width / 2,
|
|
66
|
+
-e.rect.y + f / 2 - e.rect.height / 2,
|
|
67
|
+
e.styles.zIndex + this.renderOrder * w
|
|
68
|
+
), this.scene.add(l);
|
|
69
|
+
for (const a of e.children)
|
|
70
|
+
this.buildScene(a);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
syncScene(e) {
|
|
74
|
+
this.clearScene(), this.renderOrder = 0, this.buildScene(e);
|
|
75
|
+
}
|
|
76
|
+
render() {
|
|
77
|
+
this.renderer.render(this.scene, this.camera);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function m(r) {
|
|
81
|
+
if (r.tagName === "SCRIPT" || r.tagName === "STYLE")
|
|
82
|
+
return null;
|
|
83
|
+
const e = r.getBoundingClientRect(), t = {
|
|
84
|
+
x: e.x + window.scrollX,
|
|
85
|
+
y: e.y + window.scrollY,
|
|
86
|
+
width: e.width,
|
|
87
|
+
height: e.height
|
|
88
|
+
}, s = window.getComputedStyle(r), o = {
|
|
89
|
+
backgroundColor: s.backgroundColor,
|
|
90
|
+
opacity: parseFloat(s.opacity),
|
|
91
|
+
zIndex: parseInt(s.zIndex, 10) || 0
|
|
92
|
+
}, n = [];
|
|
93
|
+
for (const c of r.children) {
|
|
94
|
+
const d = m(c);
|
|
95
|
+
d && n.push(d);
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
type: "BOX",
|
|
99
|
+
rect: t,
|
|
100
|
+
styles: o,
|
|
101
|
+
children: n
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
class b {
|
|
105
|
+
constructor(e, t) {
|
|
106
|
+
i(this, "target");
|
|
107
|
+
i(this, "renderer");
|
|
108
|
+
i(this, "observer");
|
|
109
|
+
i(this, "isDomDirty", !1);
|
|
110
|
+
i(this, "isRunning", !1);
|
|
111
|
+
i(this, "mutationTimer", null);
|
|
112
|
+
i(this, "cssTimer", null);
|
|
113
|
+
i(this, "onTransitionFinished", (e) => {
|
|
114
|
+
this.target.contains(e.target) && this.mutationTimer === null && (this.cssTimer && clearTimeout(this.cssTimer), this.cssTimer = window.setTimeout(() => {
|
|
115
|
+
this.isDomDirty = !0, this.cssTimer = null;
|
|
116
|
+
}, 50));
|
|
117
|
+
});
|
|
118
|
+
i(this, "onWindowResize", () => {
|
|
119
|
+
this.renderer.setSize(window.innerWidth, window.innerHeight), this.isDomDirty = !0;
|
|
120
|
+
});
|
|
121
|
+
i(this, "renderLoop", () => {
|
|
122
|
+
this.isRunning && (this.isDomDirty && this.forceUpdateScene(), this.renderer.render(), requestAnimationFrame(this.renderLoop));
|
|
123
|
+
});
|
|
124
|
+
this.target = e, this.renderer = t, this.observer = new MutationObserver((s) => {
|
|
125
|
+
let o = !1, n = !1;
|
|
126
|
+
for (const c of s)
|
|
127
|
+
c.type === "childList" ? o = !0 : c.type === "attributes" && (n = !0);
|
|
128
|
+
if (o) {
|
|
129
|
+
this.clearTimers(), console.log("Structural Changed"), this.isDomDirty = !0;
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
n && (this.mutationTimer && clearTimeout(this.mutationTimer), this.mutationTimer = window.setTimeout(() => {
|
|
133
|
+
this.mutationTimer = null, this.isDomDirty = !0;
|
|
134
|
+
}, 200));
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
start() {
|
|
138
|
+
this.isRunning || (this.isRunning = !0, this.observer.observe(this.target, {
|
|
139
|
+
childList: !0,
|
|
140
|
+
subtree: !0,
|
|
141
|
+
attributes: !0,
|
|
142
|
+
characterData: !0
|
|
143
|
+
}), this.target.addEventListener("transitionend", this.onTransitionFinished), this.target.addEventListener("animationend", this.onTransitionFinished), window.addEventListener("resize", this.onWindowResize), this.forceUpdateScene(), this.renderLoop());
|
|
144
|
+
}
|
|
145
|
+
stop() {
|
|
146
|
+
this.isRunning = !1, this.observer.disconnect(), this.clearTimers(), this.target.removeEventListener("transitionend", this.onTransitionFinished), this.target.removeEventListener("animationend", this.onTransitionFinished), window.removeEventListener("resize", this.onWindowResize);
|
|
147
|
+
}
|
|
148
|
+
clearTimers() {
|
|
149
|
+
this.mutationTimer && (clearTimeout(this.mutationTimer), this.mutationTimer = null), this.cssTimer && (clearTimeout(this.cssTimer), this.cssTimer = null);
|
|
150
|
+
}
|
|
151
|
+
forceUpdateScene() {
|
|
152
|
+
this.isDomDirty = !1;
|
|
153
|
+
const e = m(this.target);
|
|
154
|
+
e && this.renderer.syncScene(e);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
class C {
|
|
158
|
+
constructor(e) {
|
|
159
|
+
i(this, "renderer");
|
|
160
|
+
i(this, "syncer");
|
|
161
|
+
i(this, "target");
|
|
162
|
+
const t = document.querySelector(e);
|
|
163
|
+
if (!t)
|
|
164
|
+
throw new Error(`[Mirage] Element not found: ${e}`);
|
|
165
|
+
this.target = t, this.renderer = new S(), this.renderer.mount(document.body), this.syncer = new b(this.target, this.renderer);
|
|
166
|
+
}
|
|
167
|
+
start() {
|
|
168
|
+
this.syncer.start();
|
|
169
|
+
}
|
|
170
|
+
stop() {
|
|
171
|
+
this.syncer.stop(), this.renderer.dispose();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
export {
|
|
175
|
+
C as Mirage
|
|
176
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(s,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],o):(s=typeof globalThis<"u"?globalThis:s||self,o(s.MirageEngine={},s.THREE))})(this,function(s,o){"use strict";var O=Object.defineProperty;var C=(s,o,d)=>o in s?O(s,o,{enumerable:!0,configurable:!0,writable:!0,value:d}):s[o]=d;var i=(s,o,d)=>(C(s,typeof o!="symbol"?o+"":o,d),d);function d(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const u=d(o);class y{constructor(){i(this,"canvas");i(this,"scene");i(this,"camera");i(this,"renderer");i(this,"renderOrder",0);this.canvas=document.createElement("canvas"),this.scene=new u.Scene;const e=window.innerWidth,t=window.innerHeight;this.camera=new u.OrthographicCamera(e/-2,e/2,t/2,t/-2,1,1e3),this.camera.position.z=100,this.renderer=new u.WebGLRenderer({canvas:this.canvas,alpha:!0}),this.renderer.setSize(e,t)}mount(e){e.appendChild(this.canvas)}dispose(){try{this.renderer.dispose()}catch{}this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}setSize(e,t){this.renderer.setSize(e,t),this.camera.left=e/-2,this.camera.right=e/2,this.camera.top=t/2,this.camera.bottom=t/-2,this.camera.updateProjectionMatrix()}clearScene(){for(;this.scene.children.length>0;)this.scene.remove(this.scene.children[0])}buildScene(e){if(e.type==="BOX"){const t=new u.PlaneGeometry(e.rect.width,e.rect.height),n=e.styles.backgroundColor;let c=n,a=1;if(n==="transparent"||n==="rgba(0, 0, 0, 0)")c="#ffffff",a=0;else if(n.startsWith("rgba")){const h=n.match(/[\d.]+/g);if(h&&h.length>=4){const S=h[0],E=h[1],D=h[2];a=parseFloat(h[3]),c=`rgb(${S}, ${E}, ${D})`}}const l=e.styles.opacity*a,m=new u.MeshBasicMaterial({color:c,opacity:l,transparent:l<1}),g=new u.Mesh(t,m),T=this.renderer.domElement.width,b=this.renderer.domElement.height,v=.001;this.renderOrder++,g.position.set(e.rect.x-T/2+e.rect.width/2,-e.rect.y+b/2-e.rect.height/2,e.styles.zIndex+this.renderOrder*v),this.scene.add(g);for(const h of e.children)this.buildScene(h)}}syncScene(e){this.clearScene(),this.renderOrder=0,this.buildScene(e)}render(){this.renderer.render(this.scene,this.camera)}}function f(r){if(r.tagName==="SCRIPT"||r.tagName==="STYLE")return null;const e=r.getBoundingClientRect(),t={x:e.x+window.scrollX,y:e.y+window.scrollY,width:e.width,height:e.height},n=window.getComputedStyle(r),c={backgroundColor:n.backgroundColor,opacity:parseFloat(n.opacity),zIndex:parseInt(n.zIndex,10)||0},a=[];for(const l of r.children){const m=f(l);m&&a.push(m)}return{type:"BOX",rect:t,styles:c,children:a}}class p{constructor(e,t){i(this,"target");i(this,"renderer");i(this,"observer");i(this,"isDomDirty",!1);i(this,"isRunning",!1);i(this,"mutationTimer",null);i(this,"cssTimer",null);i(this,"onTransitionFinished",e=>{this.target.contains(e.target)&&this.mutationTimer===null&&(this.cssTimer&&clearTimeout(this.cssTimer),this.cssTimer=window.setTimeout(()=>{this.isDomDirty=!0,this.cssTimer=null},50))});i(this,"onWindowResize",()=>{this.renderer.setSize(window.innerWidth,window.innerHeight),this.isDomDirty=!0});i(this,"renderLoop",()=>{this.isRunning&&(this.isDomDirty&&this.forceUpdateScene(),this.renderer.render(),requestAnimationFrame(this.renderLoop))});this.target=e,this.renderer=t,this.observer=new MutationObserver(n=>{let c=!1,a=!1;for(const l of n)l.type==="childList"?c=!0:l.type==="attributes"&&(a=!0);if(c){this.clearTimers(),console.log("Structural Changed"),this.isDomDirty=!0;return}a&&(this.mutationTimer&&clearTimeout(this.mutationTimer),this.mutationTimer=window.setTimeout(()=>{this.mutationTimer=null,this.isDomDirty=!0},200))})}start(){this.isRunning||(this.isRunning=!0,this.observer.observe(this.target,{childList:!0,subtree:!0,attributes:!0,characterData:!0}),this.target.addEventListener("transitionend",this.onTransitionFinished),this.target.addEventListener("animationend",this.onTransitionFinished),window.addEventListener("resize",this.onWindowResize),this.forceUpdateScene(),this.renderLoop())}stop(){this.isRunning=!1,this.observer.disconnect(),this.clearTimers(),this.target.removeEventListener("transitionend",this.onTransitionFinished),this.target.removeEventListener("animationend",this.onTransitionFinished),window.removeEventListener("resize",this.onWindowResize)}clearTimers(){this.mutationTimer&&(clearTimeout(this.mutationTimer),this.mutationTimer=null),this.cssTimer&&(clearTimeout(this.cssTimer),this.cssTimer=null)}forceUpdateScene(){this.isDomDirty=!1;const e=f(this.target);e&&this.renderer.syncScene(e)}}class w{constructor(e){i(this,"renderer");i(this,"syncer");i(this,"target");const t=document.querySelector(e);if(!t)throw new Error(`[Mirage] Element not found: ${e}`);this.target=t,this.renderer=new y,this.renderer.mount(document.body),this.syncer=new p(this.target,this.renderer)}start(){this.syncer.start()}stop(){this.syncer.stop(),this.renderer.dispose()}}s.Mirage=w,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SceneNode } from '../types';
|
|
2
|
+
export declare class Renderer {
|
|
3
|
+
readonly canvas: HTMLCanvasElement;
|
|
4
|
+
private readonly scene;
|
|
5
|
+
private readonly camera;
|
|
6
|
+
private readonly renderer;
|
|
7
|
+
private renderOrder;
|
|
8
|
+
constructor();
|
|
9
|
+
mount(parent: HTMLElement): void;
|
|
10
|
+
dispose(): void;
|
|
11
|
+
setSize(width: number, height: number): void;
|
|
12
|
+
private clearScene;
|
|
13
|
+
private buildScene;
|
|
14
|
+
syncScene(graphNode: SceneNode): void;
|
|
15
|
+
render(): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface NodeRect {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
}
|
|
7
|
+
export interface BoxStyles {
|
|
8
|
+
backgroundColor: string;
|
|
9
|
+
opacity: number;
|
|
10
|
+
zIndex: number;
|
|
11
|
+
}
|
|
12
|
+
export interface SceneNode {
|
|
13
|
+
type: "BOX";
|
|
14
|
+
rect: NodeRect;
|
|
15
|
+
styles: BoxStyles;
|
|
16
|
+
children: SceneNode[];
|
|
17
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mirage-engine",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"types": "./dist/index.d.ts",
|
|
6
|
+
"main": "./dist/mirage-engine.umd.js",
|
|
7
|
+
"module": "./dist/mirage-engine.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/mirage-engine.js",
|
|
12
|
+
"require": "./dist/mirage-engine.umd.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"dev": "vite",
|
|
20
|
+
"build": "tsc && vite build",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"three": "^0.150.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/three": "^0.181.0",
|
|
28
|
+
"three": "^0.150.0",
|
|
29
|
+
"typescript": "^5.0.0",
|
|
30
|
+
"vite": "^4.0.0",
|
|
31
|
+
"vite-plugin-dts": "^4.5.4"
|
|
32
|
+
},
|
|
33
|
+
"keywords": ["webgl", "dom", "mirroring", "threejs", "typescript"],
|
|
34
|
+
"author": "dltldn333@gmail.com",
|
|
35
|
+
"license": "MIT"
|
|
36
|
+
}
|