mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
Removed useless changes on other classes.
This commit is contained in:
parent
e9873147c2
commit
9399c42ec7
@ -94,7 +94,6 @@ export class AssetManagerBase implements Disposable {
|
||||
|
||||
this.assetsLoaded[path] = new Promise<any>((resolve, reject) => {
|
||||
this.downloader.downloadBinary(path, (data: Uint8Array): void => {
|
||||
// setTimeout(() => this.success(success, path, data), 10000);
|
||||
this.success(success, path, data);
|
||||
resolve(data);
|
||||
}, (status: number, responseText: string): void => {
|
||||
@ -136,7 +135,6 @@ export class AssetManagerBase implements Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: refactor assetsLoaded and assets (we should probably merge them)
|
||||
reuseAssets(path: string,
|
||||
success: (path: string, data: any) => void = () => { },
|
||||
error: (path: string, message: string) => void = () => { }) {
|
||||
@ -375,7 +373,6 @@ export class AssetManagerBase implements Disposable {
|
||||
export class Downloader {
|
||||
private callbacks: StringMap<Array<Function>> = {};
|
||||
rawDataUris: StringMap<string> = {};
|
||||
cacheTextures: Record<string, Texture> = {};
|
||||
|
||||
dataUriToString (dataUri: string) {
|
||||
if (!dataUri.startsWith("data:")) {
|
||||
|
||||
@ -1,187 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>OverlayCanvas Example</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
}
|
||||
.spine-div {
|
||||
border: 1px solid black;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.spacer {
|
||||
height: 250px;
|
||||
}
|
||||
</style>
|
||||
<script src="./spine-webgl.min.js"></script>
|
||||
<!-- <script src="../dist/iife/spine-webgl.min.js"></script> -->
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" style="position: fixed; width: 100%; height: 100%; top: 0; left: 0; pointer-events: none;"></canvas>
|
||||
|
||||
<div class="content">
|
||||
<h1>OverlayCanvas Example</h1>
|
||||
|
||||
<p>Scroll down to div.</p>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div class="spine-div" div-spine>
|
||||
<h2>Spine Box 1</h2>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div class="spine-div" div-spine>
|
||||
<h2>Spine Box 2</h2>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div class="spine-div" style="width: 50%; margin-left: 50%;" div-spine>
|
||||
<h2>Spine Box 3</h2>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div class="spine-div" style="width: 50%; margin-left: 50%;" div-raptor>
|
||||
<h2>Raptor Box</h2>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div class="spine-div" style="width: 50%; margin-left: 20%;" div-celeste>
|
||||
<h2>Celeste Box</h2>
|
||||
</div>
|
||||
|
||||
<p>End of content.</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
class App {
|
||||
constructor() {
|
||||
const selectors = ['div-spine', 'div-raptor', 'div-celeste'];
|
||||
this.selectorToDiv = selectors.reduce((acc, next) => {
|
||||
acc[next] = {
|
||||
divs: document.querySelectorAll(`[${next}]`),
|
||||
skeleton: null,
|
||||
};
|
||||
return acc;
|
||||
}, {})
|
||||
let divs = Array.from(document.querySelectorAll('[div-spine]'));
|
||||
let divRaptor = Array.from(document.querySelectorAll('[div-raptor]'))[0];
|
||||
console.log(this.selectorToDiv)
|
||||
}
|
||||
|
||||
loadAssets(canvas) {
|
||||
canvas.assetManager.loadBinary("assets/spineboy-pro.skel");
|
||||
canvas.assetManager.loadTextureAtlas("assets/spineboy-pma.atlas");
|
||||
|
||||
canvas.assetManager.loadBinary("assets/raptor-pro.skel");
|
||||
canvas.assetManager.loadTextureAtlas("assets/raptor-pma.atlas");
|
||||
|
||||
canvas.assetManager.loadBinary("assets/celestial-circus-pro.skel");
|
||||
canvas.assetManager.loadTextureAtlas("assets/celestial-circus-pma.atlas");
|
||||
}
|
||||
|
||||
initialize(canvas) {
|
||||
let assetManager = canvas.assetManager;
|
||||
this.selectorToDiv['div-spine'].skeleton = initializeSkeleton(assetManager, "assets/spineboy-pma.atlas", "assets/spineboy-pro.skel", .5, "walk");
|
||||
|
||||
this.selectorToDiv['div-raptor'].skeleton = initializeSkeleton(assetManager, "assets/raptor-pma.atlas", "assets/raptor-pro.skel", .5, "walk");
|
||||
|
||||
this.selectorToDiv['div-celeste'].skeleton = initializeSkeleton(assetManager, "assets/celestial-circus-pma.atlas", "assets/celestial-circus-pro.skel", .2, "swing");
|
||||
}
|
||||
|
||||
update(canvas, delta) {
|
||||
for (let { skeleton: { skeleton, state } } of Object.values(this.selectorToDiv)) {
|
||||
state.update(delta);
|
||||
state.apply(skeleton);
|
||||
skeleton.update(delta);
|
||||
skeleton.updateWorldTransform(spine.Physics.update);
|
||||
}
|
||||
}
|
||||
|
||||
render(canvas) {
|
||||
let renderer = canvas.renderer;
|
||||
renderer.resize(spine.ResizeMode.Expand);
|
||||
canvas.clear(0, 0, 0, 0);
|
||||
|
||||
|
||||
// webgl canvas center
|
||||
const vec3 = new spine.Vector3(0, 0);
|
||||
renderer.camera.worldToScreen(vec3, canvas.htmlCanvas.clientWidth, canvas.htmlCanvas.clientHeight);
|
||||
|
||||
// loop over the skeleton/div comination
|
||||
for (let { divs, skeleton } of Object.values(this.selectorToDiv)) {
|
||||
// loop over each div where to render the current skeleton
|
||||
for (let div of divs) {
|
||||
const rect = div.getBoundingClientRect();
|
||||
rect.x *= window.devicePixelRatio;
|
||||
rect.y *= window.devicePixelRatio;
|
||||
|
||||
// if (rect.bottom > 0 && rect.top < window.innerHeight) {
|
||||
// renderer.drawSkeleton(skeleton.skeleton, true, -1, -1, (vertices, size, vertexSize) => {
|
||||
// for (let i = 0; i < size; i+=vertexSize) {
|
||||
// vertices[i] = vertices[i] + rect.x - vec3.x * window.devicePixelRatio;
|
||||
// vertices[i+1] = vertices[i+1] - rect.y + vec3.y * window.devicePixelRatio;
|
||||
// }
|
||||
// });
|
||||
renderer.begin();
|
||||
skeleton.skeleton.x = rect.x - vec3.x * window.devicePixelRatio;
|
||||
skeleton.skeleton.y = - rect.y + vec3.y * window.devicePixelRatio;
|
||||
|
||||
renderer.drawSkeleton(skeleton.skeleton, true);
|
||||
|
||||
// show center
|
||||
const root = skeleton.skeleton.getRootBone();
|
||||
const vec3Root = new spine.Vector3(root.x, root.y);
|
||||
renderer.camera.worldToScreen(vec3Root, canvas.htmlCanvas.clientWidth, canvas.htmlCanvas.clientHeight);
|
||||
renderer.circle(
|
||||
true,
|
||||
rect.x - vec3.x * window.devicePixelRatio,
|
||||
-rect.y + vec3.y * window.devicePixelRatio,
|
||||
20,
|
||||
{ r: 1, g: 0, b: 0, a: .5 });
|
||||
renderer.end();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// Complete rendering.
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const htmlCanvas = document.getElementById("canvas");
|
||||
new spine.SpineCanvas(htmlCanvas, {
|
||||
app: new App()
|
||||
})
|
||||
|
||||
|
||||
function initializeSkeleton(assetManager, atlas, skeletonFile, scale, animation) {
|
||||
var atlas = assetManager.require(atlas);
|
||||
var atlasLoader = new spine.AtlasAttachmentLoader(atlas);
|
||||
var skeletonBinary = new spine.SkeletonBinary(atlasLoader);
|
||||
skeletonBinary.scale = scale;
|
||||
var skeletonData = skeletonBinary.readSkeletonData(assetManager.require(skeletonFile));
|
||||
const skeleton = new spine.Skeleton(skeletonData);
|
||||
var animationStateData = new spine.AnimationStateData(skeletonData);
|
||||
const animationState = new spine.AnimationState(animationStateData);
|
||||
animationState.setAnimation(0, animation, true);
|
||||
return { skeleton, state: animationState }
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,382 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>OverlayCanvas Example</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
}
|
||||
.spine-div {
|
||||
border: 1px solid black;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.spacer {
|
||||
height: 250px;
|
||||
}
|
||||
#canvas {
|
||||
will-change: transform;
|
||||
}
|
||||
</style>
|
||||
<script src="../dist/iife/spine-webgl.js"></script>
|
||||
<!-- <script src="./spine-webgl.min.js"></script> -->
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" style="display: none;"></canvas>
|
||||
|
||||
<div class="content">
|
||||
<h1>OverlayCanvas Example</h1>
|
||||
|
||||
<p>Scroll down to div.</p>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div class="spine-div" div-spine>
|
||||
<h2>Spine Box 1</h2>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div id="spineboy2" class="spine-div" style="width: 50%; margin-left: 50%; touch-action:none" div-spine>
|
||||
<h2>Spine Box 2 (drag me)</h2>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div id="raptor" class="spine-div" style="width: 50%; margin-left: 50%; transition: transform 1s linear;" div-raptor>
|
||||
<h2>Raptor Box</h2>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div class="spine-div" style="width: 50%; margin-left: 20%;" div-celeste>
|
||||
<h2>Celeste Box</h2>
|
||||
</div>
|
||||
|
||||
<p>End of content.</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let selectorToDiv;
|
||||
class App {
|
||||
constructor() {
|
||||
const selectors = ['div-spine', 'div-raptor', 'div-celeste'];
|
||||
selectorToDiv = selectors.reduce((acc, next) => {
|
||||
const divs = document.querySelectorAll(`[${next}]`);
|
||||
acc[next] = {
|
||||
divs: [...document.querySelectorAll(`[${next}]`)].map(div => {
|
||||
const position = {};
|
||||
return { div, position };
|
||||
}),
|
||||
skeleton: null,
|
||||
};
|
||||
return acc;
|
||||
}, {})
|
||||
}
|
||||
|
||||
loadAssets(canvas) {
|
||||
canvas.assetManager.loadBinary("assets/spineboy-pro.skel");
|
||||
canvas.assetManager.loadTextureAtlas("assets/spineboy-pma.atlas");
|
||||
|
||||
canvas.assetManager.loadBinary("assets/raptor-pro.skel");
|
||||
canvas.assetManager.loadTextureAtlas("assets/raptor-pma.atlas");
|
||||
|
||||
canvas.assetManager.loadBinary("assets/celestial-circus-pro.skel");
|
||||
canvas.assetManager.loadTextureAtlas("assets/celestial-circus-pma.atlas");
|
||||
}
|
||||
|
||||
prevScrollLeft = 0;
|
||||
prevScrollTop = 0;
|
||||
initialize(canvas) {
|
||||
let assetManager = canvas.assetManager;
|
||||
selectorToDiv['div-spine'].skeleton = initializeSkeleton(assetManager, "assets/spineboy-pma.atlas", "assets/spineboy-pro.skel", .5, "walk");
|
||||
|
||||
selectorToDiv['div-raptor'].skeleton = initializeSkeleton(assetManager, "assets/raptor-pma.atlas", "assets/raptor-pro.skel", .5, "walk");
|
||||
|
||||
selectorToDiv['div-celeste'].skeleton = initializeSkeleton(assetManager, "assets/celestial-circus-pma.atlas", "assets/celestial-circus-pro.skel", .2, "swing");
|
||||
|
||||
window.addEventListener('scroll', () => {
|
||||
// console.log("canceling: " + canvas.reqAnimationFrameId);
|
||||
// cancelAnimationFrame(canvas.reqAnimationFrameId);
|
||||
// canvas.loop();
|
||||
// console.log(this.prevScrollTop, window.pageYOffset, this.prevScrollTop === window.pageYOffset);
|
||||
// this.prevScrollTop = window.pageYOffset;
|
||||
// this.render(canvas, true);
|
||||
});
|
||||
window.addEventListener('resize', () => {
|
||||
canvas.renderer.resize(spine.ResizeMode.Expand);
|
||||
});
|
||||
const bodyObserver = new ResizeObserver(() => {
|
||||
canvas.renderer.resize(spine.ResizeMode.Expand);
|
||||
});
|
||||
bodyObserver.observe(document.body);
|
||||
canvas.renderer.resize(spine.ResizeMode.Expand);
|
||||
}
|
||||
|
||||
update(canvas, delta) {
|
||||
for (let { skeleton: { skeleton, state } } of Object.values(selectorToDiv)) {
|
||||
state.update(delta);
|
||||
state.apply(skeleton);
|
||||
skeleton.update(delta);
|
||||
skeleton.updateWorldTransform(spine.Physics.update);
|
||||
}
|
||||
}
|
||||
|
||||
render(canvas, scroll) {
|
||||
let renderer = canvas.renderer;
|
||||
// renderer.resize(spine.ResizeMode.Expand);
|
||||
canvas.clear(0, 0, 0, 0);
|
||||
renderer.begin();
|
||||
|
||||
// webgl canvas center
|
||||
const vec3 = new spine.Vector3(0, 0);
|
||||
renderer.camera.worldToScreen(vec3, canvas.htmlCanvas.clientWidth, canvas.htmlCanvas.clientHeight);
|
||||
|
||||
// loop over the skeleton/div comination
|
||||
for (const { divs, skeleton } of Object.values(selectorToDiv)) {
|
||||
// loop over each div where to render the current skeleton
|
||||
for (const { position, div } of divs) {
|
||||
|
||||
// const rect = div.getBoundingClientRect();
|
||||
// rect.x *= window.devicePixelRatio;
|
||||
// rect.y *= window.devicePixelRatio;
|
||||
|
||||
|
||||
// TODO-WIP: experiment with caching div position to prevent the transform in the for loop
|
||||
// Need to find a reliable way to get notified when div origin change position
|
||||
let { x, y } = position;
|
||||
if (x === undefined || y === undefined) {
|
||||
const bounds = div.getBoundingClientRect();
|
||||
x = bounds.x;
|
||||
y = bounds.y;
|
||||
} else {
|
||||
const bounds = div.getBoundingClientRect();
|
||||
x = bounds.x;
|
||||
y = bounds.y;
|
||||
}
|
||||
|
||||
const scrollTop = window.pageYOffset;
|
||||
const scrollLeft = window.pageXOffset;
|
||||
position.x = (x + scrollLeft) * window.devicePixelRatio;
|
||||
position.y = (y + scrollTop) * window.devicePixelRatio;
|
||||
const rect = { x: position.x, y: position.y };
|
||||
|
||||
// if (rect.bottom > 0 && rect.top < window.innerHeight) {
|
||||
// renderer.drawSkeleton(skeleton.skeleton, true, -1, -1, (vertices, size, vertexSize) => {
|
||||
// for (let i = 0; i < size; i+=vertexSize) {
|
||||
// vertices[i] = vertices[i] + rect.x - vec3.x * window.devicePixelRatio;
|
||||
// vertices[i+1] = vertices[i+1] - rect.y + vec3.y * window.devicePixelRatio;
|
||||
// }
|
||||
// });
|
||||
|
||||
// if (position.x == rect.x && position.y == rect.y) {
|
||||
// renderer.drawSkeleton(skeleton.skeleton, true);
|
||||
// } else {
|
||||
renderer.drawSkeleton(skeleton.skeleton, true, -1, -1, (vertices, size, vertexSize) => {
|
||||
for (let i = 0; i < size; i+=vertexSize) {
|
||||
vertices[i] = vertices[i] + rect.x - vec3.x * window.devicePixelRatio;
|
||||
vertices[i+1] = vertices[i+1] - rect.y + vec3.y * window.devicePixelRatio;
|
||||
}
|
||||
});
|
||||
// position.x = rect.x;
|
||||
// position.y = rect.y;
|
||||
// }
|
||||
|
||||
// skeleton.skeleton.x = rect.x - vec3.x * window.devicePixelRatio,
|
||||
// skeleton.skeleton.y = -rect.y + vec3.y * window.devicePixelRatio,
|
||||
// renderer.drawSkeleton(skeleton.skeleton, true);
|
||||
|
||||
// show center
|
||||
const root = skeleton.skeleton.getRootBone();
|
||||
const vec3Root = new spine.Vector3(root.x, root.y);
|
||||
renderer.camera.worldToScreen(vec3Root, canvas.htmlCanvas.clientWidth, canvas.htmlCanvas.clientHeight);
|
||||
renderer.circle(
|
||||
true,
|
||||
rect.x - vec3.x * window.devicePixelRatio,
|
||||
-rect.y + vec3.y * window.devicePixelRatio,
|
||||
20,
|
||||
{ r: 1, g: 0, b: 0, a: 1 }
|
||||
);
|
||||
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// Complete rendering.
|
||||
renderer.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const htmlCanvas = document.getElementById("canvas");
|
||||
function updateCanvasSize(htmlCanvas) {
|
||||
htmlCanvas.style.position = 'absolute';
|
||||
htmlCanvas.style.top = '0';
|
||||
htmlCanvas.style.left = '0';
|
||||
const pageSize = getPageSize();
|
||||
htmlCanvas.style.width = pageSize.width + 'px';
|
||||
htmlCanvas.style.height = pageSize.height + 'px';
|
||||
htmlCanvas.style.display = 'inline';
|
||||
htmlCanvas.style["pointer-events"] = 'none';
|
||||
}
|
||||
|
||||
const app = new spine.SpineCanvas(htmlCanvas, {
|
||||
app: new App()
|
||||
})
|
||||
|
||||
|
||||
function initializeSkeleton(assetManager, atlas, skeletonFile, scale, animation) {
|
||||
var atlas = assetManager.require(atlas);
|
||||
var atlasLoader = new spine.AtlasAttachmentLoader(atlas);
|
||||
var skeletonBinary = new spine.SkeletonBinary(atlasLoader);
|
||||
skeletonBinary.scale = scale;
|
||||
var skeletonData = skeletonBinary.readSkeletonData(assetManager.require(skeletonFile));
|
||||
const skeleton = new spine.Skeleton(skeletonData);
|
||||
var animationStateData = new spine.AnimationStateData(skeletonData);
|
||||
const animationState = new spine.AnimationState(animationStateData);
|
||||
animationState.setAnimation(0, animation, true);
|
||||
return { skeleton, state: animationState }
|
||||
}
|
||||
|
||||
function getPageSize() {
|
||||
const width = Math.max(
|
||||
document.body.scrollWidth,
|
||||
document.documentElement.scrollWidth,
|
||||
document.body.offsetWidth,
|
||||
document.documentElement.offsetWidth,
|
||||
document.documentElement.clientWidth
|
||||
);
|
||||
|
||||
const height = Math.max(
|
||||
document.body.scrollHeight,
|
||||
document.documentElement.scrollHeight,
|
||||
document.body.offsetHeight,
|
||||
document.documentElement.offsetHeight,
|
||||
document.documentElement.clientHeight
|
||||
);
|
||||
|
||||
return { width, height };
|
||||
}
|
||||
|
||||
const canvasXY = htmlCanvas.getBoundingClientRect()
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
updateCanvasSize(htmlCanvas);
|
||||
});
|
||||
resizeObserver.observe(document.body);
|
||||
|
||||
|
||||
//////////
|
||||
//////////
|
||||
//////////
|
||||
//////////
|
||||
//////////
|
||||
|
||||
function addRandomDiv() {
|
||||
const div = document.createElement('div');
|
||||
div.style.width = Math.floor(Math.random() * 200 + 100) + 'px';
|
||||
div.style.height = Math.floor(Math.random() * 100 + 50) + 'px';
|
||||
div.style.margin = '10px';
|
||||
div.style.touchAction = 'none';
|
||||
div.className = 'spine-div';
|
||||
const divType = getRandomSpineDiv();
|
||||
div.setAttribute(divType, '');
|
||||
div.innerText = "Drag me";
|
||||
|
||||
console.log(app)
|
||||
selectorToDiv[divType].divs.push({ div, position: {} });
|
||||
|
||||
makeDraggable(div);
|
||||
document.body.appendChild(div);
|
||||
}
|
||||
|
||||
function getRandomSpineDiv() {
|
||||
const divs = ['div-spine', 'div-raptor', 'div-celeste'];
|
||||
return divs[Math.floor(Math.random() * 3)];
|
||||
}
|
||||
|
||||
// Add a button to trigger new div creation
|
||||
const addDivButton = document.createElement('button');
|
||||
addDivButton.textContent = 'Add New Div at the bottome of the page';
|
||||
addDivButton.style.position = 'fixed';
|
||||
addDivButton.style.top = '10px';
|
||||
addDivButton.style.left = '10px';
|
||||
addDivButton.style.zIndex = '1000';
|
||||
addDivButton.addEventListener('click', addRandomDiv);
|
||||
document.body.appendChild(addDivButton);
|
||||
|
||||
|
||||
|
||||
//////
|
||||
//////
|
||||
//////
|
||||
//////
|
||||
//////
|
||||
|
||||
let isMovingRight = true;
|
||||
setInterval(() => {
|
||||
const div = document.getElementById('raptor');
|
||||
let position = isMovingRight ? 50 : -50;
|
||||
isMovingRight = !isMovingRight;
|
||||
div.style.transform = `translateX(${position}px)`;
|
||||
}, 1000)
|
||||
|
||||
|
||||
|
||||
function makeDraggable(element) {
|
||||
let isDragging = false;
|
||||
let startX, startY;
|
||||
let originalX, originalY;
|
||||
|
||||
element.addEventListener('pointerdown', startDragging);
|
||||
document.addEventListener('pointermove', drag);
|
||||
document.addEventListener('pointerup', stopDragging);
|
||||
|
||||
function startDragging(e) {
|
||||
isDragging = true;
|
||||
startX = e.clientX;
|
||||
startY = e.clientY;
|
||||
|
||||
const translate = element.style.transform;
|
||||
if (translate !== '') {
|
||||
// Extract the translate values from the transform string
|
||||
const translateValues = translate.match(/translate\(([^)]+)\)/)[1].split(', ');
|
||||
originalX = parseFloat(translateValues[0]);
|
||||
originalY = parseFloat(translateValues[1]);
|
||||
} else {
|
||||
// If there is no transform, return 0,0
|
||||
originalX = 0;
|
||||
originalY = 0;
|
||||
}
|
||||
|
||||
// Prevent text selection during drag
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function drag(e) {
|
||||
if (!isDragging) return;
|
||||
|
||||
const deltaX = e.clientX - startX;
|
||||
const deltaY = e.clientY - startY;
|
||||
|
||||
element.style.transform = `translate(${originalX + deltaX}px, ${originalY + deltaY}px)`;
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function stopDragging(e) {
|
||||
isDragging = false;
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
const draggableDiv = document.getElementById('spineboy2');
|
||||
makeDraggable(draggableDiv);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,324 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WebGL Overlay Example</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
/* top: 0;
|
||||
left: 0; */
|
||||
}
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
}
|
||||
.spine-div {
|
||||
border: 1px solid black;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
position:relative;
|
||||
touch-action:none;
|
||||
}
|
||||
.spacer {
|
||||
height: 250px;
|
||||
}
|
||||
#canvas {
|
||||
/* will-change: transform; */
|
||||
}
|
||||
|
||||
</style>
|
||||
<script src="../dist/iife/spine-webgl.js"></script>
|
||||
<!-- <script src="./spine-webgl.min.js"></script> -->
|
||||
<!-- <script src="./spine-webgl.js"></script> -->
|
||||
</head>
|
||||
<body>
|
||||
<span id="fps" style="position: fixed; top: 0; left: 0">a</span>
|
||||
|
||||
<div class="content">
|
||||
|
||||
<div id="spineboy1" class="spine-div" style="width: 200px; height: 300px; margin-left: 200px;" div-spine>
|
||||
<h2>Drag and resize me</h2>
|
||||
<h3>Mode: inside</h3>
|
||||
<h4>Spineboy will be resize to remain into the div.</h4>
|
||||
<h4>Skeleton cannot be reused (side effect on skeleton scale).</h4>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div id="spineboy2" class="spine-div" style="width: 50%; margin-left: 50%;" div-spine2>
|
||||
<h2>Drag me</h2>
|
||||
<h3>Mode: origin</h3>
|
||||
<h4>You can easily change the position using offset or percentage of html element axis (origin is top-left)</h4>
|
||||
<h4>Skeleton can be reused.</h4>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div id="spineboy3" class="spine-div" style="width: 50%; margin-left: 50%;" div-spine2>
|
||||
<h3>Skeleton of previous box is being reused here</h3>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div id="spineboy4" class="spine-div" div-spine3>
|
||||
<h3>Initializer with NodeList</h3>
|
||||
</div>
|
||||
<div id="spineboy5" class="spine-div" div-spine3>
|
||||
<h3>Initializer with NodeList</h3>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div id="spineboy6" class="spine-div" style="width: 50%; height: 200px;" div-spine4>
|
||||
<h3>Initializer with HTMLElement</h3>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div id="spineboy7" class="spine-div" style="width: 50%; height: 200px;" div-spine5>
|
||||
<h3>Bounds using a Spine ounding box</h3>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<p>End of content.</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const divs = document.querySelectorAll(`[div-spine]`);
|
||||
const overlay = new spine.SpineCanvasOverlay();
|
||||
|
||||
const p = overlay.addSkeleton(
|
||||
{
|
||||
atlasPath: "assets/spineboy-pma.atlas",
|
||||
skeletonPath: "assets/spineboy-pro.skel",
|
||||
scale: .5,
|
||||
animation: 'walk',
|
||||
},
|
||||
[
|
||||
{
|
||||
element: divs[0],
|
||||
mode: 'inside',
|
||||
// showBounds: true,
|
||||
draggable: true,
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
// setTimeout(async () => {
|
||||
// const { skeleton, state } = await p;
|
||||
// state.setAnimation(0, "portal", true);
|
||||
// overlay.recalculateBounds(skeleton);
|
||||
// }, 1000)
|
||||
|
||||
const divs2 = document.querySelectorAll(`[div-spine2]`);
|
||||
const p2 = overlay.addSkeleton({
|
||||
atlasPath: "assets/celestial-circus-pma.atlas",
|
||||
skeletonPath: "assets/celestial-circus-pro.skel",
|
||||
animation: 'wings-and-feet',
|
||||
scale: .25,
|
||||
},
|
||||
[
|
||||
{
|
||||
element: divs2[0],
|
||||
mode: 'origin',
|
||||
// showBounds: true,
|
||||
xAxis: .5,
|
||||
yAxis: 1,
|
||||
draggable: true,
|
||||
},
|
||||
{
|
||||
element: divs2[1],
|
||||
mode: 'origin',
|
||||
showBounds: true,
|
||||
offsetX: 100,
|
||||
offsetY: -50
|
||||
},
|
||||
],);
|
||||
|
||||
p2.then(({ state }) => state.setAnimation(1, "eyeblink", true));
|
||||
|
||||
const divs3 = document.querySelectorAll(`[div-spine3]`);
|
||||
const p3 = overlay.addSkeleton({
|
||||
atlasPath: "assets/raptor-pma.atlas",
|
||||
skeletonPath: "assets/raptor-pro.skel",
|
||||
animation: 'walk',
|
||||
scale: .5,
|
||||
}, divs3);
|
||||
|
||||
const divs4 = document.querySelectorAll(`[div-spine4]`);
|
||||
const p4 = overlay.addSkeleton({
|
||||
atlasPath: "assets/tank-pma.atlas",
|
||||
skeletonPath: "assets/tank-pro.skel",
|
||||
animation: 'shoot',
|
||||
scale: .5,
|
||||
}, [{
|
||||
element: divs4[0],
|
||||
showBounds: true,
|
||||
}]);
|
||||
|
||||
const divs5 = document.querySelectorAll(`[div-spine5]`);
|
||||
const p5 = overlay.addSkeleton({
|
||||
atlasPath: "assets/spineboy-pma.atlas",
|
||||
skeletonPath: "assets/spineboy-pro.skel",
|
||||
animation: 'walk',
|
||||
update: (_, delta, skeleton, state) => {
|
||||
state.update(delta / 3);
|
||||
state.apply(skeleton);
|
||||
skeleton.update(delta / 3);
|
||||
skeleton.updateWorldTransform(spine.Physics.update);
|
||||
}
|
||||
}, [{
|
||||
element: divs5[0],
|
||||
showBounds: true,
|
||||
mode: 'inside',
|
||||
draggable: true,
|
||||
}]);
|
||||
|
||||
p5.then(({ skeleton }) => {
|
||||
const bbAttachmentSlot = skeleton.findSlot("head-bb");
|
||||
const currentAttachment = bbAttachmentSlot.attachment;
|
||||
skeleton.setAttachment("head-bb", "head");
|
||||
const bbAttachment = bbAttachmentSlot.attachment;
|
||||
|
||||
const computedVertices = [];
|
||||
bbAttachment.computeWorldVertices(bbAttachmentSlot, 0, bbAttachment.worldVerticesLength, computedVertices, 0, 2);
|
||||
const vertices = computedVertices;
|
||||
let x = Infinity, maxX = -Infinity, y = Infinity, maxY = -Infinity;
|
||||
for (let i = 0; i < vertices.length; i+=2) {
|
||||
x = Math.min(vertices[i], x);
|
||||
y = Math.min(vertices[i+1], y);
|
||||
maxX = Math.max(vertices[i], maxX);
|
||||
maxY = Math.max(vertices[i+1], maxY);
|
||||
}
|
||||
|
||||
const width = maxX - x;
|
||||
const height = maxY - y;
|
||||
console.log({ x, y, width, height })
|
||||
overlay.setBounds(skeleton, { x, y, width, height })
|
||||
bbAttachmentSlot.setAttachment(currentAttachment)
|
||||
})
|
||||
|
||||
|
||||
// setTimeout(async () => {
|
||||
// overlay.dispose();
|
||||
// }, 2000)
|
||||
|
||||
|
||||
makeResizable(document.getElementById('spineboy1'))
|
||||
// makeDraggable(document.getElementById('spineboy1'));
|
||||
makeResizable(document.getElementById('spineboy2'))
|
||||
makeDraggable(document.getElementById('spineboy2'));
|
||||
makeResizable(document.getElementById('spineboy7'))
|
||||
makeDraggable(document.getElementById('spineboy7'));
|
||||
makeResizable(document.getElementById('spineboy3'))
|
||||
makeDraggable(document.getElementById('spineboy3'));
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
// Drag utility
|
||||
|
||||
|
||||
function makeDraggable(element) {
|
||||
let isDragging = false;
|
||||
let startX, startY;
|
||||
let originalX, originalY;
|
||||
|
||||
element.addEventListener('pointerdown', startDragging);
|
||||
document.addEventListener('pointermove', drag);
|
||||
document.addEventListener('pointerup', stopDragging);
|
||||
|
||||
function startDragging(e) {
|
||||
if (e.target === element.querySelector('#resizeHandle')) return;
|
||||
|
||||
isDragging = true;
|
||||
startX = e.clientX;
|
||||
startY = e.clientY;
|
||||
|
||||
const translate = element.style.transform;
|
||||
if (translate !== '') {
|
||||
const translateValues = translate.match(/translate\(([^)]+)\)/)[1].split(', ');
|
||||
originalX = parseFloat(translateValues[0]);
|
||||
originalY = parseFloat(translateValues[1]);
|
||||
} else {
|
||||
originalX = 0;
|
||||
originalY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function drag(e) {
|
||||
if (!isDragging) return;
|
||||
|
||||
const deltaX = e.clientX - startX;
|
||||
const deltaY = e.clientY - startY;
|
||||
|
||||
element.style.transform = `translate(${originalX + deltaX}px, ${originalY + deltaY}px)`;
|
||||
}
|
||||
|
||||
function stopDragging(e) {
|
||||
isDragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
// Resize utility
|
||||
|
||||
function makeResizable(element) {
|
||||
const resizeHandle = document.createElement('div');
|
||||
element.appendChild(resizeHandle);
|
||||
resizeHandle.id = "resizeHandle";
|
||||
resizeHandle.style.width = "20%";
|
||||
resizeHandle.style.height = "20%";
|
||||
resizeHandle.style.bottom = "0";
|
||||
resizeHandle.style.right = "0";
|
||||
resizeHandle.style.position = "absolute";
|
||||
resizeHandle.style["background-color"] = "#007bff";
|
||||
resizeHandle.style["cursor"] = "se-resize";
|
||||
|
||||
let isResizing = false;
|
||||
let startX, startY, startWidth, startHeight, startPaddingLeft, startPaddingRight, startPaddingTop, startPaddingBottom;
|
||||
|
||||
resizeHandle.addEventListener('pointerdown', initResize);
|
||||
|
||||
function initResize(e) {
|
||||
isResizing = true;
|
||||
startX = e.clientX;
|
||||
startY = e.clientY;
|
||||
startWidth = element.offsetWidth;
|
||||
startHeight = element.offsetHeight;
|
||||
startPaddingLeft = parseFloat(window.getComputedStyle(element).paddingLeft);
|
||||
startPaddingRight = parseFloat(window.getComputedStyle(element).paddingRight);
|
||||
startPaddingTop = parseFloat(window.getComputedStyle(element).paddingTop);
|
||||
startPaddingBottom = parseFloat(window.getComputedStyle(element).paddingBottom);
|
||||
document.addEventListener('pointermove', resize);
|
||||
document.addEventListener('pointerup', stopResize);
|
||||
}
|
||||
|
||||
function resize(e) {
|
||||
if (!isResizing) return;
|
||||
const width = startWidth + (e.clientX - startX) - startPaddingLeft - startPaddingRight;
|
||||
const height = startHeight + (e.clientY - startY) - startPaddingTop - startPaddingBottom;
|
||||
element.style.width = width + 'px';
|
||||
element.style.height = height + 'px';
|
||||
}
|
||||
|
||||
function stopResize() {
|
||||
isResizing = false;
|
||||
document.removeEventListener('pointermove', resize);
|
||||
document.removeEventListener('pointerup', stopResize);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,831 +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>
|
||||
<!-- <script src="./spine-webgl.js"></script> -->
|
||||
<title>JS Library Showcase</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
.section {
|
||||
/* height: 100lvh; */
|
||||
/* height: 800px; */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
background-color: #3498db;
|
||||
}
|
||||
.split {
|
||||
display: flex;
|
||||
}
|
||||
.split-left, .split-right {
|
||||
width: 50%;
|
||||
min-height: 50%;
|
||||
padding: 1rem;
|
||||
margin: 1rem;
|
||||
border: 1px solid salmon;
|
||||
}
|
||||
.split-nosize {
|
||||
/* padding: 1rem; */
|
||||
/* margin: 1rem; */
|
||||
border: 1px solid salmon;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
|
||||
.split-top {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.split-bottom {
|
||||
width: 100%;
|
||||
/* height: 600px; */
|
||||
}
|
||||
|
||||
.split-top {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<span id="fps" style="position: fixed; top: 0; left: 0">FPS</span>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 0 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section0" class="section vertical-split">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left">
|
||||
aaa
|
||||
</div>
|
||||
<div class="split-right" id="section0-element">
|
||||
<spine identifier="section0" createDiv="true" width="220" height="50"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 0 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 1 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section1" class="section vertical-split">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left" id="section1-element">
|
||||
</div>
|
||||
<div class="split-right">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
const overlay = new spine.SpineCanvasOverlay();
|
||||
overlay.addSkeleton(
|
||||
{
|
||||
atlasPath: "assets/spineboy-pma.atlas",
|
||||
skeletonPath: "assets/spineboy-pro.skel",
|
||||
animation: 'walk',
|
||||
},
|
||||
document.getElementById(`section1-element`),
|
||||
);
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 1 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 2 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section2" class="section vertical-split">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left">
|
||||
Mode <code>origin</code> uses the HTML element top-left corner as origin for the skeleton. <br>
|
||||
You are responsible to scale the skeleton using this mode. <br>
|
||||
Move the origin by a percentage of the div width and height by using <code>xAxis</code> and <code>yAxis</code> respectively.
|
||||
</div>
|
||||
<div class="split-right" id="section2-element">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
overlay.addSkeleton(
|
||||
{
|
||||
atlasPath: "assets/spineboy-pma.atlas",
|
||||
skeletonPath: "assets/spineboy-pro.skel",
|
||||
animation: 'run',
|
||||
scale: .25,
|
||||
},
|
||||
{
|
||||
element: document.getElementById(`section2-element`),
|
||||
mode: 'origin',
|
||||
xAxis: .5,
|
||||
yAxis: 1,
|
||||
},
|
||||
);
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 2 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 3 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section3" class="section vertical-split">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left" id="section3-element">
|
||||
</div>
|
||||
<div class="split-right">
|
||||
Use <code>offsetX</code> and <code>offsetY</code> to move you skeleton left or right by the pixel amount you specify.
|
||||
This works for both mode <code>origin</code> and <code>inside</code>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
overlay.addSkeleton(
|
||||
{
|
||||
atlasPath: "assets/spineboy-pma.atlas",
|
||||
skeletonPath: "assets/spineboy-pro.skel",
|
||||
animation: 'run',
|
||||
},
|
||||
{
|
||||
element: document.getElementById(`section3-element`),
|
||||
mode: 'inside', // default
|
||||
offsetX: 100,
|
||||
offsetY: 50,
|
||||
},
|
||||
);
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 3 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 4 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section4" class="section vertical-split">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left">
|
||||
You can easily access the <code>Skeleton</code> and the <code>AnimationState</code> of your character, and use them as if you were using <code>spine-webgl</code>. <br>
|
||||
If you change animation, you can ask to scale the skeleton based on the new animation.
|
||||
</div>
|
||||
<div class="split-right" id="section4-element">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
// access the skeleton and the state asynchronously
|
||||
const { skeleton, state } = await overlay.addSkeleton(
|
||||
{
|
||||
atlasPath: "assets/raptor-pma.atlas",
|
||||
skeletonPath: "assets/raptor-pro.skel",
|
||||
animation: 'walk',
|
||||
},
|
||||
document.getElementById(`section4-element`)
|
||||
);
|
||||
|
||||
let isRoaring = false;
|
||||
setInterval(() => {
|
||||
const newAnimation = isRoaring ? "walk" : "roar";
|
||||
state.setAnimation(0, newAnimation, true);
|
||||
overlay.recalculateBounds(skeleton); // scale the skeleton based on the new animation
|
||||
isRoaring = !isRoaring;
|
||||
}, 4000);
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 4 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 5 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section5" class="section vertical-split">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left">
|
||||
You can also set a custom bounds to center a specific element or area of you animation in the div.
|
||||
</div>
|
||||
<div class="split-right" id="section5-element">
|
||||
TODO
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 5 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 6 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section6" class="section vertical-split">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left">
|
||||
Moving the div will move the skeleton origin. <br>
|
||||
Resizing the div will resize the skeleton in <code>inside</code> mode, but not in <code>origin</code> mode.
|
||||
</div>
|
||||
<div class="split-right" id="section6-element">
|
||||
</div>
|
||||
</div>
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
overlay.addSkeleton(
|
||||
{
|
||||
atlasPath: "assets/cloud-pot-pma.atlas",
|
||||
skeletonPath: "assets/cloud-pot.skel",
|
||||
animation: 'playing-in-the-rain',
|
||||
},
|
||||
document.getElementById(`section6-element`)
|
||||
);
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 6 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 7 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section7" class="section vertical-split">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left">
|
||||
You can view the skeleton world origin (green), the root bone position (red), and the bounds rectangle and center (blue) by setting <code>debug</code> to <code>true</code>.
|
||||
</div>
|
||||
<div class="split-right" id="section7-element">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
overlay.addSkeleton(
|
||||
{
|
||||
atlasPath: "assets/owl-pma.atlas",
|
||||
skeletonPath: "assets/owl-pro.skel",
|
||||
animation: 'idle',
|
||||
},
|
||||
{
|
||||
element: document.getElementById(`section7-element`),
|
||||
debug: true,
|
||||
}
|
||||
);
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 7 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 8 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section8" class="section vertical-split">
|
||||
|
||||
<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>.
|
||||
</div>
|
||||
<div class="split-right" id="section8-element">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="split-bottom">
|
||||
<pre><code id="code-display">
|
||||
overlay.addSkeleton(
|
||||
{
|
||||
atlasPath: "assets/celestial-circus-pma.atlas",
|
||||
skeletonPath: "assets/celestial-circus-pro.skel",
|
||||
animation: 'wings-and-feet',
|
||||
},
|
||||
{
|
||||
element: document.getElementById(`section8-element`),
|
||||
draggable: true,
|
||||
}
|
||||
);
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 8 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
|
||||
<!-- <div class="navigation">
|
||||
<button class="nav-btn" onclick="scrollToSection('section1')">1</button>
|
||||
<button class="nav-btn" onclick="scrollToSection('section2')">2</button>
|
||||
<button class="nav-btn" onclick="scrollToSection('section3')">3</button>
|
||||
<button class="nav-btn" onclick="scrollToSection('section4')">4</button>
|
||||
<button class="nav-btn" onclick="scrollToSection('section5')">5</button>
|
||||
<button class="nav-btn" onclick="scrollToSection('section6')">6</button>
|
||||
<button class="nav-btn" onclick="scrollToSection('section7')">7</button>
|
||||
<button class="nav-btn" onclick="scrollToSection('section8')">8</button>
|
||||
</div> -->
|
||||
|
||||
<script>
|
||||
function scrollToSection(id) {
|
||||
document.getElementById(id).scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
|
||||
let sections = document.querySelectorAll('.section');
|
||||
let currentSection = 0;
|
||||
|
||||
// window.addEventListener('wheel', (e) => {
|
||||
// if (e.deltaY > 0 && currentSection < sections.length - 1) {
|
||||
// currentSection++;
|
||||
// } else if (e.deltaY < 0 && currentSection > 0) {
|
||||
// currentSection--;
|
||||
// }
|
||||
// sections[currentSection].scrollIntoView({ behavior: 'smooth' });
|
||||
// });
|
||||
</script>
|
||||
|
||||
<script>
|
||||
(async () => {
|
||||
const overlay = new spine.SpineCanvasOverlay();
|
||||
|
||||
// overlay.addSkeleton(
|
||||
// {
|
||||
// atlasPath: "assets/spineboy-pma.atlas",
|
||||
// skeletonPath: "assets/spineboy-pro.skel",
|
||||
// // scale: 1,
|
||||
// // animation: 'walk',
|
||||
// },
|
||||
// {
|
||||
// mode: "origin",
|
||||
// xAxis: 1,
|
||||
// yAxis: 1,
|
||||
// element: document.querySelectorAll(`#section1-element`)[0],
|
||||
// debug: true
|
||||
// }
|
||||
// );
|
||||
|
||||
/////////////////////
|
||||
// start section 1 //
|
||||
/////////////////////
|
||||
overlay.addSkeleton(
|
||||
{
|
||||
atlasPath: "assets/spineboy-pma.atlas",
|
||||
skeletonPath: "assets/spineboy-pro.skel",
|
||||
animation: 'walk',
|
||||
},
|
||||
[
|
||||
{
|
||||
identifier: `section0`,
|
||||
debug: true,
|
||||
}
|
||||
]
|
||||
);
|
||||
/////////////////////
|
||||
// end section 1 //
|
||||
/////////////////////
|
||||
|
||||
// /////////////////////
|
||||
// // start section 1 //
|
||||
// /////////////////////
|
||||
// overlay.addSkeleton(
|
||||
// {
|
||||
// atlasPath: "assets/spineboy-pma.atlas",
|
||||
// skeletonPath: "assets/spineboy-pro.skel",
|
||||
// animation: 'walk',
|
||||
// },
|
||||
// document.querySelectorAll(`#section1-element`),
|
||||
// );
|
||||
// /////////////////////
|
||||
// // end section 1 //
|
||||
// /////////////////////
|
||||
|
||||
|
||||
|
||||
// /////////////////////
|
||||
// // start section 2 //
|
||||
// /////////////////////
|
||||
// overlay.addSkeleton(
|
||||
// {
|
||||
// atlasPath: "assets/spineboy-pma.atlas",
|
||||
// skeletonPath: "assets/spineboy-pro.skel",
|
||||
// animation: 'run',
|
||||
// scale: .25,
|
||||
// },
|
||||
// {
|
||||
// element: document.getElementById(`section2-element`),
|
||||
// mode: 'origin',
|
||||
// xAxis: .5,
|
||||
// yAxis: 1,
|
||||
// },
|
||||
// );
|
||||
// /////////////////////
|
||||
// // end section 2 //
|
||||
// /////////////////////
|
||||
|
||||
|
||||
// /////////////////////
|
||||
// // start section 3 //
|
||||
// /////////////////////
|
||||
// overlay.addSkeleton(
|
||||
// {
|
||||
// atlasPath: "assets/spineboy-pma.atlas",
|
||||
// skeletonPath: "assets/spineboy-pro.skel",
|
||||
// animation: 'jump',
|
||||
// },
|
||||
// {
|
||||
// element: document.getElementById(`section3-element`),
|
||||
// mode: 'inside', // default
|
||||
// offsetX: 100,
|
||||
// offsetY: 50,
|
||||
// },
|
||||
// );
|
||||
// /////////////////////
|
||||
// // end section 3 //
|
||||
// /////////////////////
|
||||
|
||||
|
||||
|
||||
// /////////////////////
|
||||
// // start section 4 //
|
||||
// /////////////////////
|
||||
// const { skeleton, state } = await overlay.addSkeleton(
|
||||
// {
|
||||
// atlasPath: "assets/raptor-pma.atlas",
|
||||
// skeletonPath: "assets/raptor-pro.skel",
|
||||
// animation: 'walk',
|
||||
// },
|
||||
// document.getElementById(`section4-element`)
|
||||
// );
|
||||
|
||||
// let isRoaring = false;
|
||||
// setInterval(() => {
|
||||
// const newAnimation = isRoaring ? "walk" : "roar";
|
||||
// state.setAnimation(0, newAnimation, true);
|
||||
// overlay.recalculateBounds(skeleton);
|
||||
// isRoaring = !isRoaring;
|
||||
// }, 4000);
|
||||
|
||||
// /////////////////////
|
||||
// // end section 4 //
|
||||
// /////////////////////
|
||||
|
||||
// /////////////////////
|
||||
// // start section 5 //
|
||||
// /////////////////////
|
||||
// // const { skeleton: skeleton5 } = await overlay.addSkeleton(
|
||||
// // {
|
||||
// // atlasPath: "assets/spineboy-pma.atlas",
|
||||
// // skeletonPath: "assets/spineboy-pro.skel",
|
||||
// // animation: 'walk',
|
||||
// // },
|
||||
// // document.getElementById(`section5-element`)
|
||||
// // );
|
||||
|
||||
// // const bbAttachmentSlot = skeleton5.findSlot("head-bb");
|
||||
// // const currentAttachment = bbAttachmentSlot.attachment;
|
||||
// // skeleton5.setAttachment("head-bb", "head");
|
||||
// // const bbAttachment = bbAttachmentSlot.attachment;
|
||||
|
||||
// // const computedVertices = [];
|
||||
// // bbAttachment.computeWorldVertices(bbAttachmentSlot, 0, bbAttachment.worldVerticesLength, computedVertices, 0, 2);
|
||||
// // const vertices = computedVertices;
|
||||
// // let x = Infinity, maxX = -Infinity, y = Infinity, maxY = -Infinity;
|
||||
// // for (let i = 0; i < vertices.length; i+=2) {
|
||||
// // x = Math.min(vertices[i], x);
|
||||
// // y = Math.min(vertices[i+1], y);
|
||||
// // maxX = Math.max(vertices[i], maxX);
|
||||
// // maxY = Math.max(vertices[i+1], maxY);
|
||||
// // }
|
||||
|
||||
// // const width = maxX - x;
|
||||
// // const height = maxY - y;
|
||||
// // console.log({ x, y, width, height })
|
||||
// // overlay.setBounds(skeleton5, { x, y, width, height })
|
||||
// // bbAttachmentSlot.setAttachment(currentAttachment)
|
||||
// /////////////////////
|
||||
// // end section 5 //
|
||||
// /////////////////////
|
||||
|
||||
// /////////////////////
|
||||
// // start section 6 //
|
||||
// /////////////////////
|
||||
// overlay.addSkeleton(
|
||||
// {
|
||||
// atlasPath: "assets/cloud-pot-pma.atlas",
|
||||
// skeletonPath: "assets/cloud-pot.skel",
|
||||
// animation: 'playing-in-the-rain',
|
||||
// },
|
||||
// document.getElementById(`section6-element`)
|
||||
// );
|
||||
// /////////////////////
|
||||
// // end section 6 //
|
||||
// /////////////////////
|
||||
|
||||
|
||||
|
||||
// /////////////////////
|
||||
// // start section 7 //
|
||||
// /////////////////////
|
||||
// overlay.addSkeleton(
|
||||
// {
|
||||
// atlasPath: "assets/owl-pma.atlas",
|
||||
// skeletonPath: "assets/owl-pro.skel",
|
||||
// animation: 'idle',
|
||||
// },
|
||||
// {
|
||||
// element: document.getElementById(`section7-element`),
|
||||
// debug: true,
|
||||
// }
|
||||
// );
|
||||
// //////////////////////
|
||||
// // end section 7 //
|
||||
// //////////////////////
|
||||
|
||||
|
||||
|
||||
// /////////////////////
|
||||
// // start section 8 //
|
||||
// /////////////////////
|
||||
// overlay.addSkeleton(
|
||||
// {
|
||||
// atlasPath: "assets/celestial-circus-pma.atlas",
|
||||
// skeletonPath: "assets/celestial-circus-pro.skel",
|
||||
// animation: 'wings-and-feet',
|
||||
// },
|
||||
// {
|
||||
// element: document.getElementById(`section8-element`),
|
||||
// draggable: true,
|
||||
// debug: true,
|
||||
// }
|
||||
// );
|
||||
// //////////////////////
|
||||
// // end section 8 //
|
||||
// //////////////////////
|
||||
|
||||
})();
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
// Drag utility
|
||||
|
||||
|
||||
function makeDraggable(element) {
|
||||
element.style["touch-action"] = "none";
|
||||
|
||||
let isDragging = false;
|
||||
let startX, startY;
|
||||
let originalX, originalY;
|
||||
|
||||
element.addEventListener('pointerdown', startDragging);
|
||||
document.addEventListener('pointermove', drag);
|
||||
document.addEventListener('pointerup', stopDragging);
|
||||
|
||||
function startDragging(e) {
|
||||
if (e.target === element.querySelector('#resizeHandle')) return;
|
||||
|
||||
isDragging = true;
|
||||
startX = e.clientX;
|
||||
startY = e.clientY;
|
||||
|
||||
const translate = element.style.transform;
|
||||
if (translate !== '') {
|
||||
const translateValues = translate.match(/translate\(([^)]+)\)/)[1].split(', ');
|
||||
originalX = parseFloat(translateValues[0]);
|
||||
originalY = parseFloat(translateValues[1]);
|
||||
} else {
|
||||
originalX = 0;
|
||||
originalY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function drag(e) {
|
||||
if (!isDragging) return;
|
||||
|
||||
const deltaX = e.clientX - startX;
|
||||
const deltaY = e.clientY - startY;
|
||||
|
||||
element.style.transform = `translate(${originalX + deltaX}px, ${originalY + deltaY}px)`;
|
||||
}
|
||||
|
||||
function stopDragging(e) {
|
||||
isDragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////
|
||||
// Resize utility
|
||||
|
||||
function makeResizable(element) {
|
||||
const resizeHandle = document.createElement('div');
|
||||
element.appendChild(resizeHandle);
|
||||
resizeHandle.id = "resizeHandle";
|
||||
resizeHandle.style.width = "20%";
|
||||
resizeHandle.style.height = "20%";
|
||||
resizeHandle.style.bottom = "0";
|
||||
resizeHandle.style.right = "0";
|
||||
resizeHandle.style.position = "absolute";
|
||||
resizeHandle.style["background-color"] = "#007bff";
|
||||
resizeHandle.style["cursor"] = "se-resize";
|
||||
|
||||
element.style["position"] = "relative";
|
||||
element.style["touch-action"] = "none";
|
||||
|
||||
let isResizing = false;
|
||||
let startX, startY, startWidth, startHeight, startPaddingLeft, startPaddingRight, startPaddingTop, startPaddingBottom;
|
||||
|
||||
resizeHandle.addEventListener('pointerdown', initResize);
|
||||
|
||||
function initResize(e) {
|
||||
isResizing = true;
|
||||
startX = e.clientX;
|
||||
startY = e.clientY;
|
||||
startWidth = element.offsetWidth;
|
||||
startHeight = element.offsetHeight;
|
||||
startPaddingLeft = parseFloat(window.getComputedStyle(element).paddingLeft);
|
||||
startPaddingRight = parseFloat(window.getComputedStyle(element).paddingRight);
|
||||
startPaddingTop = parseFloat(window.getComputedStyle(element).paddingTop);
|
||||
startPaddingBottom = parseFloat(window.getComputedStyle(element).paddingBottom);
|
||||
document.addEventListener('pointermove', resize);
|
||||
document.addEventListener('pointerup', stopResize);
|
||||
}
|
||||
|
||||
function resize(e) {
|
||||
if (!isResizing) return;
|
||||
const width = startWidth + (e.clientX - startX) - startPaddingLeft - startPaddingRight;
|
||||
const height = startHeight + (e.clientY - startY) - startPaddingTop - startPaddingBottom;
|
||||
element.style.width = width + 'px';
|
||||
element.style.height = height + 'px';
|
||||
}
|
||||
|
||||
function stopResize() {
|
||||
isResizing = false;
|
||||
document.removeEventListener('pointermove', resize);
|
||||
document.removeEventListener('pointerup', stopResize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
makeDraggable(document.getElementById(`section6-element`));
|
||||
makeResizable(document.getElementById(`section6-element`));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,210 +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>
|
||||
<!-- <script src="./spine-webgl.min.js"></script> -->
|
||||
<title>JS Library Showcase</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html {
|
||||
/* scroll-behavior: smooth; */
|
||||
}
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
.section {
|
||||
/* height: 100lvh; */
|
||||
/* height: 800px; */
|
||||
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;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function escapeHTMLandInject(text) {
|
||||
const escaped = text
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
document.currentScript.parentElement.innerHTML = escaped;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- <div style="height: 1200px; flex-direction: column;">
|
||||
</div> -->
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// start section 1 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
<div id="section1" class="section vertical-split">
|
||||
|
||||
<div class="split-top split">
|
||||
<div class="split-left">
|
||||
<spine-widget
|
||||
atlas="assets/raptor-pma.atlas"
|
||||
skeleton="assets/raptor-pro.skel"
|
||||
animation="walk"
|
||||
scale="3"
|
||||
clip="true"
|
||||
fit="height"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/spineboy-pma.atlas"
|
||||
skeleton="assets/spineboy-pro.skel"
|
||||
animation="walk"
|
||||
scale="1.5"
|
||||
fit="none"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/spineboy-pma.atlas"
|
||||
skeleton="assets/spineboy-pro.skel"
|
||||
animation="walk"
|
||||
scale="1"
|
||||
fit="none"
|
||||
clip="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<!-- <div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/cloud-pot-pma.atlas"
|
||||
skeleton="assets/cloud-pot.skel"
|
||||
animation="playing-in-the-rain"
|
||||
draggable="true"
|
||||
></spine-widget>
|
||||
</div>
|
||||
<div class="split-right">
|
||||
<spine-widget
|
||||
atlas="assets/celestial-circus-pma.atlas"
|
||||
skeleton="assets/celestial-circus-pro.skel"
|
||||
animation="wings-and-feet"
|
||||
draggable="true"
|
||||
></spine-widget>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div style="height: 1200px; flex-direction: column;">
|
||||
</div>
|
||||
|
||||
<!--
|
||||
/////////////////////
|
||||
// end section 1 //
|
||||
/////////////////////
|
||||
-->
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
@ -68,7 +68,7 @@ export class Input {
|
||||
if (this.buttonDown) {
|
||||
if (listener.dragged) listener.dragged(this.mouseX, this.mouseY, ev);
|
||||
} else {
|
||||
if (listener.moved) listener.moved(this.mouseX, this.mouseY);
|
||||
if (listener.moved) listener.moved(this.mouseX, this.mouseY, ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -80,7 +80,7 @@ export class Input {
|
||||
this.mouseX = ev.clientX - rect.left;;
|
||||
this.mouseY = ev.clientY - rect.top;
|
||||
this.buttonDown = false;
|
||||
this.listeners.map((listener) => { if (listener.up) listener.up(this.mouseX, this.mouseY); });
|
||||
this.listeners.map((listener) => { if (listener.up) listener.up(this.mouseX, this.mouseY, ev); });
|
||||
|
||||
document.removeEventListener("mousemove", mouseMove);
|
||||
document.removeEventListener("mouseup", mouseUp);
|
||||
@ -92,7 +92,7 @@ export class Input {
|
||||
let deltaY = ev.deltaY;
|
||||
if (ev.deltaMode == WheelEvent.DOM_DELTA_LINE) deltaY *= 8;
|
||||
if (ev.deltaMode == WheelEvent.DOM_DELTA_PAGE) deltaY *= 24;
|
||||
this.listeners.map((listener) => { if (listener.wheel) listener.wheel(ev.deltaY); });
|
||||
this.listeners.map((listener) => { if (listener.wheel) listener.wheel(ev.deltaY, ev); });
|
||||
};
|
||||
|
||||
element.addEventListener("mousedown", mouseDown, true);
|
||||
@ -122,7 +122,7 @@ export class Input {
|
||||
let dx = this.touch1.x - this.touch0.x;
|
||||
let dy = this.touch1.x - this.touch0.x;
|
||||
this.initialPinchDistance = Math.sqrt(dx * dx + dy * dy);
|
||||
this.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, this.initialPinchDistance) });
|
||||
this.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, this.initialPinchDistance, ev) });
|
||||
}
|
||||
}
|
||||
if (this.preventDefault) ev.preventDefault();
|
||||
@ -151,7 +151,7 @@ export class Input {
|
||||
let dx = this.touch1.x - this.touch0.x;
|
||||
let dy = this.touch1.x - this.touch0.x;
|
||||
let distance = Math.sqrt(dx * dx + dy * dy);
|
||||
this.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, distance) });
|
||||
this.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, distance, ev) });
|
||||
}
|
||||
}
|
||||
if (this.preventDefault) ev.preventDefault();
|
||||
@ -171,7 +171,7 @@ export class Input {
|
||||
this.touch0 = null;
|
||||
this.mouseX = x;
|
||||
this.mouseY = y;
|
||||
this.listeners.map((listener) => { if (listener.up) listener.up(x, y) });
|
||||
this.listeners.map((listener) => { if (listener.up) listener.up(x, y, ev) });
|
||||
|
||||
if (!this.touch1) {
|
||||
this.buttonDown = false;
|
||||
@ -216,9 +216,9 @@ export class Touch {
|
||||
|
||||
export interface InputListener {
|
||||
down?(x: number, y: number, ev?: MouseEvent | TouchEvent): void;
|
||||
up?(x: number, y: number): void;
|
||||
moved?(x: number, y: number): void;
|
||||
up?(x: number, y: number, ev?: MouseEvent | TouchEvent): void;
|
||||
moved?(x: number, y: number, ev?: MouseEvent | TouchEvent): void;
|
||||
dragged?(x: number, y: number, ev?: MouseEvent | TouchEvent): void;
|
||||
wheel?(delta: number): void;
|
||||
zoom?(initialDistance: number, distance: number): void;
|
||||
wheel?(delta: number, ev?: MouseEvent | TouchEvent): void;
|
||||
zoom?(initialDistance: number, distance: number, ev?: MouseEvent | TouchEvent): void;
|
||||
}
|
||||
|
||||
@ -463,24 +463,6 @@ export class SceneRenderer implements Disposable {
|
||||
this.activeRenderer = null;
|
||||
}
|
||||
|
||||
resize2 () {
|
||||
let canvas = this.canvas;
|
||||
this.context.gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
this.camera.setViewport(canvas.width, canvas.height);
|
||||
this.camera.update();
|
||||
}
|
||||
|
||||
resize3 (width: number, height: number) {
|
||||
console.log("resize gl")
|
||||
let canvas = this.canvas;
|
||||
const dpr = window.devicePixelRatio;
|
||||
this.canvas.width = Math.round(width * dpr);
|
||||
this.canvas.height = Math.round(height * dpr);
|
||||
this.context.gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
this.camera.setViewport(canvas.width, canvas.height);
|
||||
this.camera.update();
|
||||
}
|
||||
|
||||
resize (resizeMode: ResizeMode) {
|
||||
let canvas = this.canvas;
|
||||
var dpr = window.devicePixelRatio || 1;
|
||||
|
||||
@ -203,8 +203,6 @@ export class SkeletonRenderer {
|
||||
|
||||
clipper.clipEndWithSlot(slot);
|
||||
}
|
||||
|
||||
// console.log(renderable.vertices[1])
|
||||
clipper.clipEnd();
|
||||
}
|
||||
|
||||
|
||||
@ -110,7 +110,7 @@ export class SpineCanvas {
|
||||
|
||||
let waitForAssets = () => {
|
||||
if (this.disposed) return;
|
||||
if (!config.app.loadAssets || this.assetManager.isLoadingComplete()) {
|
||||
if (this.assetManager.isLoadingComplete()) {
|
||||
if (this.assetManager.hasErrors()) {
|
||||
if (config.app.error) config.app.error(this, this.assetManager.getErrors());
|
||||
} else {
|
||||
|
||||
@ -1303,7 +1303,7 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
|
||||
this.canvas.style.width = totalWidth + "px";
|
||||
this.canvas.style.height = totalHeight + "px";
|
||||
this.renderer.resize3(totalWidth, totalHeight);
|
||||
this.resize(totalWidth, totalHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1333,9 +1333,19 @@ class SpineWebComponentOverlay extends HTMLElement {
|
||||
widget.currentScaleDpi = scale;
|
||||
});
|
||||
|
||||
this.renderer.resize3(parseFloat(this.canvas.style.width), parseFloat(this.canvas.style.height));
|
||||
this.resize(parseFloat(this.canvas.style.width), parseFloat(this.canvas.style.height));
|
||||
}
|
||||
|
||||
private resize(width: number, height: number) {
|
||||
let canvas = this.canvas;
|
||||
const dpr = window.devicePixelRatio;
|
||||
this.canvas.width = Math.round(width * dpr);
|
||||
this.canvas.height = Math.round(height * dpr);
|
||||
this.renderer.context.gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
this.renderer.camera.setViewport(canvas.width, canvas.height);
|
||||
this.renderer.camera.update();
|
||||
}
|
||||
|
||||
// we need the bounding client rect otherwise decimals won't be returned
|
||||
// this means that during zoom it might occurs that the div would be resized
|
||||
// rounded 1px more making a scrollbar appear
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user