trackLayer.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import { type CameraState } from '../camera/camera'
  2. import { calibratedLonLatToWorldTile } from '../../utils/projection'
  3. import { worldToScreen } from '../camera/camera'
  4. import { type MapLayer, type LayerRenderContext } from './mapLayer'
  5. import { type MapScene } from '../renderer/mapRenderer'
  6. export interface ScreenPoint {
  7. x: number
  8. y: number
  9. }
  10. function buildVectorCamera(scene: MapScene): CameraState {
  11. return {
  12. centerWorldX: scene.exactCenterWorldX,
  13. centerWorldY: scene.exactCenterWorldY,
  14. viewportWidth: scene.viewportWidth,
  15. viewportHeight: scene.viewportHeight,
  16. visibleColumns: scene.visibleColumns,
  17. rotationRad: scene.rotationRad,
  18. }
  19. }
  20. export class TrackLayer implements MapLayer {
  21. projectPoints(scene: MapScene): ScreenPoint[] {
  22. const camera = buildVectorCamera(scene)
  23. return scene.track.map((point) => {
  24. const worldPoint = calibratedLonLatToWorldTile(point, scene.zoom, scene.gpsCalibration, scene.gpsCalibrationOrigin)
  25. return worldToScreen(camera, worldPoint, false)
  26. })
  27. }
  28. draw(context: LayerRenderContext): void {
  29. const { ctx, scene } = context
  30. const points = this.projectPoints(scene)
  31. if (!points.length) {
  32. return
  33. }
  34. ctx.save()
  35. ctx.lineCap = 'round'
  36. ctx.lineJoin = 'round'
  37. ctx.strokeStyle = 'rgba(23, 109, 93, 0.96)'
  38. ctx.lineWidth = 6
  39. ctx.beginPath()
  40. points.forEach((screenPoint, index) => {
  41. if (index === 0) {
  42. ctx.moveTo(screenPoint.x, screenPoint.y)
  43. return
  44. }
  45. ctx.lineTo(screenPoint.x, screenPoint.y)
  46. })
  47. ctx.stroke()
  48. ctx.fillStyle = '#f7fbf2'
  49. ctx.strokeStyle = '#176d5d'
  50. ctx.lineWidth = 4
  51. points.forEach((screenPoint, index) => {
  52. ctx.beginPath()
  53. ctx.arc(screenPoint.x, screenPoint.y, 10, 0, Math.PI * 2)
  54. ctx.fill()
  55. ctx.stroke()
  56. ctx.fillStyle = '#176d5d'
  57. ctx.font = 'bold 14px sans-serif'
  58. ctx.textAlign = 'center'
  59. ctx.textBaseline = 'middle'
  60. ctx.fillText(String(index + 1), screenPoint.x, screenPoint.y)
  61. ctx.fillStyle = '#f7fbf2'
  62. })
  63. ctx.restore()
  64. }
  65. }