Skip to content

Commit

Permalink
feat: Define custom marker types in json files (#400)
Browse files Browse the repository at this point in the history
* feat: allow loading marker types from a local json file

* fix: correct marker types import path

* refactor: wait for map to be built before trying to access it

* fix: get marker data from map rather than plugin data

* fix: ensure local icons can never be empty when getting marker types for map

* doc: document addition of local marker types
  • Loading branch information
nathonius authored Jun 29, 2023
1 parent 73e1f4b commit b9305f5
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 18 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ On real-world maps, only `unit: ` is required. It will attempt to scale the meas

New markers can be added to the map by right clicking.

If any additional marker types have been created in the settings, a list will appear to choose from.
If any additional marker types have been created in plugin settings or a `markers.json` file in the same directory, a list will appear to choose from.

Once a marker has been created, it can be dragged to a different location.

Expand Down Expand Up @@ -872,6 +872,10 @@ Adding a new marker displays a new window, where the new marker parameters can b

If layer icon is on, the icon be moved around the base icon by clicking and dragging, to customize where the icon is layered. If <kbd>Shift</kbd> is held while moving the icon, it will snap to the midlines.

#### Creating local marker types

New markers can also be defined in a `markers.json` file. These marker types will be available to any notes in the same directory as the json file. The json file should contain an array of Icon objects, See the [Icon interface](https://github.com/javalent/obsidian-leaflet/blob/1fa4c237deceff1def883872fdad3822f9bff560/types/saved.d.ts#L7) for details.

#### Using an Image as a Marker Icon

When creating an additional marker, an image may be uploaded to use as the marker icon instead of selecting a Font Awesome icon.
Expand Down
11 changes: 5 additions & 6 deletions src/layer/marker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ export class Marker extends Layer<DivIconMarker> {
) {
super();

const marker = this.map.plugin.getIconForType(type);
if (!marker) {
const markerIcon = this.map.markerIcons.get(type) ?? this.map.markerIcons.get('default');
if (!markerIcon) {
new Notice(
t(
"Leaflet: Could not create icon for %1 - does this type exist in settings?",
Expand All @@ -214,6 +214,7 @@ export class Marker extends Layer<DivIconMarker> {
);
return;
}
const marker = markerIcon.markerIcon;
const icon = markerDivIcon(this.map.plugin.parseIcon(marker));
this.leafletInstance = divIconMarker(
loc,
Expand Down Expand Up @@ -251,10 +252,8 @@ export class Marker extends Layer<DivIconMarker> {

this.link = link;

const markerIcon = this.map.plugin.getIconForType(this.type);

this.minZoom = minZoom ?? markerIcon?.minZoom ?? null;
this.maxZoom = maxZoom ?? markerIcon?.maxZoom ?? null;
this.minZoom = minZoom ?? marker?.minZoom ?? null;
this.maxZoom = maxZoom ?? marker?.maxZoom ?? null;

this.checkAndAddToMap();

Expand Down
21 changes: 19 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,8 @@ export default class ObsidianLeaflet extends Plugin {
params,
source
);
const map = renderer.map;


const map = await renderer.getMap();
this.registerMapEvents(map);

ctx.addChild(renderer);
Expand Down Expand Up @@ -636,6 +636,7 @@ export default class ObsidianLeaflet extends Plugin {
markerIcon: icon
};
}

public generateMarkerMarkup(
markers: Icon[] = this.data.markerIcons
): MarkerIcon[] {
Expand Down Expand Up @@ -663,6 +664,22 @@ export default class ObsidianLeaflet extends Plugin {
return ret;
}

public async getLocalFileMarkers(file: TFile, markerFileName = "markers.json"): Promise<MarkerIcon[]> {
const markerFilePath = `${file.parent.path}/${markerFileName}`;
const markerFile = this.app.vault.getAbstractFileByPath(markerFilePath);
const markers: MarkerIcon[] = [];
if (markerFile instanceof TFile) {
const markerJson = await this.app.vault.read(markerFile);
try {
const icons = JSON.parse(markerJson);
markers.push(...icons.map((i: Icon) => this.parseIcon(i)))
} catch {
console.error(`Badly formatted marker file ${markerFilePath}`);
}
}
return markers;
}

public getIconForTag(tags: Set<string>) {
return this.data.markerIcons.find((icon) =>
(
Expand Down
2 changes: 1 addition & 1 deletion src/map/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ export abstract class BaseMap extends Events implements BaseMapDefinition {
mapLayers: LayerGroup<L.TileLayer | L.ImageOverlay>[] = [];
get markerIcons(): Map<string, MarkerIcon> {
return new Map(
this.plugin.markerIcons.map((markerIcon) => [
[...this.plugin.markerIcons, ...(this.options.localMarkerTypes ?? [])].map((markerIcon) => [
markerIcon.type,
markerIcon
])
Expand Down
6 changes: 2 additions & 4 deletions src/modals/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {
Marker,
TooltipDisplay,
BaseMapType
} from "../types";
} from "../../types";

import { PathSuggestionModal } from "./path";
import { CommandSuggestionModal } from "./command";
Expand Down Expand Up @@ -60,9 +60,7 @@ export class MarkerContextModal extends Modal {
let newMarker =
value == "default"
? this.map.data.defaultMarker
: this.map.data.markerIcons.find(
(m) => m.type == value
);
: this.map.markerIcons.get(value);
this.tempMarker.type = newMarker.type;
});
});
Expand Down
17 changes: 14 additions & 3 deletions src/renderer/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class LeafletRenderer extends MarkdownRenderChild {
loader: Loader = new Loader(this.plugin.app);
resize: ResizeObserver;
map: BaseMapType;
private mapBuilt: Promise<void>;
verbose: boolean;
parentEl: HTMLElement;
options: LeafletMapOptions;
Expand Down Expand Up @@ -194,8 +195,7 @@ export class LeafletRenderer extends MarkdownRenderChild {
this.map.leafletInstance.invalidateSize();
}
});

this.buildMap();
this.mapBuilt = this.buildMap();

this.resize.observe(this.containerEl);
}
Expand Down Expand Up @@ -254,7 +254,17 @@ export class LeafletRenderer extends MarkdownRenderChild {
this.map.leafletInstance.invalidateSize();
}

async buildMap() {
/**
* Use this to get the map instance instead of renderer.map when it might not be defined yet
*/
async getMap(): Promise<BaseMapType> {
await this.mapBuilt;
return this.map;
}

async buildMap(): Promise<void> {
this.options.localMarkerTypes = await this.plugin.getLocalFileMarkers(this.file);

if (this.options.type === "real") {
this.map = new RealMap(this, this.options);
} else {
Expand Down Expand Up @@ -339,6 +349,7 @@ export class LeafletRenderer extends MarkdownRenderChild {
}

async onload() {
await this.mapBuilt;
this.map.log("MarkdownRenderChild loaded. Appending map.");
this.containerEl.appendChild(this.map.contentEl);

Expand Down
2 changes: 2 additions & 0 deletions types/map.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ export interface LeafletMapOptions {
geojsonColor?: string;
gpxColor?: string;

localMarkerTypes?: MarkerIcon[];

hasAdditional?: boolean;
height?: string;
width?: string;
Expand Down
2 changes: 1 addition & 1 deletion types/marker.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Icon, TooltipDisplay } from ".";
import { MarkerDivIcon } from "./map";
import type { Marker as MarkerDefinition } from "../layer/marker";
import type { Marker as MarkerDefinition } from "../src/layer/marker";

export type Marker = MarkerDefinition;
export interface MarkerIcon {
Expand Down

0 comments on commit b9305f5

Please sign in to comment.