@@ -31,12 +31,12 @@ const MapView = (() => {
3131 return 2 * R * Math . asin ( Math . sqrt ( s ) ) ;
3232 }
3333
34- function segmentTrajectory ( points ) {
34+ function segmentTrajectory ( points , maxGapKm = PORT_MAX_GAP_KM ) {
3535 if ( ! points || points . length < 2 ) return [ ] ;
3636 const segs = [ ] ;
3737 let cur = [ points [ 0 ] ] ;
3838 for ( let i = 1 ; i < points . length ; i ++ ) {
39- if ( haversineKm ( points [ i - 1 ] , points [ i ] ) > PORT_MAX_GAP_KM ) {
39+ if ( haversineKm ( points [ i - 1 ] , points [ i ] ) > maxGapKm ) {
4040 if ( cur . length >= 2 ) segs . push ( cur ) ;
4141 cur = [ points [ i ] ] ;
4242 } else {
@@ -105,39 +105,32 @@ const MapView = (() => {
105105 setData ( data , filters ) {
106106 this . _data = data ;
107107 this . _filters = filters ;
108- if ( this . _canvas ) this . _draw ( ) ;
108+ if ( this . _map ) this . _redraw ( ) ;
109109 } ,
110110
111111 onAdd ( map ) {
112112 this . _map = map ;
113- this . _canvas = document . createElement ( "canvas" ) ;
114- this . _canvas . style . cssText = "position:absolute;top:0;left:0;pointer-events:none;z-index:300;" ;
115- map . getPane ( "overlayPane" ) . appendChild ( this . _canvas ) ;
116- this . _resize ( ) ;
117- map . on ( "moveend zoomend resize" , this . _onMove , this ) ;
118- this . _draw ( ) ;
113+ this . _renderer = L . canvas ( { padding : 0.6 , tolerance : 2 } ) ;
114+ this . _layer = L . layerGroup ( ) . addTo ( map ) ;
115+ this . _redraw ( ) ;
119116 } ,
120117
121118 onRemove ( map ) {
122- map . off ( "moveend zoomend resize" , this . _onMove , this ) ;
123- this . _canvas . remove ( ) ;
124- this . _canvas = null ;
125- } ,
126-
127- _onMove ( ) { this . _resize ( ) ; this . _draw ( ) ; } ,
128-
129- _resize ( ) {
130- const sz = this . _map . getSize ( ) ;
131- this . _canvas . width = sz . x ;
132- this . _canvas . height = sz . y ;
133- L . DomUtil . setPosition ( this . _canvas , this . _map . containerPointToLayerPoint ( [ 0 , 0 ] ) ) ;
119+ if ( this . _layer ) {
120+ this . _layer . clearLayers ( ) ;
121+ map . removeLayer ( this . _layer ) ;
122+ }
123+ if ( this . _renderer ) {
124+ this . _renderer . remove ( ) ;
125+ }
126+ this . _layer = null ;
127+ this . _renderer = null ;
128+ this . _map = null ;
134129 } ,
135130
136- _draw ( ) {
137- if ( ! this . _canvas ) return ;
138- const ctx = this . _canvas . getContext ( "2d" ) ;
139- const sz = this . _map . getSize ( ) ;
140- ctx . clearRect ( 0 , 0 , sz . x , sz . y ) ;
131+ _redraw ( ) {
132+ if ( ! this . _layer || ! this . _renderer ) return ;
133+ this . _layer . clearLayers ( ) ;
141134
142135 const { activeTypes, hour } = this . _filters ;
143136
@@ -147,42 +140,21 @@ const MapView = (() => {
147140 if ( ! traj . points || traj . points . length < 2 ) continue ;
148141
149142 const meanSog = traj . points . reduce ( ( s , p ) => s + ( p . sog || 0 ) , 0 ) / traj . points . length ;
150- ctx . strokeStyle = meanSog >= GLOBAL_SOG_THRESHOLD ? GLOBAL_UNDERWAY_COLOR : GLOBAL_SLOW_COLOR ;
151- ctx . globalAlpha = 0.42 ;
152- ctx . lineWidth = 1.1 ;
153- ctx . beginPath ( ) ;
154-
155- let started = false ;
156- let prevPx = null ;
157-
158- for ( const pt of traj . points ) {
159- const px = this . _map . latLngToContainerPoint ( [ pt . lat , pt . lon ] ) ;
160-
161- if ( prevPx ) {
162- const screenDist = Math . hypot ( px . x - prevPx . x , px . y - prevPx . y ) ;
163- const kmPerPx = this . _kmPerPixel ( ) ;
164- if ( screenDist * kmPerPx > GLOBAL_MAX_STEP_KM ) {
165- if ( started ) ctx . stroke ( ) ;
166- ctx . beginPath ( ) ;
167- started = false ;
168- prevPx = null ;
169- }
170- }
171-
172- if ( ! started ) { ctx . moveTo ( px . x , px . y ) ; started = true ; }
173- else ctx . lineTo ( px . x , px . y ) ;
174- prevPx = px ;
175- }
176- if ( started ) ctx . stroke ( ) ;
143+ const color = meanSog >= GLOBAL_SOG_THRESHOLD ? GLOBAL_UNDERWAY_COLOR : GLOBAL_SLOW_COLOR ;
144+ const segs = segmentTrajectory ( traj . points , GLOBAL_MAX_STEP_KM ) ;
145+
146+ segs . forEach ( seg => {
147+ L . polyline ( seg . map ( p => [ p . lat , p . lon ] ) , {
148+ renderer : this . _renderer ,
149+ interactive : false ,
150+ bubblingMouseEvents : false ,
151+ color,
152+ weight : 1.1 ,
153+ opacity : 0.42 ,
154+ smoothFactor : 1.2 ,
155+ } ) . addTo ( this . _layer ) ;
156+ } ) ;
177157 }
178- ctx . globalAlpha = 1 ;
179- } ,
180-
181- _kmPerPixel ( ) {
182- const center = this . _map . getCenter ( ) ;
183- const zoom = this . _map . getZoom ( ) ;
184- const mPerPx = ( 156543.03392 * Math . cos ( center . lat * Math . PI / 180 ) ) / ( 2 ** zoom ) ;
185- return mPerPx / 1000 ;
186158 } ,
187159 } ) ;
188160
0 commit comments