File : dialogs/baseDialog/BackgroundTouchEL.js

1
/*
2
Copyright - 2017 2023 - wwwouaiebe - Contact: https://www.ouaie.be/
3
4
This  program is free software;
5
you can redistribute it and/or modify it under the terms of the
6
GNU General Public License as published by the Free Software Foundation;
7
either version 3 of the License, or any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
*/
18
/*
19
Changes:
20
    - v4.0.0:
21
        - created from v3.6.0
22
Doc reviewed 202208
23
 */
24
25
import theGeometry from '../../core/lib/Geometry.js';
26
import theConfig from '../../data/Config.js';
27
import theTravelNotesData from '../../data/TravelNotesData.js';
28
import { ZERO, ONE, TWO } from '../../main/Constants.js';
29
30
import { LeafletPoint } from '../../leaflet/LeafletImports.js';
31
32
/* ------------------------------------------------------------------------------------------------------------------------- */
33
/**
34
touch event listener on the background
35
*/
36
/* ------------------------------------------------------------------------------------------------------------------------- */
37
38
class BackgroundTouchEL {
39
40
    /**
41
    A reference to the dialog
42
    @type {BaseDialog}
43
    */
44
45
    #baseDialog;
46
47
    /**
48
    A flag set to true when a pan is ongoing
49
    @type {Boolean}
50
    */
51
52
    #panOngoing = false;
53
54
    /**
55
    A flag set to true when a zoom is ongoing
56
    @type {Boolean}
57
    */
58
59
    #zoomOngoing = false;
60
61
    /**
62
    The X screen coordinate of the beginning of the pan
63
    @type {Number}
64
    */
65
66
    #startPanX = ZERO;
67
68
    /**
69
    The Y screen coordinate of the beginning of the pan
70
    @type {Number}
71
    */
72
73
    #startPanY = ZERO;
74
75
    /**
76
    A leaflet LatLng object with the center of the map
77
    @type {LeafletObject}
78
    */
79
80
    #mapCenter;
81
82
    /**
83
    The zoom when the touchstart event is trigered
84
    @type {Number}
85
    */
86
87
    #initialZoom;
88
89
    /**
90
    The distance in pixel betwwen the touches when the touchstart event is trigered
91
    @type {Number}
92
    */
93
94
    #initialZoomDistance;
95
96
    /**
97
    the point on the screen around witch thz zoom is performed
98
    @type {LeafletObject}
99
    */
100
101
    #aroundPoint;
102
103
    /**
104
    Execute the pan when a touchmove or toucheend event occurs after a touchestart event
105
    @param {Touch} touch The touch object to process
106
    */
107
108
    #processPan ( touch ) {
109
        if (
110
            this.#panOngoing
111
            &&
112
            ( this.#startPanX !== touch.screenX || this.#startPanY !== touch.screenY )
113
        ) {
114
            if (
115
                theConfig.baseDialog.cancelTouchY > this.#startPanY
116
                &&
117
                touch.screenY < this.#startPanY
118
                &&
119
                theConfig.baseDialog.cancelTouchX > this.#startPanX ) {
120
                this.#baseDialog.onCancel ( );
121
            }
122
            const latLngAtStart = theGeometry.screenCoordToLatLng ( this.#startPanX, this.#startPanY );
123
            const latLngAtEnd = theGeometry.screenCoordToLatLng ( touch.screenX, touch.screenY );
124
            theTravelNotesData.map.panTo (
125
                [
126
                    this.#mapCenter.lat +
127
                        latLngAtStart [ ZERO ] -
128
                        latLngAtEnd [ ZERO ],
129
                    this.#mapCenter.lng +
130
                        latLngAtStart [ ONE ] -
131
                        latLngAtEnd [ ONE ]
132
                ]
133
            );
134
        }
135
    }
136
137
    /**
138
    Execute the zoom when a touchmove or toucheend event occurs after a touchestart event
139
    @param {TouchList} targetTouches The touch objects to process
140
    */
141
142
    #processZoom ( targetTouches ) {
143
        let zoomDistance = Math.sqrt (
144
            ( ( targetTouches.item ( ZERO ).clientX - targetTouches.item ( ONE ).clientX ) ** TWO )
145
            +
146
            ( ( targetTouches.item ( ZERO ).clientY - targetTouches.item ( ONE ).clientY ) ** TWO )
147
        );
148
        let zoom = this.#initialZoom;
149
        let deltaZoom = zoomDistance - this.#initialZoomDistance;
150
        if ( theConfig.baseDialog.deltaZoomDistance < deltaZoom ) {
151
            zoom ++;
152
        }
153
        else if ( -theConfig.baseDialog.deltaZoomDistance > deltaZoom ) {
154
            zoom --;
155
        }
156
157
        zoom = Math.min ( theTravelNotesData.map.getMaxZoom ( ), zoom );
158
        zoom = Math.max ( theTravelNotesData.map.getMinZoom ( ), zoom );
159
        if ( zoom !== this.#initialZoom ) {
160
            theTravelNotesData.map.setZoomAround ( this.#aroundPoint, zoom );
161
            this.#initialZoom = zoom;
162
            this.#initialZoomDistance = zoomDistance;
163
        }
164
    }
165
166
    /**
167
    Handle the touchend event
168
    @param {Event} touchEvent The event to handle
169
    */
170
171
    #handleEndEvent ( touchEvent ) {
172
        if ( this.#panOngoing && ONE === touchEvent.changedTouches.length ) {
173
            this.#processPan ( touchEvent.changedTouches.item ( ZERO ) );
174
            this.#panOngoing = false;
175
        }
176
    }
177
178
    /**
179
    Handle the touchmove event
180
    @param {Event} touchEvent The event to handle
181
    */
182
183
    #handleMoveEvent ( touchEvent ) {
184
        if ( this.#panOngoing && ONE === touchEvent.changedTouches.length ) {
185
            this.#processPan ( touchEvent.changedTouches.item ( ZERO ) );
186
        }
187
        else if ( this.#zoomOngoing && TWO === touchEvent.targetTouches.length ) {
188
            this.#processZoom ( touchEvent.targetTouches );
189
        }
190
    }
191
192
    /**
193
    Handle the touchstart event
194
    @param {Event} touchEvent The event to handle
195
    */
196
197
    #handleStartEvent ( touchEvent ) {
198
        if ( ONE === touchEvent.targetTouches.length ) {
199
            const touch = touchEvent.changedTouches.item ( ZERO );
200
            this.#startPanX = touch.screenX;
201
            this.#startPanY = touch.screenY;
202
            this.#mapCenter = theTravelNotesData.map.getCenter ( );
203
            this.#panOngoing = true;
204
            this.#zoomOngoing = false;
205
        }
206
        if ( TWO === touchEvent.targetTouches.length ) {
207
            this.#initialZoom = theTravelNotesData.map.getZoom ( );
208
            this.#aroundPoint = new LeafletPoint (
209
                ( touchEvent.targetTouches.item ( ZERO ).clientX + touchEvent.targetTouches.item ( ONE ).clientX ) / TWO,
210
                ( touchEvent.targetTouches.item ( ZERO ).clientY + touchEvent.targetTouches.item ( ONE ).clientY ) / TWO
211
            );
212
            this.#initialZoomDistance = Math.sqrt (
213
                ( ( touchEvent.targetTouches.item ( ZERO ).clientX - touchEvent.targetTouches.item ( ONE ).clientX ) ** TWO )
214
                +
215
                ( ( touchEvent.targetTouches.item ( ZERO ).clientY - touchEvent.targetTouches.item ( ONE ).clientY ) ** TWO )
216
            );
217
            this.#panOngoing = false;
218
            this.#zoomOngoing = true;
219
        }
220
    }
221
222
    /**
223
    The constructor
224
    @param {BaseDialog} baseDialog A reference to the dialog
225
    */
226
227
    constructor ( baseDialog ) {
228
        Object.freeze ( this );
229
        this.#baseDialog = baseDialog;
230
    }
231
232
    /**
233
    Event listener method
234
    @param {Event} touchEvent The event to handle
235
    */
236
237
    handleEvent ( touchEvent ) {
238
239
        if ( touchEvent.currentTarget === touchEvent.target ) {
240
            touchEvent.preventDefault ( );
241
        }
242
        switch ( touchEvent.type ) {
243
        case 'touchstart' :
244
            if ( touchEvent.currentTarget === touchEvent.target ) {
245
                this.#handleStartEvent ( touchEvent );
246
            }
247
            break;
248
        case 'touchmove' :
249
            this.#handleMoveEvent ( touchEvent );
250
            break;
251
        case 'touchend' :
252
            this.#handleEndEvent ( touchEvent );
253
            break;
254
        default :
255
            break;
256
        }
257
258
    }
259
}
260
261
export default BackgroundTouchEL;
262
263
/* --- End of file --------------------------------------------------------------------------------------------------------- */
264