mirage-engine 0.2.13 → 0.2.14
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/mirage-engine.js +2 -4
- package/dist/mirage-engine.umd.js +2 -2
- package/dist/src/core/Mirage.d.ts +1 -4
- package/dist/src/types/config.d.ts +2 -18
- package/dist/src/types/index.d.ts +0 -2
- package/package.json +3 -2
- package/dist/src/core/Engine.d.ts +0 -10
- package/dist/src/core/Syncer.d.ts +0 -19
- package/dist/src/dom/Extractor.d.ts +0 -2
- package/dist/src/renderer/Renderer.d.ts +0 -26
- package/dist/src/types/common.d.ts +0 -19
- package/dist/src/types/flags.d.ts +0 -6
package/dist/mirage-engine.js
CHANGED
|
@@ -477,7 +477,8 @@ class P {
|
|
|
477
477
|
}
|
|
478
478
|
}
|
|
479
479
|
class Y {
|
|
480
|
-
|
|
480
|
+
// private _engine: Engine | Traveler;
|
|
481
|
+
constructor(t, e) {
|
|
481
482
|
c(this, "_engine");
|
|
482
483
|
if (!t)
|
|
483
484
|
throw new Error("[Mirage] Target element is required.");
|
|
@@ -489,9 +490,6 @@ class Y {
|
|
|
489
490
|
stop() {
|
|
490
491
|
this._engine.stop();
|
|
491
492
|
}
|
|
492
|
-
/**
|
|
493
|
-
* 엔진 종료 및 메모리 해제
|
|
494
|
-
*/
|
|
495
493
|
destroy() {
|
|
496
494
|
this._engine.dispose();
|
|
497
495
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
(function(p,f){typeof exports=="object"&&typeof module!="undefined"?f(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],f):(p=typeof globalThis!="undefined"?globalThis:p||self,f(p.MirageEngine={},p.THREE))})(this,function(p,f){"use strict";var Y=Object.defineProperty;var U=(p,f,w)=>f in p?Y(p,f,{enumerable:!0,configurable:!0,writable:!0,value:w}):p[f]=w;var c=(p,f,w)=>(U(p,typeof f!="symbol"?f+"":f,w),w);function w(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const e in r)if(e!=="default"){const i=Object.getOwnPropertyDescriptor(r,e);Object.defineProperty(t,e,i.get?i:{enumerable:!0,get:()=>r[e]})}}return t.default=r,Object.freeze(t)}const h=w(f),T=0,C=1,S=2,z=4,E=8,B=16;function F(r,t,e){const i=t.split(`
|
|
2
|
-
`),s=[];return i.forEach(n=>{const
|
|
2
|
+
`),s=[];return i.forEach(n=>{const o=n.split(" ");let a=o[0];for(let l=1;l<o.length;l++){const d=o[l];r.measureText(a+" "+d).width<e?a+=" "+d:(s.push(a),a=d)}s.push(a)}),s}function O(r,t,e,i,s=2){const n=document.createElement("canvas"),o=n.getContext("2d");if(!o)throw new Error("[Mirage] Failed to create canvas context");const l=(window.devicePixelRatio||1)*s;n.width=e*l,n.height=i*l,o.scale(l,l),o.font=t.font,o.fillStyle=t.color,o.textBaseline="top",o.globalAlpha=1;const d=F(o,r,e),m=t.lineHeight;d.forEach((g,y)=>{const x=y*m+2;let v=0;t.textAlign==="center"?v=e/2:t.textAlign==="right"&&(v=e),o.textAlign=t.textAlign,o.fillText(g,v,x)});const u=new h.CanvasTexture(n);return u.colorSpace=h.SRGBColorSpace,u.minFilter=h.LinearFilter,u.magFilter=h.LinearFilter,u.needsUpdate=!0,u}function b(r){return typeof r=="number"?r:parseFloat(r)||0}const A=`
|
|
3
3
|
varying vec2 vUv;
|
|
4
4
|
void main() {
|
|
5
5
|
vUv = uv;
|
|
@@ -52,4 +52,4 @@
|
|
|
52
52
|
|
|
53
53
|
gl_FragColor = vec4(color, finalOpacity);
|
|
54
54
|
}
|
|
55
|
-
`;function R(r){if(!r||r==="transparent")return{color:new h.Color(16777215),alpha:0};const t=r.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);if(t){const e=parseInt(t[1],10),i=parseInt(t[2],10),s=parseInt(t[3],10),n=t[4]!==void 0?parseFloat(t[4]):1;return{color:new h.Color(`rgb(${e}, ${i}, ${s})`),alpha:n}}return{color:new h.Color(r),alpha:1}}function L(r,t,e){var o;const i=R(r.backgroundColor),s=R(r.borderColor),n={uSize:{value:new h.Vector2(t,e)},uRadius:{value:b(r.borderRadius)},uBorderWidth:{value:b(r.borderWidth)},uColor:{value:i.color},uBorderColor:{value:s.color},uOpacity:{value:(o=r.opacity)!=null?o:1},uBgOpacity:{value:i.alpha}};return new h.ShaderMaterial({uniforms:n,vertexShader:A,fragmentShader:I,transparent:!0,side:h.FrontSide})}function X(r,t,e,i){var a;const s=R(t.backgroundColor),n=R(t.borderColor);r.uniforms.uSize.value.set(e,i),r.uniforms.uRadius.value=b(t.borderRadius),r.uniforms.uBorderWidth.value=b(t.borderWidth),r.uniforms.uColor.value.copy(s.color),r.uniforms.uBorderColor.value.copy(n.color),r.uniforms.uOpacity.value=(a=t.opacity)!=null?a:1,r.uniforms.uBgOpacity.value=s.alpha}const M={create(r,t,e,i,s,n=2){if(r==="BOX")return L(t,i,s);if(r==="TEXT"){const a=O(e||"",t,i,s,n);return new h.MeshBasicMaterial({map:a,transparent:!0,side:h.FrontSide,color:16777215})}return new h.MeshBasicMaterial({visible:!1})},update(r,t,e,i,s,n,a=2){if(t==="BOX")X(r,e,s,n);else if(t==="TEXT"){const o=r;o.map&&o.map.dispose();const l=O(i||"",e,s,n,a);o.map=l,o.needsUpdate=!0}}};class N{constructor(t,e,i){c(this,"canvas");c(this,"scene");c(this,"camera");c(this,"renderer");c(this,"renderOrder",0);c(this,"textQualityFactor",2);c(this,"mode","overlay");c(this,"customZIndex","9999");c(this,"target");c(this,"mountContainer");c(this,"targetRect");c(this,"meshMap",new Map);var a,o,l;this.target=t,this.mountContainer=i,this.mode=(a=e.mode)!=null?a:"overlay",(o=e.style)!=null&&o.zIndex&&(this.customZIndex=e.style.zIndex),this.canvas=document.createElement("canvas"),this.scene=new h.Scene,this.targetRect=this.target.getBoundingClientRect();const s=this.targetRect.width,n=this.targetRect.height;this.camera=new h.OrthographicCamera(s/-2,s/2,n/2,n/-2,1,1e3),this.camera.position.z=100,this.renderer=new h.WebGLRenderer({canvas:this.canvas,alpha:!0,antialias:!0}),this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setSize(s,n),this.applyTextQuality((l=e.textQuality)!=null?l:"medium")}applyTextQuality(t){if(typeof t=="number"){this.textQualityFactor=Math.max(.1,t);return}switch(t){case"low":this.textQualityFactor=1;break;case"high":this.textQualityFactor=4;break;case"medium":default:this.textQualityFactor=2;break}}mount(){this.mountContainer.appendChild(this.canvas),this.canvas.style.zIndex=this.customZIndex,this.canvas.style.pointerEvents=this.mode==="overlay"?"none":"auto",this.updateCanvasLayout()}updateCanvasLayout(){this.canvas.style.width=`${this.targetRect.width}px`,this.canvas.style.height=`${this.targetRect.height}px`,this.mode==="duplicate"?(this.canvas.style.position="",this.canvas.style.top="",this.canvas.style.left="",this.canvas.style.display="block"):(this.canvas.style.position="absolute",this.canvas.style.top=`${this.target.offsetTop}px`,this.canvas.style.left=`${this.target.offsetLeft}px`,this.canvas.style.display="block")}dispose(){this.renderer.dispose(),this.canvas.remove()}setSize(t,e){this.renderer.setSize(t,e),this.camera.left=t/-2,this.camera.right=t/2,this.camera.top=e/2,this.camera.bottom=e/-2,this.camera.updateProjectionMatrix()}syncScene(t){const e=this.target.getBoundingClientRect(),i=Math.abs(e.width-this.targetRect.width)>.1||Math.abs(e.height-this.targetRect.height)>.1,s=this.mode==="overlay"&&(Math.abs(e.top-this.targetRect.top)>.1||Math.abs(e.left-this.targetRect.left)>.1);i?(this.targetRect=e,this.renderer.setSize(this.targetRect.width,this.targetRect.height),this.camera.left=this.targetRect.width/-2,this.camera.right=this.targetRect.width/2,this.camera.top=this.targetRect.height/2,this.camera.bottom=this.targetRect.height/-2,this.camera.updateProjectionMatrix(),this.updateCanvasLayout()):s?(this.targetRect=e,this.updateCanvasLayout()):this.targetRect=e,this.renderOrder=0;const n=new Set;this.reconcileNode(t,n);for(const[a,o]of this.meshMap.entries())n.has(a)||(this.scene.remove(o),o.geometry.dispose(),o.material instanceof h.Material&&o.material.dispose(),this.meshMap.delete(a))}reconcileNode(t,e){e.add(t.element);let i=this.meshMap.get(t.element);if(!i){const s=new h.PlaneGeometry(1,1),n=M.create("BOX",t.styles,"",t.rect.width,t.rect.height);i=new h.Mesh(s,n),t.type==="TEXT"&&(i.name="BG_MESH"),this.scene.add(i),this.meshMap.set(t.element,i)}if(i.userData.domRect=t.rect,this.updateMeshProperties(i,t),t.type==="BOX")for(const s of t.children)this.reconcileNode(s,e);else t.type==="TEXT"&&this.reconcileTextChild(i,t)}reconcileTextChild(t,e){var o,l;let i=t.children.find(d=>d.name==="TEXT_CHILD");const s=JSON.stringify(e.textStyles),n=(o=i==null?void 0:i.userData)==null?void 0:o.styleHash;if(!i||e.dirtyMask&B||s!==n){i&&((l=i.material.map)==null||l.dispose(),i.geometry.dispose(),t.remove(i));const d=M.create("TEXT",e.textStyles,e.textContent||"",e.rect.width,e.rect.height,this.textQualityFactor),m=new h.PlaneGeometry(1,1);i=new h.Mesh(m,d),i.name="TEXT_CHILD",i.userData={styleHash:s},i.position.z=.005,t.add(i)}if(i){const d=t.userData.domRect,m=d.x+d.width/2,u=d.y+d.height/2,g=e.rect.x+e.rect.width/2,y=e.rect.y+e.rect.height/2,x=g-m,v=-(y-u);i.position.set(x,v,.005)}}updateMeshProperties(t,e){const{rect:i,styles:s}=e,n=this.renderer.getPixelRatio(),a=this.renderer.domElement.width/n,o=this.renderer.domElement.height/n;t.scale.set(i.width,i.height,1);const l=.001;this.renderOrder++;const d=this.targetRect.left+window.scrollX,m=this.targetRect.top+window.scrollY,u=i.x-d,g=i.y-m;t.position.set(u-a/2+i.width/2,-g+o/2-i.height/2,s.zIndex+this.renderOrder*l),M.update(t.material,"BOX",e.styles,"",e.rect.width,e.rect.height)}render(){this.renderer.render(this.scene,this.camera)}}function _(r){const t=document.createRange();t.selectNodeContents(r);const e=t.getBoundingClientRect();return{left:e.left,top:e.top,width:e.width,height:e.height}}function k(r){const t=parseFloat(r.fontSize);let e=parseFloat(r.lineHeight);isNaN(e)&&(e=t*1.2);let i=parseFloat(r.letterSpacing);return isNaN(i)&&(i=0),{font:`${r.fontStyle} ${r.fontWeight} ${r.fontSize} ${r.fontFamily}`,color:r.color,textAlign:r.textAlign||"start",textBaseline:"alphabetic",direction:r.direction||"inherit",lineHeight:e,letterSpacing:i}}function D(r,t=C|S|z|B|E){if(r.nodeType===Node.TEXT_NODE){const u=r;if(!u.textContent||!u.textContent.trim())return null;const g=u.textContent.replace(/\s+/g," ").trim();if(g.length===0)return null;const y=_(u);if(y.width===0||y.height===0)return null;const x=u.parentElement,v=x?window.getComputedStyle(x):null;return v?{id:Math.random().toString(36).substring(2,9),type:"TEXT",element:u,rect:{x:y.left+window.scrollX,y:y.top+window.scrollY,width:y.width,height:y.height},styles:{backgroundColor:"transparent",opacity:parseFloat(v.opacity),zIndex:0,borderRadius:"0px",borderColor:"transparent",borderWidth:"0px"},textContent:g,textStyles:k(v),dirtyMask:t,children:[]}:null}const e=r,i=e.getBoundingClientRect(),s=window.getComputedStyle(e);if(i.width===0||i.height===0||s.display==="none")return null;let n=e.getAttribute("data-mid");n||(n=Math.random().toString(36).substring(2,11),e.setAttribute("data-mid",n));const a=parseInt(s.zIndex),o={backgroundColor:s.backgroundColor,opacity:parseFloat(s.opacity),zIndex:isNaN(a)?0:a,borderRadius:s.borderRadius,borderColor:s.borderColor,borderWidth:s.borderWidth};let l,d;const m=[];return Array.from(e.childNodes).forEach(u=>{const g=D(u,t);g&&m.push(g)}),{id:n,type:"BOX",element:e,rect:{x:i.left+window.scrollX,y:i.top+window.scrollY,width:i.width,height:i.height},styles:o,textContent:l,textStyles:d,dirtyMask:t,children:m}}class P{constructor(t,e){c(this,"target");c(this,"renderer");c(this,"observer");c(this,"isDomDirty",!1);c(this,"isRunning",!1);c(this,"pendingMask",T);c(this,"mutationTimer",null);c(this,"cssTimer",null);c(this,"onTransitionFinished",t=>{this.target.contains(t.target)&&this.mutationTimer===null&&(this.cssTimer&&clearTimeout(this.cssTimer),this.pendingMask|=C|S,this.cssTimer=window.setTimeout(()=>{this.isDomDirty=!0,this.cssTimer=null},50))});c(this,"onWindowResize",()=>{this.renderer.setSize(window.innerWidth,window.innerHeight),this.isDomDirty=!0});c(this,"renderLoop",()=>{this.isRunning&&(this.isDomDirty&&this.forceUpdateScene(),this.renderer.render(),requestAnimationFrame(this.renderLoop))});this.target=t,this.renderer=e,this.observer=new MutationObserver(i=>{let s=T;for(const n of i)n.type==="childList"?s|=E:n.type==="attributes"&&(n.attributeName==="style"||n.attributeName==="class")&&(s|=C|S);if(s!==T){if(this.pendingMask|=s,s&E){this.clearTimers(),console.log("Structural Change detected"),this.isDomDirty=!0;return}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 t=D(this.target,this.pendingMask);t&&this.renderer.syncScene(t),this.pendingMask=T}}class H{constructor(t,e){c(this,"renderer");c(this,"syncer");c(this,"target");var s,n,a;this.target=t;let i;if(e.mode==="duplicate"?i=(n=(s=e.container)!=null?s:this.target.parentElement)!=null?n:void 0:i=(a=this.target.parentElement)!=null?a:void 0,!i)throw new Error("[Mirage] Cannot find a container (parent or option).");this.renderer=new N(this.target,e,i),this.renderer.mount(),this.syncer=new P(this.target,this.renderer)}start(){this.syncer.start()}stop(){this.syncer.stop()}dispose(){this.syncer.stop(),this.renderer.dispose()}}class W{constructor(t,e={}){c(this,"_engine");if(!t)throw new Error("[Mirage] Target element is required.");this._engine=new H(t,e)}start(){this._engine.start()}stop(){this._engine.stop()}destroy(){this._engine.dispose()}}p.Mirage=W,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})});
|
|
55
|
+
`;function R(r){if(!r||r==="transparent")return{color:new h.Color(16777215),alpha:0};const t=r.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);if(t){const e=parseInt(t[1],10),i=parseInt(t[2],10),s=parseInt(t[3],10),n=t[4]!==void 0?parseFloat(t[4]):1;return{color:new h.Color(`rgb(${e}, ${i}, ${s})`),alpha:n}}return{color:new h.Color(r),alpha:1}}function L(r,t,e){var a;const i=R(r.backgroundColor),s=R(r.borderColor),n={uSize:{value:new h.Vector2(t,e)},uRadius:{value:b(r.borderRadius)},uBorderWidth:{value:b(r.borderWidth)},uColor:{value:i.color},uBorderColor:{value:s.color},uOpacity:{value:(a=r.opacity)!=null?a:1},uBgOpacity:{value:i.alpha}};return new h.ShaderMaterial({uniforms:n,vertexShader:A,fragmentShader:I,transparent:!0,side:h.FrontSide})}function X(r,t,e,i){var o;const s=R(t.backgroundColor),n=R(t.borderColor);r.uniforms.uSize.value.set(e,i),r.uniforms.uRadius.value=b(t.borderRadius),r.uniforms.uBorderWidth.value=b(t.borderWidth),r.uniforms.uColor.value.copy(s.color),r.uniforms.uBorderColor.value.copy(n.color),r.uniforms.uOpacity.value=(o=t.opacity)!=null?o:1,r.uniforms.uBgOpacity.value=s.alpha}const M={create(r,t,e,i,s,n=2){if(r==="BOX")return L(t,i,s);if(r==="TEXT"){const o=O(e||"",t,i,s,n);return new h.MeshBasicMaterial({map:o,transparent:!0,side:h.FrontSide,color:16777215})}return new h.MeshBasicMaterial({visible:!1})},update(r,t,e,i,s,n,o=2){if(t==="BOX")X(r,e,s,n);else if(t==="TEXT"){const a=r;a.map&&a.map.dispose();const l=O(i||"",e,s,n,o);a.map=l,a.needsUpdate=!0}}};class N{constructor(t,e,i){c(this,"canvas");c(this,"scene");c(this,"camera");c(this,"renderer");c(this,"renderOrder",0);c(this,"textQualityFactor",2);c(this,"mode","overlay");c(this,"customZIndex","9999");c(this,"target");c(this,"mountContainer");c(this,"targetRect");c(this,"meshMap",new Map);var o,a,l;this.target=t,this.mountContainer=i,this.mode=(o=e.mode)!=null?o:"overlay",(a=e.style)!=null&&a.zIndex&&(this.customZIndex=e.style.zIndex),this.canvas=document.createElement("canvas"),this.scene=new h.Scene,this.targetRect=this.target.getBoundingClientRect();const s=this.targetRect.width,n=this.targetRect.height;this.camera=new h.OrthographicCamera(s/-2,s/2,n/2,n/-2,1,1e3),this.camera.position.z=100,this.renderer=new h.WebGLRenderer({canvas:this.canvas,alpha:!0,antialias:!0}),this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setSize(s,n),this.applyTextQuality((l=e.textQuality)!=null?l:"medium")}applyTextQuality(t){if(typeof t=="number"){this.textQualityFactor=Math.max(.1,t);return}switch(t){case"low":this.textQualityFactor=1;break;case"high":this.textQualityFactor=4;break;case"medium":default:this.textQualityFactor=2;break}}mount(){this.mountContainer.appendChild(this.canvas),this.canvas.style.zIndex=this.customZIndex,this.canvas.style.pointerEvents=this.mode==="overlay"?"none":"auto",this.updateCanvasLayout()}updateCanvasLayout(){this.canvas.style.width=`${this.targetRect.width}px`,this.canvas.style.height=`${this.targetRect.height}px`,this.mode==="duplicate"?(this.canvas.style.position="",this.canvas.style.top="",this.canvas.style.left="",this.canvas.style.display="block"):(this.canvas.style.position="absolute",this.canvas.style.top=`${this.target.offsetTop}px`,this.canvas.style.left=`${this.target.offsetLeft}px`,this.canvas.style.display="block")}dispose(){this.renderer.dispose(),this.canvas.remove()}setSize(t,e){this.renderer.setSize(t,e),this.camera.left=t/-2,this.camera.right=t/2,this.camera.top=e/2,this.camera.bottom=e/-2,this.camera.updateProjectionMatrix()}syncScene(t){const e=this.target.getBoundingClientRect(),i=Math.abs(e.width-this.targetRect.width)>.1||Math.abs(e.height-this.targetRect.height)>.1,s=this.mode==="overlay"&&(Math.abs(e.top-this.targetRect.top)>.1||Math.abs(e.left-this.targetRect.left)>.1);i?(this.targetRect=e,this.renderer.setSize(this.targetRect.width,this.targetRect.height),this.camera.left=this.targetRect.width/-2,this.camera.right=this.targetRect.width/2,this.camera.top=this.targetRect.height/2,this.camera.bottom=this.targetRect.height/-2,this.camera.updateProjectionMatrix(),this.updateCanvasLayout()):s?(this.targetRect=e,this.updateCanvasLayout()):this.targetRect=e,this.renderOrder=0;const n=new Set;this.reconcileNode(t,n);for(const[o,a]of this.meshMap.entries())n.has(o)||(this.scene.remove(a),a.geometry.dispose(),a.material instanceof h.Material&&a.material.dispose(),this.meshMap.delete(o))}reconcileNode(t,e){e.add(t.element);let i=this.meshMap.get(t.element);if(!i){const s=new h.PlaneGeometry(1,1),n=M.create("BOX",t.styles,"",t.rect.width,t.rect.height);i=new h.Mesh(s,n),t.type==="TEXT"&&(i.name="BG_MESH"),this.scene.add(i),this.meshMap.set(t.element,i)}if(i.userData.domRect=t.rect,this.updateMeshProperties(i,t),t.type==="BOX")for(const s of t.children)this.reconcileNode(s,e);else t.type==="TEXT"&&this.reconcileTextChild(i,t)}reconcileTextChild(t,e){var a,l;let i=t.children.find(d=>d.name==="TEXT_CHILD");const s=JSON.stringify(e.textStyles),n=(a=i==null?void 0:i.userData)==null?void 0:a.styleHash;if(!i||e.dirtyMask&B||s!==n){i&&((l=i.material.map)==null||l.dispose(),i.geometry.dispose(),t.remove(i));const d=M.create("TEXT",e.textStyles,e.textContent||"",e.rect.width,e.rect.height,this.textQualityFactor),m=new h.PlaneGeometry(1,1);i=new h.Mesh(m,d),i.name="TEXT_CHILD",i.userData={styleHash:s},i.position.z=.005,t.add(i)}if(i){const d=t.userData.domRect,m=d.x+d.width/2,u=d.y+d.height/2,g=e.rect.x+e.rect.width/2,y=e.rect.y+e.rect.height/2,x=g-m,v=-(y-u);i.position.set(x,v,.005)}}updateMeshProperties(t,e){const{rect:i,styles:s}=e,n=this.renderer.getPixelRatio(),o=this.renderer.domElement.width/n,a=this.renderer.domElement.height/n;t.scale.set(i.width,i.height,1);const l=.001;this.renderOrder++;const d=this.targetRect.left+window.scrollX,m=this.targetRect.top+window.scrollY,u=i.x-d,g=i.y-m;t.position.set(u-o/2+i.width/2,-g+a/2-i.height/2,s.zIndex+this.renderOrder*l),M.update(t.material,"BOX",e.styles,"",e.rect.width,e.rect.height)}render(){this.renderer.render(this.scene,this.camera)}}function _(r){const t=document.createRange();t.selectNodeContents(r);const e=t.getBoundingClientRect();return{left:e.left,top:e.top,width:e.width,height:e.height}}function k(r){const t=parseFloat(r.fontSize);let e=parseFloat(r.lineHeight);isNaN(e)&&(e=t*1.2);let i=parseFloat(r.letterSpacing);return isNaN(i)&&(i=0),{font:`${r.fontStyle} ${r.fontWeight} ${r.fontSize} ${r.fontFamily}`,color:r.color,textAlign:r.textAlign||"start",textBaseline:"alphabetic",direction:r.direction||"inherit",lineHeight:e,letterSpacing:i}}function D(r,t=C|S|z|B|E){if(r.nodeType===Node.TEXT_NODE){const u=r;if(!u.textContent||!u.textContent.trim())return null;const g=u.textContent.replace(/\s+/g," ").trim();if(g.length===0)return null;const y=_(u);if(y.width===0||y.height===0)return null;const x=u.parentElement,v=x?window.getComputedStyle(x):null;return v?{id:Math.random().toString(36).substring(2,9),type:"TEXT",element:u,rect:{x:y.left+window.scrollX,y:y.top+window.scrollY,width:y.width,height:y.height},styles:{backgroundColor:"transparent",opacity:parseFloat(v.opacity),zIndex:0,borderRadius:"0px",borderColor:"transparent",borderWidth:"0px"},textContent:g,textStyles:k(v),dirtyMask:t,children:[]}:null}const e=r,i=e.getBoundingClientRect(),s=window.getComputedStyle(e);if(i.width===0||i.height===0||s.display==="none")return null;let n=e.getAttribute("data-mid");n||(n=Math.random().toString(36).substring(2,11),e.setAttribute("data-mid",n));const o=parseInt(s.zIndex),a={backgroundColor:s.backgroundColor,opacity:parseFloat(s.opacity),zIndex:isNaN(o)?0:o,borderRadius:s.borderRadius,borderColor:s.borderColor,borderWidth:s.borderWidth};let l,d;const m=[];return Array.from(e.childNodes).forEach(u=>{const g=D(u,t);g&&m.push(g)}),{id:n,type:"BOX",element:e,rect:{x:i.left+window.scrollX,y:i.top+window.scrollY,width:i.width,height:i.height},styles:a,textContent:l,textStyles:d,dirtyMask:t,children:m}}class P{constructor(t,e){c(this,"target");c(this,"renderer");c(this,"observer");c(this,"isDomDirty",!1);c(this,"isRunning",!1);c(this,"pendingMask",T);c(this,"mutationTimer",null);c(this,"cssTimer",null);c(this,"onTransitionFinished",t=>{this.target.contains(t.target)&&this.mutationTimer===null&&(this.cssTimer&&clearTimeout(this.cssTimer),this.pendingMask|=C|S,this.cssTimer=window.setTimeout(()=>{this.isDomDirty=!0,this.cssTimer=null},50))});c(this,"onWindowResize",()=>{this.renderer.setSize(window.innerWidth,window.innerHeight),this.isDomDirty=!0});c(this,"renderLoop",()=>{this.isRunning&&(this.isDomDirty&&this.forceUpdateScene(),this.renderer.render(),requestAnimationFrame(this.renderLoop))});this.target=t,this.renderer=e,this.observer=new MutationObserver(i=>{let s=T;for(const n of i)n.type==="childList"?s|=E:n.type==="attributes"&&(n.attributeName==="style"||n.attributeName==="class")&&(s|=C|S);if(s!==T){if(this.pendingMask|=s,s&E){this.clearTimers(),console.log("Structural Change detected"),this.isDomDirty=!0;return}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 t=D(this.target,this.pendingMask);t&&this.renderer.syncScene(t),this.pendingMask=T}}class H{constructor(t,e){c(this,"renderer");c(this,"syncer");c(this,"target");var s,n,o;this.target=t;let i;if(e.mode==="duplicate"?i=(n=(s=e.container)!=null?s:this.target.parentElement)!=null?n:void 0:i=(o=this.target.parentElement)!=null?o:void 0,!i)throw new Error("[Mirage] Cannot find a container (parent or option).");this.renderer=new N(this.target,e,i),this.renderer.mount(),this.syncer=new P(this.target,this.renderer)}start(){this.syncer.start()}stop(){this.syncer.stop()}dispose(){this.syncer.stop(),this.renderer.dispose()}}class W{constructor(t,e){c(this,"_engine");if(!t)throw new Error("[Mirage] Target element is required.");this._engine=new H(t,e)}start(){this._engine.start()}stop(){this._engine.stop()}destroy(){this._engine.dispose()}}p.Mirage=W,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { MirageConfig } from '../types';
|
|
2
2
|
export declare class Mirage {
|
|
3
3
|
private _engine;
|
|
4
|
-
constructor(
|
|
4
|
+
constructor(target: HTMLElement, config: MirageConfig);
|
|
5
5
|
start(): void;
|
|
6
6
|
stop(): void;
|
|
7
|
-
/**
|
|
8
|
-
* 엔진 종료 및 메모리 해제
|
|
9
|
-
*/
|
|
10
7
|
destroy(): void;
|
|
11
8
|
}
|
|
@@ -1,18 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export type
|
|
3
|
-
interface BaseConfig {
|
|
4
|
-
debug?: boolean;
|
|
5
|
-
textQuality?: TextQuality;
|
|
6
|
-
style?: {
|
|
7
|
-
zIndex?: string;
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
export interface OverlayConfig extends BaseConfig {
|
|
11
|
-
mode?: "overlay";
|
|
12
|
-
}
|
|
13
|
-
export interface DuplicateConfig extends BaseConfig {
|
|
14
|
-
mode: "duplicate";
|
|
15
|
-
container?: HTMLElement;
|
|
16
|
-
}
|
|
17
|
-
export type MirageConfig = OverlayConfig | DuplicateConfig;
|
|
18
|
-
export {};
|
|
1
|
+
import { CoreConfig } from '../../packages/core/src/index.ts';
|
|
2
|
+
export type MirageConfig = CoreConfig;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mirage-engine",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.14",
|
|
4
4
|
"description": "An engine that mirrors HTML DOM elements to a WebGL scene in real-time.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@mirage-engine/painter": "0.2.
|
|
24
|
+
"@mirage-engine/painter": "0.2.3",
|
|
25
|
+
"@mirage-engine/core": "0.0.2"
|
|
25
26
|
},
|
|
26
27
|
"peerDependencies": {
|
|
27
28
|
"three": "^0.150.0"
|
|
@@ -1,19 +0,0 @@
|
|
|
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 pendingMask;
|
|
9
|
-
private mutationTimer;
|
|
10
|
-
private cssTimer;
|
|
11
|
-
constructor(target: HTMLElement, renderer: Renderer);
|
|
12
|
-
start(): void;
|
|
13
|
-
stop(): void;
|
|
14
|
-
private clearTimers;
|
|
15
|
-
private onTransitionFinished;
|
|
16
|
-
private onWindowResize;
|
|
17
|
-
private forceUpdateScene;
|
|
18
|
-
private renderLoop;
|
|
19
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { SceneNode, MirageConfig } 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
|
-
private textQualityFactor;
|
|
9
|
-
private mode;
|
|
10
|
-
private customZIndex;
|
|
11
|
-
private target;
|
|
12
|
-
private mountContainer;
|
|
13
|
-
private targetRect;
|
|
14
|
-
private meshMap;
|
|
15
|
-
constructor(target: HTMLElement, config: MirageConfig, mountContainer: HTMLElement);
|
|
16
|
-
private applyTextQuality;
|
|
17
|
-
mount(): void;
|
|
18
|
-
private updateCanvasLayout;
|
|
19
|
-
dispose(): void;
|
|
20
|
-
setSize(width: number, height: number): void;
|
|
21
|
-
syncScene(graphNode: SceneNode): void;
|
|
22
|
-
private reconcileNode;
|
|
23
|
-
private reconcileTextChild;
|
|
24
|
-
private updateMeshProperties;
|
|
25
|
-
render(): void;
|
|
26
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { TextStyles, BoxStyles } from '../../packages/painter/src/index.ts';
|
|
2
|
-
export type NodeType = "BOX" | "TEXT";
|
|
3
|
-
export interface NodeRect {
|
|
4
|
-
x: number;
|
|
5
|
-
y: number;
|
|
6
|
-
width: number;
|
|
7
|
-
height: number;
|
|
8
|
-
}
|
|
9
|
-
export interface SceneNode {
|
|
10
|
-
id: string;
|
|
11
|
-
type: NodeType;
|
|
12
|
-
element: HTMLElement;
|
|
13
|
-
rect: NodeRect;
|
|
14
|
-
styles: BoxStyles;
|
|
15
|
-
textContent?: string;
|
|
16
|
-
textStyles?: TextStyles;
|
|
17
|
-
dirtyMask: number;
|
|
18
|
-
children: SceneNode[];
|
|
19
|
-
}
|