hengine
Version:
A simple graphic engine for `canvasom`.
119 lines (114 loc) • 5.92 kB
JavaScript
import { CanvasNode, CanvasRoot, Schedule, Event } from 'canvasom';
var t;!function(t){t.fill=t=>{const{paddingLeft:i,paddingTop:e}=t;return {width:t.containerWidth-i-t.paddingRight,height:t.containerHeight-e-t.paddingBottom,left:i,top:e,scale:1}},t.fixedWidth=t=>{const{targetWidth:i,paddingLeft:e,paddingTop:n}=t,d=t.containerWidth-e-t.paddingRight;return {width:d,height:t.containerHeight-n-t.paddingBottom,left:e,top:n,scale:d/i}},t.fixedHeight=t=>{const{targetHeight:i,paddingLeft:e,paddingTop:n}=t,d=t.containerWidth-e-t.paddingRight,a=t.containerHeight-n-t.paddingBottom;return {width:d,height:a,left:e,top:n,scale:a/i}},t.semifixed=i=>{const{targetWidth:e,targetHeight:n,paddingLeft:d,paddingTop:a}=i;return (i.containerWidth-d-i.paddingRight)/(i.containerHeight-a-i.paddingBottom)<e/n?t.fixedWidth(i):t.fixedHeight(i)},t.contain=t=>{const{targetWidth:i,targetHeight:e,paddingLeft:n,paddingTop:d}=t,a=t.containerWidth-n-t.paddingRight,h=t.containerHeight-d-t.paddingBottom;if(a/h<i/e){const t=a/i,g=e*t;return {width:a,height:g,left:n,top:(h-g)/2+d,scale:t}}{const t=h/e,g=i*t;return {width:g,height:h,left:(a-g)/2+n,top:d,scale:t}}},t.center=t=>{const{targetWidth:i,targetHeight:e,paddingLeft:n,paddingTop:d}=t;return {width:i,height:e,left:(t.containerWidth-n-t.paddingRight-i)/2+n,top:(t.containerHeight-d-t.paddingBottom-e)/2+d,scale:1}};}(t||(t={}));class Resizer{constructor(i){const e=i?.target||null;this.target=e,this.container=i?.container??(e&&e.parentElement);const n=i?.padding??0;this.paddingTop=i?.paddingTop??n,this.paddingRight=i?.paddingRight??n,this.paddingBottom=i?.paddingBottom??n,this.paddingLeft=i?.paddingLeft??n,this.active=i?.active??!0,this.width=i?.width??0,this.height=i?.height??0,this.sizing=i?.sizing??t.center,this.callback=i?.callback||null,this.updateSync=this.updateSync.bind(this),this.onResize=this.onResize.bind(this),this.update=((t,i)=>{let e=null;const debounceWrapper=(...t)=>{null!==e&&clearTimeout(e),e=setTimeout(i,debounceWrapper.debounceTimeout,...t);};return debounceWrapper.debounceTimeout=t,debounceWrapper})(100,this.updateSync),!1!==i?.autoResize&&(window.addEventListener("resize",this.onResize),window.addEventListener("orientationchange",this.onResize)),this.active&&this.update();}active;target;container;width;height;sizing;paddingTop;paddingRight;paddingBottom;paddingLeft;callback;updateSync(t){const{target:i,container:e}=this;if(!this.active||!i||!e)return;const{style:n}=i,d=e.getBoundingClientRect(),a=this.sizing({containerWidth:d.width,containerHeight:d.height,paddingTop:this.paddingTop,paddingRight:this.paddingRight,paddingBottom:this.paddingBottom,paddingLeft:this.paddingLeft,targetWidth:this.width,targetHeight:this.height});n.width=a.width+"px",n.height=a.height+"px",n.marginLeft=a.left+"px",n.marginTop=a.top+"px",this.callback?.(a),t?.(a);}update;onResize(){this.update();}}
/** dts2md break */
/**
* Class of scene nodes.
*/
class SceneNode extends CanvasNode {
/** dts2md break */
/**
* Constructor of {@link SceneNode}.
*/
constructor(options) {
super({
stretch: 1,
penetrable: true,
...options,
});
}
}
/** dts2md break */
/**
* Class of canvas engines.
*/
class CanvasEngine extends CanvasRoot {
/** dts2md break */
/**
* Constructor of {@link CanvasEngine}.
*/
constructor(options) {
super(options);
this.onResize = this.onResize.bind(this);
const resizerOptions = {
width: this.renderer.width,
height: this.renderer.height,
target: this.renderer.canvas,
sizing: t.contain,
callback: this.onResize,
};
if (options?.resizerOptions) {
Object.assign(resizerOptions, options.resizerOptions);
}
this.resizer = new Resizer(resizerOptions);
this.renderer.autoStyle = false;
}
/** dts2md break */
/**
* The resizer in use.
*/
resizer;
/** dts2md break */
/**
* Current scene.
*/
currentScene = null;
/** dts2md break */
/**
* Resize callback.
* (Remember to invoke this in your implemention
* of `resizer.callback` if you have one.)
*/
onResize(result) {
const { scale } = result;
this.renderer.resize(result.width / scale, result.height / scale);
Schedule.updateAndRender(this);
}
/** dts2md break */
/**
* Enter specific scene.
* (Pass `null` to exit current scene
* without entering another scene.)
* @returns Whether the scene change is successful.
*/
enter(nextScene) {
const { currentScene } = this;
if (currentScene) {
const exitEvent = new Event({
name: 'exit',
stoppable: true,
cancelable: true,
data: {
nextScene,
},
});
currentScene.emit(exitEvent);
if (exitEvent.canceled) {
return false;
}
}
if (nextScene) {
const enterEvent = new Event({
name: 'enter',
stoppable: true,
cancelable: true,
data: {
currentScene,
},
});
nextScene.emit(enterEvent);
if (enterEvent.canceled) {
return false;
}
this.appendChild(nextScene);
}
if (currentScene) {
this.removeChild(currentScene);
}
this.currentScene = nextScene;
if (currentScene || nextScene) {
Schedule.updateAndRender(this);
}
return true;
}
}
export { CanvasEngine, Resizer, SceneNode, t as Sizing };