[ts][player] Added viewport.clip and ResizeMode.FitClip.

This commit is contained in:
Nathan Sweet 2025-04-10 16:15:00 -04:00
parent 9710b0f08b
commit 9424018102
2 changed files with 30 additions and 18 deletions

View File

@ -103,6 +103,9 @@ export interface SpinePlayerConfig {
width?: number
height?: number
/* Optional: When true, drawing won't go outside the viewport. Default: false */
clip?: boolean
/* Optional: Padding around the viewport size, given as a number or percentage (eg "25%"). Default: 10% */
padLeft?: string | number
padRight?: string | number
@ -736,6 +739,7 @@ export class SpinePlayer implements Disposable {
// Determine the base viewport.
let globalViewport = this.config.viewport!;
let viewport = this.currentViewport = {
clip: globalViewport.clip,
padLeft: globalViewport.padLeft !== void 0 ? globalViewport.padLeft : "10%",
padRight: globalViewport.padRight !== void 0 ? globalViewport.padRight : "10%",
padTop: globalViewport.padTop !== void 0 ? globalViewport.padTop : "10%",
@ -758,6 +762,7 @@ export class SpinePlayer implements Disposable {
viewport.width = userAnimViewport.width;
viewport.height = userAnimViewport.height;
}
if (userAnimViewport.clip !== void 0) viewport.clip = userAnimViewport.clip;
if (userAnimViewport.padLeft !== void 0) viewport.padLeft = userAnimViewport.padLeft;
if (userAnimViewport.padRight !== void 0) viewport.padRight = userAnimViewport.padRight;
if (userAnimViewport.padTop !== void 0) viewport.padTop = userAnimViewport.padTop;
@ -827,10 +832,6 @@ export class SpinePlayer implements Disposable {
let skeleton = this.skeleton!;
let config = this.config!;
if (skeleton) {
// Resize the canvas.
let renderer = this.sceneRenderer!;
renderer.resize(ResizeMode.Expand);
let playDelta = this.paused ? 0 : delta * this.speed;
if (config.frame) config.frame(this, playDelta);
@ -878,11 +879,15 @@ export class SpinePlayer implements Disposable {
}
}
let renderer = this.sceneRenderer!;
renderer.camera.zoom = this.canvas!.height / this.canvas!.width > viewport.height / viewport.width
? viewport.width / this.canvas!.width : viewport.height / this.canvas!.height;
renderer.camera.position.x = viewport.x + viewport.width / 2;
renderer.camera.position.y = viewport.y + viewport.height / 2;
// Resize the canvas.
renderer.resize(this.currentViewport.clip ? ResizeMode.FitClip : ResizeMode.Fit, viewport.width, viewport.height);
// Clear the screen.
let gl = this.context!.gl;
gl.clearColor(bg.r, bg.g, bg.b, bg.a);

View File

@ -463,28 +463,34 @@ export class SceneRenderer implements Disposable {
this.activeRenderer = null;
}
resize (resizeMode: ResizeMode) {
resize (resizeMode: ResizeMode, worldWidth?: number, worldHeight?: number) {
let canvas = this.canvas;
var dpr = window.devicePixelRatio || 1;
var w = Math.round(canvas.clientWidth * dpr);
var h = Math.round(canvas.clientHeight * dpr);
if (canvas.width != w || canvas.height != h) {
canvas.width = w;
canvas.height = h;
}
this.context.gl.viewport(0, 0, canvas.width, canvas.height);
// Nothing to do for stretch, we simply apply the viewport size of the camera.
if (resizeMode === ResizeMode.Expand)
this.camera.setViewport(w, h);
else if (resizeMode === ResizeMode.Fit) {
let sourceWidth = canvas.width, sourceHeight = canvas.height;
let targetWidth = this.camera.viewportWidth, targetHeight = this.camera.viewportHeight;
let targetRatio = targetHeight / targetWidth;
let sourceRatio = sourceHeight / sourceWidth;
let scale = targetRatio < sourceRatio ? targetWidth / sourceWidth : targetHeight / sourceHeight;
this.camera.setViewport(sourceWidth * scale, sourceHeight * scale);
if (resizeMode === ResizeMode.FitClip) {
let targetRatio = h / w, sourceRatio = worldHeight / worldWidth;
let scale = targetRatio > sourceRatio ? w / worldWidth : h / worldHeight;
worldWidth *= scale;
worldHeight *= scale;
this.camera.setViewport(worldWidth, worldHeight);
this.context.gl.viewport((w - worldWidth) / 2, (h - worldHeight) / 2, worldWidth, worldHeight);
} else {
if (resizeMode === ResizeMode.Fit) {
let targetWidth = this.camera.viewportWidth, targetHeight = this.camera.viewportHeight;
let targetRatio = targetHeight / targetWidth, sourceRatio = h / w;
let scale = targetRatio < sourceRatio ? targetWidth / w : targetHeight / h;
this.camera.setViewport(w * scale, h * scale);
} else if (resizeMode === ResizeMode.Expand)
this.camera.setViewport(w, h);
// Nothing to do for stretch, we simply apply the viewport size of the camera.
this.context.gl.viewport(0, 0, w, h);
}
this.camera.update();
}
@ -511,5 +517,6 @@ export class SceneRenderer implements Disposable {
export enum ResizeMode {
Stretch,
Expand,
Fit
Fit,
FitClip,
}