Search code examples
javascriptopenlayerstraccar

How to Insert Bing maps into the traccar Embed html page?


There are two files that are used so that traccar gps devices can be tracked publicly on an embed html page with an Open Layers map with traccar user token generated from the traccar server.

Now I see that Open Layers is using also Bing maps, so can I use Bing Maps as a default embedded map for the traccar instead of this default open layers map ?

Here is the original two files (one is the js file the second one is html file) for the traccar which is used to get embedded map on the html page:

app.js first file

 * Copyright 2016 - 2017 Anton Tananaev ([email protected])
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, "find", {
    value: function(predicate) {
      var value;
      for (var i = 0; i < this.length; i++) {
        value = this[i];
        if (predicate.call(arguments[1], value, i, this)) {
          return value;
        }
      }
      return undefined;
    }
  });
}

var getQueryParameter = function(name) {
    return (window.location.search.match('[?&]' + name + '=([^&]*)') || [])[1];
};

var url = window.location.protocol + '//' + window.location.host;
var token = getQueryParameter('token');

var style = function (label) {
    return new ol.style.Style({
        image: new ol.style.Circle({
            fill: new ol.style.Fill({
                color: 'teal'
            }),
            stroke: new ol.style.Stroke({
                color: 'black',
                width: 2
            }),
            radius: 7
        }),
        text: new ol.style.Text({
            text: label,
            fill: new ol.style.Fill({
                color: 'black'
            }),
            stroke: new ol.style.Stroke({
                color: 'white',
                width: 2
            }),
            font: 'bold 12px sans-serif',
            offsetY: -16
        })
    });
};

var source = new ol.source.Vector();

var markers = {};

var map = new ol.Map({
    layers: [
        new ol.layer.Tile({
            source: new ol.source.OSM()
        }),
        new ol.layer.Vector({
            source: source
        })
    ],
    target: 'map',
    view: new ol.View({
        center: ol.proj.fromLonLat([0, 0]),
        zoom: 2
    })
});

var ajax = function (method, url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.withCredentials = true;
    xhr.open(method, url, true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            callback(JSON.parse(xhr.responseText));
        }
    };
    if (method == 'POST') {
        xhr.setRequestHeader('Content-type', 'application/json');
    }
    xhr.send()
};

ajax('GET', url + '/api/server', function(server) {
    ajax('GET', url + '/api/session?token=' + token, function(user) {

        map.getView().setCenter(ol.proj.fromLonLat([
            parseFloat(getQueryParameter('longitude')) || user.longitude || server.longitude || 0.0,
            parseFloat(getQueryParameter('latitude')) || user.latitude || server.latitude || 0.0
        ]));
        map.getView().setZoom(parseFloat(getQueryParameter('zoom')) || user.zoom || server.zoom || 2);

        ajax('GET', url + '/api/devices', function(devices) {

            var socket = new WebSocket('ws' + url.substring(4) + '/api/socket');

            socket.onclose = function (event) {
                console.log('socket closed');
            };

            socket.onmessage = function (event) {
                var data = JSON.parse(event.data);
                if (data.positions) {
                    for (i = 0; i < data.positions.length; i++) {
                        var position = data.positions[i];
                        var marker = markers[position.deviceId];
                        var point = new ol.geom.Point(ol.proj.fromLonLat([position.longitude, position.latitude]));
                        if (!marker) {
                            var device = devices.find(function (device) { return device.id === position.deviceId });
                            marker = new ol.Feature(point);
                            marker.setStyle(style(device.name));
                            markers[position.deviceId] = marker;
                            source.addFeature(marker);
                        } else {
                            marker.setGeometry(point);
                        }
                    }
                }
            };

        });
    });
});

second file is index.html

<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Traccar</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.20.1/ol.css" type="text/css">
</head>
<body style="margin: 0; padding: 0;">
<div id="map" style="width: 100%; height: 100%; position:fixed;"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.20.1/ol.js" type="text/javascript"></script>
<script id="loadScript" src="app.js"></script>
</body>
</html>

and this is the Open Layers Bing Map that I want to use it as a default Map on embedded html page, there is three files (source: Open Layers Bing Map)

First file is main.js file

import BingMaps from 'ol/source/BingMaps';
import Map from 'ol/Map';
import TileLayer from 'ol/layer/Tile';
import View from 'ol/View';

var styles = [
  'RoadOnDemand',
  'Aerial',
  'AerialWithLabelsOnDemand',
  'CanvasDark',
  'OrdnanceSurvey' ];
var layers = [];
var i, ii;
for (i = 0, ii = styles.length; i < ii; ++i) {
  layers.push(
    new TileLayer({
      visible: false,
      preload: Infinity,
      source: new BingMaps({
        key: 'Your Bing Maps Key from http://www.bingmapsportal.com/ here',
        imagerySet: styles[i],
        // use maxZoom 19 to see stretched tiles instead of the BingMaps
        // "no photos at this zoom level" tiles
        // maxZoom: 19
      }),
    })
  );
}
var map = new Map({
  layers: layers,
  target: 'map',
  view: new View({
    center: [-6655.5402445057125, 6709968.258934638],
    zoom: 13,
  }),
});

var select = document.getElementById('layer-select');
function onChange() {
  var style = select.value;
  for (var i = 0, ii = layers.length; i < ii; ++i) {
    layers[i].setVisible(styles[i] === style);
  }
}
select.addEventListener('change', onChange);
onChange();

Second file is index.html

<html lang="en">
  <head>
    <title>Bing Maps</title>
    <!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
    <script src="https://unpkg.com/elm-pep"></script>
    <style>
      .map {
        width: 100%;
        height:400px;
      }
    </style>
  </head>
  <body>
     <div id="map" class="map"></div>
     <select id="layer-select">
       <option value="Aerial">Aerial</option>
       <option value="AerialWithLabelsOnDemand" selected>Aerial with labels</option>
       <option value="RoadOnDemand">Road</option>
       <option value="CanvasDark">Road dark</option>
       <option value="OrdnanceSurvey">Ordnance Survey</option>
     </select>
    <script src="main.js"></script>
  </body>
</html>

third file is .json file

  "name": "bing-maps",
  "dependencies": {
    "ol": "6.4.3"
  },
  "devDependencies": {
    "parcel": "1.11.0"
  },
  "scripts": {
    "start": "parcel index.html",
    "build": "parcel build --experimental-scope-hoisting --public-url . index.html"
  }
}

My question is how to use the Open Layers Bing Map for the traccar embadded html page?


Solution

  • To replace OpenStreetMap with a Bing road map

    change

          source: new ol.source.OSM()
    

    to

          source: new ol.source.BingMaps({
            key: 'xxxxxx',
            imagerySet: 'RoadOnDemand'
          })
    

    (replace xxxxxx with an API key from https://www.microsoft.com/en-us/maps/create-a-bing-maps-key )