mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
Fixed multiple click events on mobile touches. Add team example.
This commit is contained in:
parent
3a279d2ff0
commit
29a30a07c1
@ -3177,6 +3177,135 @@ const darkPicker = document.getElementById("dark-picker");
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
/////////////////////
|
||||||
|
// start section //
|
||||||
|
/////////////////////
|
||||||
|
-->
|
||||||
|
<div class="section vertical-split">
|
||||||
|
<div class="split-left" style="min-height: 0;">
|
||||||
|
<p>You could use some Spine widgets to show your team.</p>
|
||||||
|
<p>Hover to the widgets to make them jump, or click on them to change randomly the default animation.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style=" background-color: #fff;">
|
||||||
|
<h2 style="text-align: center; padding: 2rem; color: #333;">Meet our team!</h2>
|
||||||
|
<div id="team-container" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; width: 100%;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const container = document.getElementById("team-container");
|
||||||
|
|
||||||
|
const members = [
|
||||||
|
{ skin: "mario", name: "Mario", role: "Developer" },
|
||||||
|
{ skin: "misaki", name: "Misaki", role: "Artist" },
|
||||||
|
{ skin: "erikari", name: "Erika", role: "Artist" },
|
||||||
|
{ skin: "nate", name: "Nate", role: "Developer" },
|
||||||
|
{ skin: "luke", name: "Luke", role: "Support" },
|
||||||
|
{ skin: "sinisa", name: "Sinisa", role: "Artist" },
|
||||||
|
{ skin: "harri", name: "Harri", role: "Developer" },
|
||||||
|
{ skin: "soeren", name: "Sören", role: "Artist" },
|
||||||
|
{ skin: "spineboy", name: "Spineboy", role: "Mascotte" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const style = document.createElement("style");
|
||||||
|
style.innerHTML = `
|
||||||
|
.team-member:hover {
|
||||||
|
transform: scale(1.25);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
|
||||||
|
members.forEach(async (member, i) => {
|
||||||
|
const div1 = document.createElement("div");
|
||||||
|
container.appendChild(div1);
|
||||||
|
div1.style.display = "flex";
|
||||||
|
div1.style.flexDirection = "column";
|
||||||
|
div1.style.alignItems = "center";
|
||||||
|
div1.style.textAlign = "center";
|
||||||
|
div1.style.backgroundColor = "#f9f9f9";
|
||||||
|
div1.style.padding = "1rem";
|
||||||
|
div1.style.borderRadius = "8px";
|
||||||
|
div1.style.boxShadow = "0 4px 6px rgba(0,0,0,0.1)";
|
||||||
|
div1.style.transition = "transform 0.3s ease";
|
||||||
|
div1.classList.add("team-member");
|
||||||
|
|
||||||
|
|
||||||
|
const div2 = document.createElement("div");
|
||||||
|
div1.appendChild(div2);
|
||||||
|
div2.style.width = "150px";
|
||||||
|
div2.style.height = "150px";
|
||||||
|
div2.style.border = "4px solid #333";
|
||||||
|
|
||||||
|
|
||||||
|
const widget = spine.createSpineWidget({
|
||||||
|
identifier: member.skin,
|
||||||
|
atlasPath: "assets/pwd/chibi-stickers-pro-pwd-test.atlas",
|
||||||
|
skeletonPath: "assets/pwd/chibi-stickers.json",
|
||||||
|
skin: member.skin,
|
||||||
|
animation: "emotes/wave",
|
||||||
|
padTop: "0.05",
|
||||||
|
padBottom: "0.05",
|
||||||
|
isInteractive: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
div2.appendChild(widget);
|
||||||
|
|
||||||
|
const div3 = document.createElement("div");
|
||||||
|
div1.appendChild(div3);
|
||||||
|
div3.style.marginTop = "15px";
|
||||||
|
div3.style.width = "100%";
|
||||||
|
|
||||||
|
const div4 = document.createElement("div");
|
||||||
|
div3.appendChild(div4);
|
||||||
|
div4.innerHTML = member.name;
|
||||||
|
div4.style.fontWeight = "bold";
|
||||||
|
div4.style.fontSize = "1.1rem";
|
||||||
|
div4.style.marginBottom = "5px";
|
||||||
|
div4.style.color = "#333";
|
||||||
|
|
||||||
|
const div5 = document.createElement("div");
|
||||||
|
div3.appendChild(div5);
|
||||||
|
div5.classList.add("team-member-role");
|
||||||
|
div5.innerHTML = member.role;
|
||||||
|
div5.style.fontSize = "0.9rem";
|
||||||
|
div5.style.color = "#666";
|
||||||
|
|
||||||
|
await widget.loadingPromise;
|
||||||
|
|
||||||
|
const emotes = widget.skeleton.data.animations.reduce((acc, { name }) => name.startsWith("emotes") ? [...acc, name] : acc, []);
|
||||||
|
let leaveAnimation = "emotes/wave";
|
||||||
|
widget.cursorBoundsEventCallback = (event) => {
|
||||||
|
if (event === "enter") widget.state.setAnimation(0, "emotes/hooray", true).mixDuration = .15;
|
||||||
|
else if (event === "leave") widget.state.setAnimation(0, leaveAnimation, true).mixDuration = .25;
|
||||||
|
else if (event === "down") {
|
||||||
|
leaveAnimation = emotes[Math.floor(Math.random() * emotes.length)];
|
||||||
|
widget.state.setAnimation(0, leaveAnimation, true).mixDuration = .25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="split-bottom">
|
||||||
|
<pre><code id="code-display">
|
||||||
|
<script>escapeHTMLandInject(`
|
||||||
|
TODO`
|
||||||
|
);</script>
|
||||||
|
</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
/////////////////////
|
||||||
|
// end section //
|
||||||
|
///////
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// start section //
|
// start section //
|
||||||
|
|||||||
@ -38,6 +38,11 @@ export class Input implements Disposable {
|
|||||||
initialPinchDistance = 0;
|
initialPinchDistance = 0;
|
||||||
private listeners = new Array<InputListener>();
|
private listeners = new Array<InputListener>();
|
||||||
private autoPreventDefault: boolean;
|
private autoPreventDefault: boolean;
|
||||||
|
|
||||||
|
// this is needed because browsers sends mousedown-mousemove-mousesup after a touch sequence, unless touch end preventDefault
|
||||||
|
// but preventing default will result in preventing interaction with the page.
|
||||||
|
private isTouch = false;
|
||||||
|
|
||||||
private callbacks: {
|
private callbacks: {
|
||||||
mouseDown: (ev: UIEvent) => void;
|
mouseDown: (ev: UIEvent) => void;
|
||||||
mouseMove: (ev: UIEvent) => void;
|
mouseMove: (ev: UIEvent) => void;
|
||||||
@ -56,7 +61,7 @@ export class Input implements Disposable {
|
|||||||
|
|
||||||
private setupCallbacks (element: HTMLElement) {
|
private setupCallbacks (element: HTMLElement) {
|
||||||
const mouseDown = (ev: UIEvent) => {
|
const mouseDown = (ev: UIEvent) => {
|
||||||
if (ev instanceof MouseEvent) {
|
if (ev instanceof MouseEvent && !this.isTouch) {
|
||||||
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;
|
||||||
@ -66,7 +71,7 @@ export class Input implements Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mouseMove = (ev: UIEvent) => {
|
const mouseMove = (ev: UIEvent) => {
|
||||||
if (ev instanceof MouseEvent) {
|
if (ev instanceof MouseEvent && !this.isTouch) {
|
||||||
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;
|
||||||
@ -82,7 +87,7 @@ export class Input implements Disposable {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const mouseUp = (ev: UIEvent) => {
|
const mouseUp = (ev: UIEvent) => {
|
||||||
if (ev instanceof MouseEvent) {
|
if (ev instanceof MouseEvent && !this.isTouch) {
|
||||||
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;
|
||||||
@ -100,6 +105,7 @@ export class Input implements Disposable {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const touchStart = (ev: TouchEvent) => {
|
const touchStart = (ev: TouchEvent) => {
|
||||||
|
this.isTouch = true;
|
||||||
if (!this.touch0 || !this.touch1) {
|
if (!this.touch0 || !this.touch1) {
|
||||||
var touches = ev.changedTouches;
|
var touches = ev.changedTouches;
|
||||||
let nativeTouch = touches.item(0);
|
let nativeTouch = touches.item(0);
|
||||||
@ -127,6 +133,7 @@ export class Input implements Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const touchMove = (ev: TouchEvent) => {
|
const touchMove = (ev: TouchEvent) => {
|
||||||
|
this.isTouch = true;
|
||||||
if (this.touch0) {
|
if (this.touch0) {
|
||||||
var touches = ev.changedTouches;
|
var touches = ev.changedTouches;
|
||||||
let rect = element.getBoundingClientRect();
|
let rect = element.getBoundingClientRect();
|
||||||
@ -156,6 +163,7 @@ export class Input implements Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const touchEnd = (ev: TouchEvent) => {
|
const touchEnd = (ev: TouchEvent) => {
|
||||||
|
this.isTouch = true;
|
||||||
if (this.touch0) {
|
if (this.touch0) {
|
||||||
var touches = ev.changedTouches;
|
var touches = ev.changedTouches;
|
||||||
let rect = element.getBoundingClientRect();
|
let rect = element.getBoundingClientRect();
|
||||||
|
|||||||
@ -1143,11 +1143,6 @@ export class SpineWebComponentWidget extends HTMLElement implements Disposable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private checkBoundsInteraction (type: CursorEventTypesInput, originalEvent?: UIEvent) {
|
private checkBoundsInteraction (type: CursorEventTypesInput, originalEvent?: UIEvent) {
|
||||||
if ((type === "down" || type === "up") && this.cursorInsideBounds) {
|
|
||||||
this.cursorBoundsEventCallback(type, originalEvent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.checkCursorInsideBounds()) {
|
if (this.checkCursorInsideBounds()) {
|
||||||
|
|
||||||
if (!this.cursorInsideBounds) {
|
if (!this.cursorInsideBounds) {
|
||||||
@ -2001,7 +1996,7 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
|
|||||||
let prevX = 0;
|
let prevX = 0;
|
||||||
let prevY = 0;
|
let prevY = 0;
|
||||||
inputManager.addListener({
|
inputManager.addListener({
|
||||||
// moved is used to pass curson position wrt to canvas and widget position and currently is EXPERIMENTAL
|
// moved is used to pass cursor position wrt to canvas and widget position and currently is EXPERIMENTAL
|
||||||
moved: (x, y, ev) => {
|
moved: (x, y, ev) => {
|
||||||
const input = getInput(ev);
|
const input = getInput(ev);
|
||||||
this.cursorUpdate(input);
|
this.cursorUpdate(input);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user