Skip to content

Commit 505d605

Browse files
committed
Added touch control to Orbits and Moons/GRS views. Improved mobile keyboard input. Fixed checkbox layout problem.
1 parent ce2e7d9 commit 505d605

16 files changed

Lines changed: 167 additions & 72 deletions

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "svc-ng",
3-
"version": "1.4.9",
3+
"version": "1.4.10",
44
"license": "MIT AND GPL-3.0-or-later",
55
"author": "Kerry Shetline <kerry@shetline.com>",
66
"scripts": {

src/app/app.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="about-dialog">
33
<img src="/assets/resources/svc_lunar_eclipse.png" alt="lunar eclipse" width="64" height="64">
44
<h2>Sky View Café NP</h2>
5-
Version 1.4.9<br><br>
5+
Version 1.4.10<br><br>
66
Copyright © 2016-2018 Kerry Shetline.
77
</div>
88
</p-dialog>

src/app/svc/generic-view.ts

Lines changed: 73 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
ASTEROID_BASE, COMET_BASE, EARTH, FIRST_PLANET, HALF_MINUTE, ISkyObserver, LAST_PLANET, NO_MATCH, SkyObserver, SolarSystem,
2727
StarCatalog, UT_to_TDB
2828
} from 'ks-astronomy';
29-
import { abs, ceil, max, Point } from 'ks-math';
29+
import { abs, ceil, max, Point, sqrt } from 'ks-math';
3030
import { FontMetrics, getFontMetrics, isSafari } from 'ks-util';
3131
import * as _ from 'lodash';
3232
import { KsDateTime } from 'ks-date-time-zone';
@@ -75,9 +75,10 @@ export abstract class GenericView implements AfterViewInit {
7575
protected clickX = -1;
7676
protected clickY = -1;
7777
protected canDrag = true;
78+
protected canTouchZoom = false;
79+
protected initialZoomSpread = 0; // 0 means not zooming.
7880
protected goodDragStart = false;
79-
protected debouncedDraw: () => void;
80-
protected throttledMouseMove: () => void;
81+
protected throttledRedraw: () => void;
8182
protected debouncedResize: () => void;
8283
protected dragging = false;
8384
protected excludedPlanets: number[] = [EARTH];
@@ -125,9 +126,9 @@ export abstract class GenericView implements AfterViewInit {
125126

126127
this.updatePlanetsToDraw();
127128

128-
this.debouncedDraw = _.debounce(() => {
129+
this.throttledRedraw = _.throttle(() => {
129130
this.draw();
130-
}, 0);
131+
}, 100);
131132

132133
appService.getCurrentTabUpdates((currentTab: CurrentTab) => {
133134
if (this.tabId === currentTab)
@@ -221,19 +222,27 @@ export abstract class GenericView implements AfterViewInit {
221222

222223
// TODO: Turn into utility function
223224
// noinspection JSMethodCanBeStatic
224-
protected getXYForTouchEvent(event: TouchEvent): Point {
225+
protected getXYForTouchEvent(event: TouchEvent, index = 0): Point {
225226
const touches = event.touches;
226227

227-
if (touches.length < 1)
228+
if (touches.length <= index)
228229
return {x: -1, y: -1};
229230

230-
const rect = (touches[0].target as HTMLElement).getBoundingClientRect();
231+
const rect = (touches[index].target as HTMLElement).getBoundingClientRect();
231232

232-
return {x: touches[0].clientX - rect.left, y: touches[0].clientY - rect.top};
233+
return {x: touches[index].clientX - rect.left, y: touches[0].clientY - rect.top};
233234
}
234235

235236
onTouchStart(event: TouchEvent): void {
236-
const pt = this.getXYForTouchEvent(event);
237+
const pt0 = this.getXYForTouchEvent(event);
238+
const pt = _.clone(pt0);
239+
let pt1;
240+
241+
if (event.touches.length > 1) {
242+
pt1 = this.getXYForTouchEvent(event, 1);
243+
pt.x = (pt0.x + pt1.x) / 2;
244+
pt.y = (pt0.y + pt1.y) / 2;
245+
}
237246

238247
this.clickX = this.lastMoveX = pt.x;
239248
this.clickY = this.lastMoveY = pt.y;
@@ -242,9 +251,21 @@ export abstract class GenericView implements AfterViewInit {
242251
this.goodDragStart = true;
243252
this.draw();
244253
event.preventDefault();
254+
255+
if (this.canTouchZoom && pt1) {
256+
const dx = pt1.x - pt0.x;
257+
const dy = pt1.y - pt0.y;
258+
259+
this.initialZoomSpread = max(sqrt(dx * dx + dy * dy), 1);
260+
this.startTouchZoom();
261+
}
262+
else
263+
this.initialZoomSpread = 0;
245264
}
246-
else
265+
else {
247266
this.goodDragStart = false;
267+
this.initialZoomSpread = 0;
268+
}
248269
}
249270

250271
onMouseDown(event: MouseEvent): void {
@@ -254,15 +275,42 @@ export abstract class GenericView implements AfterViewInit {
254275
}
255276

256277
onTouchMove(event: TouchEvent): void {
257-
const pt = this.getXYForTouchEvent(event);
278+
const pt0 = this.getXYForTouchEvent(event);
279+
const pt = _.clone(pt0);
280+
let pt1;
281+
282+
if (event.touches.length > 1) {
283+
pt1 = this.getXYForTouchEvent(event, 1);
284+
pt.x = (pt0.x + pt1.x) / 2;
285+
pt.y = (pt0.y + pt1.y) / 2;
286+
}
258287

259288
if (this.goodDragStart)
260289
this.handleMouseMove(pt.x, pt.y, true);
261290

291+
if (this.initialZoomSpread) {
292+
if (pt1) {
293+
const dx = pt1.x - pt0.x;
294+
const dy = pt1.y - pt0.y;
295+
const newSpread = max(sqrt(dx * dx + dy * dy), 1);
296+
const zoomRatio = newSpread / this.initialZoomSpread;
297+
298+
this.touchZoom(zoomRatio);
299+
}
300+
else
301+
this.initialZoomSpread = 0;
302+
}
303+
262304
if (this.isInsideView())
263305
event.preventDefault();
264306
}
265307

308+
protected startTouchZoom(): void {
309+
}
310+
311+
protected touchZoom(zoomRatio: number): void {
312+
}
313+
266314
onMouseMove(event: MouseEvent): void {
267315
if (this.goodDragStart || !this.dragging)
268316
this.handleMouseMove(event.offsetX, event.offsetY, !!((event.buttons & 0x01) || (this.isSafari && (event.which & 0x01))));
@@ -272,7 +320,7 @@ export abstract class GenericView implements AfterViewInit {
272320
this.lastMoveX = x;
273321
this.lastMoveY = y;
274322

275-
let justCleared = false;
323+
let justCleared = false;
276324

277325
if (!this.isInsideView()) {
278326
this.clearMouseHighlighting();
@@ -289,30 +337,26 @@ export abstract class GenericView implements AfterViewInit {
289337
this.resetCursor();
290338
}
291339

292-
if (!this.dragging || justCleared) {
293-
if (!this.throttledMouseMove) {
294-
this.throttledMouseMove = _.throttle(() => {
295-
this.draw();
296-
}, 100);
297-
}
298-
299-
this.throttledMouseMove();
300-
}
340+
if (!this.dragging || justCleared)
341+
this.throttledRedraw();
301342
}
302343

303344
protected clearMouseHighlighting(): void {
304345
this.lastMoveX = this.lastMoveY = -1;
305346
}
306347

307348
onTouchEnd(event: TouchEvent): void {
308-
const pt = this.getXYForTouchEvent(event);
349+
if (event.touches.length < 2)
350+
this.initialZoomSpread = 0;
309351

310-
this.lastMoveX = pt.x;
311-
this.lastMoveY = pt.y;
312-
this.resetCursor();
313-
this.draw();
314-
this.dragging = false;
315-
event.preventDefault();
352+
if (event.touches.length === 1)
353+
this.onTouchStart(event);
354+
else if (event.touches.length === 0) {
355+
this.resetCursor();
356+
this.draw();
357+
this.dragging = false;
358+
event.preventDefault();
359+
}
316360
}
317361

318362
onMouseUp(event: MouseEvent): void {

src/app/svc/svc-ecliptic-view/svc-ecliptic-view.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export class SvcEclipticViewComponent extends GenericSkyView implements AfterVie
134134
this.updatePlanetsToDraw();
135135
}
136136

137-
this.debouncedDraw();
137+
this.throttledRedraw();
138138
}
139139
});
140140
}

src/app/svc/svc-insolation-view/svc-insolation-view.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export class SvcInsolationViewComponent extends GenericView implements AfterView
100100
this.showMoonlight = <boolean> setting.value;
101101

102102
this.refreshImage = true;
103-
this.debouncedDraw();
103+
this.throttledRedraw();
104104
}
105105
});
106106

@@ -323,7 +323,7 @@ export class SvcInsolationViewComponent extends GenericView implements AfterView
323323

324324
if (this.wasWithinGraph !== within) {
325325
this.wasWithinGraph = within;
326-
this.debouncedDraw();
326+
this.throttledRedraw();
327327
}
328328
}
329329

src/app/svc/svc-map-view/svc-map-view.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ export class SvcMapViewComponent extends GenericView implements AfterViewInit {
137137
else if (setting.property === PROPERTY_BLINK_LOCATION_MARKERS)
138138
this.blink = <boolean> setting.value;
139139

140-
this.debouncedDraw();
140+
this.throttledRedraw();
141141
}
142142
});
143143

@@ -185,7 +185,7 @@ export class SvcMapViewComponent extends GenericView implements AfterViewInit {
185185
context.fillStyle = shadowColor;
186186
context.fillRect(0, 0, this.politicalMap.width, this.politicalMap.height);
187187

188-
this.debouncedDraw();
188+
this.throttledRedraw();
189189
}).catch((reason: any) => {
190190
return Promise.reject('Failed to load all images: ' + reason);
191191
});

src/app/svc/svc-moons-view/svc-moons-view.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<div #canvasWrapper class="canvasWrapper">
22
<div class="canvasAnchor">
33
<canvas #orbitCanvas (window:resize)="onResize()"
4-
(mousedown)="onMouseDown($event)"
5-
(mousemove)="onMouseMove($event)"
6-
(mouseup)="onMouseUp($event)"
4+
(touchstart)="onTouchStart($event)"
5+
(touchmove)="onTouchMove($event)" (mousemove)="onMouseMove($event)"
6+
(touchend)="onTouchEnd($event)" (touchcancel)="onTouchEnd($event)"
77
(wheel)="onWheel($event)"
88
[style.cursor]="cursor"
99
></canvas>

src/app/svc/svc-moons-view/svc-moons-view.component.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ export class SvcMoonsViewComponent extends GenericPlanetaryView implements After
8484
private jupiterMoons = new JupitersMoons();
8585
private saturnDrawer: SaturnDrawer;
8686
private saturnMoons = new SaturnMoons();
87-
private debouncedWheelRedraw: () => void;
8887

8988
private northOnTop = true;
9089
private eastOnLeft = true;
@@ -95,6 +94,7 @@ export class SvcMoonsViewComponent extends GenericPlanetaryView implements After
9594
private grsOverride = false;
9695
private fixedGrs = DEFAULT_FIXED_GRS;
9796
private zoom = SvcMoonsViewComponent.zoomToZoomSteps(DEFAULT_ZOOM);
97+
private initialZoomScale: number;
9898

9999
@ViewChild('canvasWrapper') private wrapperRef: ElementRef;
100100
@ViewChild('orbitCanvas') private canvasRef: ElementRef;
@@ -103,6 +103,8 @@ export class SvcMoonsViewComponent extends GenericPlanetaryView implements After
103103
constructor(appService: AppService, private astroDataService: AstroDataService, private httpClient: HttpClient) {
104104
super(appService, CurrentTab.MOONS_GRS);
105105

106+
this.canTouchZoom = true;
107+
106108
appService.getUserSettingUpdates((setting: UserSetting) => {
107109
if (setting.view === VIEW_MOONS && setting.source !== this) {
108110
if (setting.property === PROPERTY_NORTH_ON_TOP)
@@ -124,7 +126,7 @@ export class SvcMoonsViewComponent extends GenericPlanetaryView implements After
124126
else if (setting.property === PROPERTY_ZOOM)
125127
this.zoom = <number> setting.value;
126128

127-
this.debouncedDraw();
129+
this.throttledRedraw();
128130
}
129131
});
130132
}
@@ -137,12 +139,12 @@ export class SvcMoonsViewComponent extends GenericPlanetaryView implements After
137139
JupiterDrawer.getJupiterDrawer(this.astroDataService, this.httpClient).then((drawer: JupiterDrawer) => {
138140
this.jupiterDrawer = drawer;
139141
this.jupiterInfo = this.jupiterDrawer.getJupiterInfo();
140-
this.debouncedDraw();
142+
this.throttledRedraw();
141143
});
142144

143145
SaturnDrawer.getSaturnDrawer().then((drawer: SaturnDrawer) => {
144146
this.saturnDrawer = drawer;
145-
this.debouncedDraw();
147+
this.throttledRedraw();
146148
});
147149

148150
setTimeout(() => this.appService.requestViewSettings(VIEW_MOONS));
@@ -505,13 +507,6 @@ export class SvcMoonsViewComponent extends GenericPlanetaryView implements After
505507
// noinspection JSUnusedGlobalSymbols
506508
onWheel(event: WheelEvent): void {
507509
const oldZoom = this.zoom;
508-
509-
if (!this.debouncedWheelRedraw) {
510-
this.debouncedWheelRedraw = _.debounce(() => {
511-
this.draw();
512-
}, 10);
513-
}
514-
515510
let zoomDelta = event.wheelDeltaY;
516511

517512
if (zoomDelta === undefined)
@@ -527,13 +522,30 @@ export class SvcMoonsViewComponent extends GenericPlanetaryView implements After
527522
this.zoom = min(max(this.zoom + round(zoomDelta), 0), ZOOM_STEPS);
528523

529524
if (this.zoom !== oldZoom) {
530-
this.debouncedWheelRedraw();
525+
this.throttledRedraw();
531526
this.appService.updateUserSetting({view: VIEW_MOONS, property: PROPERTY_ZOOM, value: this.zoom, source: this});
532527
}
533528

534529
event.preventDefault();
535530
}
536531

532+
protected startTouchZoom(): void {
533+
this.initialZoomScale = pow(10.0, LOG_MIN_ZOOM + ZOOM_LOG_RANGE * this.zoom / ZOOM_STEPS);
534+
}
535+
536+
protected touchZoom(zoomRatio: number): void {
537+
const oldZoom = this.zoom;
538+
const scale = this.initialZoomScale / zoomRatio;
539+
const newZoom = ZOOM_STEPS * (log10(scale) - LOG_MIN_ZOOM) / ZOOM_LOG_RANGE;
540+
541+
this.zoom = min(max(newZoom, 0), ZOOM_STEPS);
542+
543+
if (this.zoom !== oldZoom) {
544+
this.throttledRedraw();
545+
this.appService.updateUserSetting({view: VIEW_MOONS, property: PROPERTY_ZOOM, value: this.zoom, source: this});
546+
}
547+
}
548+
537549
protected drawSkyPlotLine(pt1: Point, pt2: Point, dc: DrawingContextPlanetary, subject: SUBJECT): boolean {
538550
return false;
539551
}

src/app/svc/svc-orbit-view/svc-orbit-view.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
<div #canvasWrapper class="canvasWrapper">
1717
<div class="canvasAnchor">
1818
<canvas #orbitCanvas (window:resize)="onResize()"
19-
(mousedown)="onMouseDown($event)"
20-
(mousemove)="onMouseMove($event)"
21-
(mouseup)="onMouseUp($event)"
19+
(touchstart)="onTouchStart($event)" (mousedown)="onMouseDown($event)"
20+
(touchmove)="onTouchMove($event)" (mousemove)="onMouseMove($event)"
21+
(touchend)="onTouchEnd($event)" (touchcancel)="onTouchEnd($event)" (mouseup)="onMouseUp($event)"
2222
(wheel)="onWheel($event)"
2323
[style.cursor]="cursor"
2424
></canvas>

0 commit comments

Comments
 (0)