自适应父容器

要实现自适应大小,使用spritejs是很简单的,Scene能够在初始化的时候自动根据容器的宽高来设置canvas的样式宽高。

屏幕适配 - 图1

  1. const scene = new Scene('#adaptive', {resolution: [700, 700]});
  2. const resolution = scene.resolution;
  3. const viewport = scene.viewport;
  4. const layer = scene.layer('fglayer');
  5. const label = new Label(`resolution: ${resolution} | viewport: ${viewport}`);
  6. label.attr({
  7. anchor: [0.5, 0.5],
  8. pos: [350, 350],
  9. font: '36px Arial',
  10. });
  11. layer.append(label);

如果我们的容器适配窗口大小,当我们改变窗口大小时,canvas的大小不会随着改变,但是我们可以通过将Scene的viewport设置为['auto', 'auto'],这样就让canvas大小在窗口调整时随着容器大小改变。

屏幕适配 - 图2

  1. const scene = new Scene('#resize', {viewport: ['auto', 'auto'], resolution: [770, 770]});
  2. const resolution = scene.resolution;
  3. const viewport = scene.viewport;
  4. const layer = scene.layer('fglayer');
  5. const label = new Label(`resolution: ${resolution} | viewport: ${viewport}`);
  6. label.attr({
  7. anchor: [0.5, 0.5],
  8. pos: [350, 350],
  9. font: '36px Arial',
  10. });
  11. layer.append(label);
  12. scene.on('viewportChange', () => {
  13. const viewport = scene.viewport;
  14. label.text = `resolution: ${resolution} | viewport: ${viewport}`;
  15. });

displayRatio

当我们给Scene设置了resolution的时候,默认的resolution决定了Canvas的绘图大小,但是有时候我们的屏幕比较小,设置了很大的resolution会导致Canvas绘图性能消耗比较大。这时候,我们可以给Scene设置displayRatio和maxDisplayRatio。

  1. const scene = new Scene('#container', {
  2. viewport: ['auto', 'auto'],
  3. resolution: [3840, 2160], // 绘制一个很大的Canvas
  4. displayRatio: '2vw', // 设置实际创建的Canvas宽度不会超过viewport宽度的2倍
  5. maxDisplayRatio: 1, // 设置最大Canvas宽度不超过实际resolution宽度
  6. })

在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种适配容器的粘连模式
stickExtendBooleantrue,false如果在前面的任何一种粘连模式中,Canvas宽/高小于容器宽/高时,stickExtend如果设为true,那么将Canvas宽高补齐到容器的宽高

屏幕适配 - 图3

增加高度:

stickExtend:

  1. ;(async function () {
  2. const scene = new Scene('#stickMode', {
  3. viewport: ['auto', 'auto'],
  4. resolution: [640, 1000],
  5. stickMode: 'width',
  6. // renderMode: 'repaintDirty',
  7. });
  8. const heightBtn = document.getElementById('heightBtn'),
  9. stickMode = document.getElementById('stickMode'),
  10. extendBtn = document.getElementById('extendBtn');
  11. heightBtn.addEventListener('change', (evt) => {
  12. stickMode.style.paddingBottom = `${50 + evt.target.value / 2}%`;
  13. scene.updateViewport();
  14. });
  15. extendBtn.addEventListener('click', (evt) => {
  16. scene.stickExtend = evt.target.checked;
  17. scene.updateViewport().updateResolution();
  18. });
  19. await scene.preload(
  20. {id: 'snow', src: 'https://p5.ssl.qhimg.com/t01bfde08606e87f1fe.png'},
  21. {id: 'cloud', src: 'https://p5.ssl.qhimg.com/t01d2ff600bae7fe897.png'}
  22. );
  23. const layer = scene.layer('fglayer');
  24. const cloud = new Sprite('cloud');
  25. cloud.attr({
  26. anchor: [0.5, 0],
  27. pos: [320, -50],
  28. size: [200, 130],
  29. });
  30. layer.append(cloud);
  31. function addRandomSnow() {
  32. const snow = new Sprite('snow');
  33. const x0 = 20 + Math.random() * 600,
  34. y0 = 0;
  35. snow.attr({
  36. anchor: [0.5, 0.5],
  37. pos: [x0, y0],
  38. size: [50, 50],
  39. });
  40. snow.animate([
  41. {x: x0 - 10},
  42. {x: x0 + 10},
  43. ], {
  44. duration: 1000,
  45. fill: 'forwards',
  46. direction: 'alternate',
  47. iterations: Infinity,
  48. easing: 'ease-in-out',
  49. });
  50. const dropAnim = snow.animate([
  51. {y: -200, rotate: 0},
  52. {y: 2000, rotate: 1880},
  53. ], {
  54. duration: 15000,
  55. fill: 'forwards',
  56. });
  57. dropAnim.finished.then(() => {
  58. snow.remove();
  59. });
  60. layer.append(snow);
  61. }
  62. setInterval(addRandomSnow, 200);
  63. }())

竖屏的9种适配情况:

屏幕适配 - 图4

对应横屏的9种适配情况

屏幕适配 - 图5