mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
Docs and minor fixes.
This commit is contained in:
parent
0fa960251a
commit
38f5231cd2
@ -1431,7 +1431,7 @@ skins.forEach((skin, i) => {
|
||||
By default, the callback does two things:
|
||||
<ul>
|
||||
<li>set <code>onScreenAtLeastOnce</code> to <code>true</code> when the widget enters the viewport the first time</li>
|
||||
<li>if <code>manual-start</code> and <code>on-viewport-manual-start</code> are set the widget <code>start</code> is invoked
|
||||
<li>if <code>manual-start</code> and <code>on-screen-manual-start</code> are set the widget <code>start</code> is invoked
|
||||
the first time the widget enters the viewport and the assets are loaded only in that moment.</li>
|
||||
</ul>
|
||||
<br>
|
||||
@ -1449,7 +1449,7 @@ skins.forEach((skin, i) => {
|
||||
skeleton="assets/coin-pro.skel"
|
||||
animation="animation"
|
||||
manual-start
|
||||
on-viewport-manual-start
|
||||
on-screen-manual-start
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="skin-grid-element">
|
||||
@ -1981,7 +1981,7 @@ stretchyman.update = (canvas, delta, skeleton, state) => {
|
||||
2) For scrollable containers, the widget will overflow the container bounds until the widget html element container is visible <br>
|
||||
3) For fixed containers, the widget will scroll in a jerky way <br>
|
||||
<br>
|
||||
In order to fix this behaviour, it is necessary to insert a dedicated <code>spine-overlay</code> webcomponent as a direct child of the container.
|
||||
In order to fix this behaviour, it is necessary to insert a dedicated <code>spine-overlay</code> webcomponent as a direct child of the container.
|
||||
Moreover, it is necessary to perform the following actions: <br>
|
||||
<br>
|
||||
1) The scrollable container must have a <code>transform</code> css attribute. If it hasn't this attribute the <code>spine-overlay</code> will add it for you.
|
||||
|
||||
@ -1,367 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="../dist/iife/spine-webgl.js"></script>
|
||||
<title>Webcomponent Tutorial</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
.section {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
background-color: #3498db;
|
||||
}
|
||||
.split {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
.split-left, .split-right {
|
||||
width: 50%;
|
||||
min-height: 50%;
|
||||
padding: 1rem;
|
||||
margin: 1rem;
|
||||
border: 1px solid salmon;
|
||||
}
|
||||
.split-nosize {
|
||||
border: 1px solid salmon;
|
||||
}
|
||||
.split-size {
|
||||
padding: 1rem;
|
||||
margin: 1rem;
|
||||
}
|
||||
.navigation {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
left: 20px;
|
||||
bottom: 20px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.nav-btn {
|
||||
display: block;
|
||||
margin: 0px 5px;
|
||||
padding: 10px;
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vertical-split {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.high-page {
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.split-top {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.split-bottom {
|
||||
width: 100%;
|
||||
/* height: 600px; */
|
||||
}
|
||||
|
||||
.split-bottom {
|
||||
background-color: #1e1e1e;
|
||||
color: #d4d4d4;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.split-bottom pre {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.split-bottom code {
|
||||
font-family: 'Consolas', 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
display: block;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.skin-grid {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
justify-content: space-evenly;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.skin-grid-element {
|
||||
border: 1px solid #ccc;
|
||||
width: 150px;
|
||||
aspect-ratio: 3 / 3;
|
||||
}
|
||||
|
||||
.overflow-grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 100px);
|
||||
grid-template-rows: repeat(4, 100px);
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.overflow-grid-item {
|
||||
background-color: lightblue;;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section //
|
||||
/////////////////////
|
||||
-->
|
||||
<!-- <div class="section vertical-split" id="section-popup">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-right" style="background-color: red;" id="inserting">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(async() => {
|
||||
const div = document.getElementById("inserting");
|
||||
const widget = spine.createSpineWidget({
|
||||
atlasPath: "assets/chibi-stickers-pma.atlas",
|
||||
skeletonPath: "assets/chibi-stickers.json",
|
||||
animation: "emotes/wave",
|
||||
skin: "soeren",
|
||||
manualStart: false,
|
||||
});
|
||||
|
||||
await widget.appendTo(div);
|
||||
|
||||
// widget.start();
|
||||
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
</div> -->
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section //
|
||||
/////////////////////
|
||||
-->
|
||||
<div class="section vertical-split" id="section-popup">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-right" style="background-color: red;">
|
||||
<spine-widget
|
||||
atlas="assets/raptor-pma.atlas"
|
||||
skeleton="assets/raptor-pro.skel"
|
||||
animation="walk"
|
||||
fit="fill"
|
||||
></spine-widget>
|
||||
</div>
|
||||
|
||||
<div class="split-right" style="background-color: red;">
|
||||
<spine-widget
|
||||
atlas="assets/raptor-pma.atlas"
|
||||
skeleton="assets/raptor-pro.skel"
|
||||
animation="walk"
|
||||
fit="fill"
|
||||
overlay-id="pippo"
|
||||
manual-start
|
||||
identifier="aaa"
|
||||
></spine-widget>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<spine-overlay overlay-id="pippo"></spine-overlay>
|
||||
|
||||
<script>
|
||||
(async () => {
|
||||
const w = spine.getSpineWidget("aaa");
|
||||
|
||||
await w.overlayAssignedPromise;
|
||||
w.start();
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
|
||||
<div class="section vertical-split" id="section-owls">
|
||||
<label>
|
||||
<input type="checkbox" id="owl-checkbox" checked> Limit control bone movement
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
function createCircleOfDivs(numDivs = 8) {
|
||||
const container = document.createElement('div');
|
||||
container.style.position = 'relative';
|
||||
container.style.width = '400px';
|
||||
container.style.height = '400px';
|
||||
container.style.backgroundColor = '#f3f4f6';
|
||||
container.style.borderRadius = '50%';
|
||||
container.style.display = 'flex';
|
||||
container.style.justifyContent = 'center';
|
||||
container.style.alignItems = 'center';
|
||||
|
||||
const radius = 150;
|
||||
|
||||
for (let i = 0; i < numDivs; i++) {
|
||||
const angle = (i / numDivs) * 2 * Math.PI;
|
||||
const x = Math.cos(angle) * radius;
|
||||
const y = Math.sin(angle) * radius;
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.style.position = 'absolute';
|
||||
div.style.width = '100px';
|
||||
div.style.height = '100px';
|
||||
div.style.backgroundColor = '#3b82f6';
|
||||
div.style.borderRadius = '8px';
|
||||
div.style.display = 'flex';
|
||||
div.style.justifyContent = 'center';
|
||||
div.style.alignItems = 'center';
|
||||
div.style.color = 'white';
|
||||
div.style.fontWeight = 'bold';
|
||||
div.style.transform = `translate(${x}px, ${y}px)`;
|
||||
div.textContent = i + 1;
|
||||
div.innerHTML = `
|
||||
<spine-widget
|
||||
identifier="pippo${i + 1}"
|
||||
atlas="../demos/assets/atlas2.atlas"
|
||||
skeleton="../demos/assets/demos.json"
|
||||
json-skeleton-key="owl"
|
||||
animation="idle"
|
||||
></spine-widget>
|
||||
`;
|
||||
|
||||
container.appendChild(div);
|
||||
|
||||
customElements.whenDefined('spine-widget').then(async () => {
|
||||
const widget = spine.getSpineWidget(`pippo${i+1}`);
|
||||
await widget.loadingPromise;
|
||||
widget.state.setAnimation(1, "blink", true)
|
||||
|
||||
const control = widget.skeleton.findBone("control");
|
||||
const tempVector = new spine.Vector3();
|
||||
const mouse = Ola({ x: 0, y: 0 }, 200);
|
||||
widget.afterUpdateWorldTransforms = () => {
|
||||
updateControl(widget, control, mouse, tempVector);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
// document.getElementById('section-owls').appendChild(createCircleOfDivs(1));
|
||||
}, 1000)
|
||||
|
||||
|
||||
const checkbox = document.getElementById('owl-checkbox');
|
||||
|
||||
let limitOwl = true;
|
||||
checkbox.addEventListener('change', () => {
|
||||
limitOwl = checkbox.checked;
|
||||
});
|
||||
|
||||
const updateControl = (widget, controlBone, mouse, tempVector) => {
|
||||
controlBone.parent.worldToLocal(tempVector.set(
|
||||
widget.cursorWorldX,
|
||||
widget.cursorWorldY,
|
||||
));
|
||||
|
||||
let x = tempVector.x;
|
||||
let y = tempVector.y;
|
||||
|
||||
if (limitOwl) {
|
||||
x = x / widget.overlay.canvas.width * 30;
|
||||
y = y / widget.overlay.canvas.height * 30;
|
||||
}
|
||||
|
||||
mouse.set({ x, y });
|
||||
|
||||
controlBone.x = controlBone.data.x + mouse.x;
|
||||
controlBone.y = controlBone.data.y + mouse.y;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script>
|
||||
spine.SpineWebComponentWidget.SHOW_FPS = true;
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):(global=global||self,global.Ola=factory())})(this,function(){"use strict";const position=(x0,v0,t1,t)=>{const a=(v0*t1+2*x0)/t1**3;const b=-(2*v0*t1+3*x0)/t1**2;const c=v0;const d=x0;return a*t**3+b*t**2+c*t+d};const speed=(x0,v0,t1,t)=>{const a=(v0*t1+2*x0)/t1**3;const b=-(2*v0*t1+3*x0)/t1**2;const c=v0;return 3*a*t**2+2*b*t+c};const each=function(values,cb){const multi=typeof values==="number"?{value:values}:values;Object.entries(multi).map(([key,value])=>cb(value,key))};function Single(init,time){this.start=new Date/1e3;this.time=time;this.from=init;this.current=init;this.to=init;this.speed=0}Single.prototype.get=function(now){const t=now/1e3-this.start;if(t<0){throw new Error("Cannot read in the past")}if(t>=this.time){return this.to}return this.to-position(this.to-this.from,this.speed,this.time,t)};Single.prototype.getSpeed=function(now){const t=now/1e3-this.start;if(t>=this.time){return 0}return speed(this.to-this.from,this.speed,this.time,t)};Single.prototype.set=function(value,time){const now=new Date;const current=this.get(now);this.speed=this.getSpeed(now);this.start=now/1e3;this.from=current;this.to=value;if(time){this.time=time}return current};function Ola(values,time=300){if(typeof values==="number"){values={value:values}}each(values,(init,key)=>{const value=new Single(init,time/1e3);Object.defineProperty(values,"_"+key,{value:value});Object.defineProperty(values,"$"+key,{get:()=>value.to});Object.defineProperty(values,key,{get:()=>value.get(new Date),set:val=>value.set(val),enumerable:true})});Object.defineProperty(values,"get",{get:()=>(function(name="value",now=new Date){return this["_"+name].get(now)})});Object.defineProperty(values,"set",{get:()=>(function(values,time=0){each(values,(value,key)=>{this["_"+key].set(value,time/1e3)})})});return values}return Ola});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -126,7 +126,7 @@ interface WidgetAttributes {
|
||||
debug: boolean
|
||||
identifier: string
|
||||
manualStart: boolean
|
||||
onViewportManualStart: boolean
|
||||
onScreenManualStart: boolean
|
||||
pages?: Array<number>
|
||||
clip: boolean
|
||||
offScreenUpdateBehaviour: OffScreenUpdateBehaviourType
|
||||
@ -167,13 +167,6 @@ interface WidgetInternalProperties {
|
||||
|
||||
export class SpineWebComponentWidget extends HTMLElement implements Disposable, WidgetAttributes, WidgetOverridableMethods, WidgetInternalProperties, Partial<WidgetPublicProperties> {
|
||||
|
||||
public worldX = 0;
|
||||
public worldY = 0;
|
||||
public cursorWorldX = 1;
|
||||
public cursorWorldY = 1;
|
||||
public jsonSkeletonKey?: string;
|
||||
public onViewportManualStart = false;
|
||||
|
||||
// this promise in necessary only for manual start. Before calling manual start is necessary that the overlay has been assigned to the widget.
|
||||
// overlay assignment is asynchronous due to webcomponent promotion and dom load termination.
|
||||
// When manual start is false, loadSkeleton is invoked after the overlay is assigned. loadSkeleton needs the assetManager that is owned by the overlay.
|
||||
@ -206,6 +199,12 @@ export class SpineWebComponentWidget extends HTMLElement implements Disposable,
|
||||
*/
|
||||
public skeletonPath?: string;
|
||||
|
||||
/**
|
||||
* The name of the skeleton when the skeleton file is a JSON and contains multiple skeletons.
|
||||
* Connected to `json-skeleton-key` attribute.
|
||||
*/
|
||||
public jsonSkeletonKey?: string;
|
||||
|
||||
/**
|
||||
* The scale passed to the Skeleton Loader. SkeletonData values will be scaled accordingly.
|
||||
* Default: 1
|
||||
@ -410,6 +409,30 @@ export class SpineWebComponentWidget extends HTMLElement implements Disposable,
|
||||
*/
|
||||
public isDraggable = false;
|
||||
|
||||
/**
|
||||
* The x of the root relative to the canvas/webgl context center in spine world coordinates.
|
||||
* This is an experimental property and might be removed in the future.
|
||||
*/
|
||||
public worldX = 0;
|
||||
|
||||
/**
|
||||
* The y of the root relative to the canvas/webgl context center in spine world coordinates.
|
||||
* This is an experimental property and might be removed in the future.
|
||||
*/
|
||||
public worldY = 0;
|
||||
|
||||
/**
|
||||
* The x coordinate of the cursor relative to the cursor relative to the skeleton root in spine world coordinates.
|
||||
* This is an experimental property and might be removed in the future.
|
||||
*/
|
||||
public cursorWorldX = 1;
|
||||
|
||||
/**
|
||||
* The x coordinate of the cursor relative to the cursor relative to the skeleton root in spine world coordinates.
|
||||
* This is an experimental property and might be removed in the future.
|
||||
*/
|
||||
public cursorWorldY = 1;
|
||||
|
||||
/**
|
||||
* If true, some convenience elements are drawn to show the skeleton world origin (green),
|
||||
* the root (red), and the bounds rectangle (blue)
|
||||
@ -430,6 +453,14 @@ export class SpineWebComponentWidget extends HTMLElement implements Disposable,
|
||||
*/
|
||||
public manualStart = false;
|
||||
|
||||
/**
|
||||
* If true and manualStart is true, allows the default {@link onScreenFunction} to invoke the {@link start} method.
|
||||
* This is useful when you want to load the assets only when the widget is revealed.
|
||||
* By default, is false implying the start method to be invoked manually.
|
||||
* Connected to `on-screen-manual-start` attribute.
|
||||
*/
|
||||
public onScreenManualStart = false;
|
||||
|
||||
/**
|
||||
* An array of indexes indicating the atlas pages indexes to be loaded.
|
||||
* If undefined, all pages are loaded. If empty (default), no page is loaded;
|
||||
@ -488,7 +519,7 @@ export class SpineWebComponentWidget extends HTMLElement implements Disposable,
|
||||
if (widget.loading && !widget.onScreenAtLeastOnce) {
|
||||
widget.onScreenAtLeastOnce = true;
|
||||
|
||||
if (widget.manualStart && widget.onViewportManualStart) {
|
||||
if (widget.manualStart && widget.onScreenManualStart) {
|
||||
widget.start();
|
||||
}
|
||||
}
|
||||
@ -631,7 +662,7 @@ export class SpineWebComponentWidget extends HTMLElement implements Disposable,
|
||||
identifier: { propertyName: "identifier", type: "string" },
|
||||
debug: { propertyName: "debug", type: "boolean" },
|
||||
"manual-start": { propertyName: "manualStart", type: "boolean" },
|
||||
"on-viewport-manual-start": { propertyName: "onViewportManualStart", type: "boolean" },
|
||||
"on-screen-manual-start": { propertyName: "onScreenManualStart", type: "boolean" },
|
||||
spinner: { propertyName: "loadingSpinner", type: "boolean" },
|
||||
clip: { propertyName: "clip", type: "boolean" },
|
||||
pages: { propertyName: "pages", type: "string-number" },
|
||||
@ -703,6 +734,9 @@ export class SpineWebComponentWidget extends HTMLElement implements Disposable,
|
||||
this.debugDragDiv?.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the widget from the overlay and the DOM.
|
||||
*/
|
||||
dispose () {
|
||||
this.remove();
|
||||
this.loadingScreen?.dispose();
|
||||
@ -938,6 +972,7 @@ export class SpineWebComponentWidget extends HTMLElement implements Disposable,
|
||||
interface OverlayAttributes {
|
||||
overlayId?: string
|
||||
scrollable: boolean
|
||||
scrollableTweakOff: boolean
|
||||
overflowTop: number
|
||||
overflowBottom: number
|
||||
overflowLeft: number
|
||||
@ -946,8 +981,12 @@ interface OverlayAttributes {
|
||||
|
||||
class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes, Disposable {
|
||||
|
||||
public static OVERLAY_ID = "spine-overlay-default-identifier";
|
||||
public static OVERLAY_LIST = new Map<string, SpineWebComponentOverlay>();
|
||||
private static OVERLAY_ID = "spine-overlay-default-identifier";
|
||||
private static OVERLAY_LIST = new Map<string, SpineWebComponentOverlay>();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
static getOrCreateOverlay(overlayId: string | null): SpineWebComponentOverlay {
|
||||
let overlay = SpineWebComponentOverlay.OVERLAY_LIST.get(overlayId || SpineWebComponentOverlay.OVERLAY_ID);
|
||||
if (!overlay) {
|
||||
@ -958,14 +997,85 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
|
||||
return overlay;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list holding the widgets added to this overlay.
|
||||
*/
|
||||
public skeletonList = new Array<SpineWebComponentWidget>();
|
||||
|
||||
/**
|
||||
* A reference to the {@link SceneRenderer} used by this overlay.
|
||||
*/
|
||||
public renderer: SceneRenderer;
|
||||
|
||||
/**
|
||||
* A reference to the {@link AssetManager} used by this overlay.
|
||||
*/
|
||||
public assetManager: AssetManager;
|
||||
|
||||
private root: ShadowRoot;
|
||||
/**
|
||||
* The identifier of this overlay. This is necessary when multiply overlay are created.
|
||||
* Connected to `overlay-id` attribute.
|
||||
*/
|
||||
public overlayId?: string;
|
||||
|
||||
/**
|
||||
* If true, the overlay will have the size of the element container in contrast to the default behaviour where the
|
||||
* overlay has always the size of the screen.
|
||||
* This is necessary when the overlay is inserted into a container that scroll in a different way with respect to the page.
|
||||
* Otherwise the following problems might occur:
|
||||
* 1) For scrollable containers, the widget will be slightly slower to scroll than the html behind. The effect is more evident for lower refresh rate display.
|
||||
* 2) For scrollable containers, the widget will overflow the container bounds until the widget html element container is visible
|
||||
* 3) For fixed containers, the widget will scroll in a jerky way
|
||||
*
|
||||
* In order to fix this behaviour, it is necessary to insert a dedicated `spine-overlay` webcomponent as a direct child of the container.
|
||||
* Moreover, it is necessary to perform the following actions:
|
||||
* 1) The scrollable container must have a `transform`css attribute. If it hasn't this attribute the `spine-overlay` will add it for you.
|
||||
* If your scrollable container has already this css attribute, or if you prefer to add it by yourself (example: `transform: translateZ(0);`), set the `scrollable-tweak-off` to the `spine-overlay`.
|
||||
* 2) The `spine-overlay` must have the `scrollable`attribute
|
||||
* 3) The `spine-overlay` must have an `overlay-id` attribute. Choose the value you prefer.
|
||||
* 4) Each `spine-widget` must have an `overlay-id` attribute. The same as the hosting `spine-overlay`.
|
||||
* Connected to `scrollable` attribute.
|
||||
*/
|
||||
public scrollable = false;
|
||||
|
||||
/**
|
||||
* If `false` (default value), the overlay container style will be affected adding `transform: translateZ(0);` to it.
|
||||
* The `transform` is not affected if it already exists on the container.
|
||||
* This is necessary to make the scrolling works with containers that scroll in a different way with respect to the page, as explained in {@link scrollable}.
|
||||
* Connected to `scrollable-tweak-off` attribute.
|
||||
*/
|
||||
public scrollableTweakOff = false;
|
||||
|
||||
/**
|
||||
* How many pixels to add to the top of the canvas to prevent "edge cutting" on fast scrolling, in canvas height units.
|
||||
* By default, the canvas is big as the screen resolution. Making it too big might reduce performance.
|
||||
* Connected to `overflow-top` attribute.
|
||||
*/
|
||||
public overflowTop = .2;
|
||||
|
||||
/**
|
||||
* How many pixels to add to the bottom of the canvas to prevent "edge cutting" on fast scrolling, in canvas height units.
|
||||
* By default, the canvas is big as the screen resolution. Making it too big might reduce performance.
|
||||
* Connected to `overflow-bottom` attribute.
|
||||
*/
|
||||
public overflowBottom = .0;
|
||||
|
||||
/**
|
||||
* How many pixels to add to the left of the canvas to prevent "edge cutting" on fast scrolling, in canvas width units.
|
||||
* By default, the canvas is big as the screen resolution. Making it too big might reduce performance.
|
||||
* Connected to `overflow-left` attribute.
|
||||
*/
|
||||
public overflowLeft = .0;
|
||||
|
||||
/**
|
||||
* How many pixels to add to the right of the canvas to prevent "edge cutting" on fast scrolling, in canvas width units.
|
||||
* By default, the canvas is big as the screen resolution. Making it too big might reduce performance.
|
||||
* Connected to `overflow-right` attribute.
|
||||
*/
|
||||
public overflowRight = .0;
|
||||
|
||||
private root: ShadowRoot;
|
||||
|
||||
private div: HTMLDivElement;
|
||||
private canvas: HTMLCanvasElement;
|
||||
private fps: HTMLSpanElement;
|
||||
@ -975,13 +1085,6 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
|
||||
private resizeObserver?:ResizeObserver;
|
||||
private input?: Input;
|
||||
|
||||
// how many pixels to add to the edges to prevent "edge cutting" on fast scrolling
|
||||
// be aware that the canvas is already big as the display size
|
||||
// making it bigger might reduce performance significantly
|
||||
public overflowTop = .2;
|
||||
public overflowBottom = .2;
|
||||
public overflowLeft = .0;
|
||||
public overflowRight = .0;
|
||||
private overflowLeftSize = 0;
|
||||
private overflowTopSize = 0;
|
||||
|
||||
@ -1068,7 +1171,7 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
|
||||
this.resizeObserver = new ResizeObserver(this.resizeCallback);
|
||||
if (this.scrollable) {
|
||||
const style = getComputedStyle(this.parentElement!);
|
||||
if (style.transform === "none") {
|
||||
if (style.transform === "none" && !this.scrollableTweakOff) {
|
||||
this.parentElement!.style.transform = `translateZ(0)`;
|
||||
}
|
||||
this.resizeObserver.observe(this.parentElement!);
|
||||
@ -1100,6 +1203,7 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
|
||||
static attributesDescription: Record<string, { propertyName: keyof OverlayAttributes, type: AttributeTypes, defaultValue?: any }> = {
|
||||
"overlay-id": { propertyName: "overlayId", type: "string" },
|
||||
"scrollable": { propertyName: "scrollable", type: "boolean" },
|
||||
"scrollable-tweak-off": { propertyName: "scrollableTweakOff", type: "boolean" },
|
||||
"overflow-top": { propertyName: "overflowTop", type: "number" },
|
||||
"overflow-bottom": { propertyName: "overflowBottom", type: "number" },
|
||||
"overflow-left": { propertyName: "overflowLeft", type: "number" },
|
||||
@ -1144,8 +1248,12 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
|
||||
this.loaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the overlay from the DOM, dispose all the contained widgets, and dispose the renderer.
|
||||
*/
|
||||
dispose (): void {
|
||||
this.remove();
|
||||
this.skeletonList.forEach(widget => widget.dispose());
|
||||
this.skeletonList.length = 0;
|
||||
this.renderer.dispose();
|
||||
this.disposed = true;
|
||||
@ -1154,7 +1262,7 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
|
||||
addWidget (widget: SpineWebComponentWidget) {
|
||||
this.skeletonList.push(widget);
|
||||
this.intersectionObserver?.observe(widget.getHTMLElementReference());
|
||||
if (this.loaded) {
|
||||
if (this.loaded && (this.compareDocumentPosition(widget) & Node.DOCUMENT_POSITION_FOLLOWING)) {
|
||||
this.parentElement!.appendChild(this);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user