UNPKG

7.2 kBJavaScriptView Raw
1goog.require('ol.Feature');
2goog.require('ol.Map');
3goog.require('ol.View');
4goog.require('ol.format.Polyline');
5goog.require('ol.geom.Point');
6goog.require('ol.layer.Tile');
7goog.require('ol.layer.Vector');
8goog.require('ol.source.BingMaps');
9goog.require('ol.source.Vector');
10goog.require('ol.style.Circle');
11goog.require('ol.style.Fill');
12goog.require('ol.style.Icon');
13goog.require('ol.style.Stroke');
14goog.require('ol.style.Style');
15
16// This long string is placed here due to jsFiddle limitations.
17// It is usually loaded with AJAX.
18var polyline = [
19 'hldhx@lnau`BCG_EaC??cFjAwDjF??uBlKMd@}@z@??aC^yk@z_@se@b[wFdE??wFfE}N',
20 'fIoGxB_I\\gG}@eHoCyTmPqGaBaHOoD\\??yVrGotA|N??o[N_STiwAtEmHGeHcAkiA}^',
21 'aMyBiHOkFNoI`CcVvM??gG^gF_@iJwC??eCcA]OoL}DwFyCaCgCcCwDcGwHsSoX??wI_E',
22 'kUFmq@hBiOqBgTwS??iYse@gYq\\cp@ce@{vA}s@csJqaE}{@iRaqE{lBeRoIwd@_T{]_',
23 'Ngn@{PmhEwaA{SeF_u@kQuyAw]wQeEgtAsZ}LiCarAkVwI}D??_}RcjEinPspDwSqCgs@',
24 'sPua@_OkXaMeT_Nwk@ob@gV}TiYs[uTwXoNmT{Uyb@wNg]{Nqa@oDgNeJu_@_G}YsFw]k',
25 'DuZyDmm@i_@uyIJe~@jCg|@nGiv@zUi_BfNqaAvIow@dEed@dCcf@r@qz@Egs@{Acu@mC',
26 'um@yIey@gGig@cK_m@aSku@qRil@we@{mAeTej@}Tkz@cLgr@aHko@qOmcEaJw~C{w@ka',
27 'i@qBchBq@kmBS{kDnBscBnFu_Dbc@_~QHeU`IuyDrC_}@bByp@fCyoA?qMbD}{AIkeAgB',
28 'k_A_A{UsDke@gFej@qH{o@qGgb@qH{`@mMgm@uQus@kL{_@yOmd@ymBgwE}x@ouBwtA__',
29 'DuhEgaKuWct@gp@cnBii@mlBa_@}|Asj@qrCg^eaC}L{dAaJ_aAiOyjByH{nAuYu`GsAw',
30 'Xyn@ywMyOyqD{_@cfIcDe}@y@aeBJmwA`CkiAbFkhBlTgdDdPyiB`W}xDnSa}DbJyhCrX',
31 'itAhT}x@bE}Z_@qW_Kwv@qKaaAiBgXvIm}A~JovAxCqW~WanB`XewBbK{_A`K}fBvAmi@',
32 'xBycBeCauBoF}}@qJioAww@gjHaPopA_NurAyJku@uGmi@cDs[eRaiBkQstAsQkcByNma',
33 'CsK_uBcJgbEw@gkB_@ypEqDoqSm@eZcDwjBoGw`BoMegBaU_`Ce_@_uBqb@ytBwkFqiT_',
34 'fAqfEwe@mfCka@_eC_UmlB}MmaBeWkkDeHwqAoX}~DcBsZmLcxBqOwqE_DkyAuJmrJ\\o',
35 '~CfIewG|YibQxBssB?es@qGciA}RorAoVajA_nAodD{[y`AgPqp@mKwr@ms@umEaW{dAm',
36 'b@umAw|@ojBwzDaaJsmBwbEgdCsrFqhAihDquAi`Fux@}_Dui@_eB_u@guCuyAuiHukA_',
37 'lKszAu|OmaA{wKm}@clHs_A_rEahCssKo\\sgBsSglAqk@yvDcS_wAyTwpBmPc|BwZknF',
38 'oFscB_GsaDiZmyMyLgtHgQonHqT{hKaPg}Dqq@m~Hym@c`EuiBudIabB{hF{pWifx@snA',
39 'w`GkFyVqf@y~BkoAi}Lel@wtc@}`@oaXi_C}pZsi@eqGsSuqJ|Lqeb@e]kgPcaAu}SkDw',
40 'zGhn@gjYh\\qlNZovJieBqja@ed@siO{[ol\\kCmjMe\\isHorCmec@uLebB}EqiBaCg}',
41 '@m@qwHrT_vFps@kkI`uAszIrpHuzYxx@e{Crw@kpDhN{wBtQarDy@knFgP_yCu\\wyCwy',
42 'A{kHo~@omEoYmoDaEcPiuAosDagD}rO{{AsyEihCayFilLaiUqm@_bAumFo}DgqA_uByi',
43 '@swC~AkzDlhA}xEvcBa}Cxk@ql@`rAo|@~bBq{@``Bye@djDww@z_C_cAtn@ye@nfC_eC',
44 '|gGahH~s@w}@``Fi~FpnAooC|u@wlEaEedRlYkrPvKerBfYs}Arg@m}AtrCkzElw@gjBb',
45 'h@woBhR{gCwGkgCc[wtCuOapAcFoh@uBy[yBgr@c@iq@o@wvEv@sp@`FajBfCaq@fIipA',
46 'dy@ewJlUc`ExGuaBdEmbBpBssArAuqBBg}@s@g{AkB{bBif@_bYmC}r@kDgm@sPq_BuJ_',
47 's@{X_{AsK_d@eM{d@wVgx@oWcu@??aDmOkNia@wFoSmDyMyCkPiBePwAob@XcQ|@oNdCo',
48 'SfFwXhEmOnLi\\lbAulB`X_d@|k@au@bc@oc@bqC}{BhwDgcD`l@ed@??bL{G|a@eTje@',
49 'oS~]cLr~Bgh@|b@}Jv}EieAlv@sPluD{z@nzA_]`|KchCtd@sPvb@wSb{@ko@f`RooQ~e',
50 '[upZbuIolI|gFafFzu@iq@nMmJ|OeJn^{Qjh@yQhc@uJ~j@iGdd@kAp~BkBxO{@|QsAfY',
51 'gEtYiGd]}Jpd@wRhVoNzNeK`j@ce@vgK}cJnSoSzQkVvUm^rSgc@`Uql@xIq\\vIgg@~k',
52 'Dyq[nIir@jNoq@xNwc@fYik@tk@su@neB}uBhqEesFjoGeyHtCoD|D}Ed|@ctAbIuOzqB',
53 '_}D~NgY`\\um@v[gm@v{Cw`G`w@o{AdjAwzBh{C}`Gpp@ypAxn@}mAfz@{bBbNia@??jI',
54 'ab@`CuOlC}YnAcV`@_^m@aeB}@yk@YuTuBg^uCkZiGk\\yGeY}Lu_@oOsZiTe[uWi[sl@',
55 'mo@soAauAsrBgzBqgAglAyd@ig@asAcyAklA}qAwHkGi{@s~@goAmsAyDeEirB_{B}IsJ',
56 'uEeFymAssAkdAmhAyTcVkFeEoKiH}l@kp@wg@sj@ku@ey@uh@kj@}EsFmG}Jk^_r@_f@m',
57 '~@ym@yjA??a@cFd@kBrCgDbAUnAcBhAyAdk@et@??kF}D??OL'
58].join('');
59
60var route = /** @type {ol.geom.LineString} */ (new ol.format.Polyline({
61 factor: 1e6
62}).readGeometry(polyline, {
63 dataProjection: 'EPSG:4326',
64 featureProjection: 'EPSG:3857'
65}));
66
67var routeCoords = route.getCoordinates();
68var routeLength = routeCoords.length;
69
70var routeFeature = new ol.Feature({
71 type: 'route',
72 geometry: route
73});
74var geoMarker = new ol.Feature({
75 type: 'geoMarker',
76 geometry: new ol.geom.Point(routeCoords[0])
77});
78var startMarker = new ol.Feature({
79 type: 'icon',
80 geometry: new ol.geom.Point(routeCoords[0])
81});
82var endMarker = new ol.Feature({
83 type: 'icon',
84 geometry: new ol.geom.Point(routeCoords[routeLength - 1])
85});
86
87var styles = {
88 'route': new ol.style.Style({
89 stroke: new ol.style.Stroke({
90 width: 6, color: [237, 212, 0, 0.8]
91 })
92 }),
93 'icon': new ol.style.Style({
94 image: new ol.style.Icon({
95 anchor: [0.5, 1],
96 src: 'data/icon.png'
97 })
98 }),
99 'geoMarker': new ol.style.Style({
100 image: new ol.style.Circle({
101 radius: 7,
102 snapToPixel: false,
103 fill: new ol.style.Fill({color: 'black'}),
104 stroke: new ol.style.Stroke({
105 color: 'white', width: 2
106 })
107 })
108 })
109};
110
111var animating = false;
112var speed, now;
113var speedInput = document.getElementById('speed');
114var startButton = document.getElementById('start-animation');
115
116var vectorLayer = new ol.layer.Vector({
117 source: new ol.source.Vector({
118 features: [routeFeature, geoMarker, startMarker, endMarker]
119 }),
120 style: function(feature) {
121 // hide geoMarker if animation is active
122 if (animating && feature.get('type') === 'geoMarker') {
123 return null;
124 }
125 return styles[feature.get('type')];
126 }
127});
128
129var center = [-5639523.95, -3501274.52];
130var map = new ol.Map({
131 target: document.getElementById('map'),
132 loadTilesWhileAnimating: true,
133 view: new ol.View({
134 center: center,
135 zoom: 10,
136 minZoom: 2,
137 maxZoom: 19
138 }),
139 layers: [
140 new ol.layer.Tile({
141 source: new ol.source.BingMaps({
142 imagerySet: 'AerialWithLabels',
143 key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5'
144 })
145 }),
146 vectorLayer
147 ]
148});
149
150var moveFeature = function(event) {
151 var vectorContext = event.vectorContext;
152 var frameState = event.frameState;
153
154 if (animating) {
155 var elapsedTime = frameState.time - now;
156 // here the trick to increase speed is to jump some indexes
157 // on lineString coordinates
158 var index = Math.round(speed * elapsedTime / 1000);
159
160 if (index >= routeLength) {
161 stopAnimation(true);
162 return;
163 }
164
165 var currentPoint = new ol.geom.Point(routeCoords[index]);
166 var feature = new ol.Feature(currentPoint);
167 vectorContext.drawFeature(feature, styles.geoMarker);
168 }
169 // tell OpenLayers to continue the postcompose animation
170 map.render();
171};
172
173function startAnimation() {
174 if (animating) {
175 stopAnimation(false);
176 } else {
177 animating = true;
178 now = new Date().getTime();
179 speed = speedInput.value;
180 startButton.textContent = 'Cancel Animation';
181 // hide geoMarker
182 geoMarker.setStyle(null);
183 // just in case you pan somewhere else
184 map.getView().setCenter(center);
185 map.on('postcompose', moveFeature);
186 map.render();
187 }
188}
189
190
191/**
192 * @param {boolean} ended end of animation.
193 */
194function stopAnimation(ended) {
195 animating = false;
196 startButton.textContent = 'Start Animation';
197
198 // if animation cancelled set the marker at the beginning
199 var coord = ended ? routeCoords[routeLength - 1] : routeCoords[0];
200 /** @type {ol.geom.Point} */ (geoMarker.getGeometry())
201 .setCoordinates(coord);
202 //remove listener
203 map.un('postcompose', moveFeature);
204}
205
206startButton.addEventListener('click', startAnimation, false);