图片的异步加载

spritejs支持图片URL作为资源,我们前面已经看过,我们可以把URL作为texture直接传给Sprite的texture属性。但是,因为网络图片资源是异步加载的,这会可能导致sprite的异步显示以及我们拿到的sprite的contentSize为0。

  1. const {Scene, Sprite, Label} = spritejs;
  2. const container = document.getElementById('adaptive');
  3. const scene = new Scene({
  4. container,
  5. width: 1200,
  6. height: 600,
  7. // contextType: '2d',
  8. });
  9. const layer = scene.layer();
  10. const robot = new Sprite('https://p5.ssl.qhimg.com/t01c33383c0e168c3c4.png');
  11. robot.attr({
  12. anchor: [0.5, 0.5],
  13. pos: [600, 300],
  14. scale: 0.5,
  15. });
  16. layer.append(robot);
  17. const label = new Label(`图片大小: ${robot.contentSize}`);
  18. label.attr({
  19. anchor: [0.5, 0.5],
  20. pos: [600, 100],
  21. font: '36px Arial',
  22. });
  23. layer.append(label);

获取图片大小之所以为0,是因为当我们把sprite添加到layer上的时候,图片还没有完成加载,因此此时的sprite里没有内容来撑开宽高,所以得到的大小就是0。

scene提供了preload方法来预加载和保存图片资源。这个方法可以接受一个或多个图片数据,返回一个promise对象。

  1. const {Scene, Sprite, Label} = spritejs;
  2. const container = document.getElementById('adaptive');
  3. const scene = new Scene({
  4. container,
  5. width: 1200,
  6. height: 600,
  7. // contextType: '2d',
  8. });
  9. const layer = scene.layer();
  10. (async function () {
  11. await scene.preload({
  12. id: 'robot',
  13. src: 'https://p5.ssl.qhimg.com/t01c33383c0e168c3c4.png',
  14. });
  15. const robot = new Sprite('robot');
  16. robot.attr({
  17. anchor: [0.5, 0.5],
  18. pos: [600, 300],
  19. scale: 0.5,
  20. });
  21. layer.append(robot);
  22. const label = new Label(`图片大小: ${robot.contentSize}`);
  23. label.attr({
  24. anchor: [0.5, 0.5],
  25. pos: [600, 100],
  26. font: '36px Arial',
  27. });
  28. layer.append(label);
  29. }());

我们通过preload事先预加载并缓存了图片,所以我们使用id:’robot’来创建sprite时,就可以立即显示出来,并得到contentSize。

雪碧图

与css雪碧图一样,SpriteJS Next 也支持雪碧图。SpriteJS Next 支持texture packer生成的标准JSON雪碧图。

  1. const {Scene, Sprite, Group} = spritejs;
  2. const container = document.getElementById('adaptive');
  3. const scene = new Scene({
  4. container,
  5. width: 1200,
  6. height: 600,
  7. // contextType: '2d',
  8. });
  9. const layer = scene.layer();
  10. (async function () {
  11. const earthPNG = 'https://p3.ssl.qhimg.com/t01806718065fe97c65.png',
  12. earthJSON = 'https://s3.ssl.qhres.com/static/d479c28f553c6cff.json';
  13. await scene.preload([earthPNG, earthJSON]);
  14. const group = new Group();
  15. group.attr({
  16. pos: [455, 215],
  17. });
  18. const earth = new Sprite();
  19. earth.attr({
  20. texture: 'earth_blue.png',
  21. pos: [115, 115],
  22. anchor: [0.5, 0.5],
  23. });
  24. const earthShadow = new Sprite();
  25. earthShadow.attr({
  26. texture: 'earth_shadow2.png',
  27. pos: [0, 0],
  28. });
  29. group.append(earth, earthShadow);
  30. layer.append(group);
  31. earth.animate([
  32. {rotate: 0, texture: 'earth_blue.png'},
  33. {rotate: 360, texture: 'earth_yellow.png'},
  34. {rotate: 720, texture: 'earth_green.png'},
  35. {rotate: 1080, texture: 'earth_white.png'},
  36. {rotate: 1440, texture: 'earth_blue.png'},
  37. ], {
  38. duration: 20000,
  39. iterations: Infinity,
  40. });
  41. }());

使用雪碧图可以有效减少HTTP请求,从而提高响应速度。

批量资源预加载进度

有时候,我们要预加载大量的资源,此时我们可以在preload的时候显示一个进度。

  1. const {Scene, Sprite, Label} = spritejs;
  2. const container = document.getElementById('adaptive');
  3. const scene = new Scene({
  4. container,
  5. width: 1600,
  6. height: 800,
  7. // contextType: '2d',
  8. });
  9. const layer = scene.layer();
  10. const images = [
  11. 'https://p1.ssl.qhimg.com/t016dc86e4b2c9b83a4.jpg',
  12. 'https://p0.ssl.qhimg.com/t01408bb4e2bed11d2e.jpg',
  13. 'https://p2.ssl.qhimg.com/t014e6d3eddccf40638.jpg',
  14. 'https://p2.ssl.qhimg.com/t014db3a8e2bf146c5b.jpg',
  15. 'https://p4.ssl.qhimg.com/t01ff1bf2a37a741821.jpg',
  16. 'https://p2.ssl.qhimg.com/t01dc1341ab5d0fe663.jpg',
  17. 'https://p5.ssl.qhimg.com/t01a0acf6aa37d00f91.jpg',
  18. 'https://p1.ssl.qhimg.com/t013b8514570a69a1c8.jpg',
  19. 'https://p2.ssl.qhimg.com/t011c71494e6d98d92b.jpg',
  20. 'https://p4.ssl.qhimg.com/t01ab40609e924d995c.jpg',
  21. 'https://p0.ssl.qhimg.com/t01794495bebb84f47d.jpg',
  22. 'https://p4.ssl.qhimg.com/t01a30bb66a9d11d624.jpg',
  23. 'https://p4.ssl.qhimg.com/t01b3d2c0b0093a957d.jpg',
  24. 'https://p0.ssl.qhimg.com/t010da5e7311c8dd3a9.jpg',
  25. 'https://p5.ssl.qhimg.com/t0189dd547c322b2357.jpg',
  26. 'https://p4.ssl.qhimg.com/t01feb50457ebbada10.jpg',
  27. ];
  28. const label = new Label('加载中... 0 / 16');
  29. label.attr({
  30. anchor: [0.5, 0.5],
  31. font: '36px Arial',
  32. lineHeight: 40,
  33. pos: [800, 300],
  34. });
  35. layer.append(label);
  36. const button = new Label('点击加载');
  37. button.attr({
  38. anchor: [0.5, 0.5],
  39. font: '44px Arial',
  40. pos: [800, 400],
  41. border: [2, 'black'],
  42. borderRadius: 12,
  43. padding: [10, 10],
  44. });
  45. layer.append(button);
  46. async function loadRes() {
  47. button.remove();
  48. scene.addEventListener('preload', (evt) => {
  49. label.text = `加载中... ${evt.detail.loaded.length} / ${evt.detail.resources.length}`;
  50. });
  51. const imgs = await scene.preload(...images);
  52. label.remove();
  53. imgs.forEach((texture, i) => {
  54. const sprite = new Sprite();
  55. sprite.attr({
  56. texture,
  57. x: 55 + (i % 8) * 170,
  58. y: 150 + Math.floor(i / 8) * 200,
  59. size: [150, 150],
  60. });
  61. layer.append(sprite);
  62. });
  63. }
  64. button.addEventListener('mouseenter', (evt) => {
  65. scene.container.style.cursor = 'pointer';
  66. });
  67. button.addEventListener('mouseleave', (evt) => {
  68. scene.container.style.cursor = 'default';
  69. });
  70. button.addEventListener('mousedown', (evt) => {
  71. evt.target.attr('scale', 0.8);
  72. });
  73. button.addEventListener('mouseup', (evt) => {
  74. evt.target.attr('scale', 1);
  75. loadRes();
  76. });