mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +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();
|
||||
new spine.SpinePlayer("player", {
|
||||
skeleton: "assets/celestial-circus-pro.skel",
|
||||
url: "assets/celestial-circus-pma.atlas",
|
||||
atlas: "assets/celestial-circus-pma.atlas",
|
||||
showControls: true,
|
||||
animation: "swing",
|
||||
success: (player) => {
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
}
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
.section {
|
||||
display: flex;
|
||||
@ -1712,7 +1713,7 @@ stretchyman.update = (canvas, delta, skeleton, state) => {
|
||||
atlas="assets/celestial-circus-pma.atlas"
|
||||
skeleton="assets/celestial-circus-pro.skel"
|
||||
clip
|
||||
draggable
|
||||
isdraggable
|
||||
></spine-widget>
|
||||
|
||||
<script>
|
||||
@ -1779,7 +1780,7 @@ stretchyman.update = (canvas, delta, skeleton, state) => {
|
||||
skeleton="assets/celestial-circus-pro.skel"
|
||||
animation="wings-and-feet"
|
||||
clip
|
||||
draggable
|
||||
isdraggable
|
||||
></spine-widget>
|
||||
</div>
|
||||
|
||||
@ -1814,14 +1815,14 @@ stretchyman.update = (canvas, delta, skeleton, state) => {
|
||||
|
||||
<div class="split-top split">
|
||||
<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 class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/celestial-circus-pma.atlas"
|
||||
skeleton="assets/celestial-circus-pro.skel"
|
||||
animation="wings-and-feet"
|
||||
draggable
|
||||
isdraggable
|
||||
></spine-widget>
|
||||
</div>
|
||||
</div>
|
||||
@ -1833,7 +1834,7 @@ stretchyman.update = (canvas, delta, skeleton, state) => {
|
||||
atlas="assets/celestial-circus-pma.atlas"
|
||||
skeleton="assets/celestial-circus-pro.skel"
|
||||
animation="wings-and-feet"
|
||||
draggable="true"
|
||||
isdraggable="true"
|
||||
></spine-widget>`
|
||||
);</script>
|
||||
</code></pre>
|
||||
|
||||
@ -36,11 +36,11 @@ export class Input {
|
||||
touch1: Touch | null = null;
|
||||
initialPinchDistance = 0;
|
||||
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.preventDefault = preventDefault;
|
||||
this.autoPreventDefault = autoPreventDefault;
|
||||
this.setupCallbacks(element);
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ export class Input {
|
||||
let mouseDown = (ev: UIEvent) => {
|
||||
if (ev instanceof MouseEvent) {
|
||||
let rect = element.getBoundingClientRect();
|
||||
this.mouseX = ev.clientX - rect.left;;
|
||||
this.mouseX = ev.clientX - rect.left;
|
||||
this.mouseY = ev.clientY - rect.top;
|
||||
this.buttonDown = true;
|
||||
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) => {
|
||||
if (this.preventDefault) ev.preventDefault();
|
||||
if (this.autoPreventDefault) ev.preventDefault();
|
||||
let deltaY = ev.deltaY;
|
||||
if (ev.deltaMode == WheelEvent.DOM_DELTA_LINE) deltaY *= 8;
|
||||
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) });
|
||||
}
|
||||
}
|
||||
if (this.preventDefault) ev.preventDefault();
|
||||
}, { passive: this.preventDefault });
|
||||
if (this.autoPreventDefault) ev.preventDefault();
|
||||
}, { passive: false, capture: false });
|
||||
|
||||
element.addEventListener("touchmove", (ev: TouchEvent) => {
|
||||
if (this.touch0) {
|
||||
@ -154,8 +154,8 @@ export class Input {
|
||||
this.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, distance, ev) });
|
||||
}
|
||||
}
|
||||
if (this.preventDefault) ev.preventDefault();
|
||||
}, { passive: this.preventDefault });
|
||||
if (this.autoPreventDefault) ev.preventDefault();
|
||||
}, { passive: false, capture: false });
|
||||
|
||||
let touchEnd = (ev: TouchEvent) => {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -111,7 +111,7 @@ interface WidgetAttributes {
|
||||
offsetY: number
|
||||
width: number
|
||||
height: number
|
||||
draggable: boolean
|
||||
isDraggable: boolean
|
||||
debug: boolean
|
||||
identifier: string
|
||||
manualStart: boolean
|
||||
@ -280,9 +280,9 @@ export class SpineWebComponentWidget extends HTMLElement implements WidgetAttrib
|
||||
|
||||
/**
|
||||
* 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),
|
||||
@ -488,7 +488,7 @@ export class SpineWebComponentWidget extends HTMLElement implements WidgetAttrib
|
||||
skin: { propertyName: "skin", type: "string" },
|
||||
width: { propertyName: "width", 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" },
|
||||
"y-axis": { propertyName: "yAxis", type: "number" },
|
||||
"offset-x": { propertyName: "offsetX", type: "number" },
|
||||
@ -505,29 +505,7 @@ export class SpineWebComponentWidget extends HTMLElement implements WidgetAttrib
|
||||
}
|
||||
|
||||
static get observedAttributes(): string[] {
|
||||
return [
|
||||
"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
|
||||
];
|
||||
return Object.keys(SpineWebComponentWidget.attributesDescription);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
@ -843,7 +821,6 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
public skeletonList = new Array<SpineWebComponentWidget>();
|
||||
|
||||
private intersectionObserver? : IntersectionObserver;
|
||||
private resizeObserver:ResizeObserver;
|
||||
private input: Input;
|
||||
|
||||
// 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 });
|
||||
this.renderer = new SceneRenderer(this.canvas, context);
|
||||
this.assetManager = new AssetManager(context);
|
||||
this.input = new Input(this.canvas);
|
||||
this.input = new Input(this.canvas, false);
|
||||
this.setupRenderingElements();
|
||||
|
||||
this.updateCanvasSize();
|
||||
this.zoomHandler();
|
||||
|
||||
// translateCanvas starts a requestAnimationFrame loop
|
||||
this.translateCanvas();
|
||||
|
||||
this.overflowLeftSize = this.overflowLeft * document.documentElement.clientWidth;
|
||||
this.overflowTopSize = this.overflowTop * document.documentElement.clientHeight;
|
||||
|
||||
// resize and zoom
|
||||
// TODO: should I use the resize event?
|
||||
this.resizeObserver = new ResizeObserver(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
this.updateCanvasSize();
|
||||
this.zoomHandler();
|
||||
this.zoomHandler();
|
||||
});
|
||||
this.resizeObserver.observe(document.body);
|
||||
|
||||
const screen = window.screen;
|
||||
screen.orientation.onchange = () => {
|
||||
window.screen.orientation.onchange = () => {
|
||||
this.updateCanvasSize();
|
||||
// after an orientation change the scrolling changes, but the scroll event does not fire
|
||||
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.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) {
|
||||
this.skeletonList.push(widget);
|
||||
this.intersectionObserver!.observe(widget.getHTMLElementReference());
|
||||
@ -1028,12 +1026,13 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
const devicePixelRatio = window.devicePixelRatio;
|
||||
const tempVector = new Vector3();
|
||||
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;
|
||||
const divBounds = widget.getHTMLElementReference().getBoundingClientRect();
|
||||
divBounds.x += this.overflowLeftSize;
|
||||
divBounds.y += this.overflowTopSize;
|
||||
// need to use left and top, because x and y are not available on older browser
|
||||
divBounds.x = divBounds.left + this.overflowLeftSize;
|
||||
divBounds.y = divBounds.top + this.overflowTopSize;
|
||||
|
||||
let divOriginX = 0;
|
||||
let divOriginY = 0;
|
||||
@ -1137,8 +1136,8 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
}
|
||||
});
|
||||
|
||||
// store the draggable surface to make darg logic easier
|
||||
if (draggable) {
|
||||
// store the draggable surface to make drag logic easier
|
||||
if (isDraggable) {
|
||||
let { x: ax, y: ay, width: aw, height: ah } = bounds!;
|
||||
this.worldToScreen(tempVector, ax * skeleton.scaleX + worldOffsetX, ay * skeleton.scaleY + worldOffsetY);
|
||||
widget.dragBoundsRectangle.x = tempVector.x + window.scrollX;
|
||||
@ -1211,24 +1210,6 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
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() {
|
||||
// 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 };
|
||||
@ -1246,7 +1227,7 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
down: (x, y, ev) => {
|
||||
const input = getInput(ev);
|
||||
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)) {
|
||||
widget.dragging = true;
|
||||
ev?.preventDefault();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user