mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
Made some changes to make it work on old browsers.
This commit is contained in:
parent
27edd8a284
commit
e26034426a
@ -17,7 +17,7 @@
|
|||||||
last = new spine.Vector3();
|
last = new spine.Vector3();
|
||||||
new spine.SpinePlayer("player", {
|
new spine.SpinePlayer("player", {
|
||||||
skeleton: "assets/celestial-circus-pro.skel",
|
skeleton: "assets/celestial-circus-pro.skel",
|
||||||
url: "assets/celestial-circus-pma.atlas",
|
atlas: "assets/celestial-circus-pma.atlas",
|
||||||
showControls: true,
|
showControls: true,
|
||||||
animation: "swing",
|
animation: "swing",
|
||||||
success: (player) => {
|
success: (player) => {
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
.section {
|
.section {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -1712,7 +1713,7 @@ stretchyman.update = (canvas, delta, skeleton, state) => {
|
|||||||
atlas="assets/celestial-circus-pma.atlas"
|
atlas="assets/celestial-circus-pma.atlas"
|
||||||
skeleton="assets/celestial-circus-pro.skel"
|
skeleton="assets/celestial-circus-pro.skel"
|
||||||
clip
|
clip
|
||||||
draggable
|
isdraggable
|
||||||
></spine-widget>
|
></spine-widget>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -1779,7 +1780,7 @@ stretchyman.update = (canvas, delta, skeleton, state) => {
|
|||||||
skeleton="assets/celestial-circus-pro.skel"
|
skeleton="assets/celestial-circus-pro.skel"
|
||||||
animation="wings-and-feet"
|
animation="wings-and-feet"
|
||||||
clip
|
clip
|
||||||
draggable
|
isdraggable
|
||||||
></spine-widget>
|
></spine-widget>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -1814,14 +1815,14 @@ stretchyman.update = (canvas, delta, skeleton, state) => {
|
|||||||
|
|
||||||
<div class="split-top split">
|
<div class="split-top split">
|
||||||
<div class="split-left">
|
<div class="split-left">
|
||||||
As a bonus item, you can move you skeleton around just by setting the <code>draggable</code> property to <code>true</code>.
|
As a bonus item, you can move you skeleton around just by setting the <code>isdraggable</code> property to <code>true</code>.
|
||||||
</div>
|
</div>
|
||||||
<div class="split-right">
|
<div class="split-right">
|
||||||
<spine-widget
|
<spine-widget
|
||||||
atlas="assets/celestial-circus-pma.atlas"
|
atlas="assets/celestial-circus-pma.atlas"
|
||||||
skeleton="assets/celestial-circus-pro.skel"
|
skeleton="assets/celestial-circus-pro.skel"
|
||||||
animation="wings-and-feet"
|
animation="wings-and-feet"
|
||||||
draggable
|
isdraggable
|
||||||
></spine-widget>
|
></spine-widget>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1833,7 +1834,7 @@ stretchyman.update = (canvas, delta, skeleton, state) => {
|
|||||||
atlas="assets/celestial-circus-pma.atlas"
|
atlas="assets/celestial-circus-pma.atlas"
|
||||||
skeleton="assets/celestial-circus-pro.skel"
|
skeleton="assets/celestial-circus-pro.skel"
|
||||||
animation="wings-and-feet"
|
animation="wings-and-feet"
|
||||||
draggable="true"
|
isdraggable="true"
|
||||||
></spine-widget>`
|
></spine-widget>`
|
||||||
);</script>
|
);</script>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|||||||
@ -36,11 +36,11 @@ export class Input {
|
|||||||
touch1: Touch | null = null;
|
touch1: Touch | null = null;
|
||||||
initialPinchDistance = 0;
|
initialPinchDistance = 0;
|
||||||
private listeners = new Array<InputListener>();
|
private listeners = new Array<InputListener>();
|
||||||
private preventDefault: boolean;
|
private autoPreventDefault: boolean;
|
||||||
|
|
||||||
constructor (element: HTMLElement, preventDefault = true) {
|
constructor (element: HTMLElement, autoPreventDefault = true) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.preventDefault = preventDefault;
|
this.autoPreventDefault = autoPreventDefault;
|
||||||
this.setupCallbacks(element);
|
this.setupCallbacks(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ export class Input {
|
|||||||
let mouseDown = (ev: UIEvent) => {
|
let mouseDown = (ev: UIEvent) => {
|
||||||
if (ev instanceof MouseEvent) {
|
if (ev instanceof MouseEvent) {
|
||||||
let rect = element.getBoundingClientRect();
|
let rect = element.getBoundingClientRect();
|
||||||
this.mouseX = ev.clientX - rect.left;;
|
this.mouseX = ev.clientX - rect.left;
|
||||||
this.mouseY = ev.clientY - rect.top;
|
this.mouseY = ev.clientY - rect.top;
|
||||||
this.buttonDown = true;
|
this.buttonDown = true;
|
||||||
this.listeners.map((listener) => { if (listener.down) listener.down(this.mouseX, this.mouseY, ev); });
|
this.listeners.map((listener) => { if (listener.down) listener.down(this.mouseX, this.mouseY, ev); });
|
||||||
@ -88,7 +88,7 @@ export class Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mouseWheel = (ev: WheelEvent) => {
|
let mouseWheel = (ev: WheelEvent) => {
|
||||||
if (this.preventDefault) ev.preventDefault();
|
if (this.autoPreventDefault) ev.preventDefault();
|
||||||
let deltaY = ev.deltaY;
|
let deltaY = ev.deltaY;
|
||||||
if (ev.deltaMode == WheelEvent.DOM_DELTA_LINE) deltaY *= 8;
|
if (ev.deltaMode == WheelEvent.DOM_DELTA_LINE) deltaY *= 8;
|
||||||
if (ev.deltaMode == WheelEvent.DOM_DELTA_PAGE) deltaY *= 24;
|
if (ev.deltaMode == WheelEvent.DOM_DELTA_PAGE) deltaY *= 24;
|
||||||
@ -125,8 +125,8 @@ export class Input {
|
|||||||
this.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, this.initialPinchDistance, ev) });
|
this.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, this.initialPinchDistance, ev) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.preventDefault) ev.preventDefault();
|
if (this.autoPreventDefault) ev.preventDefault();
|
||||||
}, { passive: this.preventDefault });
|
}, { passive: false, capture: false });
|
||||||
|
|
||||||
element.addEventListener("touchmove", (ev: TouchEvent) => {
|
element.addEventListener("touchmove", (ev: TouchEvent) => {
|
||||||
if (this.touch0) {
|
if (this.touch0) {
|
||||||
@ -154,8 +154,8 @@ export class Input {
|
|||||||
this.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, distance, ev) });
|
this.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, distance, ev) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.preventDefault) ev.preventDefault();
|
if (this.autoPreventDefault) ev.preventDefault();
|
||||||
}, { passive: this.preventDefault });
|
}, { passive: false, capture: false });
|
||||||
|
|
||||||
let touchEnd = (ev: TouchEvent) => {
|
let touchEnd = (ev: TouchEvent) => {
|
||||||
if (this.touch0) {
|
if (this.touch0) {
|
||||||
@ -191,9 +191,9 @@ export class Input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.preventDefault) ev.preventDefault();
|
if (this.autoPreventDefault) ev.preventDefault();
|
||||||
};
|
};
|
||||||
element.addEventListener("touchend", touchEnd, false);
|
element.addEventListener("touchend", touchEnd, { passive: false, capture: false });
|
||||||
element.addEventListener("touchcancel", touchEnd);
|
element.addEventListener("touchcancel", touchEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -111,7 +111,7 @@ interface WidgetAttributes {
|
|||||||
offsetY: number
|
offsetY: number
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
draggable: boolean
|
isDraggable: boolean
|
||||||
debug: boolean
|
debug: boolean
|
||||||
identifier: string
|
identifier: string
|
||||||
manualStart: boolean
|
manualStart: boolean
|
||||||
@ -280,9 +280,9 @@ export class SpineWebComponentWidget extends HTMLElement implements WidgetAttrib
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the widget is draggable
|
* If true, the widget is draggable
|
||||||
* Connected to `draggable` attribute.
|
* Connected to `isdraggable` attribute.
|
||||||
*/
|
*/
|
||||||
public draggable = false;
|
public isDraggable = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, some convenience elements are drawn to show the skeleton world origin (green),
|
* If true, some convenience elements are drawn to show the skeleton world origin (green),
|
||||||
@ -488,7 +488,7 @@ export class SpineWebComponentWidget extends HTMLElement implements WidgetAttrib
|
|||||||
skin: { propertyName: "skin", type: "string" },
|
skin: { propertyName: "skin", type: "string" },
|
||||||
width: { propertyName: "width", type: "number", defaultValue: -1 },
|
width: { propertyName: "width", type: "number", defaultValue: -1 },
|
||||||
height: { propertyName: "height", type: "number", defaultValue: -1 },
|
height: { propertyName: "height", type: "number", defaultValue: -1 },
|
||||||
draggable: { propertyName: "draggable", type: "boolean" },
|
isdraggable: { propertyName: "isDraggable", type: "boolean" },
|
||||||
"x-axis": { propertyName: "xAxis", type: "number" },
|
"x-axis": { propertyName: "xAxis", type: "number" },
|
||||||
"y-axis": { propertyName: "yAxis", type: "number" },
|
"y-axis": { propertyName: "yAxis", type: "number" },
|
||||||
"offset-x": { propertyName: "offsetX", type: "number" },
|
"offset-x": { propertyName: "offsetX", type: "number" },
|
||||||
@ -505,29 +505,7 @@ export class SpineWebComponentWidget extends HTMLElement implements WidgetAttrib
|
|||||||
}
|
}
|
||||||
|
|
||||||
static get observedAttributes(): string[] {
|
static get observedAttributes(): string[] {
|
||||||
return [
|
return Object.keys(SpineWebComponentWidget.attributesDescription);
|
||||||
"atlas", // atlasPath
|
|
||||||
"skeleton", // skeletonPath
|
|
||||||
"scale", // scale
|
|
||||||
"animation", // animation
|
|
||||||
"skin", // skin
|
|
||||||
"fit", // fit
|
|
||||||
"width", // width
|
|
||||||
"height", // height
|
|
||||||
"draggable", // draggable
|
|
||||||
"mode", // mode
|
|
||||||
"x-axis", // xAxis
|
|
||||||
"y-axis", // yAxis
|
|
||||||
"offset-x", // offsetX
|
|
||||||
"offset-y", // offsetY
|
|
||||||
"identifier", // identifier
|
|
||||||
"debug", // debug
|
|
||||||
"manual-start", // manualStart
|
|
||||||
"spinner", // loadingSpinner
|
|
||||||
"pages", // pages
|
|
||||||
"offscreen", // offScreenUpdateBehaviour
|
|
||||||
"clip", // clip
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -843,7 +821,6 @@ class SpineWebComponentOverlay extends HTMLElement {
|
|||||||
public skeletonList = new Array<SpineWebComponentWidget>();
|
public skeletonList = new Array<SpineWebComponentWidget>();
|
||||||
|
|
||||||
private intersectionObserver? : IntersectionObserver;
|
private intersectionObserver? : IntersectionObserver;
|
||||||
private resizeObserver:ResizeObserver;
|
|
||||||
private input: Input;
|
private input: Input;
|
||||||
|
|
||||||
// how many pixels to add to the edges to prevent "edge cuttin" on fast scrolling
|
// how many pixels to add to the edges to prevent "edge cuttin" on fast scrolling
|
||||||
@ -896,40 +873,61 @@ class SpineWebComponentOverlay extends HTMLElement {
|
|||||||
const context = new ManagedWebGLRenderingContext(this.canvas, { alpha: true });
|
const context = new ManagedWebGLRenderingContext(this.canvas, { alpha: true });
|
||||||
this.renderer = new SceneRenderer(this.canvas, context);
|
this.renderer = new SceneRenderer(this.canvas, context);
|
||||||
this.assetManager = new AssetManager(context);
|
this.assetManager = new AssetManager(context);
|
||||||
this.input = new Input(this.canvas);
|
this.input = new Input(this.canvas, false);
|
||||||
this.setupRenderingElements();
|
this.setupRenderingElements();
|
||||||
|
|
||||||
this.updateCanvasSize();
|
|
||||||
this.zoomHandler();
|
|
||||||
|
|
||||||
// translateCanvas starts a requestAnimationFrame loop
|
|
||||||
this.translateCanvas();
|
|
||||||
|
|
||||||
this.overflowLeftSize = this.overflowLeft * document.documentElement.clientWidth;
|
this.overflowLeftSize = this.overflowLeft * document.documentElement.clientWidth;
|
||||||
this.overflowTopSize = this.overflowTop * document.documentElement.clientHeight;
|
this.overflowTopSize = this.overflowTop * document.documentElement.clientHeight;
|
||||||
|
|
||||||
// resize and zoom
|
window.addEventListener('resize', () => {
|
||||||
// TODO: should I use the resize event?
|
|
||||||
this.resizeObserver = new ResizeObserver(() => {
|
|
||||||
this.updateCanvasSize();
|
this.updateCanvasSize();
|
||||||
this.zoomHandler();
|
this.zoomHandler();
|
||||||
});
|
});
|
||||||
this.resizeObserver.observe(document.body);
|
|
||||||
|
|
||||||
const screen = window.screen;
|
window.screen.orientation.onchange = () => {
|
||||||
screen.orientation.onchange = () => {
|
|
||||||
this.updateCanvasSize();
|
this.updateCanvasSize();
|
||||||
// after an orientation change the scrolling changes, but the scroll event does not fire
|
// after an orientation change the scrolling changes, but the scroll event does not fire
|
||||||
this.scrollHandler();
|
this.scrollHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("scroll", this.scrollHandler);
|
window.addEventListener("scroll", this.scrollHandler);
|
||||||
this.scrollHandler();
|
|
||||||
|
window.onload = () => {
|
||||||
|
this.updateCanvasSize();
|
||||||
|
this.zoomHandler();
|
||||||
|
|
||||||
|
// translateCanvas starts a requestAnimationFrame loop
|
||||||
|
this.translateCanvas();
|
||||||
|
|
||||||
|
this.scrollHandler();
|
||||||
|
};
|
||||||
|
|
||||||
this.input = new Input(document.body, false);
|
this.input = new Input(document.body, false);
|
||||||
this.setupDragUtility();
|
this.setupDragUtility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connectedCallback(): void {
|
||||||
|
this.intersectionObserver = new IntersectionObserver((widgets) => {
|
||||||
|
widgets.forEach(({ isIntersecting, target, intersectionRatio }) => {
|
||||||
|
const widget = this.skeletonList.find(w => w.getHTMLElementReference() == target);
|
||||||
|
if (!widget) return;
|
||||||
|
|
||||||
|
// old browsers do not have isIntersecting
|
||||||
|
if (isIntersecting === undefined) {
|
||||||
|
isIntersecting = intersectionRatio > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.onScreen = isIntersecting;
|
||||||
|
if (isIntersecting) {
|
||||||
|
widget.onScreenFunction(widget);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, { rootMargin: "30px 20px 30px 20px" });
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback(): void {
|
||||||
|
}
|
||||||
|
|
||||||
addWidget(widget: SpineWebComponentWidget) {
|
addWidget(widget: SpineWebComponentWidget) {
|
||||||
this.skeletonList.push(widget);
|
this.skeletonList.push(widget);
|
||||||
this.intersectionObserver!.observe(widget.getHTMLElementReference());
|
this.intersectionObserver!.observe(widget.getHTMLElementReference());
|
||||||
@ -1028,12 +1026,13 @@ class SpineWebComponentOverlay extends HTMLElement {
|
|||||||
const devicePixelRatio = window.devicePixelRatio;
|
const devicePixelRatio = window.devicePixelRatio;
|
||||||
const tempVector = new Vector3();
|
const tempVector = new Vector3();
|
||||||
this.skeletonList.forEach((widget) => {
|
this.skeletonList.forEach((widget) => {
|
||||||
const { skeleton, bounds, mode, debug, offsetX, offsetY, xAxis, yAxis, dragX, dragY, fit, loadingSpinner, onScreen, loading, clip, draggable } = widget;
|
const { skeleton, bounds, mode, debug, offsetX, offsetY, xAxis, yAxis, dragX, dragY, fit, loadingSpinner, onScreen, loading, clip, isDraggable } = widget;
|
||||||
|
|
||||||
if ((!onScreen && dragX === 0 && dragY === 0)) return;
|
if ((!onScreen && dragX === 0 && dragY === 0)) return;
|
||||||
const divBounds = widget.getHTMLElementReference().getBoundingClientRect();
|
const divBounds = widget.getHTMLElementReference().getBoundingClientRect();
|
||||||
divBounds.x += this.overflowLeftSize;
|
// need to use left and top, because x and y are not available on older browser
|
||||||
divBounds.y += this.overflowTopSize;
|
divBounds.x = divBounds.left + this.overflowLeftSize;
|
||||||
|
divBounds.y = divBounds.top + this.overflowTopSize;
|
||||||
|
|
||||||
let divOriginX = 0;
|
let divOriginX = 0;
|
||||||
let divOriginY = 0;
|
let divOriginY = 0;
|
||||||
@ -1137,8 +1136,8 @@ class SpineWebComponentOverlay extends HTMLElement {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// store the draggable surface to make darg logic easier
|
// store the draggable surface to make drag logic easier
|
||||||
if (draggable) {
|
if (isDraggable) {
|
||||||
let { x: ax, y: ay, width: aw, height: ah } = bounds!;
|
let { x: ax, y: ay, width: aw, height: ah } = bounds!;
|
||||||
this.worldToScreen(tempVector, ax * skeleton.scaleX + worldOffsetX, ay * skeleton.scaleY + worldOffsetY);
|
this.worldToScreen(tempVector, ax * skeleton.scaleX + worldOffsetX, ay * skeleton.scaleY + worldOffsetY);
|
||||||
widget.dragBoundsRectangle.x = tempVector.x + window.scrollX;
|
widget.dragBoundsRectangle.x = tempVector.x + window.scrollX;
|
||||||
@ -1211,24 +1210,6 @@ class SpineWebComponentOverlay extends HTMLElement {
|
|||||||
const transparentWhite = new Color(1, 1, 1, .3);
|
const transparentWhite = new Color(1, 1, 1, .3);
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback(): void {
|
|
||||||
this.intersectionObserver = new IntersectionObserver((widgets) => {
|
|
||||||
widgets.forEach(({ isIntersecting, target }) => {
|
|
||||||
|
|
||||||
const widget = this.skeletonList.find(w => w.getHTMLElementReference() == target);
|
|
||||||
if (!widget) return;
|
|
||||||
widget.onScreen = isIntersecting;
|
|
||||||
if (isIntersecting) {
|
|
||||||
widget.onScreenFunction(widget);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, { rootMargin: "30px 20px 30px 20px" });
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnectedCallback(): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: drag is bugged when zoom on browser (just zoom and activare debug to see the drag surface has some offset)
|
|
||||||
private setupDragUtility() {
|
private setupDragUtility() {
|
||||||
// TODO: we should use document - body might have some margin that offset the click events - Meanwhile I take event pageX/Y
|
// TODO: we should use document - body might have some margin that offset the click events - Meanwhile I take event pageX/Y
|
||||||
const point: Point = { x: 0, y: 0 };
|
const point: Point = { x: 0, y: 0 };
|
||||||
@ -1246,7 +1227,7 @@ class SpineWebComponentOverlay extends HTMLElement {
|
|||||||
down: (x, y, ev) => {
|
down: (x, y, ev) => {
|
||||||
const input = getInput(ev);
|
const input = getInput(ev);
|
||||||
this.skeletonList.forEach(widget => {
|
this.skeletonList.forEach(widget => {
|
||||||
if (!widget.draggable || (!widget.onScreen && widget.dragX === 0 && widget.dragY === 0)) return;
|
if (!widget.isDraggable || (!widget.onScreen && widget.dragX === 0 && widget.dragY === 0)) return;
|
||||||
if (inside(input, widget.dragBoundsRectangle)) {
|
if (inside(input, widget.dragBoundsRectangle)) {
|
||||||
widget.dragging = true;
|
widget.dragging = true;
|
||||||
ev?.preventDefault();
|
ev?.preventDefault();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user