openstmap
Added ability to upload multiple sets of map tiles
Support for zooming in on map
Satellite count moved to widget bar to leave more room for the map
master
parent
f4a48e62e6
commit
459a643c87
|
|
@ -12,3 +12,5 @@
|
|||
Fix alignment of satellite info text
|
||||
0.12: switch to using normal OpenStreetMap tiles (opentopomap was too slow)
|
||||
0.13: Use a single image file with 'frames' of data (drastically reduces file count, possibility of >1 map on device)
|
||||
0.14: Added ability to upload multiple sets of map tiles
|
||||
Support for zooming in on map
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
# OpenStreetMap
|
||||
|
||||
This app allows you to upload and use OpenSteetMap map tiles onto your
|
||||
Bangle. There's an uploader, the app, and also a library that
|
||||
allows you to use the maps in your Bangle.js applications.
|
||||
|
||||
## Uploader
|
||||
|
||||
Once you've installed OpenStreepMap on your Bangle, find it
|
||||
in the App Loader and click the Disk icon next to it.
|
||||
|
||||
A window will pop up showing what maps you have loaded.
|
||||
|
||||
To add a map:
|
||||
|
||||
* Click `Add Map`
|
||||
* Scroll and zoom to the area of interest or use the Search button in the top left
|
||||
* Now choose the size you want to upload (Small/Medium/etc)
|
||||
* On Bangle.js 1 you can choose if you want a 3 bits per pixel map (this is lower
|
||||
quality but uploads faster and takes less space). On Bangle.js 2 you only have a 3bpp
|
||||
display so can only use 3bpp.
|
||||
* Click `Get Map`, and a preview will be displayed. If you need to adjust the area you
|
||||
can change settings, move the map around, and click `Get Map` again.
|
||||
* When you're ready, click `Upload`
|
||||
|
||||
## Bangle.js App
|
||||
|
||||
The Bangle.js app allows you to view a map - it also turns the GPS on and marks
|
||||
the path that you've been travelling.
|
||||
|
||||
* Drag on the screen to move the map
|
||||
* Press the button to bring up a menu, where you can zoom, go to GPS location
|
||||
or put the map back in its default location
|
||||
|
||||
## Library
|
||||
|
||||
See the documentation in the library itself for full usage info:
|
||||
https://github.com/espruino/BangleApps/blob/master/apps/openstmap/openstmap.js
|
||||
|
||||
Or check the app itself: https://github.com/espruino/BangleApps/blob/master/apps/openstmap/app.js
|
||||
|
||||
But in the most simple form:
|
||||
|
||||
```
|
||||
var m = require("openstmap");
|
||||
// m.lat/lon are now the center of the loaded map
|
||||
m.draw(); // draw centered on the middle of the loaded map
|
||||
```
|
||||
|
|
@ -1,20 +1,27 @@
|
|||
var m = require("openstmap");
|
||||
var HASWIDGETS = true;
|
||||
var y1,y2;
|
||||
var R;
|
||||
var fix = {};
|
||||
var mapVisible = false;
|
||||
var hasScrolled = false;
|
||||
|
||||
// Redraw the whole page
|
||||
function redraw() {
|
||||
g.setClipRect(0,y1,g.getWidth()-1,y2);
|
||||
g.setClipRect(R.x,R.y,R.x2,R.y2);
|
||||
m.draw();
|
||||
drawMarker();
|
||||
if (WIDGETS["gpsrec"] && WIDGETS["gpsrec"].plotTrack) {
|
||||
g.flip(); // force immediate draw on double-buffered screens - track will update later
|
||||
g.setColor(0.75,0.2,0);
|
||||
if (HASWIDGETS && WIDGETS["gpsrec"] && WIDGETS["gpsrec"].plotTrack) {
|
||||
g.flip().setColor("#f00"); // force immediate draw on double-buffered screens - track will update later
|
||||
WIDGETS["gpsrec"].plotTrack(m);
|
||||
}
|
||||
if (HASWIDGETS && WIDGETS["recorder"] && WIDGETS["recorder"].plotTrack) {
|
||||
g.flip().setColor("#f00"); // force immediate draw on double-buffered screens - track will update later
|
||||
WIDGETS["recorder"].plotTrack(m);
|
||||
}
|
||||
g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1);
|
||||
}
|
||||
|
||||
// Draw the marker for where we are
|
||||
function drawMarker() {
|
||||
if (!fix.fix) return;
|
||||
var p = m.latLonToXY(fix.lat, fix.lon);
|
||||
|
|
@ -22,50 +29,66 @@ function drawMarker() {
|
|||
g.fillRect(p.x-2, p.y-2, p.x+2, p.y+2);
|
||||
}
|
||||
|
||||
var fix;
|
||||
Bangle.on('GPS',function(f) {
|
||||
fix=f;
|
||||
g.reset().clearRect(0,y1,g.getWidth()-1,y1+8).setFont("6x8").setFontAlign(0,0);
|
||||
var txt = fix.satellites+" satellites";
|
||||
if (!fix.fix)
|
||||
txt += " - NO FIX";
|
||||
g.drawString(txt,g.getWidth()/2,y1 + 4);
|
||||
drawMarker();
|
||||
if (HASWIDGETS) WIDGETS["sats"].draw(WIDGETS["sats"]);
|
||||
if (mapVisible) drawMarker();
|
||||
});
|
||||
Bangle.setGPSPower(1, "app");
|
||||
|
||||
if (HASWIDGETS) {
|
||||
Bangle.loadWidgets();
|
||||
WIDGETS["sats"] = { area:"tl", width:48, draw:w=>{
|
||||
var txt = (0|fix.satellites)+" Sats";
|
||||
if (!fix.fix) txt += "\nNO FIX";
|
||||
g.reset().setFont("6x8").setFontAlign(0,0)
|
||||
.drawString(txt,w.x+24,w.y+12);
|
||||
}
|
||||
};
|
||||
Bangle.drawWidgets();
|
||||
y1 = 24;
|
||||
var hasBottomRow = Object.keys(WIDGETS).some(w=>WIDGETS[w].area[0]=="b");
|
||||
y2 = g.getHeight() - (hasBottomRow ? 24 : 1);
|
||||
} else {
|
||||
y1=0;
|
||||
y2=g.getHeight()-1;
|
||||
}
|
||||
R = Bangle.appRect;
|
||||
|
||||
redraw();
|
||||
|
||||
function recenter() {
|
||||
if (!fix.fix) return;
|
||||
m.lat = fix.lat;
|
||||
m.lon = fix.lon;
|
||||
function showMap() {
|
||||
mapVisible = true;
|
||||
g.reset().clearRect(R);
|
||||
redraw();
|
||||
Bangle.setUI({mode:"custom",drag:e=>{
|
||||
if (e.b) {
|
||||
g.setClipRect(R.x,R.y,R.x2,R.y2);
|
||||
g.scroll(e.dx,e.dy);
|
||||
m.scroll(e.dx,e.dy);
|
||||
g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1);
|
||||
hasScrolled = true;
|
||||
} else if (hasScrolled) {
|
||||
hasScrolled = false;
|
||||
redraw();
|
||||
}
|
||||
}, btn: btn=>{
|
||||
mapVisible = false;
|
||||
var menu = {"":{title:"Map"},
|
||||
"< Back": ()=> showMap(),
|
||||
/*LANG*/"Zoom In": () =>{
|
||||
m.scale /= 2;
|
||||
showMap();
|
||||
},
|
||||
/*LANG*/"Zoom Out": () =>{
|
||||
m.scale *= 2;
|
||||
showMap();
|
||||
},
|
||||
/*LANG*/"Center Map": () =>{
|
||||
m.lat = m.map.lat;
|
||||
m.lon = m.map.lon;
|
||||
m.scale = m.map.scale;
|
||||
showMap();
|
||||
}};
|
||||
if (fix.fix) menu[/*LANG*/"Center GPS"]=() =>{
|
||||
m.lat = fix.lat;
|
||||
m.lon = fix.lon;
|
||||
showMap();
|
||||
};
|
||||
E.showMenu(menu);
|
||||
}});
|
||||
}
|
||||
|
||||
setWatch(recenter, global.BTN2?BTN2:BTN1, {repeat:true});
|
||||
|
||||
var hasScrolled = false;
|
||||
Bangle.on('drag',e=>{
|
||||
if (e.b) {
|
||||
g.setClipRect(0,y1,g.getWidth()-1,y2);
|
||||
g.scroll(e.dx,e.dy);
|
||||
m.scroll(e.dx,e.dy);
|
||||
g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1);
|
||||
hasScrolled = true;
|
||||
} else if (hasScrolled) {
|
||||
hasScrolled = false;
|
||||
redraw();
|
||||
}
|
||||
});
|
||||
showMap();
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
html, body, #map {
|
||||
html, body, #map, #mapsLoaded, #mapContainer {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -27,20 +28,40 @@
|
|||
width: 256px;
|
||||
height: 256px;
|
||||
}
|
||||
.tile-title {
|
||||
font-weight:bold;
|
||||
font-size: 125%;
|
||||
}
|
||||
.tile-map {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map">
|
||||
<div id="mapsLoadedContainer">
|
||||
</div>
|
||||
<div id="controls">
|
||||
<div style="display:inline-block;text-align:center;vertical-align: top;" id="3bitdiv"> <input type="checkbox" id="3bit"></input><br/><span>3 bit</span></div>
|
||||
<button id="getmap" class="btn btn-primary">Get Map</button><br/>
|
||||
<canvas id="maptiles" style="display:none"></canvas>
|
||||
<div id="uploadbuttons" style="display:none"><button id="upload" class="btn btn-primary">Upload</button>
|
||||
<button id="cancel" class="btn">Cancel</button></div>
|
||||
<div id="mapContainer">
|
||||
<div id="map">
|
||||
</div>
|
||||
<div id="controls">
|
||||
<div style="display:inline-block;text-align:center;vertical-align: top;" id="3bitdiv"> <input type="checkbox" id="3bit"></input><br/><span>3 bit</span></div>
|
||||
<div class="form-group" style="display:inline-block;">
|
||||
<select class="form-select" id="mapSize">
|
||||
<option value="4">Small</option>
|
||||
<option value="5" selected>Medium</option>
|
||||
<option value="6">Large</option>
|
||||
<option value="7">XL</option>
|
||||
</select>
|
||||
</div>
|
||||
<button id="getmap" class="btn btn-primary">Get Map</button><button class="btn" onclick="showLoadedMaps()">Map List</button><br/>
|
||||
<canvas id="maptiles" style="display:none"></canvas>
|
||||
<div id="uploadbuttons" style="display:none"><button id="upload" class="btn btn-primary">Upload</button>
|
||||
<button id="cancel" class="btn">Cancel</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../../core/lib/customize.js"></script>
|
||||
<script src="../../core/lib/interface.js"></script>
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
|
||||
<script src="../../webtools/heatshrink.js"></script>
|
||||
|
|
@ -60,8 +81,6 @@ TODO:
|
|||
*/
|
||||
var TILESIZE = 96; // Size of our tiles
|
||||
var OSMTILESIZE = 256; // Size of openstreetmap tiles
|
||||
var MAPSIZE = TILESIZE*5; ///< 480 - Size of map we download
|
||||
var OSMTILECOUNT = 3; // how many tiles do we download in each direction (Math.floor(MAPSIZE / OSMTILESIZE)+1)
|
||||
/* Can see possible tiles on http://leaflet-extras.github.io/leaflet-providers/preview/
|
||||
However some don't allow cross-origin use */
|
||||
//var TILELAYER = 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'; // simple, high contrast, TOO SLOW
|
||||
|
|
@ -69,8 +88,8 @@ TODO:
|
|||
var TILELAYER = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
|
||||
var PREVIEWTILELAYER = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
|
||||
|
||||
// Create map and try and set the location to where the browser thinks we are
|
||||
var map = L.map('map').locate({setView: true, maxZoom: 16, enableHighAccuracy:true});
|
||||
var loadedMaps = [];
|
||||
|
||||
// Tiles used for Bangle.js itself
|
||||
var bangleTileLayer = L.tileLayer(TILELAYER, {
|
||||
maxZoom: 18,
|
||||
|
|
@ -83,6 +102,10 @@ TODO:
|
|||
});
|
||||
// Could optionally overlay trails: https://wiki.openstreetmap.org/wiki/Tiles
|
||||
|
||||
// Create map and try and set the location to where the browser thinks we are
|
||||
var map = L.map('map').locate({setView: true, maxZoom: 16, enableHighAccuracy:true});
|
||||
previewTileLayer.addTo(map);
|
||||
|
||||
// Search box:
|
||||
const searchProvider = new window.GeoSearch.OpenStreetMapProvider();
|
||||
const searchControl = new GeoSearch.GeoSearchControl({
|
||||
|
|
@ -96,6 +119,7 @@ TODO:
|
|||
});
|
||||
map.addControl(searchControl);
|
||||
|
||||
// ---------------------------------------- Run at startup
|
||||
function onInit(device) {
|
||||
if (device && device.info && device.info.g) {
|
||||
// On 3 bit devices, don't even offer the option. 3 bit is the only way
|
||||
|
|
@ -104,12 +128,120 @@ TODO:
|
|||
document.getElementById("3bitdiv").style = "display:none";
|
||||
}
|
||||
}
|
||||
|
||||
showLoadedMaps();
|
||||
}
|
||||
|
||||
var mapFiles = [];
|
||||
previewTileLayer.addTo(map);
|
||||
function showLoadedMaps() {
|
||||
document.getElementById("mapsLoadedContainer").style.display = "";
|
||||
document.getElementById("mapContainer").style.display = "none";
|
||||
|
||||
function tilesLoaded(ctx, width, height) {
|
||||
Util.showModal("Loading maps...");
|
||||
let mapsLoadedContainer = document.getElementById("mapsLoadedContainer");
|
||||
mapsLoadedContainer.innerHTML = "";
|
||||
loadedMaps = [];
|
||||
|
||||
Puck.write(`\x10Bluetooth.println(require("Storage").list(/openstmap\\.\\d+\\.json/))\n`,function(files) {
|
||||
console.log("MAPS:",files);
|
||||
let promise = Promise.resolve();
|
||||
files.trim().split(",").forEach(filename => {
|
||||
if (filename=="") return;
|
||||
promise = promise.then(() => new Promise(resolve => {
|
||||
Util.readStorage(filename, fileContents => {
|
||||
console.log(filename + " => " + fileContents);
|
||||
let mapNumber = filename.match(/\d+/)[0]; // figure out what map number we are
|
||||
let mapInfo;
|
||||
try {
|
||||
mapInfo = JSON.parse(fileContents);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
loadedMaps[mapNumber] = mapInfo;
|
||||
if (mapInfo!==undefined) {
|
||||
let latlon = L.latLng(mapInfo.lat, mapInfo.lon);
|
||||
mapsLoadedContainer.innerHTML += `
|
||||
<div class="tile">
|
||||
<div class="tile-icon">
|
||||
<div class="tile-map" id="tile-map-${mapNumber}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile-content">
|
||||
<p class="tile-title">Map ${mapNumber}</p>
|
||||
<p class="tile-subtitle">${mapInfo.w*mapInfo.h} Tiles (${((mapInfo.imgx*mapInfo.imgy)>>11).toFixed(0)}k)</p>
|
||||
</div>
|
||||
<div class="tile-action">
|
||||
<button class="btn btn-primary" onclick="onMapDelete(${mapNumber})">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
let map = L.map(`tile-map-${mapNumber}`);
|
||||
L.tileLayer(PREVIEWTILELAYER, {
|
||||
maxZoom: 18
|
||||
}).addTo(map);
|
||||
let marker = new L.marker(latlon).addTo(map);
|
||||
map.fitBounds(latlon.toBounds(2000/*meters*/), {animation: false});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
}));
|
||||
});
|
||||
promise = promise.then(() => new Promise(resolve => {
|
||||
if (!loadedMaps.length) {
|
||||
mapsLoadedContainer.innerHTML += `
|
||||
<div class="tile">
|
||||
<div class="tile-icon">
|
||||
<div class="tile-map">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile-content">
|
||||
<p class="tile-title">No Maps Loaded</p>
|
||||
</div>
|
||||
<div class="tile-action">
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
mapsLoadedContainer.innerHTML += `
|
||||
<div class="tile">
|
||||
<div class="tile-icon">
|
||||
<div class="tile-map">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile-content">
|
||||
</div>
|
||||
<div class="tile-action">
|
||||
<button class="btn btn-primary" onclick="showMap()">Add Map</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
Util.hideModal();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
function onMapDelete(mapNumber) {
|
||||
console.log("delete", mapNumber);
|
||||
Util.showModal(`Erasing map ${mapNumber}...`);
|
||||
Util.eraseStorage(`openstmap.${mapNumber}.json`, function() {
|
||||
Util.eraseStorage(`openstmap.${mapNumber}.img`, function() {
|
||||
Util.hideModal();
|
||||
showLoadedMaps();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showMap() {
|
||||
document.getElementById("mapsLoadedContainer").style.display = "none";
|
||||
document.getElementById("mapContainer").style.display = "";
|
||||
document.getElementById("maptiles").style.display="none";
|
||||
document.getElementById("uploadbuttons").style.display="none";
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
var mapFiles = [];
|
||||
|
||||
// convert canvas into an actual tiled image file
|
||||
function tilesLoaded(ctx, width, height, mapImageFile) {
|
||||
var options = {
|
||||
compression:false, output:"raw",
|
||||
mode:"web"
|
||||
|
|
@ -166,12 +298,17 @@ TODO:
|
|||
}
|
||||
}
|
||||
return [{
|
||||
name:"openstmap.0.img",
|
||||
name:mapImageFile,
|
||||
content:tiledImage
|
||||
}];
|
||||
}
|
||||
|
||||
document.getElementById("getmap").addEventListener("click", function() {
|
||||
|
||||
var MAPTILES = parseInt(document.getElementById("mapSize").value);
|
||||
var MAPSIZE = TILESIZE*MAPTILES; /// Size of map we download to Bangle in pixels
|
||||
var OSMTILECOUNT = (Math.ceil((MAPSIZE+TILESIZE) / OSMTILESIZE)+1); // how many tiles do we download from OSM in each direction
|
||||
|
||||
var zoom = map.getZoom();
|
||||
var centerlatlon = map.getBounds().getCenter();
|
||||
var center = map.project(centerlatlon, zoom).divideBy(OSMTILESIZE);
|
||||
|
|
@ -242,8 +379,11 @@ TODO:
|
|||
|
||||
Promise.all(tileGetters).then(() => {
|
||||
document.getElementById("uploadbuttons").style.display="";
|
||||
mapFiles = tilesLoaded(ctx, canvas.width, canvas.height);
|
||||
mapFiles.unshift({name:"openstmap.0.json",content:JSON.stringify({
|
||||
var mapNumber = 0;
|
||||
while (loadedMaps[mapNumber]) mapNumber++;
|
||||
let mapImageFile = `openstmap.${mapNumber}.img`;
|
||||
mapFiles = tilesLoaded(ctx, canvas.width, canvas.height, mapImageFile);
|
||||
mapFiles.unshift({name:`openstmap.${mapNumber}.json`,content:JSON.stringify({
|
||||
imgx : canvas.width,
|
||||
imgy : canvas.height,
|
||||
tilesize : TILESIZE,
|
||||
|
|
@ -252,21 +392,31 @@ TODO:
|
|||
lon : centerlatlon.lng,
|
||||
w : Math.round(canvas.width / TILESIZE), // width in tiles
|
||||
h : Math.round(canvas.height / TILESIZE), // height in tiles
|
||||
fn : "openstmap.0.img"
|
||||
fn : mapImageFile
|
||||
})});
|
||||
console.log(mapFiles);
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById("upload").addEventListener("click", function() {
|
||||
sendCustomizedApp({
|
||||
storage:mapFiles
|
||||
Util.showModal("Uploading...");
|
||||
let promise = Promise.resolve();
|
||||
mapFiles.forEach(file => {
|
||||
promise = promise.then(function() {
|
||||
return new Promise(resolve => {
|
||||
Util.writeStorage(file.name, file.content, resolve);
|
||||
});
|
||||
});
|
||||
});
|
||||
promise.then(function() {
|
||||
Util.hideModal();
|
||||
console.log("Upload Complete");
|
||||
showLoadedMaps();
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById("cancel").addEventListener("click", function() {
|
||||
document.getElementById("maptiles").style.display="none";
|
||||
document.getElementById("uploadbuttons").style.display="none";
|
||||
showMap();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
@ -2,17 +2,20 @@
|
|||
"id": "openstmap",
|
||||
"name": "OpenStreetMap",
|
||||
"shortName": "OpenStMap",
|
||||
"version": "0.13",
|
||||
"version": "0.14",
|
||||
"description": "Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are. Once installed this also adds map functionality to `GPS Recorder` and `Recorder` apps",
|
||||
"readme": "README.md",
|
||||
"icon": "app.png",
|
||||
"tags": "outdoors,gps,osm",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"screenshots": [{"url":"screenshot.png"}],
|
||||
"custom": "custom.html",
|
||||
"customConnect": true,
|
||||
"interface": "interface.html",
|
||||
"storage": [
|
||||
{"name":"openstmap","url":"openstmap.js"},
|
||||
{"name":"openstmap.app.js","url":"app.js"},
|
||||
{"name":"openstmap.img","url":"app-icon.js","evaluate":true}
|
||||
], "data": [
|
||||
{"wildcard":"openstmap.*.json"},
|
||||
{"wildcard":"openstmap.*.img"}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,32 +20,59 @@ function center() {
|
|||
m.draw();
|
||||
}
|
||||
|
||||
// you can even change the scale - eg 'm/scale *= 2'
|
||||
|
||||
*/
|
||||
|
||||
var map = require("Storage").readJSON("openstmap.0.json");
|
||||
map.center = Bangle.project({lat:map.lat,lon:map.lon});
|
||||
exports.map = map;
|
||||
exports.lat = map.lat; // actual position of middle of screen
|
||||
exports.lon = map.lon; // actual position of middle of screen
|
||||
var m = exports;
|
||||
m.maps = require("Storage").list(/openstmap\.\d+\.json/).map(f=>{
|
||||
let map = require("Storage").readJSON(f);
|
||||
map.center = Bangle.project({lat:map.lat,lon:map.lon});
|
||||
return map;
|
||||
});
|
||||
// we base our start position on the middle of the first map
|
||||
m.map = m.maps[0];
|
||||
m.scale = m.map.scale; // current scale (based on first map)
|
||||
m.lat = m.map.lat; // position of middle of screen
|
||||
m.lon = m.map.lon; // position of middle of screen
|
||||
|
||||
exports.draw = function() {
|
||||
var img = require("Storage").read(map.fn);
|
||||
var cx = g.getWidth()/2;
|
||||
var cy = g.getHeight()/2;
|
||||
var p = Bangle.project({lat:m.lat,lon:m.lon});
|
||||
var ix = (p.x-map.center.x)/map.scale + (map.imgx/2) - cx;
|
||||
var iy = (map.center.y-p.y)/map.scale + (map.imgy/2) - cy;
|
||||
//console.log(ix,iy);
|
||||
var tx = 0|(ix/map.tilesize);
|
||||
var ty = 0|(iy/map.tilesize);
|
||||
var ox = (tx*map.tilesize)-ix;
|
||||
var oy = (ty*map.tilesize)-iy;
|
||||
for (var x=ox,ttx=tx;x<g.getWidth();x+=map.tilesize,ttx++)
|
||||
for (var y=oy,tty=ty;y<g.getHeight();y+=map.tilesize,tty++) {
|
||||
if (ttx>=0 && ttx<map.w && tty>=0 && tty<map.h) g.drawImage(img,x,y,{frame:ttx+(tty*map.w)});
|
||||
else g.clearRect(x,y,x+map.tilesize-1,y+map.tilesize-1).drawLine(x,y,x+map.tilesize-1,y+map.tilesize-1).drawLine(x,y+map.tilesize-1,x+map.tilesize-1,y);
|
||||
m.maps.forEach((map,idx) => {
|
||||
var d = map.scale/m.scale;
|
||||
var ix = (p.x-map.center.x)/m.scale + (map.imgx*d/2) - cx;
|
||||
var iy = (map.center.y-p.y)/m.scale + (map.imgy*d/2) - cy;
|
||||
var o = {};
|
||||
var s = map.tilesize;
|
||||
if (d!=1) { // if the two are different, add scaling
|
||||
s *= d;
|
||||
o.scale = d;
|
||||
}
|
||||
//console.log(ix,iy);
|
||||
var tx = 0|(ix/s);
|
||||
var ty = 0|(iy/s);
|
||||
var ox = (tx*s)-ix;
|
||||
var oy = (ty*s)-iy;
|
||||
var img = require("Storage").read(map.fn);
|
||||
// fix out of range so we don't have to iterate over them
|
||||
if (tx<0) {
|
||||
ox+=s*-tx;
|
||||
tx=0;
|
||||
}
|
||||
if (ty<0) {
|
||||
oy+=s*-ty;
|
||||
ty=0;
|
||||
}
|
||||
var mx = g.getWidth();
|
||||
var my = g.getHeight();
|
||||
for (var x=ox,ttx=tx; x<mx && ttx<map.w; x+=s,ttx++)
|
||||
for (var y=oy,tty=ty;y<my && tty<map.h;y+=s,tty++) {
|
||||
o.frame = ttx+(tty*map.w);
|
||||
g.drawImage(img,x,y,o);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/// Convert lat/lon to pixels on the screen
|
||||
|
|
@ -55,15 +82,15 @@ exports.latLonToXY = function(lat, lon) {
|
|||
var cx = g.getWidth()/2;
|
||||
var cy = g.getHeight()/2;
|
||||
return {
|
||||
x : (q.x-p.x)/map.scale + cx,
|
||||
y : cy - (q.y-p.y)/map.scale
|
||||
x : (q.x-p.x)/m.scale + cx,
|
||||
y : cy - (q.y-p.y)/m.scale
|
||||
};
|
||||
};
|
||||
|
||||
/// Given an amount to scroll in pixels on the screen, adjust the lat/lon of the map to match
|
||||
exports.scroll = function(x,y) {
|
||||
var a = Bangle.project({lat:this.lat,lon:this.lon});
|
||||
var b = Bangle.project({lat:this.lat+1,lon:this.lon+1});
|
||||
this.lon += x * this.map.scale / (a.x-b.x);
|
||||
this.lat -= y * this.map.scale / (a.y-b.y);
|
||||
var a = Bangle.project({lat:m.lat,lon:m.lon});
|
||||
var b = Bangle.project({lat:m.lat+1,lon:m.lon+1});
|
||||
this.lon += x * m.scale / (a.x-b.x);
|
||||
this.lat -= y * m.scale / (a.y-b.y);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@
|
|||
WIDGETS["recorder"].reload();
|
||||
return Promise.resolve(settings.recording);
|
||||
}/*,plotTrack:function(m) { // m=instance of openstmap module
|
||||
// FIXME - add track plotting
|
||||
// if we're here, settings was already loaded
|
||||
var f = require("Storage").open(settings.file,"r");
|
||||
var l = f.readLine(f);
|
||||
|
|
|
|||
Loading…
Reference in New Issue