@openglobus/og 0.14.10 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/og.css +378 -275
- package/dist/@openglobus/og.css +1 -1
- package/dist/@openglobus/og.esm.js +2 -2
- package/dist/@openglobus/og.esm.js.map +1 -1
- package/dist/@openglobus/og.umd.js +2 -2
- package/dist/@openglobus/og.umd.js.map +1 -1
- package/package.json +18 -17
- package/src/og/Clock.js +218 -194
- package/src/og/Globe.js +5 -5
- package/src/og/Object3d.js +104 -145
- package/src/og/camera/Camera.js +31 -27
- package/src/og/camera/PlanetCamera.js +22 -14
- package/src/og/cons.js +107 -107
- package/src/og/control/Atmosphere.js +396 -0
- package/src/og/control/CompassButton.js +11 -18
- package/src/og/control/Control.js +187 -188
- package/src/og/control/GeoImageDragControl.js +84 -66
- package/src/og/control/LayerSwitcher.js +56 -138
- package/src/og/control/Lighting.js +314 -186
- package/src/og/control/MouseNavigation.js +2 -2
- package/src/og/control/RulerSwitcher.js +24 -19
- package/src/og/control/ScaleControl.js +30 -10
- package/src/og/control/SimpleSkyBackground.js +210 -0
- package/src/og/control/Sun.js +2 -0
- package/src/og/control/ZoomControl.js +30 -42
- package/src/og/control/index.js +6 -0
- package/src/og/control/ruler/RulerScene.js +5 -23
- package/src/og/control/selection/Selection.js +99 -0
- package/src/og/control/selection/SelectionScene.js +350 -0
- package/src/og/control/timeline/TimelineControl.js +99 -0
- package/src/og/control/timeline/TimelineModel.js +133 -0
- package/src/og/control/timeline/TimelineView.js +449 -0
- package/src/og/control/timeline/timelineUtils.js +132 -0
- package/src/og/ellipsoid/Ellipsoid.js +120 -93
- package/src/og/ellipsoid/wgs84.js +13 -13
- package/src/og/entity/Entity.js +36 -9
- package/src/og/entity/EntityCollection.js +0 -2
- package/src/og/entity/GeoObject.js +72 -56
- package/src/og/entity/GeoObjectHandler.js +487 -656
- package/src/og/entity/GeometryHandler.js +1341 -1337
- package/src/og/entity/Polyline.js +0 -16
- package/src/og/entity/Ray.js +0 -10
- package/src/og/entity/RayHandler.js +3 -44
- package/src/og/entity/Strip.js +1 -6
- package/src/og/index.js +10 -6
- package/src/og/input/input.js +3 -1
- package/src/og/layer/CanvasTiles.js +39 -34
- package/src/og/layer/Layer.js +69 -9
- package/src/og/layer/Material.js +1 -8
- package/src/og/layer/WMS.js +16 -5
- package/src/og/light/LightSource.js +2 -0
- package/src/og/math/Line3.js +140 -139
- package/src/og/math/Plane.js +118 -117
- package/src/og/math/Ray.js +242 -239
- package/src/og/math/Vec3.js +56 -37
- package/src/og/math/Vec4.js +3 -4
- package/src/og/math.js +21 -21
- package/src/og/quadTree/Node.js +5 -4
- package/src/og/quadTree/index.js +12 -0
- package/src/og/renderer/Renderer.js +64 -37
- package/src/og/renderer/RendererEvents.js +1071 -1065
- package/src/og/scene/Planet.js +352 -172
- package/src/og/scene/RenderNode.js +27 -12
- package/src/og/segment/Segment.js +0 -5
- package/src/og/shaders/atmos.js +332 -0
- package/src/og/shaders/drawnode.js +475 -109
- package/src/og/shaders/geoObject.js +96 -51
- package/src/og/shaders/polyline.js +212 -17
- package/src/og/shaders/ray.js +13 -6
- package/src/og/shaders/toneMapping.js +5 -5
- package/src/og/shaders/utils.js +88 -0
- package/src/og/terrain/GlobusTerrain.js +5 -4
- package/src/og/terrain/MapboxTerrain.js +231 -52
- package/src/og/ui/Button.js +106 -0
- package/src/og/ui/ButtonGroup.js +57 -0
- package/src/og/ui/Dialog.js +242 -0
- package/src/og/ui/Slider.js +144 -0
- package/src/og/ui/ToggleButton.js +51 -0
- package/src/og/{control → ui}/UIhelpers.js +11 -2
- package/src/og/ui/View.js +190 -0
- package/src/og/utils/shared.js +960 -942
- package/src/og/webgl/Framebuffer.js +308 -387
- package/src/og/webgl/Handler.js +90 -30
- package/src/og/webgl/Multisample.js +8 -0
- package/types/Clock.d.ts +7 -2
- package/types/Object3d.d.ts +14 -3
- package/types/camera/Camera.d.ts +18 -17
- package/types/camera/PlanetCamera.d.ts +3 -1
- package/types/control/Atmosphere.d.ts +15 -0
- package/types/control/CompassButton.d.ts +1 -2
- package/types/control/GeoImageDragControl.d.ts +7 -1
- package/types/control/LayerSwitcher.d.ts +5 -6
- package/types/control/Lighting.d.ts +32 -7
- package/types/control/ScaleControl.d.ts +2 -1
- package/types/control/SimpleSkyBackground.d.ts +15 -0
- package/types/control/ZoomControl.d.ts +0 -1
- package/types/control/index.d.ts +4 -1
- package/types/control/ruler/RulerScene.d.ts +0 -1
- package/types/control/selection/Selection.d.ts +49 -0
- package/types/control/selection/SelectionScene.d.ts +34 -0
- package/types/ellipsoid/Ellipsoid.d.ts +3 -2
- package/types/entity/Entity.d.ts +8 -0
- package/types/entity/GeoObject.d.ts +28 -22
- package/types/entity/GeoObjectHandler.d.ts +16 -56
- package/types/entity/Ray.d.ts +0 -3
- package/types/entity/RayHandler.d.ts +0 -4
- package/types/index.d.ts +7 -5
- package/types/input/input.d.ts +2 -0
- package/types/layer/CanvasTiles.d.ts +1 -0
- package/types/layer/Layer.d.ts +9 -0
- package/types/layer/WMS.d.ts +7 -3
- package/types/math/Plane.d.ts +1 -1
- package/types/math/Vec3.d.ts +19 -16
- package/types/math/Vec4.d.ts +2 -3
- package/types/math.d.ts +20 -20
- package/types/quadTree/index.d.ts +10 -0
- package/types/renderer/Renderer.d.ts +11 -37
- package/types/scene/Planet.d.ts +27 -1
- package/types/scene/RenderNode.d.ts +2 -1
- package/types/segment/Segment.d.ts +1 -1
- package/types/shaders/atmos.d.ts +4 -0
- package/types/shaders/drawnode.d.ts +3 -2
- package/types/shaders/utils.d.ts +1 -0
- package/types/terrain/GlobusTerrain.d.ts +1 -1
- package/types/terrain/MapboxTerrain.d.ts +2 -1
- package/types/ui/Button.d.ts +21 -0
- package/types/ui/Dialog.d.ts +41 -0
- package/types/ui/Slider.d.ts +30 -0
- package/types/ui/ToggleButton.d.ts +10 -0
- package/types/{control → ui}/UIhelpers.d.ts +1 -1
- package/types/ui/View.d.ts +32 -0
- package/types/utils/shared.d.ts +16 -14
- package/types/webgl/Framebuffer.d.ts +2 -5
- package/types/webgl/Handler.d.ts +15 -10
- package/types/webgl/Multisample.d.ts +2 -0
- package/src/og/ajax.js +0 -204
- package/src/og/entity/Object3d.js +0 -504
- package/src/og/utils/quadTreeType.js +0 -11
- package/types/ajax.d.ts +0 -24
- package/types/utils/quadTreeType.d.ts +0 -8
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { View } from '../../ui/View.js';
|
|
4
|
+
import { TimelineModel } from './TimelineModel.js';
|
|
5
|
+
import {
|
|
6
|
+
addSeconds,
|
|
7
|
+
createCanvasHTML,
|
|
8
|
+
dateToStr,
|
|
9
|
+
drawNotch,
|
|
10
|
+
drawText,
|
|
11
|
+
getNearestTimeLeft,
|
|
12
|
+
getScale
|
|
13
|
+
} from './timelineUtils.js';
|
|
14
|
+
import { ToggleButton } from "../../ui/ToggleButton.js";
|
|
15
|
+
import { Button } from "../../ui/Button.js";
|
|
16
|
+
import { ButtonGroup } from "../../ui/ButtonGroup.js";
|
|
17
|
+
|
|
18
|
+
const SECONDS_TO_MILLISECONDS = 1000.0;
|
|
19
|
+
const MILLISECONDS_TO_SECONDS = 1.0 / SECONDS_TO_MILLISECONDS;
|
|
20
|
+
const EVENT_LIST = [
|
|
21
|
+
'startdrag',
|
|
22
|
+
'stopdrag',
|
|
23
|
+
'startdragcurrent',
|
|
24
|
+
'stopdragcurrent',
|
|
25
|
+
'setcurrent',
|
|
26
|
+
'reset',
|
|
27
|
+
'play',
|
|
28
|
+
'playback',
|
|
29
|
+
'pause',
|
|
30
|
+
'visibility'
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const ICON_PLAY_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/><path d="M0 0h24v24H0z" fill="none"/></svg>';
|
|
34
|
+
const ICON_PAUSE_SVG = '<?xml version="1.0" ?><!DOCTYPE svg PUBLIC \'-//W3C//DTD SVG 1.1//EN\' \'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\'><svg enable-background="new 0 0 512 512" height="512px" version="1.1" viewBox="0 0 512 512" width="512px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="Layer_6"><rect fill="#252525" height="320" width="60" x="153" y="96"/><rect fill="#252525" height="320" width="60" x="299" y="96"/></g></svg>';
|
|
35
|
+
|
|
36
|
+
const SCALE_FILL_COLOR = "rgba(64, 59, 59, 1.0)";
|
|
37
|
+
const SCALE_NOTCH_COLOR = "#bfbfbf";
|
|
38
|
+
const SCALE_TIME_COLOR = "#bfbfbf";
|
|
39
|
+
|
|
40
|
+
const TEMPLATE =
|
|
41
|
+
`<div class="og-timeline">
|
|
42
|
+
|
|
43
|
+
<div class="og-timeline-top">
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="og-timeline-frame">
|
|
47
|
+
<div class="og-timeline-current">
|
|
48
|
+
<div class="og-timeline-current-spin">
|
|
49
|
+
<div class="og-timeline-current-arrow"></div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="og-timeline-scale"></div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<div class="og-timeline-bottom">
|
|
56
|
+
<div class="og-timeline-controls">
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
</div>`;
|
|
61
|
+
|
|
62
|
+
class TimelineView extends View {
|
|
63
|
+
|
|
64
|
+
constructor(options = {}) {
|
|
65
|
+
super({
|
|
66
|
+
template: TEMPLATE,
|
|
67
|
+
eventList: EVENT_LIST,
|
|
68
|
+
model: new TimelineModel({
|
|
69
|
+
rangeStart: options.rangeStart,
|
|
70
|
+
rangeEnd: options.rangeEnd,
|
|
71
|
+
current: options.currentDate,
|
|
72
|
+
minDate: options.minDate,
|
|
73
|
+
maxDate: options.maxDate
|
|
74
|
+
})
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
this.fillStyle = options.fillStyle || SCALE_FILL_COLOR;
|
|
78
|
+
|
|
79
|
+
this.$controls;
|
|
80
|
+
|
|
81
|
+
this._frameEl = null;
|
|
82
|
+
this._currentEl = null;
|
|
83
|
+
this._canvasEl = createCanvasHTML();
|
|
84
|
+
this._ctx = this._canvasEl.getContext('2d');
|
|
85
|
+
|
|
86
|
+
this._isMouseOver = false;
|
|
87
|
+
this._isDragging = false;
|
|
88
|
+
this._isCurrentDragging = false;
|
|
89
|
+
this._isCurrentMouseOver = false;
|
|
90
|
+
|
|
91
|
+
this._minWidth = 330;
|
|
92
|
+
this._canvasScale = 2;
|
|
93
|
+
|
|
94
|
+
this._millisecondsInPixel = 0;
|
|
95
|
+
|
|
96
|
+
this._clickPosX = 0;
|
|
97
|
+
this._clickRangeStart = new Date();
|
|
98
|
+
this._clickRangeEnd = new Date();
|
|
99
|
+
this._clickCurrentDate = new Date();
|
|
100
|
+
|
|
101
|
+
this._clickTime = 0;
|
|
102
|
+
this._clickDelay = 450;
|
|
103
|
+
|
|
104
|
+
this._onResizeObserver_ = this._onResizeObserver.bind(this);
|
|
105
|
+
this._resizeObserver = new ResizeObserver(this._onResizeObserver_);
|
|
106
|
+
|
|
107
|
+
this._pauseBtn = new ToggleButton({
|
|
108
|
+
classList: ["og-timeline-control_button"],
|
|
109
|
+
icon: ICON_PAUSE_SVG,
|
|
110
|
+
name: "pause"
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
this._playBtn = new ToggleButton({
|
|
114
|
+
classList: ["og-timeline-control_button"],
|
|
115
|
+
icon: ICON_PLAY_SVG,
|
|
116
|
+
name: "play",
|
|
117
|
+
isActive: true,
|
|
118
|
+
preventClick: true
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
this._buttons = new ButtonGroup({
|
|
122
|
+
buttons: [this._pauseBtn, this._playBtn]
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
this._visibility = null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
_onResizeObserver() {
|
|
129
|
+
this.resize();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
get canvasScale() {
|
|
133
|
+
return this._canvasScale;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
set canvasScale(scale) {
|
|
137
|
+
if (scale !== this._canvasScale) {
|
|
138
|
+
this._canvasScale = scale;
|
|
139
|
+
this.resize();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
resize() {
|
|
144
|
+
this._resize();
|
|
145
|
+
this.draw();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
afterRender(parentNode) {
|
|
149
|
+
this.resize();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
render() {
|
|
153
|
+
super.render();
|
|
154
|
+
|
|
155
|
+
this.$controls = this.select(".og-timeline-controls");
|
|
156
|
+
|
|
157
|
+
this._frameEl = this.select(".og-timeline-frame");
|
|
158
|
+
this._currentEl = this.select(".og-timeline-current");
|
|
159
|
+
this.select(".og-timeline-frame .og-timeline-scale").appendChild(this._canvasEl);
|
|
160
|
+
|
|
161
|
+
this._resizeObserver.observe(this.el);
|
|
162
|
+
|
|
163
|
+
this.model.on("change", () => {
|
|
164
|
+
this.draw()
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
this.model.on("current", (d) => {
|
|
168
|
+
this._drawCurrent();
|
|
169
|
+
this._events.dispatch(this._events.setcurrent, d);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
this._canvasEl.addEventListener("mouseenter", this._onMouseEnter.bind(this));
|
|
173
|
+
this._canvasEl.addEventListener("mouseout", this._onMouseOut.bind(this));
|
|
174
|
+
|
|
175
|
+
this._currentEl.addEventListener("mouseenter", this._onCurrentMouseEnter.bind(this));
|
|
176
|
+
this._currentEl.addEventListener("mouseout", this._onCurrentMouseOut.bind(this));
|
|
177
|
+
|
|
178
|
+
document.body.addEventListener("mousemove", this._onMouseMove.bind(this));
|
|
179
|
+
document.body.addEventListener("mousedown", this._onMouseDown.bind(this));
|
|
180
|
+
document.body.addEventListener("mouseup", this._onMouseUp.bind(this));
|
|
181
|
+
document.body.addEventListener("mousewheel", this._onMouseWheel.bind(this));
|
|
182
|
+
|
|
183
|
+
this._playBtn.appendTo(this.$controls);
|
|
184
|
+
this._pauseBtn.appendTo(this.$controls);
|
|
185
|
+
|
|
186
|
+
this._buttons.on("change", (btn) => {
|
|
187
|
+
switch (btn.name) {
|
|
188
|
+
case "play":
|
|
189
|
+
this.play();
|
|
190
|
+
break;
|
|
191
|
+
case "pause":
|
|
192
|
+
this.pause();
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// let mltView = new View({
|
|
198
|
+
// template: `<div class="og-timeline-multiplier">
|
|
199
|
+
// <select>
|
|
200
|
+
// <option value="0.25">0.25</option>
|
|
201
|
+
// <option value="0.5">0.5</option>
|
|
202
|
+
// <option value="1" selected>1.0</option>
|
|
203
|
+
// <option value="2">2.0</option>
|
|
204
|
+
// <option value="3">3.0</option>
|
|
205
|
+
// <option value="5">5.0</option>
|
|
206
|
+
// </select>
|
|
207
|
+
// </div>`
|
|
208
|
+
// });
|
|
209
|
+
|
|
210
|
+
//mltView.appendTo($ctl)
|
|
211
|
+
|
|
212
|
+
// let multiplierEl = this.select(".og-timeline-multiplier select");
|
|
213
|
+
//
|
|
214
|
+
// multiplierEl.value = this.model.multiplier.toString();
|
|
215
|
+
// multiplierEl.addEventListener("change", (e) => {
|
|
216
|
+
// this.model.multiplier = Math.sign(this.model.multiplier) * Number(e.target.value);
|
|
217
|
+
// });
|
|
218
|
+
|
|
219
|
+
this.setVisibility(true);
|
|
220
|
+
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
setVisibility(visibility) {
|
|
225
|
+
if (visibility !== this._visibility) {
|
|
226
|
+
this._visibility = visibility;
|
|
227
|
+
if (visibility) {
|
|
228
|
+
this.el.style.display = "block";
|
|
229
|
+
} else {
|
|
230
|
+
this.el.style.display = "none";
|
|
231
|
+
}
|
|
232
|
+
this._events.dispatch(this._events.visibility, visibility);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
reset() {
|
|
237
|
+
this.model.stop();
|
|
238
|
+
this._events.dispatch(this._events.reset, this.model);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
play() {
|
|
242
|
+
this.model.multiplier = Math.abs(this.model.multiplier);
|
|
243
|
+
this.model.play();
|
|
244
|
+
this._events.dispatch(this._events.play, this.model);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
pause() {
|
|
248
|
+
this.model.stop();
|
|
249
|
+
this._events.dispatch(this._events.pause, this.model);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
playBack() {
|
|
253
|
+
this.model.multiplier = -1 * Math.abs(this.model.multiplier);
|
|
254
|
+
this.model.play();
|
|
255
|
+
this._events.dispatch(this._events.playback, this.model);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
_onMouseWheel(e) {
|
|
259
|
+
if (this._isMouseOver) {
|
|
260
|
+
let rect = this._canvasEl.getBoundingClientRect();
|
|
261
|
+
let pointerPosX = e.clientX - rect.left,
|
|
262
|
+
pointerCenterOffsetX = -(pointerPosX - this.clientWidth * 0.5);
|
|
263
|
+
let pointerTime = this.model.rangeStartTime + this._millisecondsInPixel * pointerPosX;
|
|
264
|
+
this._zoom(pointerTime, pointerCenterOffsetX, Math.sign(e.wheelDelta));
|
|
265
|
+
} else if (this._isCurrentMouseOver) {
|
|
266
|
+
let pointerCenterOffsetX = -((this.model.currentTime - this.model.rangeStartTime) / this._millisecondsInPixel - this.clientWidth * 0.5);
|
|
267
|
+
this._zoom(this.model.currentTime, pointerCenterOffsetX, Math.sign(e.wheelDelta));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
_zoom(pointerTime, pointerCenterOffsetX, dir) {
|
|
272
|
+
let centerTime = this.model.rangeStartTime + 0.5 * this.model.range;
|
|
273
|
+
|
|
274
|
+
let centerTimeOffset = (pointerTime - centerTime) * MILLISECONDS_TO_SECONDS;
|
|
275
|
+
|
|
276
|
+
let rangeStart = addSeconds(this.model.rangeStart, centerTimeOffset),
|
|
277
|
+
rangeEnd = addSeconds(this.model.rangeEnd, centerTimeOffset);
|
|
278
|
+
|
|
279
|
+
let delta = ((rangeEnd.getTime() - rangeStart.getTime()) / 20) * MILLISECONDS_TO_SECONDS;
|
|
280
|
+
|
|
281
|
+
let newRangeStart = addSeconds(rangeStart, delta * dir);
|
|
282
|
+
let newRangeEnd = addSeconds(rangeEnd, -delta * dir);
|
|
283
|
+
let msPx = (newRangeEnd.getTime() - newRangeStart.getTime()) / this.clientWidth;
|
|
284
|
+
|
|
285
|
+
if (msPx < 31536000000 && msPx > 0.1) {
|
|
286
|
+
let timeOffset = msPx * pointerCenterOffsetX * MILLISECONDS_TO_SECONDS;
|
|
287
|
+
|
|
288
|
+
this.model.set(
|
|
289
|
+
addSeconds(newRangeStart, timeOffset),
|
|
290
|
+
addSeconds(newRangeEnd, timeOffset)
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
_onMouseDown(e) {
|
|
296
|
+
if (this._isMouseOver) {
|
|
297
|
+
this._isDragging = true;
|
|
298
|
+
document.body.classList.add("og-timeline-unselectable");
|
|
299
|
+
|
|
300
|
+
this._clickPosX = e.clientX;
|
|
301
|
+
this._clickTime = Date.now();
|
|
302
|
+
|
|
303
|
+
this._clickRangeStart = this.model.rangeStart;
|
|
304
|
+
this._clickRangeEnd = this.model.rangeEnd;
|
|
305
|
+
|
|
306
|
+
this._events.dispatch(this._events.startdrag, e);
|
|
307
|
+
} else if (this._isCurrentMouseOver) {
|
|
308
|
+
this._isCurrentDragging = true;
|
|
309
|
+
document.body.classList.add("og-timeline-unselectable");
|
|
310
|
+
|
|
311
|
+
this._clickPosX = e.clientX;
|
|
312
|
+
|
|
313
|
+
this._clickCurrentDate = this.model.current;
|
|
314
|
+
|
|
315
|
+
this._events.dispatch(this._events.startdragcurrent, e);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
_onMouseUp(e) {
|
|
320
|
+
if (this._isDragging) {
|
|
321
|
+
this._isDragging = false;
|
|
322
|
+
document.body.classList.remove("og-timeline-unselectable");
|
|
323
|
+
if (this._clickPosX === e.clientX && (Date.now() - this._clickTime) < this._clickDelay) {
|
|
324
|
+
let rect = this._canvasEl.getBoundingClientRect();
|
|
325
|
+
let current = new Date(this.model.rangeStartTime + (e.clientX - rect.left) * this._millisecondsInPixel);
|
|
326
|
+
this.model.current = current;
|
|
327
|
+
this._events.dispatch(this._events.stopdrag, current);
|
|
328
|
+
this._events.dispatch(this._events.setcurrent, current);
|
|
329
|
+
} else {
|
|
330
|
+
this._events.dispatch(this._events.stopdrag, this.model.current);
|
|
331
|
+
}
|
|
332
|
+
} else if (this._isCurrentDragging) {
|
|
333
|
+
this._isCurrentDragging = false;
|
|
334
|
+
document.body.classList.remove("og-timeline-unselectable");
|
|
335
|
+
this._events.dispatch(this._events.stopdragcurrent, this.model.current);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
_onMouseEnter() {
|
|
340
|
+
this._isMouseOver = true;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
_onMouseOut() {
|
|
344
|
+
this._isMouseOver = false;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
_onCurrentMouseEnter() {
|
|
348
|
+
this._isCurrentMouseOver = true;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
_onCurrentMouseOut() {
|
|
352
|
+
this._isCurrentMouseOver = false;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
_onMouseMove(e) {
|
|
356
|
+
if (this._isDragging) {
|
|
357
|
+
let offsetSec = (this._clickPosX - e.clientX) * this._millisecondsInPixel * MILLISECONDS_TO_SECONDS;
|
|
358
|
+
this.model.set(addSeconds(this._clickRangeStart, offsetSec), addSeconds(this._clickRangeEnd, offsetSec))
|
|
359
|
+
} else if (this._isCurrentDragging) {
|
|
360
|
+
let offsetSec = (this._clickPosX - e.clientX) * this._millisecondsInPixel * MILLISECONDS_TO_SECONDS;
|
|
361
|
+
let newCurrent = addSeconds(this._clickCurrentDate, -offsetSec);
|
|
362
|
+
if (newCurrent >= this.model.rangeStart && newCurrent <= this.model.rangeEnd) {
|
|
363
|
+
this.model.current = addSeconds(this._clickCurrentDate, -offsetSec);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
get clientWidth() {
|
|
369
|
+
return this._canvasEl ? this._canvasEl.width / this._canvasScale : 0;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
get clientHeight() {
|
|
373
|
+
return this._canvasEl ? this._canvasEl.height / this._canvasScale : 0;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
_resize() {
|
|
377
|
+
if (this._canvasEl && this._frameEl) {
|
|
378
|
+
this._canvasEl.width = this._frameEl.clientWidth * this._canvasScale;
|
|
379
|
+
this._canvasEl.height = this._frameEl.clientHeight * this._canvasScale;
|
|
380
|
+
this._canvasEl.style.width = `${this._frameEl.clientWidth}px`;
|
|
381
|
+
this._canvasEl.style.height = `${this._frameEl.clientHeight}px`;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
getOffsetbyTime(milliseconds) {
|
|
386
|
+
return (milliseconds - this.model.rangeStartTime) / this._millisecondsInPixel;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
remove() {
|
|
390
|
+
super.remove();
|
|
391
|
+
this.model.stop();
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
_clearCanvas() {
|
|
395
|
+
if (this._ctx) {
|
|
396
|
+
this._ctx.fillStyle = this.fillStyle;
|
|
397
|
+
this._ctx.fillRect(0, 0, this.clientWidth * this._canvasScale, this.clientHeight * this._canvasScale);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
_drawCurrent() {
|
|
402
|
+
let curPosX = (this.model.currentTime - this.model.rangeStartTime) / this._millisecondsInPixel;
|
|
403
|
+
if (this.model.current < this.model.rangeStart || this.model.current > this.model.rangeEnd) {
|
|
404
|
+
this._currentEl.style.display = "none";
|
|
405
|
+
} else {
|
|
406
|
+
this._currentEl.style.display = "block";
|
|
407
|
+
this._currentEl.style.transform = `translateX(${curPosX}px)`;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
draw() {
|
|
412
|
+
if (this._ctx) {
|
|
413
|
+
this._millisecondsInPixel = (this.model.range / this.clientWidth);
|
|
414
|
+
let minWidthMs = this._minWidth * this._millisecondsInPixel;
|
|
415
|
+
let scaleData = getScale(minWidthMs * MILLISECONDS_TO_SECONDS);
|
|
416
|
+
if (scaleData) {
|
|
417
|
+
|
|
418
|
+
this._clearCanvas();
|
|
419
|
+
|
|
420
|
+
let scaleMs = scaleData[0] * SECONDS_TO_MILLISECONDS,
|
|
421
|
+
scalePx = scaleMs / this._millisecondsInPixel,
|
|
422
|
+
segCount = scaleData[1];
|
|
423
|
+
|
|
424
|
+
let originTime = getNearestTimeLeft(this.model.rangeStartTime, scaleMs);
|
|
425
|
+
|
|
426
|
+
let showMillisconds = scaleData[0] < 1.0,
|
|
427
|
+
showTime = scaleData[0] < 86400.0;
|
|
428
|
+
|
|
429
|
+
for (let i = originTime, rangeEnd = this.model.rangeEndTime + scaleMs; i < rangeEnd; i += scaleMs) {
|
|
430
|
+
let x = this.getOffsetbyTime(i);
|
|
431
|
+
if (x >= 0 && x <= this.clientWidth * this._canvasScale) {
|
|
432
|
+
drawNotch(this._ctx, x * this._canvasScale, 10 * this._canvasScale, 2 * this._canvasScale, SCALE_NOTCH_COLOR);
|
|
433
|
+
}
|
|
434
|
+
for (let j = 1; j < segCount; j++) {
|
|
435
|
+
let xx = x + j * (scalePx / segCount);
|
|
436
|
+
if (xx >= 0 && xx <= this.clientWidth * this._canvasScale) {
|
|
437
|
+
drawNotch(this._ctx, xx * this._canvasScale, 5 * this._canvasScale, 1 * this._canvasScale, SCALE_NOTCH_COLOR);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
drawText(this._ctx, dateToStr(new Date(i), showTime, showMillisconds), x * this._canvasScale, 26 * this._canvasScale, "24px monospace", SCALE_TIME_COLOR, "center");
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
this._drawCurrent();
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
export { TimelineView }
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import * as math from '../../math.js';
|
|
4
|
+
|
|
5
|
+
export function addSeconds(date, seconds) {
|
|
6
|
+
return new Date(+date + seconds * 1000);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function dateToStr(date, showTime = true, showMilliseconds = false) {
|
|
10
|
+
|
|
11
|
+
let month = MONTHS[date.getMonth()],
|
|
12
|
+
day = date.getUTCDate(),
|
|
13
|
+
year = date.getUTCFullYear();
|
|
14
|
+
|
|
15
|
+
if (showTime) {
|
|
16
|
+
let h = date.getUTCHours().toString().padStart(2, '0'),
|
|
17
|
+
m = date.getUTCMinutes().toString().padStart(2, '0'),
|
|
18
|
+
s = date.getUTCSeconds().toString().padStart(2, '0');
|
|
19
|
+
|
|
20
|
+
if (showMilliseconds) {
|
|
21
|
+
let ms = date.getUTCMilliseconds().toString().padStart(3, '0');
|
|
22
|
+
return `${month} ${day} ${year} ${h}:${m}:${s}.${ms}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return `${month} ${day} ${year} ${h}:${m}:${s}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return `${month} ${day} ${year}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function createCanvasHTML() {
|
|
32
|
+
return document.createElement("canvas");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getNearestTimeLeft(t, div) {
|
|
36
|
+
return t - (t % div);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function drawNotch(ctx, xOffset = 0, size = 10, thickness = 2, color = "white") {
|
|
40
|
+
ctx.lineWidth = thickness;
|
|
41
|
+
ctx.strokeStyle = color;
|
|
42
|
+
ctx.beginPath();
|
|
43
|
+
ctx.moveTo(xOffset, 0);
|
|
44
|
+
ctx.lineTo(xOffset, size);
|
|
45
|
+
ctx.stroke();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function drawText(ctx, text, x, y, font = "12px Arial", fillStyle = "black", align = "left", baseLine = "bottom", rotDeg) {
|
|
49
|
+
ctx.save();
|
|
50
|
+
ctx.translate(x, y);
|
|
51
|
+
ctx.rotate(rotDeg * math.RADIANS);
|
|
52
|
+
ctx.fillStyle = fillStyle;
|
|
53
|
+
ctx.textBaseline = baseLine;
|
|
54
|
+
ctx.font = font;
|
|
55
|
+
ctx.textAlign = align;
|
|
56
|
+
ctx.fillText(text, 0, 0);
|
|
57
|
+
ctx.restore();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const SCALES = [
|
|
61
|
+
[0.001, 10],
|
|
62
|
+
[0.002, 10],
|
|
63
|
+
[0.005, 10],
|
|
64
|
+
[0.01, 10],
|
|
65
|
+
[0.02, 10],
|
|
66
|
+
[0.05, 10],
|
|
67
|
+
[0.1, 10],
|
|
68
|
+
[0.25, 10],
|
|
69
|
+
[0.5, 5],
|
|
70
|
+
[1.0, 10],
|
|
71
|
+
[2.0, 10],
|
|
72
|
+
[5.0, 5],
|
|
73
|
+
[10.0, 10],
|
|
74
|
+
[15.0, 15],
|
|
75
|
+
[30.0, 6],
|
|
76
|
+
[60.0, 12], // 1min
|
|
77
|
+
[120.0, 12], // 2min
|
|
78
|
+
[300.0, 5], // 5min
|
|
79
|
+
[600.0, 10], // 10min
|
|
80
|
+
[900.0, 15], // 15min
|
|
81
|
+
[1800.0, 6], // 30min
|
|
82
|
+
[3600.0, 12], // 1hr
|
|
83
|
+
[7200.0, 10], // 2hr
|
|
84
|
+
[14400.0, 4], // 4hr
|
|
85
|
+
[21600.0, 6], // 6hr
|
|
86
|
+
[43200.0, 12], // 12hr
|
|
87
|
+
[86400.0, 24], // 24hr
|
|
88
|
+
[172800.0, 2], // 2days
|
|
89
|
+
[345600.0, 4], // 4days
|
|
90
|
+
[604800.0, 7], // 7days
|
|
91
|
+
[1296000.0, 15], // 15days
|
|
92
|
+
[2592000.0, 5], // 30days
|
|
93
|
+
[5184000.0, 6], // 60days
|
|
94
|
+
[7776000.0, 9], // 90days
|
|
95
|
+
[15552000.0, 18], // 180days
|
|
96
|
+
[31536000.0, 12], // 365days
|
|
97
|
+
[63072000.0, 2], // 2years
|
|
98
|
+
[126144000.0, 4], // 4years
|
|
99
|
+
[157680000.0, 5], // 5years
|
|
100
|
+
[315360000.0, 10], // 10years
|
|
101
|
+
[630720000.0, 2], // 20years
|
|
102
|
+
[1261440000.0, 4], // 40years
|
|
103
|
+
[1576800000.0, 5], // 50years
|
|
104
|
+
[3153600000.0, 10], // 100years
|
|
105
|
+
[6307200000.0, 2], // 200years
|
|
106
|
+
[12614400000.0, 4], // 400years
|
|
107
|
+
[15768000000.0, 5], // 500years
|
|
108
|
+
[31536000000.0, 10], // 1000years
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
export function getScale(seconds) {
|
|
112
|
+
for (let i = 0, len = SCALES.length; i < len; i++) {
|
|
113
|
+
if (SCALES[i][0] > seconds) {
|
|
114
|
+
return SCALES[i - 1];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export const MONTHS = [
|
|
120
|
+
"Jan",
|
|
121
|
+
"Feb",
|
|
122
|
+
"Mar",
|
|
123
|
+
"Apr",
|
|
124
|
+
"May",
|
|
125
|
+
"Jun",
|
|
126
|
+
"Jul",
|
|
127
|
+
"Aug",
|
|
128
|
+
"Sep",
|
|
129
|
+
"Oct",
|
|
130
|
+
"Nov",
|
|
131
|
+
"Dec",
|
|
132
|
+
];
|