外部时钟

SpriteJS Next 有自己的内容更新机制,只要layer中的元素的属性有变化,layer就会将该元素放到等待刷新的列表中,在下一个渲染周期内刷新。

不过,SpriteJS可以使用外部时钟进行更新。这使得它对很多第三方库非常友好。

SpriteJS要指定layer使用外部时钟,可以手动调用layer的render方法,同时要屏蔽掉layer自己的更新机制,可以在创建layer的时候指定选项{autoRender:false}

比如下面的例子将一个layer的canvas给ThreeJS:

  1. const {Scene, Sprite} = spritejs;
  2. const container = document.getElementById('adaptive');
  3. const spriteScene = new Scene({
  4. container,
  5. width: 600,
  6. height: 600,
  7. autoRender: false,
  8. // contextType: '2d',
  9. });
  10. const bglayer = spriteScene.layer('bglayer');
  11. const fglayer = spriteScene.layer('fglayer');
  12. const imgUrl = 'https://p5.ssl.qhimg.com/t01a2bd87890397464a.png';
  13. const sprite = new Sprite({
  14. texture: imgUrl,
  15. pos: [300, 300],
  16. anchor: 0.5,
  17. });
  18. bglayer.append(sprite);
  19. /* globals THREE */
  20. const scene = new THREE.Scene();
  21. const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  22. const renderer = new THREE.WebGLRenderer({
  23. canvas: fglayer.canvas,
  24. });
  25. const geometry = new THREE.BoxGeometry(1, 1, 1);
  26. const material = new THREE.MeshBasicMaterial({color: 0x00ff00});
  27. const cube = new THREE.Mesh(geometry, material);
  28. scene.add(cube);
  29. camera.position.z = 5;
  30. function update() {
  31. bglayer.render();
  32. cube.rotation.x += 0.01;
  33. cube.rotation.y += 0.01;
  34. renderer.render(scene, camera);
  35. requestAnimationFrame(update);
  36. }
  37. update();

再比如下面的例子将一个layer的canvas给ClayGL:

  1. const {Scene, Sprite} = spritejs;
  2. const container = document.getElementById('adaptive');
  3. const spriteScene = new Scene({
  4. container,
  5. width: 600,
  6. height: 600,
  7. autoRender: false,
  8. // contextType: '2d',
  9. });
  10. const bglayer = spriteScene.layer('bglayer');
  11. const fglayer = spriteScene.layer('fglayer', {
  12. handleEvent: false,
  13. });
  14. const imgUrl = 'https://p5.ssl.qhimg.com/t01a2bd87890397464a.png';
  15. const sprite = new Sprite({
  16. texture: imgUrl,
  17. pos: [300, 300],
  18. anchor: 0.5,
  19. });
  20. bglayer.append(sprite);
  21. /* globals clay */
  22. const app = clay.application.create(fglayer.canvas, {
  23. // Enable event. Or the mouseover, mouseout events will not be triggered.
  24. event: true,
  25. init(app) {
  26. // Create camera
  27. this._camera = app.createCamera([0, 0.5, 7], [0, 0, 0]);
  28. function makeRandomColor() {
  29. return [Math.random(), Math.random(), Math.random()];
  30. }
  31. function createCube() {
  32. const randomColor = makeRandomColor();
  33. const cube = app.createCube({
  34. color: randomColor,
  35. });
  36. cube.on('mouseover', () => {
  37. cube.material.set('color', [1, 0, 0]);
  38. }, this).on('mouseout', () => {
  39. cube.material.set('color', randomColor);
  40. }, this);
  41. return cube;
  42. }
  43. this._cubes = [];
  44. // Create cube
  45. for(let i = 0; i < 3; i++) {
  46. for(let k = 0; k < 3; k++) {
  47. const cube = createCube();
  48. cube.scale.set(0.5, 0.5, 0.5);
  49. cube.position.set((i - 1) * 2, (k - 1) * 2, 0);
  50. this._cubes.push(cube);
  51. }
  52. }
  53. // Create light
  54. this._mainLight = app.createDirectionalLight([-1, -1, -1]);
  55. app.createAmbientLight('#fff', 0.3);
  56. },
  57. loop(app) {
  58. this._cubes.forEach((cube) => {
  59. bglayer.render();
  60. cube.rotation.rotateY(app.frameTime / 1000);
  61. });
  62. },
  63. });

layer.tick

除了直接用requestAnimationFrame之外,我们可以用layer.tick来执行时钟。

  1. layer.tick((t, p) => {
  2. // do something...
  3. }, {duration, playbackRate});

使用layer.tick比较方便,如果是其他第三方框架先渲染,SpriteJS最后渲染,可以不用设置{autoRender: false},也不用手动调用layer.render()

另外layer.tick还支持设置duration以及playbackRate参数。