Add a Home button and fill icon gaps from NPS's newer symbol library
Two things pulled in from github.com/nationalparkservice/npmap5-plugins: - A "Home" button (public/vendor/npmap-home-button/, NPS's own MapLibre control) pinned to the app's CENTER/ZOOM, sitting top-left on the map. Now that the URL hash permalink can open the map at any view, "current view" and "the default view" aren't the same thing anymore, so a quick way back to the default is worth having. - npmap5-plugins bundles a newer, actively-maintained version of the same NPS symbol-library already used for POI_ICONS (confirmed by its maintainer to be the designated replacement for the older standalone repo: nationalparkservice/npmap5-plugins#4), with a much larger icon vocabulary and a simpler CC0 (public domain) license. All 25 icons already in use came back byte-identical from the new source, so this just repoints their attribution — but it also has icons the old repo didn't: `forest` (POI_ICONS) is now the official "wilderness" pictogram instead of hand-drawn, and three of the five previously icon-less Services/Activities tags (wifi, mobile data coverage, winter/snow camping) now have real icons too. Only bakery and vehicle wash still have no NPS equivalent.
This commit is contained in:
1 parent
481233c232
commit
170af80cac
6 files changed
+235
-39
No files matched your search
+5
@@ -0,0 +1,5 @@
|
||||
### LICENSE.md
|
||||
|
||||
This project constitutes a work of the United States Government and is not subject to domestic copyright protection under [17 USC § 105](https://www.govinfo.gov/app/details/USCODE-2010-title17/USCODE-2010-title17-chap1-sec105).
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
class HomeButton {
|
||||
static createSvgElement() {
|
||||
// Create the SVG element
|
||||
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
svg.setAttribute("viewBox", "0 0 576 512");
|
||||
svg.setAttribute("fill", "#333");
|
||||
svg.setAttribute("stroke", "currentColor");
|
||||
svg.setAttribute("stroke-width", "2");
|
||||
svg.setAttribute("stroke-linecap", "round");
|
||||
svg.setAttribute("stroke-linejoin", "round");
|
||||
svg.setAttribute("class", "feather feather-home");
|
||||
svg.setAttribute("width", '80%');
|
||||
// Create the path for the house
|
||||
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
||||
path.setAttribute("d", "M575.8 255.5c0 18-15 32.1-32 32.1h-32l.7 160.2c0 2.7-.2 5.4-.5 8.1V472c0 22.1-17.9 40-40 40H456c-1.1 0-2.2 0-3.3-.1c-1.4 .1-2.8 .1-4.2 .1H416 392c-22.1 0-40-17.9-40-40V448 384c0-17.7-14.3-32-32-32H256c-17.7 0-32 14.3-32 32v64 24c0 22.1-17.9 40-40 40H160 128.1c-1.5 0-3-.1-4.5-.2c-1.2 .1-2.4 .2-3.6 .2H104c-22.1 0-40-17.9-40-40V360c0-.9 0-1.9 .1-2.8V287.6H32c-18 0-32-14-32-32.1c0-9 3-17 10-24L266.4 8c7-7 15-8 22-8s15 2 21 7L564.8 231.5c8 7 12 15 11 24z");
|
||||
// Append the path and polyline to the SVG
|
||||
svg.appendChild(path);
|
||||
return svg;
|
||||
}
|
||||
/**
|
||||
* Class constructor which calls the `setOptions` function to merge
|
||||
* the default options and user-provided options.
|
||||
*
|
||||
* @param {homeButtonOptions} options - The options provided by the user
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
this.defaultOptions = HomeButton.DefaultOptions;
|
||||
this._options = this.setOptions(options);
|
||||
}
|
||||
/**
|
||||
* Sets the button options by merging the default options with user-provided options.
|
||||
* Overrides the default `fitBoundsOptions` if any are provided by the user.
|
||||
*
|
||||
* @param {homeButtonOptions} options - The options provided by the user
|
||||
* @returns {homeButtonOptions} - The merged options
|
||||
*/
|
||||
setOptions(options) {
|
||||
// Merge fitBoundsOptions from default and user-provided options
|
||||
const fitBoundsOptions = {
|
||||
...this.defaultOptions.fitBoundsOptions,
|
||||
...options.fitBoundsOptions
|
||||
};
|
||||
// Merge all options
|
||||
this._options = {
|
||||
...this.defaultOptions,
|
||||
...options,
|
||||
fitBoundsOptions
|
||||
};
|
||||
return this._options;
|
||||
}
|
||||
/**
|
||||
* Setter for the `options` property.
|
||||
*
|
||||
* @param {homeButtonOptions} options - The options provided by the user
|
||||
*/
|
||||
set options(options) {
|
||||
this.setOptions(options);
|
||||
}
|
||||
/**
|
||||
* Creates a DOM div element with a child button element.
|
||||
* The div is assigned CSS classes for styling, and the button has ARIA attributes for accessibility.
|
||||
* The button also has an event listener to prevent the context menu from appearing on right click.
|
||||
*
|
||||
* @returns {HTMLDivElement} The created div element with its child button.
|
||||
*/
|
||||
createDiv() {
|
||||
const div = document.createElement("div");
|
||||
div.className = "maplibregl-ctrl maplibregl-ctrl-group";
|
||||
const button = document.createElement("button");
|
||||
// Add ARIA attributes to the button for accessibility
|
||||
button.setAttribute('aria-label', 'Pan/zoom to initial extent'); // For screen readers
|
||||
button.alt = 'Pan/zoom to initial extent'; // For legacy screen readers
|
||||
button.appendChild(this._options.icon);
|
||||
div.appendChild(button);
|
||||
div.addEventListener("contextmenu", (e) => e.preventDefault());
|
||||
this.div = div;
|
||||
return this.div;
|
||||
}
|
||||
/**
|
||||
* Adds the created div to the map and sets up its click behavior.
|
||||
* If the `bounds` option is set, the map will fit to these bounds when the div is clicked.
|
||||
* If the `bounds` option is not set, the map will fly to the `homePosition` at the specified `zoom` level.
|
||||
* If the `homePosition` and `zoom` level are not set, it defaults to the current map center and zoom level.
|
||||
*
|
||||
* @param {MapLibraryMap} map - The map to which the div is being added.
|
||||
* @returns {HTMLDivElement} The div that has been added to the map.
|
||||
*/
|
||||
onAdd(map) {
|
||||
// Create the div
|
||||
const div = this.createDiv();
|
||||
// Destructure the options for cleaner code
|
||||
let { bounds, fitBoundsOptions } = this._options;
|
||||
// If the homePosition and zoom options are not set, use the current map center and zoom level
|
||||
const center = this._options.homePosition || map.getCenter();
|
||||
const zoom = this._options.zoom || map.getZoom();
|
||||
// Add a click event listener to the div
|
||||
div.addEventListener("click", () => {
|
||||
// If the bounds option is set, fit the map to these bounds
|
||||
if (bounds) {
|
||||
map.fitBounds(bounds, fitBoundsOptions);
|
||||
}
|
||||
// If bounds option is not set, fly the map to the home position or current map center at the specified zoom level
|
||||
else {
|
||||
map.flyTo({
|
||||
center,
|
||||
zoom,
|
||||
// Merge in the fitBoundsOptions, but exclude 'linear' and 'maxZoom' properties as they are not compatible with flyTo
|
||||
...{
|
||||
...fitBoundsOptions,
|
||||
linear: undefined,
|
||||
maxZoom: undefined
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// Return the div to be added to the map
|
||||
return div;
|
||||
}
|
||||
/**
|
||||
* Removes the div from the DOM and resets the `div` property.
|
||||
* If `div` does not exist, the function simply exits.
|
||||
*/
|
||||
onRemove() {
|
||||
// Check if this.div exists
|
||||
if (this.div) {
|
||||
// If it does, remove the div from the DOM
|
||||
this.div.remove();
|
||||
}
|
||||
// Reset the div property to undefined
|
||||
this.div = undefined;
|
||||
}
|
||||
getDefaultPosition() {
|
||||
return 'top-left';
|
||||
}
|
||||
}
|
||||
HomeButton.DefaultOptions = {
|
||||
homePosition: null,
|
||||
zoom: null,
|
||||
bounds: null,
|
||||
fitBoundsOptions: {
|
||||
pitch: 0,
|
||||
bearing: 0
|
||||
},
|
||||
icon: HomeButton.createSvgElement()
|
||||
};
|
||||
|
||||
export { HomeButton as default };
|
||||
Reference in new issue
Block a user