动态调整Pixi舞台及其内容以适应窗口大小的变化,在窗口调整大小和加载时进行。

28

我正在尝试在窗口大小调整时动态调整Pixi舞台(画布和内容)的大小。同时,让它最初在浏览器窗口的大小下加载而不改变比例。

我使用以下方法来设置初始大小,基本上是使用window.innerWidthwindow.innerHeight

但出现了奇怪的情况,它以较小的尺寸加载(但并不是在HTML中指定的画布尺寸),然后才扩展以适合窗口。

var w;
var h;
    
window.onload = function() {
    var w = window.innerWidth;
    var h = window.innerHeight;

    //this part resizes the canvas but keeps ratio the same
    renderer.view.style.width = w + "px";
    renderer.view.style.height = h + "px"

//  init();
}; 

这是我的onresize函数 - 它正在调整画布的大小,但不是内容。

我以为由于它更新了renderer.view,它会调整内容的大小,但实际上并没有。

我该如何调整stage/renderer.view内容的大小呢?

window.onresize = function (event){
    var w = window.innerWidth;
    var h = window.innerHeight;

    //this part resizes the canvas but keeps ratio the same
    renderer.view.style.width = w + "px";
    renderer.view.style.height = h + "px";

    //this part adjusts the ratio:
    renderer.resize(w,h);
}

    // create an new instance of a pixi stage
    var stage = new PIXI.Stage(0xff00ff);
    var renderer = PIXI.autoDetectRenderer(window.innerWidth, window.innerHeight);

    // add the renderer view element to the DOM
   var mypixiStage = document.body.appendChild(renderer.view);

你想保持什么比例?或者,默认画布尺寸是多少? - Bitwise Creative
这是一个非常好的问题:D。现在它是1920x1080,因此是16x9。但以后可能需要更改。我已经编辑了上面的内容供您参考。 - Agent Zebra
我的回答有帮助吗? - Bitwise Creative
1
虽然有点晚了,但我也遇到了同样的问题,解决方法很简单,只需使用 window.addEventListener("resize", onResizeHandler) 而不是 window.onresize = onResizeHandler 即可。 - Matt
8个回答

50

3
这个功能可以使用,但不会重绘元素位置,只会改变画布大小。为此我创建了一个功能请求:https://github.com/pixijs/pixi.js/issues/6081 - Fabian von Ellerts
注意:如果您在网站上使用Pixi,这会在移动浏览器滚动期间创建性能问题。每次窗口大小调整时都会重新调整大小,而浏览器会经常隐藏/显示URL栏。这可能会导致闪烁等问题。 - Dlacrem

33

您需要设置一个大小和比率,以供缩放事件函数引用。然后,您需要一个缩放函数来检查窗口大小,以在缩放时保持比率。我还手动运行了缩放函数来启动初始页面加载。

另外,请注意我没有运行renderer.resize,我只是调整了绘图区域的大小。

以下是一个示例:http://jsfiddle.net/2wjw043f/

以下是示例代码:

var size = [1920, 1080];
var ratio = size[0] / size[1];
var stage = new PIXI.Stage(0x333333, true);
var renderer = PIXI.autoDetectRenderer(size[0], size[1], null);
document.body.appendChild(renderer.view);
var texture = new PIXI.RenderTexture();
r1 = new PIXI.Graphics();
r1.beginFill(0x00ffff);
r1.drawRect(0, 0, 100, 100);
r1.endFill();
texture.render(r1);
var block = new PIXI.Sprite(texture);
block.position.x = 100;
block.position.y = 100;
block.anchor.x = .5;
block.anchor.y = .5;
stage.addChild(block);
requestAnimFrame(animate);
resize();
function animate() {
    requestAnimFrame(animate);
    block.rotation += .01;
    renderer.render(stage);
}
function resize() {
    if (window.innerWidth / window.innerHeight >= ratio) {
        var w = window.innerHeight * ratio;
        var h = window.innerHeight;
    } else {
        var w = window.innerWidth;
        var h = window.innerWidth / ratio;
    }
    renderer.view.style.width = w + 'px';
    renderer.view.style.height = h + 'px';
}
window.onresize = resize;

我几天前收藏了你的JSFiddle,现在它不再工作了。控制台显示PIXI未定义。你能修复一下吗?编辑:算了,看起来托管外部PIXI(goodboydigital)的域名已经挂了。 - FanaticD

4

我已经使用Pixi.js几周了,解决了相同的问题——调整画布大小。这个类创建了一个精灵,它有一个方法“applyResize”,可以完成大部分工作。在构造函数中,画布背景的大小将等于父级“domElement”的大小。在初始化后,您必须添加“resize”事件监听器到精灵上。或者您可以做一些其他的事情来改善它。

class PixiBackground {

    constructor(type = 'cover', domElement, imgUrl) {
        this.domElement = domElement;
        this.imgUrl = imgUrl;
        this.parent = new PIXI.Container();
        this.sprite = new PIXI.Sprite.fromImage(this.imgUrl);
        this.parent.addChild(this.sprite);
        this.type = type;
    }

    addTo(container) {
        container.addChild(this.parent);
        this.applyResize();
    }

    applyResize() {
        const domSize = {
            x: this.domElement.clientWidth,
            y: this.domElement.clientHeight
        };
        const imageSize = {
            x: this.sprite.texture.width,
            y: this.sprite.texture.height
        };
        const domElementRatio = domSize.x / domSize.y;
        const imageRatio = imageSize.x / imageSize.y;
        var scale = 1;
        var position = new PIXI.Point(0, 0);

        if (this.type == 'cover' ? domElementRatio > imageRatio : domElementRatio < imageRatio) {
            //photo is taller than background
            scale = domSize.x / imageSize.x;
            position.y = -(imageSize.y * scale - domSize.y) / 2;
            position.x = 0;
        } else {
            //photo is wider than background
            scale = domSize.y / imageSize.y;
            position.x = -(imageSize.x * scale - domSize.x) / 2;
            position.y = 0;
        }
        this.sprite.scale = new PIXI.Point(scale, scale);
        this.sprite.position = position;
        return this;
    }
}

const imgUrl = 'https://images.unsplash.com/photo-1528723624453-3e53a413b392?ixlib=rb-0.3.5&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ&s=b44ae61a30e1a05f5defbf48cb5956eb';
const canvasParentElement = document.getElementById('canvasParentElement');
const renderer = PIXI.autoDetectRenderer({
    width: canvasParentElement.clientWidth,
    height: canvasParentElement.clientHeight
});
canvasParentElement.appendChild(renderer.view);

const stage = new PIXI.Container();
const pixiTestObject = new PixiBackground('cover', canvasParentElement, imgUrl);

PIXI.loader.add(imgUrl).load(function() {
    pixiTestObject.addTo(stage)
    requestAnimationFrame(animate);

    function animate() {
        requestAnimationFrame(animate);
        renderer.render(stage);
    }
});

window.addEventListener('resize', debounce(() => onResizeWindow(), 250));
window.addEventListener('resize', debounce(() => pixiTestObject.applyResize(), 250));

// From underscrore.js
function debounce(func, wait, immediate) {
    let timeout;
    return function() {
        let args = arguments;
        let later = () => {
            timeout = null;
            if (!immediate) func.apply(this, args);
        };
        let callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(this, args);
    }
}

function onResizeWindow() {
    const canvas = renderer.view;
    const w = canvasParentElement.clientWidth;
    const h = canvasParentElement.clientHeight;
    canvas.style.width = w + 'px';
    canvas.style.height = h + 'px';
    canvas.width = w;
    canvas.height = h;
    renderer.resize(w, h);
}
  #canvasParentElement {
    background: black;
    width: 100vw;
    height: 100vh;
    overflow: hidden;
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.8.1/pixi.min.js"></script>
<div id="canvasParentElement"></div>


1

根据我的使用情况,我只需要根据精灵的宽度来缩放。我使用 scale 函数来实现,并将其限制在最大值为1:

sprite.scale.set(Math.min(app.screen.width / sprite.texture.width, 1))

从PixiJS 5.3.0开始,渲染器将会触发一个名为resize的事件。这得益于Fabian von Ellerts在他的评论中提到的问题#6081。请注意保留HTML标记。
app.renderer.on('resize', (width, height) => {
  sprite.scale.set(Math.min(width / sprite.texture.width, 1))
})

⚠️ 这只会设置精灵的尺寸。您仍然需要以类似的方式在画布上定位它,即还要缩放其位置。


0
使用CSS解决方案来调整画布的大小比其他人提到的从窗口"resize"事件更新画布更可行且更好的选择,因为您不需要改变内容的位置,并且可以获得更好的性能。
您可以在HTML文件中添加一个canvas元素,并将其分配给应用程序的view属性,该canvas元素的id由您自己选择。
<canvas id="game"></canvas>

const app = new PIXI.Application({
    width: 960,
    height: 540,

    view: document.getElementById("game")
});

然后,将这段代码添加到你的CSS文件中:
#game {
    padding: 0;
    margin: 0;

    width: 100vw; 
    max-width: 100%; /* ensures that it doesn't overflow */
    height: auto;
    max-height: 100%; /* ensures that it doesn't overflow */

    user-select: none; /* removes accidental selection */
}

根据您的网站需要,调整CSS属性。

0
var mobiledev;
if (window.innerWidth <= window.innerHeight){
   mobiledev = true;
   app.renderer.resize(window.innerWidth, window.innerHeight + (((((window.innerWidth * 100) / window.innerHeight) / 100) - 0.5) * window.innerWidth));
    } else {
   mobiledev = false;
   app.renderer.resize(window.innerWidth, window.innerHeight - (((((window.innerHeight * 100) / window.innerWidth) / 100) - 0.65) * window.innerWidth));
    }

我已经使用PIXI.js快接近一年了,当涉及到调整大小和响应性时遇到了问题。这是我想出的一段代码块,对于响应性没有任何问题。我创建了一个if语句来检查设备分辨率,并根据其放置项目。


0
app.renderer.resize(window.innerWidth, window.innerHeight);
window.onresize = function()
{
    app.renderer.resize(window.innerWidth, window.innerHeight);
}

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接