openstmap 0.33: Map zoom by tapping is now only when tapping at each corner (helps with accidental zooming)

When GPS location is offscreen, draw a blue circle showing the direction to scroll
master
Gordon Williams 2025-06-03 15:30:23 +01:00
parent 88ba56baf3
commit f23a8c3975
4 changed files with 54 additions and 32 deletions

View File

@ -39,3 +39,5 @@
0.31: Reset draw colours before rendering (to allow black and white maps) 0.31: Reset draw colours before rendering (to allow black and white maps)
0.32: Move to non-deprecated track drawing using the recorder library 0.32: Move to non-deprecated track drawing using the recorder library
Add option to hide widgets Add option to hide widgets
0.33: Map zoom by tapping is now only when tapping at each corner (helps with accidental zooming)
When GPS location is offscreen, draw a blue circle showing the direction to scroll

View File

@ -6,7 +6,7 @@ allows you to use the maps in your Bangle.js applications.
## Uploader ## Uploader
Once you've installed OpenStreepMap on your Bangle, find it Once you've installed OpenStreetMap on your Bangle, find it
in the App Loader and click the Disk icon next to it. in the App Loader and click the Disk icon next to it.
A window will pop up showing what maps you have loaded. A window will pop up showing what maps you have loaded.
@ -34,13 +34,16 @@ and marks the path that you've been travelling (if enabled), and
displays waypoints in the watch (if dependencies exist). displays waypoints in the watch (if dependencies exist).
* Drag on the screen to move the map * Drag on the screen to move the map
* Click bottom left to zoom in, bottom right to zoom out * Click at the bottom left corner to zoom in, bottom right to zoom out (or you can choose from the menu)
* Press the button to bring up a menu, where you can zoom, go to GPS location, * Press the button to bring up a menu, where you can zoom, go to GPS location,
put the map back in its default location, or choose whether to draw the currently put the map back in its default location, or choose whether to draw the currently
recording GPS track (from the `Recorder` app). recording GPS track (from the `Recorder` app).
**Note:** If enabled, drawing the currently recorded GPS track can take a second The map displays:
or two (which happens after you've finished scrolling the screen with your finger).
* Your current GPS location and angle (in blue) or a circle at the edge of the screen if your location is offscreen
* Your currently recorded/recording track in red (if the `Recorder` app is installed)
* Any waypoints as red markers (if the `Waypoint` app is installed)
## Library ## Library

View File

@ -2,20 +2,21 @@ var m = require("openstmap");
var R; var R;
var fix = {}; var fix = {};
var mapVisible = false; var mapVisible = false;
var hasScrolled = false;
var settings = require("Storage").readJSON("openstmap.json",1)||{}; var settings = require("Storage").readJSON("openstmap.json",1)||{};
var HASWIDGETS = !settings.noWidgets; var HASWIDGETS = !settings.noWidgets;
var plotTrack; var plotTrack;
let checkMapPos = false; // Do we need to check the if the coordinates we have are valid let checkMapPos = false; // Do we need to check the if the coordinates we have are valid
var startDrag = 0; var startDrag = 0; //< to detect a short tap when zooming
var hasRecorder = require("Storage").read("recorder")!=undefined; // do we have the recorder library? var hasRecorder = require("Storage").read("recorder")!=undefined; // do we have the recorder library?
var hasWaypoints = require("Storage").read("waypoints")!=undefined; // do we have the recorder library?
var labelFont = g.getFonts().includes("17")?"17":"6x8:2";
var imgLoc, ovLoc, ovSize = 34; /*Math.ceil(Math.sqrt(imgLoc[0]*imgLoc[0]+imgLoc[1]*imgLoc[1]))*/
if (Bangle.setLCDOverlay) { if (Bangle.setLCDOverlay) {
// Icon for current location+direction: https://icons8.com/icon/11932/gps 24x24, 1 Bit + transparency + inverted // Icon for current location+direction: https://icons8.com/icon/11932/gps 24x24, 1 Bit + transparency + inverted
var imgLoc = require("heatshrink").decompress(atob("jEYwINLAQk8AQl+AQn/AQcB/+AAQUD//AAQUH//gAQUP//wAQUf//4j8AvA9IA==")); imgLoc = require("heatshrink").decompress(atob("jEYwINLAQk8AQl+AQn/AQcB/+AAQUD//AAQUH//gAQUP//wAQUf//4j8AvA9IA=="));
// overlay buffer for current location, a bit bigger then image so we can rotate // overlay buffer for current location, a bit bigger then image so we can rotate
const ovSize = Math.ceil(Math.sqrt(imgLoc[0]*imgLoc[0]+imgLoc[1]*imgLoc[1])); ovLoc = Graphics.createArrayBuffer(ovSize,ovSize,imgLoc[2] & 0x7f,{msb:true});
var ovLoc = Graphics.createArrayBuffer(ovSize,ovSize,imgLoc[2] & 0x7f,{msb:true});
} }
if (settings.lat !== undefined && settings.lon !== undefined && settings.scale !== undefined) { if (settings.lat !== undefined && settings.lon !== undefined && settings.scale !== undefined) {
@ -66,6 +67,7 @@ function redraw() {
// Draw the POIs // Draw the POIs
function drawPOI() { function drawPOI() {
if (!hasWaypoints) return;
let waypoints; let waypoints;
try { try {
waypoints = require("waypoints").load(); waypoints = require("waypoints").load();
@ -73,16 +75,15 @@ function drawPOI() {
// Waypoints module not available. // Waypoints module not available.
return; return;
} }
g.setFont("Vector", 18); if (!waypoints) return;
g;
var img = atob("DRXCAP//APgfAAAAAFVAAVVVAVVVUFUBVFUAFVVABVVQAVRVAVQVVVUBVVUAVVVABVVAAVVQABVQAAVUAABUAACVgACJiACISIAIiIAAiIAA");
g.setFont(labelFont).setFontAlign(-1,0);
waypoints.forEach((wp, idx) => { waypoints.forEach((wp, idx) => {
if (wp.lat === undefined || wp.lon === undefined) return; if (wp.lat === undefined || wp.lon === undefined) return;
var p = m.latLonToXY(wp.lat, wp.lon); var p = m.latLonToXY(wp.lat, wp.lon);
var sz = 2; g.setColor("#fff").drawImage(img, p.x-6, p.y-18);
g.setColor(0,0,0); g.setColor(0).drawString(wp.name, p.x+8, p.y);
g.fillRect(p.x-sz, p.y-sz, p.x+sz, p.y+sz);
g.setColor(0,0,0);
g.drawString(wp.name, p.x, p.y);
//print(wp.name);
}); });
} }
@ -119,17 +120,31 @@ function drawLocation() {
// TODO: if this is getting off the screen, we could adjust the map over? Also show marker to show what direction we're offscreen // TODO: if this is getting off the screen, we could adjust the map over? Also show marker to show what direction we're offscreen
ovLoc.clear(); ovLoc.clear();
if (isInside(R, p, ovLoc.getWidth(), ovLoc.getHeight())) { // avoid drawing over widget area if (isInside(R, p, ovLoc.getWidth(), ovLoc.getHeight())) { // avoid drawing over widget area
const angle = settings.dirSrc === 1 ? fix.course : Bangle.getCompass().heading; const angle = settings.dirSrc === 1 ? fix.course : Bangle.getCompass().heading;
if (!isNaN(angle)) { if (!isNaN(angle)) {
ovLoc.drawImage(imgLoc, ovLoc.getWidth()/2, ovLoc.getHeight()/2, {rotate: angle*Math.PI/180}); ovLoc.drawImage(imgLoc, ovLoc.getWidth()/2, ovLoc.getHeight()/2, {rotate: angle*Math.PI/180});
} }
} else { // if off-screen, draw a blue dot on the edge
var mx = (R.x+R.x2)/2, my = (R.y+R.y2)/2;
var dy = p.y - mx, dx = p.x - my;
if (Math.abs(dx)>Math.abs(dy)) {
dy = mx * dy / Math.abs(dx);
dx = mx * Math.sign(dx);
} else {
dx = my * dx / Math.abs(dy);
dy = my * Math.sign(dy);
} }
Bangle.setLCDOverlay({width:ovLoc.getWidth(), height:ovLoc.getHeight(), p.x = mx+dx;
p.y = my+dy;
ovLoc.fillCircle(ovSize/2,ovSize/2,16);
}
Bangle.setLCDOverlay({width:ovSize, height:ovSize,
bpp:ovLoc.getBPP(), transparent:0, bpp:ovLoc.getBPP(), transparent:0,
palette:new Uint16Array([0, g.toColor("#00F")]), palette:new Uint16Array([0, g.toColor("#00F")]),
buffer:ovLoc.buffer buffer:ovLoc.buffer
}, p.x-ovLoc.getWidth()/2, p.y-ovLoc.getHeight()/2); }, p.x-ovSize/2, p.y-ovSize/2);
this.hasOverlay = true; this.hasOverlay = true;
} }
@ -252,26 +267,28 @@ function showMap() {
if (e.b) { if (e.b) {
if (!startDrag) if (!startDrag)
startDrag = getTime(); startDrag = getTime();
if (e.dx || e.dy) {
g.setClipRect(R.x,R.y,R.x2,R.y2); g.setClipRect(R.x,R.y,R.x2,R.y2);
g.scroll(e.dx,e.dy); g.scroll(e.dx,e.dy);
m.scroll(e.dx,e.dy); m.scroll(e.dx,e.dy);
g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1); g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1);
hasScrolled = true; }
drawLocation(); drawLocation();
} else if (hasScrolled) { } else if (startDrag) {
const delta = getTime() - startDrag; const delta = getTime() - startDrag;
startDrag = 0; startDrag = 0;
hasScrolled = false; if (delta < 0.2) { // short tap?
if (delta < 0.2) { if (e.y > g.getHeight() - 32) { // at bottom egde?
if (e.y > g.getHeight() / 2) { if (e.x < 32) { // zoom in/out
if (e.x < g.getWidth() / 2) {
m.scale /= 2; m.scale /= 2;
} else {
m.scale *= 2;
}
}
g.reset().clearRect(R); g.reset().clearRect(R);
} }
if (e.x > g.getHeight() - 32) {
m.scale *= 2;
g.reset().clearRect(R);
}
}
}
redraw(); redraw();
} }
}, btn: () => showMenu() }); }, btn: () => showMenu() });

View File

@ -2,7 +2,7 @@
"id": "openstmap", "id": "openstmap",
"name": "OpenStreetMap", "name": "OpenStreetMap",
"shortName": "OpenStMap", "shortName": "OpenStMap",
"version": "0.32", "version": "0.33",
"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", "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", "readme": "README.md",
"icon": "app.png", "icon": "app.png",