On a map
The map entries draw symbols on OpenLayers and MapLibre from one collection, and an editor places and edits them on either. Every renderer draws the same marks: the symbol is rendered once, turned into a glyph and placed at any zoom.
The saved object
A symbol on a map is a GeoJSON Point whose properties.military says what it is:
json
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-116.68, 35.27]},
"properties": {
"military": {
"name": "130310000012110000000000000000",
"amplifiers": {"T": "1-66", "M": "2BCT"},
"size": "medium",
"direction": 45
}
}
}| Property | |
|---|---|
name | the code: 2525D or 2525E, or a letter code |
amplifiers | by Table VI letter, as for renderSymbol |
size | 'small', 'medium' or 'large' |
direction | Q, the direction of movement, in degrees |
letterStandard | for a letter code: '2525C', '2525B' or 'APP-6B' |
Nothing about the view travels with it. Store it, send it, load it back.
The collection
ts
import {MilitaryCollection} from '@zaes/military-symbols/map';
const collection = new MilitaryCollection();
const id = collection.add(feature);
collection.setProperties(id, {amplifiers: {T: '1-67'}});
collection.move(id, 'front'); // stacking: 'front', 'back', 'forward', 'backward'
const saved = collection.toGeoJSON(); // a FeatureCollection
const {loaded, skipped} = collection.load(saved, {replace: true});load takes any GeoJSON and keeps the features it can draw: a single-point code of a standard this library draws. skipped says why each other one was left out.
OpenLayers
ts
import {MilitarySymbolsOpenLayers} from '@zaes/military-symbols/openlayers';
const renderer = new MilitarySymbolsOpenLayers(map, collection);MapLibre
ts
import {MilitarySymbolsMapLibre} from '@zaes/military-symbols/maplibre';
const renderer = new MilitarySymbolsMapLibre(map, collection, {pointLeaders: true});On a tilted map with terrain a symbol lying on the ground is foreshortened, and a ridge can hide it. pointLeaders stands each symbol upright on a leader line; renderer.setLeaderLines(false) lays them down again. Symbols stack in the collection's order, whole, one over another.
The editor
ts
import {MilitarySymbolsInteraction, MilitarySymbolsHistory, attachMilitaryEditor} from '@zaes/military-symbols/editor';
const history = new MilitarySymbolsHistory(collection);
const editor = new MilitarySymbolsInteraction(collection, renderer.view);
const detach = attachMilitaryEditor(renderer, editor);
editor.startDrawing('130310000012110000000000000000'); // the next click places it
editor.subscribe((e) => {
if (e.type === 'drawend') editor.select(e.id);
if (e.type === 'commit' || e.type === 'drawend') history.checkpoint();
});
history.undo();A click places a symbol; any part of a symbol (frame, staff, echelon, amplifiers) selects it; a handle steps through the three sizes and another sets the direction of movement. The same editor works on either renderer: switch engines and call editor.setView(newRenderer.view).
How every symbol draws
ts
import {configureMilitarySymbols} from '@zaes/military-symbols/map';
configureMilitarySymbols({
symbolPx: 40, // the octagon's height at medium size
amplifiers: true,
display: {fillOpacity: 0.8, textHalo: 3}, // the display options of renderSymbol
fullSizeScale: 0, // shrink past this map scale (1:N); 0 never
});It applies to every symbol on every map and redraws them.