trackLayer.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import { type CameraState } from '../camera/camera'
  2. import { lonLatToWorldTile } 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. export class TrackLayer implements MapLayer {
  11. projectPoints(scene: MapScene, camera: CameraState): ScreenPoint[] {
  12. return scene.track.map((point) => {
  13. const worldPoint = lonLatToWorldTile(point, scene.zoom)
  14. const screenPoint = worldToScreen(camera, worldPoint, false)
  15. return {
  16. x: screenPoint.x + scene.translateX,
  17. y: screenPoint.y + scene.translateY,
  18. }
  19. })
  20. }
  21. draw(context: LayerRenderContext): void {
  22. const { ctx, camera, scene } = context
  23. const points = this.projectPoints(scene, camera)
  24. ctx.save()
  25. ctx.lineCap = 'round'
  26. ctx.lineJoin = 'round'
  27. ctx.strokeStyle = 'rgba(23, 109, 93, 0.96)'
  28. ctx.lineWidth = 6
  29. ctx.beginPath()
  30. points.forEach((screenPoint, index) => {
  31. if (index === 0) {
  32. ctx.moveTo(screenPoint.x, screenPoint.y)
  33. return
  34. }
  35. ctx.lineTo(screenPoint.x, screenPoint.y)
  36. })
  37. ctx.stroke()
  38. ctx.fillStyle = '#f7fbf2'
  39. ctx.strokeStyle = '#176d5d'
  40. ctx.lineWidth = 4
  41. points.forEach((screenPoint, index) => {
  42. ctx.beginPath()
  43. ctx.arc(screenPoint.x, screenPoint.y, 10, 0, Math.PI * 2)
  44. ctx.fill()
  45. ctx.stroke()
  46. ctx.fillStyle = '#176d5d'
  47. ctx.font = 'bold 14px sans-serif'
  48. ctx.textAlign = 'center'
  49. ctx.textBaseline = 'middle'
  50. ctx.fillText(String(index + 1), screenPoint.x, screenPoint.y)
  51. ctx.fillStyle = '#f7fbf2'
  52. })
  53. ctx.restore()
  54. }
  55. }