@@ -24,10 +24,10 @@ import type {Coordinate} from 'ol/coordinate';
24
24
import type { FeatureType } from './TrackData' ;
25
25
import type { Snapper } from 'src/snapper' ;
26
26
import { Densifier } from 'src/densifier' ;
27
- import { fromExtent } from "ol/geom/Polygon" ;
28
27
import { Extent } from "ol/extent" ;
29
- import { EXTENT as epsg3857Extent } from "ol/proj/epsg3857" ;
30
- import { EXTENT as epsg4326Extent } from "ol/proj/epsg4326" ;
28
+ import { EventsKey } from 'ol/events' ;
29
+ import RenderEvent from "ol/render/Event" ;
30
+ import { unByKey } from "ol/Observable" ;
31
31
32
32
export type TrackMode = 'edit' | '' ;
33
33
export type TrackSubMode = 'addpoi' | 'editpoi' | '' ;
@@ -78,14 +78,16 @@ export interface Options {
78
78
* Pixel tolerance for considering the pointer close enough to a segment for snapping.
79
79
*/
80
80
hitTolerance : number ;
81
+
81
82
/**
82
- * Optional layer to display a drawing area mask. drawExtent should be specified to use mask .
83
+ * Drawing area extent .
83
84
*/
84
- drawMaskLayer ?: VectorLayer < VectorSource > ;
85
+ drawExtent ?: Extent ;
86
+
85
87
/**
86
- * Drawing area extent. drawMaskLayer should be specified.
88
+ * Drawing mask color. CSS string
87
89
*/
88
- drawExtent ?: Extent ;
90
+ drawMaskColor ?: string ;
89
91
}
90
92
91
93
@@ -127,7 +129,9 @@ export default class TrackManager<POIMeta> {
127
129
private interaction_ : TrackInteraction ;
128
130
private historyManager_ = new HistoryManager < Feature < Point | LineString > [ ] > ( ) ;
129
131
130
- private drawMaskLayer : VectorLayer < VectorSource > ;
132
+ private drawExtent_ : Extent | undefined ;
133
+ private drawMaskColor_ : string = 'rgba(241, 245, 249, 1)' ;
134
+ private addDrawingMaskKey_ : EventsKey | undefined ;
131
135
132
136
constructor ( options : Options ) {
133
137
this . map_ = options . map ;
@@ -148,10 +152,9 @@ export default class TrackManager<POIMeta> {
148
152
trackData : this . trackData_
149
153
} ) ;
150
154
151
- this . drawMaskLayer = options . drawMaskLayer ;
152
- if ( options . drawExtent && this . drawMaskLayer ) {
153
- this . drawMaskLayer . getSource ( ) . addFeature ( this . calculateMaskFeature ( options . drawExtent ) )
154
- this . drawMaskLayer . setVisible ( false )
155
+ this . drawExtent_ = options . drawExtent ;
156
+ if ( options . drawMaskColor ) {
157
+ this . drawMaskColor_ = options . drawMaskColor ;
155
158
}
156
159
157
160
this . interaction_ = new TrackInteraction ( {
@@ -352,6 +355,10 @@ export default class TrackManager<POIMeta> {
352
355
this . map_ . once ( "postrender" , ( ) => {
353
356
this . interaction_ . addMapInOutEventListeners ( this . map_ . getViewport ( ) ) ;
354
357
} ) ;
358
+
359
+ if ( this . drawExtent_ ) {
360
+ this . addDrawingMaskKey_ = this . map_ . on ( 'postcompose' , ( evt ) => this . addDrawingMask ( evt , this . drawExtent_ ) ) ;
361
+ }
355
362
} else {
356
363
this . historyManager_ . clear ( ) ;
357
364
if ( this . shadowTrackLayer_ ) {
@@ -360,8 +367,11 @@ export default class TrackManager<POIMeta> {
360
367
if ( this . map_ ?. getViewport ( ) ) {
361
368
this . interaction_ . removeMapInOutEventListeners ( this . map_ . getViewport ( ) ) ;
362
369
}
370
+ if ( this . addDrawingMaskKey_ ) {
371
+ unByKey ( this . addDrawingMaskKey_ ) ;
372
+ this . addDrawingMaskKey_ = undefined ;
373
+ }
363
374
}
364
- this . drawMaskLayer ?. setVisible ( edit ) ;
365
375
this . interaction_ . setActive ( edit ) ;
366
376
this . mode_ = mode || '' ;
367
377
this . render ( ) ;
@@ -637,18 +647,35 @@ export default class TrackManager<POIMeta> {
637
647
this . shadowTrackLayer_ . getSource ( ) . changed ( ) ;
638
648
}
639
649
640
- private calculateMaskFeature ( extent : Extent ) {
641
- const projection = this . map_ . getView ( ) . getProjection ( ) ;
642
- // for some projections (like EPSG:2056) extent smaller than visible map
643
- let wExtent = projection . getExtent ( ) ;
644
- if ( projection . getUnits ( ) === 'm' ) {
645
- wExtent = epsg3857Extent ;
646
- } else if ( projection . getUnits ( ) === 'degrees' ) {
647
- wExtent = epsg4326Extent ;
648
- }
649
- const mask = fromExtent ( wExtent ) ;
650
- const drawingArea = fromExtent ( extent ) ;
651
- mask . appendLinearRing ( drawingArea . getLinearRing ( 0 ) ) ;
652
- return new Feature ( mask ) ;
650
+ addDrawingMask ( event : RenderEvent , extent : Extent ) {
651
+ if ( ! extent ?. length ) return ;
652
+ const viewport = event . target . getViewport ( ) ;
653
+ const canvases = viewport . getElementsByTagName ( 'canvas' ) ;
654
+ const canvas = canvases . item ( canvases . length - 1 ) ;
655
+ const context = canvas . getContext ( '2d' ) ;
656
+
657
+ const coordinates = [
658
+ [ extent [ 0 ] , extent [ 1 ] ] , // Bottom-left
659
+ [ extent [ 0 ] , extent [ 3 ] ] , // Top-left
660
+ [ extent [ 2 ] , extent [ 3 ] ] , // Top-right
661
+ [ extent [ 2 ] , extent [ 1 ] ] , // Bottom-right
662
+ ] ;
663
+
664
+ const pixelCoordinates = coordinates . map ( ( coord ) => this . map_ . getPixelFromCoordinate ( coord ) ) ;
665
+
666
+ context . beginPath ( ) ;
667
+
668
+ // outer rectangle
669
+ context . rect ( 0 , 0 , canvas . width , canvas . height ) ;
670
+
671
+ const width = pixelCoordinates [ 3 ] [ 0 ] - pixelCoordinates [ 0 ] [ 0 ] ;
672
+ const height = pixelCoordinates [ 1 ] [ 1 ] - pixelCoordinates [ 0 ] [ 1 ] ;
673
+
674
+ // inner rectangle
675
+ context . rect ( pixelCoordinates [ 0 ] [ 0 ] , pixelCoordinates [ 0 ] [ 1 ] , width , height ) ;
676
+
677
+ context . closePath ( ) ;
678
+ context . fillStyle = this . drawMaskColor_ ;
679
+ context . fill ( 'evenodd' ) ;
653
680
}
654
681
}
0 commit comments