diff --git a/spine-ts/spine-player/src/Player.ts b/spine-ts/spine-player/src/Player.ts index d9ae263d8..13f7d92c1 100644 --- a/spine-ts/spine-player/src/Player.ts +++ b/spine-ts/spine-player/src/Player.ts @@ -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); diff --git a/spine-ts/spine-webgl/src/SceneRenderer.ts b/spine-ts/spine-webgl/src/SceneRenderer.ts index fdfa3a979..835ea7a8f 100644 --- a/spine-ts/spine-webgl/src/SceneRenderer.ts +++ b/spine-ts/spine-webgl/src/SceneRenderer.ts @@ -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, }