mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-06 02:36:56 +08:00
[canvaskit] HDPI support, fix blending, physics example
This commit is contained in:
parent
cc965237b3
commit
81312c8983
@ -26,6 +26,7 @@
|
|||||||
<li><a href="/spine-canvaskit/example/animation-state-events.html">Animation State Events</a></li>
|
<li><a href="/spine-canvaskit/example/animation-state-events.html">Animation State Events</a></li>
|
||||||
<li><a href="/spine-canvaskit/example/mix-and-match.html">Skins Mix & Match</a></li>
|
<li><a href="/spine-canvaskit/example/mix-and-match.html">Skins Mix & Match</a></li>
|
||||||
<li><a href="/spine-canvaskit/example/ik-following.html">IK Following</a></li>
|
<li><a href="/spine-canvaskit/example/ik-following.html">IK Following</a></li>
|
||||||
|
<li><a href="/spine-canvaskit/example/physics.html">Physics</a></li>
|
||||||
<li><a href="/spine-canvaskit/example/micro-benchmark.html">Micro Benchmark</a></li>
|
<li><a href="/spine-canvaskit/example/micro-benchmark.html">Micro Benchmark</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<li>Pixi</li>
|
<li>Pixi</li>
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
<body class="p-4 flex flex-col items-center">
|
<body class="p-4 flex flex-col items-center">
|
||||||
<h1>Animation State Events</h1>
|
<h1>Animation State Events</h1>
|
||||||
<p class="mb-4">Open the console in the developer tools to view events logs.</p>
|
<p class="mb-4">Open the console in the developer tools to view events logs.</p>
|
||||||
<canvas id=foo width=600 height=400 style="margin: 0 auto;"></canvas>
|
<canvas id=foo style="margin: 0 auto; width: 600px; height: 400px;"></canvas>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
@ -28,8 +28,14 @@
|
|||||||
return await response.arrayBuffer();
|
return await response.arrayBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const canvasElement = document.querySelector("#foo");
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
canvasElement.width = canvasElement.clientWidth * dpr;
|
||||||
|
canvasElement.height = canvasElement.clientHeight * dpr;
|
||||||
|
|
||||||
const ck = await CanvasKitInit();
|
const ck = await CanvasKitInit();
|
||||||
const surface = ck.MakeCanvasSurface('foo');
|
const surface = ck.MakeCanvasSurface('foo');
|
||||||
|
surface.getCanvas().scale(dpr, dpr);
|
||||||
|
|
||||||
const atlas = await spine.loadTextureAtlas(ck, "assets/spineboy.atlas", readFile);
|
const atlas = await spine.loadTextureAtlas(ck, "assets/spineboy.atlas", readFile);
|
||||||
const skeletonData = await spine.loadSkeletonData("assets/spineboy-pro.skel", atlas, readFile);
|
const skeletonData = await spine.loadSkeletonData("assets/spineboy-pro.skel", atlas, readFile);
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
<body class="p-4 flex flex-col items-center">
|
<body class="p-4 flex flex-col items-center">
|
||||||
<h1>IK Following</h1>
|
<h1>IK Following</h1>
|
||||||
<p class="mb-4">Click/touch to set the aim</p>
|
<p class="mb-4">Click/touch to set the aim</p>
|
||||||
<canvas id=foo width=600 height=400 style="margin: 0 auto;"></canvas>
|
<canvas id=foo style="margin: 0 auto; width: 600px; height: 400px;"></canvas>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
@ -28,8 +28,14 @@
|
|||||||
return await response.arrayBuffer();
|
return await response.arrayBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const canvasElement = document.querySelector("#foo");
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
canvasElement.width = canvasElement.clientWidth * dpr;
|
||||||
|
canvasElement.height = canvasElement.clientHeight * dpr;
|
||||||
|
|
||||||
const ck = await CanvasKitInit();
|
const ck = await CanvasKitInit();
|
||||||
const surface = ck.MakeCanvasSurface('foo');
|
const surface = ck.MakeCanvasSurface('foo');
|
||||||
|
surface.getCanvas().scale(dpr, dpr);
|
||||||
|
|
||||||
const atlas = await spine.loadTextureAtlas(ck, "assets/spineboy.atlas", readFile);
|
const atlas = await spine.loadTextureAtlas(ck, "assets/spineboy.atlas", readFile);
|
||||||
const skeletonData = await spine.loadSkeletonData("assets/spineboy-pro.skel", atlas, readFile);
|
const skeletonData = await spine.loadSkeletonData("assets/spineboy-pro.skel", atlas, readFile);
|
||||||
@ -65,7 +71,6 @@
|
|||||||
const clientRect = canvasElement.getBoundingClientRect();
|
const clientRect = canvasElement.getBoundingClientRect();
|
||||||
let x = touchX - clientRect.left;
|
let x = touchX - clientRect.left;
|
||||||
let y = touchY - clientRect.top;
|
let y = touchY - clientRect.top;
|
||||||
console.log(`${x}, ${y}`);
|
|
||||||
|
|
||||||
// Transform the touch/mouse position to the crosshair
|
// Transform the touch/mouse position to the crosshair
|
||||||
// bone's parent bone coordinate system
|
// bone's parent bone coordinate system
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<body class="p-4 flex flex-col items-center">
|
<body class="p-4 flex flex-col items-center">
|
||||||
<h1>CanvasKit Example</h1>
|
<h1>CanvasKit Example</h1>
|
||||||
<canvas id=foo width=600 height=400 style="margin: 0 auto;"></canvas>
|
<canvas id=foo style="margin: 0 auto; width: 600px; height: 400px;"></canvas>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
@ -28,11 +28,20 @@
|
|||||||
return await response.arrayBuffer();
|
return await response.arrayBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure we render at full DPI.
|
||||||
|
const canvasElement = document.querySelector("#foo");
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
canvasElement.width = canvasElement.clientWidth * dpr;
|
||||||
|
canvasElement.height = canvasElement.clientHeight * dpr;
|
||||||
|
|
||||||
|
|
||||||
// Initialize CanvasKit and create a surface from the Canvas element to draw to
|
// Initialize CanvasKit and create a surface from the Canvas element to draw to
|
||||||
const ck = await CanvasKitInit();
|
const ck = await CanvasKitInit();
|
||||||
const surface = ck.MakeCanvasSurface('foo');
|
const surface = ck.MakeCanvasSurface('foo');
|
||||||
|
|
||||||
|
// Scale the CanvasKit coordinate system
|
||||||
|
surface.getCanvas().scale(dpr, dpr);
|
||||||
|
|
||||||
// Load the texture atlas
|
// Load the texture atlas
|
||||||
const atlas = await spine.loadTextureAtlas(ck, "assets/spineboy.atlas", readFile);
|
const atlas = await spine.loadTextureAtlas(ck, "assets/spineboy.atlas", readFile);
|
||||||
|
|
||||||
@ -54,6 +63,7 @@
|
|||||||
let lastTime = performance.now();
|
let lastTime = performance.now();
|
||||||
// Rendering loop
|
// Rendering loop
|
||||||
function drawFrame(canvas) {
|
function drawFrame(canvas) {
|
||||||
|
// Clear the canvas
|
||||||
canvas.clear(ck.Color(52, 52, 54, 1));
|
canvas.clear(ck.Color(52, 52, 54, 1));
|
||||||
|
|
||||||
// Calculate the time that's passed between now and the last frame
|
// Calculate the time that's passed between now and the last frame
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
<body class="p-4 flex flex-col items-center">
|
<body class="p-4 flex flex-col items-center">
|
||||||
<h1>Micro Benchmark</h1>
|
<h1>Micro Benchmark</h1>
|
||||||
<div id="timing"></div>
|
<div id="timing"></div>
|
||||||
<canvas id=foo width=600 height=400 style="margin: 0 auto;"></canvas>
|
<canvas id=foo style="margin: 0 auto; width: 600px; height: 400px;"></canvas>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
@ -28,13 +28,19 @@
|
|||||||
return await response.arrayBuffer();
|
return await response.arrayBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const canvasElement = document.querySelector("#foo");
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
canvasElement.width = canvasElement.clientWidth * dpr;
|
||||||
|
canvasElement.height = canvasElement.clientHeight * dpr;
|
||||||
|
|
||||||
const ck = await CanvasKitInit();
|
const ck = await CanvasKitInit();
|
||||||
const surface = ck.MakeCanvasSurface('foo');
|
const surface = ck.MakeCanvasSurface('foo');
|
||||||
|
surface.getCanvas().scale(dpr, dpr);
|
||||||
|
|
||||||
const atlas = await spine.loadTextureAtlas(ck, "assets/spineboy.atlas", readFile);
|
const atlas = await spine.loadTextureAtlas(ck, "assets/spineboy.atlas", readFile);
|
||||||
const skeletonData = await spine.loadSkeletonData("assets/spineboy-pro.skel", atlas, readFile);
|
const skeletonData = await spine.loadSkeletonData("assets/spineboy-pro.skel", atlas, readFile);
|
||||||
|
|
||||||
// Instantiate 100 skeletons, randomly placed and scaled.
|
// Instantiate 100 drawables, randomly placed and scaled.
|
||||||
const drawables = [];
|
const drawables = [];
|
||||||
for (let i = 0; i < 100; i++) {
|
for (let i = 0; i < 100; i++) {
|
||||||
const drawable = new spine.SkeletonDrawable(skeletonData);
|
const drawable = new spine.SkeletonDrawable(skeletonData);
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<body class="p-4 flex flex-col items-center">
|
<body class="p-4 flex flex-col items-center">
|
||||||
<h1>Skins Mix & Match Example</h1>
|
<h1>Skins Mix & Match Example</h1>
|
||||||
<canvas id=foo width=600 height=400 style="margin: 0 auto;"></canvas>
|
<canvas id=foo style="margin: 0 auto; width: 600px; height: 400px;"></canvas>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
@ -27,8 +27,14 @@
|
|||||||
return await response.arrayBuffer();
|
return await response.arrayBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const canvasElement = document.querySelector("#foo");
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
canvasElement.width = canvasElement.clientWidth * dpr;
|
||||||
|
canvasElement.height = canvasElement.clientHeight * dpr;
|
||||||
|
|
||||||
const ck = await CanvasKitInit();
|
const ck = await CanvasKitInit();
|
||||||
const surface = ck.MakeCanvasSurface('foo');
|
const surface = ck.MakeCanvasSurface('foo');
|
||||||
|
surface.getCanvas().scale(dpr, dpr);
|
||||||
|
|
||||||
const atlas = await spine.loadTextureAtlas(ck, "assets/mix-and-match.atlas", readFile);
|
const atlas = await spine.loadTextureAtlas(ck, "assets/mix-and-match.atlas", readFile);
|
||||||
const skeletonData = await spine.loadSkeletonData("assets/mix-and-match-pro.skel", atlas, readFile);
|
const skeletonData = await spine.loadSkeletonData("assets/mix-and-match-pro.skel", atlas, readFile);
|
||||||
|
|||||||
103
spine-ts/spine-canvaskit/example/physics.html
Normal file
103
spine-ts/spine-canvaskit/example/physics.html
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="../../index.css">
|
||||||
|
<script src="https://unpkg.com/canvaskit-wasm@latest/bin/canvaskit.js"></script>
|
||||||
|
<script src="../dist/iife/spine-canvaskit.js"></script>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="p-4 flex flex-col items-center">
|
||||||
|
<h1>IK Following</h1>
|
||||||
|
<p class="mb-4">Drag anywhere</p>
|
||||||
|
<canvas id=foo style="margin: 0 auto; width: 600px; height: 400px;"></canvas>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
async function readFile(path) {
|
||||||
|
const response = await fetch(path);
|
||||||
|
if (!response.ok) throw new Error("Could not load file " + path);
|
||||||
|
return await response.arrayBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvasElement = document.querySelector("#foo");
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
canvasElement.width = canvasElement.clientWidth * dpr;
|
||||||
|
canvasElement.height = canvasElement.clientHeight * dpr;
|
||||||
|
|
||||||
|
const ck = await CanvasKitInit();
|
||||||
|
const surface = ck.MakeCanvasSurface('foo');
|
||||||
|
surface.getCanvas().scale(dpr, dpr);
|
||||||
|
|
||||||
|
const atlas = await spine.loadTextureAtlas(ck, "assets/celestial-circus.atlas", readFile);
|
||||||
|
const skeletonData = await spine.loadSkeletonData("assets/celestial-circus-pro.json", atlas, readFile);
|
||||||
|
const drawable = new spine.SkeletonDrawable(skeletonData);
|
||||||
|
drawable.skeleton.scaleX = drawable.skeleton.scaleY = 0.15;
|
||||||
|
drawable.skeleton.x = 300;
|
||||||
|
drawable.skeleton.y = 300;
|
||||||
|
|
||||||
|
// Set the blink animation on track 0
|
||||||
|
drawable.animationState.setAnimation(0, "eyeblink-long", true);
|
||||||
|
|
||||||
|
// Set up touch and mouse listeners on the canvas element
|
||||||
|
// and set the touch/mouse coordinate on the aim bone
|
||||||
|
let mouseDown = false;
|
||||||
|
let lastX = -1, lastY = -1;
|
||||||
|
canvasElement.addEventListener("touchmove", (ev) => drag(ev.changedTouches[0].clientX, ev.changedTouches[0].clientY));
|
||||||
|
canvasElement.addEventListener("mousedown", (ev) => {
|
||||||
|
mouseDown = true;
|
||||||
|
drag(ev.clientX, ev.clientY);
|
||||||
|
});
|
||||||
|
canvasElement.addEventListener("mouseup", () => {
|
||||||
|
mouseDown = false;
|
||||||
|
lastX = -1; lastY = -1;
|
||||||
|
})
|
||||||
|
canvasElement.addEventListener("mousemove", (ev) => {
|
||||||
|
if (mouseDown) drag(ev.clientX, ev.clientY);
|
||||||
|
})
|
||||||
|
|
||||||
|
// Move the skeleton around based on the distance between
|
||||||
|
// the last touch/mouse location and the current touch/mouse location.
|
||||||
|
const drag = (touchX, touchY) => {
|
||||||
|
const clientRect = canvasElement.getBoundingClientRect();
|
||||||
|
let x = touchX - clientRect.left;
|
||||||
|
let y = touchY - clientRect.top;
|
||||||
|
if (lastX == -1 && lastY == -1) {
|
||||||
|
lastX = x;
|
||||||
|
lastY = y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawable.skeleton.x += (x - lastX);
|
||||||
|
drawable.skeleton.y += (y - lastY);
|
||||||
|
lastX = x;
|
||||||
|
lastY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderer = new spine.SkeletonRenderer(ck);
|
||||||
|
let lastTime = performance.now();
|
||||||
|
|
||||||
|
function drawFrame(canvas) {
|
||||||
|
canvas.clear(ck.Color(52, 52, 54, 1));
|
||||||
|
|
||||||
|
const now = performance.now();
|
||||||
|
const deltaTime = (now - lastTime) / 1000;
|
||||||
|
lastTime = now;
|
||||||
|
|
||||||
|
drawable.update(deltaTime);
|
||||||
|
renderer.render(canvas, drawable);
|
||||||
|
|
||||||
|
surface.requestAnimationFrame(drawFrame);
|
||||||
|
}
|
||||||
|
surface.requestAnimationFrame(drawFrame);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
||||||
@ -12,7 +12,7 @@ function toCkBlendMode(ck: CanvasKit, blendMode: BlendMode) {
|
|||||||
switch(blendMode) {
|
switch(blendMode) {
|
||||||
case BlendMode.Normal: return ck.BlendMode.SrcOver;
|
case BlendMode.Normal: return ck.BlendMode.SrcOver;
|
||||||
case BlendMode.Additive: return ck.BlendMode.Plus;
|
case BlendMode.Additive: return ck.BlendMode.Plus;
|
||||||
case BlendMode.Multiply: return ck.BlendMode.Modulate;
|
case BlendMode.Multiply: return ck.BlendMode.SrcOver;
|
||||||
case BlendMode.Screen: return ck.BlendMode.Screen;
|
case BlendMode.Screen: return ck.BlendMode.Screen;
|
||||||
default: return ck.BlendMode.SrcOver;
|
default: return ck.BlendMode.SrcOver;
|
||||||
}
|
}
|
||||||
@ -92,7 +92,11 @@ export async function loadTextureAtlas(ck: CanvasKit, atlasFile: string, readFil
|
|||||||
export async function loadSkeletonData(skeletonFile: string, atlas: TextureAtlas, readFile: (path: string) => Promise<Buffer>): Promise<SkeletonData> {
|
export async function loadSkeletonData(skeletonFile: string, atlas: TextureAtlas, readFile: (path: string) => Promise<Buffer>): Promise<SkeletonData> {
|
||||||
const attachmentLoader = new AtlasAttachmentLoader(atlas);
|
const attachmentLoader = new AtlasAttachmentLoader(atlas);
|
||||||
const loader = skeletonFile.endsWith(".json") ? new SkeletonJson(attachmentLoader) : new SkeletonBinary(attachmentLoader);
|
const loader = skeletonFile.endsWith(".json") ? new SkeletonJson(attachmentLoader) : new SkeletonBinary(attachmentLoader);
|
||||||
const skeletonData = loader.readSkeletonData(await readFile(skeletonFile));
|
let data = await readFile(skeletonFile);
|
||||||
|
if (skeletonFile.endsWith(".json")) {
|
||||||
|
data = bufferToUtf8String(data);
|
||||||
|
}
|
||||||
|
const skeletonData = loader.readSkeletonData(data);
|
||||||
return skeletonData;
|
return skeletonData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user