I spent some time earlier this week tweaking the location-based JS that @Moonbase59 created. I was having numerous issues with formatting of locations in notes, probably due to ongoing enhancements by the Obsidian team on how front-matter properties are managed.
The core issue for me was storing locations in notes as a tuple / list of lat/lng pairs. To make things easier I moved to storing latitude and longitude as their own properties. This has a side effect of making this Dataview work better with the Geocoding properties plugin.
I removed the “driving distance” function because it was just a scale of the crow-flies distance and didn’t seem all that useful to me. I also refactored the filtering / querying so that it only needs to call the getDistance function once per note.
// Nearby Family Members, Friends and Places
// 2021-05-15 - Matthias C. Hormann (Moonbase59)
// 2025-01-02 - Chris Brooks updates
// set parameters (to be supplied via YAML frontmatter, eventually)
// DV 0.3.3 interprets "500000 m" as a Luxon duration,
// so we have to put nearby: '"500000 m"' and remove the ".
let nearby = dv.current().nearby.replace(/['"]+/g, '');
let unit = nearby.split(' ')[1];
let radius = nearby.split(' ')[0];
let origin = [dv.current().lat, dv.current().lng];
// search term as used in dv.pages()
// use "#tags" or '"folder/subfolder"' for a folder
let searchterm = dv.current().searchterm;
//======================================================================
function getDistance(origin, destination, unit='m') {
// return distance in selected unit (m,km,yd,mi)
var factor = 1.0;
switch (unit) {
case 'm':
factor = 1.0;
break;
case 'km':
factor = 1000.0;
break;
case 'yd':
factor = 0.9144;
break;
case 'mi':
factor = 1609.344;
break;
default:
factor = 1.0;
console.warn("getDistance: Invalid unit '%s', using 'm'. Valid units are: m,km,yd,mi.",unit);
}
var lon1 = toRadian(origin[1]),
lat1 = toRadian(origin[0]),
lon2 = toRadian(destination[1]),
lat2 = toRadian(destination[0]);
var deltaLat = lat2 - lat1;
var deltaLon = lon2 - lon1;
var a = Math.pow(Math.sin(deltaLat/2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(deltaLon/2), 2);
var c = 2 * Math.asin(Math.sqrt(a));
var EARTH_RADIUS = 6371000; // 6,371 km in metres
return c * EARTH_RADIUS / factor;
}
function toRadian(degree) {
return degree*Math.PI/180;
}
//======================================================================
// Show what we will display.
dv.paragraph("List shows nearby places (within " + radius + " " + unit + " driving distance).");
dv.paragraph("<br><br>");
// get the pages
let pages = dv.pages(searchterm)
.filter(p => {
if (!p.lat || !p.lng) return false;
p.distance = getDistance(origin, [p.lat, p.lng], unit);
return p.distance > 0.0 && p.distance <= radius;
}).sort(p => p.distance);
// create table
dv.table(["Name", "Tags", "Last Played", "Distance"],
pages.map(p => [
// The name
p.file.link,
// tags (show '–' if none defined)
(p.file.etags ? p.file.etags.join(' ') : '–'),
p.played,
// straight-line distance
/*
getDistance(origin, p.location, unit)
.toLocaleString(moment.locale(), {maximumFractionDigits: 1}) + " " + unit,
*/
// predicted driving distance and Google Maps Route Planner Link
(p.distance
.toLocaleString(moment.locale(), {maximumFractionDigits: 1}) + " " + unit)
.link('https://www.google.com/maps/dir/?api=1&dir_action=navigate&destination=' + p.lat + ',' + p.lng),
])
);