SVG Overlay
SvgOverlay creates an SVG overlay within a geographic bounds that scales with zoom level.
SVG overlays have lower performance and are not recommended for heavy use. They may also cause distortion at very high zoom levels and become invisible at large pitch angles.
Type Definitions
// Creates an SVG overlay within a geographic bounds that scales with zoom level
export class SvgOverlay {
constructor(options?: {
/** Maximum zoom level to display */
minZoom?: number;
/** Minimum zoom level to display */
maxZoom?: number;
/** Maximum pitch angle to display */
maxPitch?: number;
/** Auto-update div size (set to true if SVG needs to scale) */
updateDivSize?: boolean;
/** Maximum div size when scaling; beyond this, pixel scaling is used */
maxDivSize?: number;
/** Do not auto-update bounds when move ends */
noUpdateBoundsWhenMoveend?: boolean;
/** Class name */
divClassName?: string;
/** Maximum pixel width when initializing SVG, default 1000 */
svgMaxWidth?: number;
/** Maximum pixel height when initializing SVG, default 1000 */
svgMaxHeight?: number;
/** SVG initialization offset in pixels, default 100 */
svgOffset?: number;
});
addTo(map: Map, insertId?: string | HTMLElement): void;
remove(): void;
/**
* Add SVG element
* @param element Element to add
* @param noUpdate Do not update immediately
*/
addElement(element: SvgElementOptions | string, noUpdate?: boolean): void;
/**
* Add SVG elements
* @param elements Multiple element contents
* @param noUpdate Do not update immediately
*/
addElements(elements: SvgElementOptions[], noUpdate?: boolean): void;
/**
* Get SVG container
*/
getSvgContainer(): SVGSVGElement;
/**
* Get all elements
*/
getElements(): SvgElementOptions[];
/**
* Remove element(s)
*/
removeElements(id: string[] | string): SvgElementOptions[];
/**
* Update element(s)
*/
updateElements(elements: SvgElementOptions[] | SvgElementOptions): SvgElementOptions[];
/**
* Circle center-radius attribute string
*/
static attr_cx_cy_r(cx: number, cy: number, r: number): string;
/**
* Ellipse center-radius attribute string
*/
static attr_cx_cy_rx_ry(cx: number, cy: number, rx: number, ry: number): string;
/**
* Line coordinate attribute string
*/
static attr_x1_y1_x2_y2(x1: number, y1: number, x2: number, y2: number): string;
/**
* Coordinate width-height attribute string
*/
static attr_x_y_w_h(x: number, y: number, w: number, h: number): string;
/**
* Coordinate attribute string
*/
static attr_x_y(x: number, y: number): string;
/**
* Font attribute string
*/
static attr_fontsize(fontsize: number): string;
/**
* Length-related attribute string
*/
static attr_length(len: number): string;
/**
* Point coordinate attribute string
*/
static attr_point(point: GeoPoint, joinComma?: boolean): string;
/**
* Coordinate sequence attribute string
*/
static attr_points(points: GeoPoint[]): string;
/**
* Path sequence attribute string
*/
static attr_path(points: GeoPoint[]): string;
}
Usage
let mapBounds = map.getGeoBounds();
let len = mapBounds.width() / 5;
let svgOverlay = new vjmap.SvgOverlay({
maxZoom: 5, // All hidden at zoom level 5
maxPitch: 60 // Hidden when pitch exceeds 60 degrees
});
svgOverlay.addTo(map);
// Add a gradient
svgOverlay.addElement(`
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:${vjmap.randomColor()};stop-opacity:0.8" />
<stop offset="100%" style="stop-color:${vjmap.randomColor()};stop-opacity:1" />
</radialGradient>
</defs>
`)
const getStyle = (style = {}) => {
return Object.keys(style).map(key => `${key}:${style[key]}`).join(";")
}
const svgCircleHtml = (id, point, r, style) => {
return ` <circle id="${id}" ${vjmap.SvgOverlay.attr_cx_cy_r(point.x, point.y, r)} style="${getStyle(style)}"/>`
}
const addCircle = ()=> {
let id = "circle" + vjmap.RandomID();
return svgOverlay.addElement({
html: svgCircleHtml(id, mapBounds.randomPoint(), len / 4, {fill: "url(#grad1)", stroke: vjmap.randomColor(), "stroke-width": 3, cursor: "pointer"}),
event: svgParentElement => {
// Event callback
let ele = svgParentElement.getElementById(id);
if (!ele) return;
ele.addEventListener("mouseover", e => ele.style.opacity = 0.6);
ele.addEventListener("mouseout", e => ele.style.opacity = 1.0);
ele.addEventListener("click", e => message.info("Clicked circle " + id));
}
})
}
for(let i = 0; i < 10; i++) {
addCircle();
}
Runs in a sandbox against the VJMAP public demo service
// Create map service object with service URL and token
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
// Open map
let res = await svc.openMap({
mapid: env.exampleMapId, // Map ID (ensure this ID exists, upload new graphic to create ID)
mapopenway: vjmap.MapOpenWay.GeomRender, // Open with geometry data rendering
style: vjmap.openMapDarkStyle() // Use dark background style when div has dark background
})
if (res.error) {
message.error(res.error)
}
// Get map extent
let mapExtent = vjmap.GeoBounds.fromString(res.bounds);
// Create coordinate system
let prj = new vjmap.GeoProjection(mapExtent);
// Create map object
let map = new vjmap.Map({
container: 'map', // container ID
style: svc.rasterStyle(), // Raster tile style
center: prj.toLngLat(mapExtent.center()), // Center point
zoom: 2,
renderWorldCopies: false
});
// Associate map with service object and coordinate system
map.attach(svc, prj);
await map.onLoad();
let mapBounds = map.getGeoBounds();
let len = mapBounds.width() / 5;
let svgOverlay = new vjmap.SvgOverlay({
maxZoom: 5, // All hidden at zoom level 5
maxPitch: 60 // Hidden when pitch exceeds 60 degrees
});
svgOverlay.addTo(map);
// Add a gradient
svgOverlay.addElement(`
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:${vjmap.randomColor()};stop-opacity:0.6" />
<stop offset="100%" style="stop-color:${vjmap.randomColor()};stop-opacity:1" />
</radialGradient>
</defs>
`)
const getStyle = (style = {}) => {
return Object.keys(style).map(key => `${key}:${style[key]}`).join(";")
}
const svgCircleHtml = (id, point, r, style) => {
return ` <circle id="${id}" ${vjmap.SvgOverlay.attr_cx_cy_r(point.x, point.y, r)} style="${getStyle(style)}"/>`
}
const addCircle = ()=> {
let id = "circle" + vjmap.RandomID();
return svgOverlay.addElement({
html: svgCircleHtml(id, mapBounds.randomPoint(), len / 4, {fill: "url(#grad1)", stroke: vjmap.randomColor(), "stroke-width": 3, cursor: "pointer"}),
event: svgParentElement => {
// Event callback
let ele = svgParentElement.getElementById(id);
if (!ele) return;
ele.addEventListener("mouseover", e => ele.style.opacity = 0.4);
ele.addEventListener("mouseout", e => ele.style.opacity = 0.6);
ele.addEventListener("click", e => map.logInfo("Clicked circle " + id));
}
})
}
for(let i = 0; i < 10; i++) {
addCircle();
}Examples

Was this page helpful?Thanks for the feedback!