* _app * The "Rapid" part of the drawing. * Where we set up the scene graph and tell Pixi what needs to be drawn.
()
| 466 | * Where we set up the scene graph and tell Pixi what needs to be drawn. |
| 467 | */ |
| 468 | _app() { |
| 469 | // Wait for textures to be loaded before attempting rendering. |
| 470 | if (!this.textures?.loaded) return; |
| 471 | if (!this._started || this._paused) return; |
| 472 | |
| 473 | const context = this.context; |
| 474 | const map = context.systems.map; |
| 475 | |
| 476 | // If the user is currently resizing, skip rendering until the size has settled |
| 477 | if (context.container().classed('resizing')) return; |
| 478 | |
| 479 | const mapViewport = context.viewport; |
| 480 | const pixiViewport = this._pixiViewport; |
| 481 | |
| 482 | // At this point, the map transform is settled |
| 483 | // (`_tform` is called immediately before `_app`) |
| 484 | const mapTransform = mapViewport.transform; |
| 485 | const pixiTransform = pixiViewport.transform; |
| 486 | |
| 487 | // Determine "offset" |
| 488 | // We try to avoid reprojecting the pixi geometries unless zoom has changed, or map has translated very far. |
| 489 | // If the user is just panning, we can leave the geometries alone and add an offset translation to the origin. |
| 490 | const pixiXY = pixiTransform.translation; |
| 491 | const mapXY = mapTransform.translation; |
| 492 | const dist = vecLength(pixiXY, mapXY); |
| 493 | let offset; |
| 494 | |
| 495 | if (pixiTransform.k !== mapTransform.k || dist > 100000) { |
| 496 | offset = [0,0]; |
| 497 | pixiViewport.transform = mapTransform; // reset (sync pixi = map) |
| 498 | this.scene.dirtyScene(); // all geometry must be reprojected |
| 499 | } else { |
| 500 | offset = vecSubtract(pixiXY, mapXY); |
| 501 | } |
| 502 | |
| 503 | if (pixiTransform.r !== mapTransform.r) { |
| 504 | pixiTransform.rotation = mapTransform.r; |
| 505 | this.scene.dirtyScene(); // only really needs restyle |
| 506 | } |
| 507 | |
| 508 | // The `stage` should be positioned so that `[0,0]` is at the center of the viewport, |
| 509 | // and this is the pivot point for map rotation. |
| 510 | const mapCenter = pixiViewport.center(); |
| 511 | this.stage.pivot.set(0, 0); |
| 512 | this.stage.position.set(mapCenter[0], mapCenter[1]); |
| 513 | this.stage.rotation = mapTransform.r; |
| 514 | |
| 515 | // The `origin` returns `[0,0]` back to the `[top,left]` coordinate of the viewport, |
| 516 | // so `project/unproject` continues to work. |
| 517 | // This also includes the `offset`, which includes any panning that the user has done. |
| 518 | this.origin.position.set(-offset[0] - mapCenter[0], -offset[1] - mapCenter[1]); |
| 519 | |
| 520 | // Let's go! |
| 521 | const effectiveZoom = map.effectiveZoom(); |
| 522 | this.scene.render(this._frame, pixiViewport, effectiveZoom); |
| 523 | // this._renderDebug(); |
| 524 | |
| 525 | this._appPending = false; |
no test coverage detected