自适应父容器
要实现自适应大小,使用spritejs是很简单的,Scene能够在初始化的时候自动根据容器的宽高来设置canvas的样式宽高。
const scene = new Scene('#adaptive', {resolution: [700, 700]});
const resolution = scene.resolution;
const viewport = scene.viewport;
const layer = scene.layer('fglayer');
const label = new Label(`resolution: ${resolution} | viewport: ${viewport}`);
label.attr({
anchor: [0.5, 0.5],
pos: [350, 350],
font: '36px Arial',
});
layer.append(label);
如果我们的容器适配窗口大小,当我们改变窗口大小时,canvas的大小不会随着改变,但是我们可以通过将Scene的viewport设置为['auto', 'auto']
,这样就让canvas大小在窗口调整时随着容器大小改变。
const scene = new Scene('#resize', {viewport: ['auto', 'auto'], resolution: [770, 770]});
const resolution = scene.resolution;
const viewport = scene.viewport;
const layer = scene.layer('fglayer');
const label = new Label(`resolution: ${resolution} | viewport: ${viewport}`);
label.attr({
anchor: [0.5, 0.5],
pos: [350, 350],
font: '36px Arial',
});
layer.append(label);
scene.on('viewportChange', () => {
const viewport = scene.viewport;
label.text = `resolution: ${resolution} | viewport: ${viewport}`;
});
displayRatio
当我们给Scene设置了resolution的时候,默认的resolution决定了Canvas的绘图大小,但是有时候我们的屏幕比较小,设置了很大的resolution会导致Canvas绘图性能消耗比较大。这时候,我们可以给Scene设置displayRatio和maxDisplayRatio。
const scene = new Scene('#container', {
viewport: ['auto', 'auto'],
resolution: [3840, 2160], // 绘制一个很大的Canvas
displayRatio: '2vw', // 设置实际创建的Canvas宽度不会超过viewport宽度的2倍
maxDisplayRatio: 1, // 设置最大Canvas宽度不超过实际resolution宽度
})
在webkit浏览器上,有window.devicePixelRatio,如果我们把displayRatio设置为'auto',那么实际displayRatio会自动根据devicePixelRatio实际值进行设置。
另外我们可以通过layer.setDisplayRatio(ratio, maxRatio)
来单独设置layer上的值,使得不同的layer用不同的displayRatio。不过如果之后我们重置了scene的displayRatio值,那么所有layer的displayRatio将会被覆盖更新。
Stick Mode 粘连模式
在移动设备上,要适配不同的屏幕比例,简单的auto适配可能会导致sprite元素被拉伸变形。如果要避免这个问题,我们可以通过配置Scene的Stick Mode相关属性来解决这个问题。
属性名称 | 属性类型 | 属性值 | 属性说明 |
---|---|---|---|
stickMode | 枚举 | "width" ,"height" ,"top" ,"bottom" ,"left" ,"right" | 6种适配容器的粘连模式 |
stickExtend | Boolean | true ,false | 如果在前面的任何一种粘连模式中,Canvas宽/高小于容器宽/高时,stickExtend如果设为true,那么将Canvas宽高补齐到容器的宽高 |
增加高度:
stickExtend:
;(async function () {
const scene = new Scene('#stickMode', {
viewport: ['auto', 'auto'],
resolution: [640, 1000],
stickMode: 'width',
// renderMode: 'repaintDirty',
});
const heightBtn = document.getElementById('heightBtn'),
stickMode = document.getElementById('stickMode'),
extendBtn = document.getElementById('extendBtn');
heightBtn.addEventListener('change', (evt) => {
stickMode.style.paddingBottom = `${50 + evt.target.value / 2}%`;
scene.updateViewport();
});
extendBtn.addEventListener('click', (evt) => {
scene.stickExtend = evt.target.checked;
scene.updateViewport().updateResolution();
});
await scene.preload(
{id: 'snow', src: 'https://p5.ssl.qhimg.com/t01bfde08606e87f1fe.png'},
{id: 'cloud', src: 'https://p5.ssl.qhimg.com/t01d2ff600bae7fe897.png'}
);
const layer = scene.layer('fglayer');
const cloud = new Sprite('cloud');
cloud.attr({
anchor: [0.5, 0],
pos: [320, -50],
size: [200, 130],
});
layer.append(cloud);
function addRandomSnow() {
const snow = new Sprite('snow');
const x0 = 20 + Math.random() * 600,
y0 = 0;
snow.attr({
anchor: [0.5, 0.5],
pos: [x0, y0],
size: [50, 50],
});
snow.animate([
{x: x0 - 10},
{x: x0 + 10},
], {
duration: 1000,
fill: 'forwards',
direction: 'alternate',
iterations: Infinity,
easing: 'ease-in-out',
});
const dropAnim = snow.animate([
{y: -200, rotate: 0},
{y: 2000, rotate: 1880},
], {
duration: 15000,
fill: 'forwards',
});
dropAnim.finished.then(() => {
snow.remove();
});
layer.append(snow);
}
setInterval(addRandomSnow, 200);
}())
竖屏的9种适配情况:
对应横屏的9种适配情况