Interactive SVG layer example
This commit is contained in:
5188
examples/data/world.svg
Normal file
5188
examples/data/world.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 3.2 MiB |
7
examples/svg-layer.css
Normal file
7
examples/svg-layer.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#map {
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.svg-layer path:hover {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
9
examples/svg-layer.html
Normal file
9
examples/svg-layer.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
layout: example.html
|
||||||
|
title: SVG Layer
|
||||||
|
shortdesc: Example of a map with an interactive svg layer.
|
||||||
|
docs: >
|
||||||
|
With a plain `ol/Layer` and a `render` function, we can use an interactive svg as layer. Hover over countries to see the interactivity that is defined purely with a css `:hover` pseudo-class.
|
||||||
|
tags: "svg, layer, render, transform"
|
||||||
|
---
|
||||||
|
<div id="map" class="map"></div>
|
||||||
48
examples/svg-layer.js
Normal file
48
examples/svg-layer.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import Map from '../src/ol/Map.js';
|
||||||
|
import View from '../src/ol/View.js';
|
||||||
|
import Layer from '../src/ol/layer/Layer.js';
|
||||||
|
import {composeCssTransform} from '../src/ol/transform.js';
|
||||||
|
|
||||||
|
const map = new Map({
|
||||||
|
target: 'map',
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
extent: [-180, -90, 180, 90],
|
||||||
|
projection: 'EPSG:4326',
|
||||||
|
zoom: 2
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const svgContainer = document.createElement('div');
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', 'data/world.svg');
|
||||||
|
xhr.addEventListener('load', function() {
|
||||||
|
const svg = xhr.responseXML.documentElement;
|
||||||
|
svgContainer.ownerDocument.importNode(svg);
|
||||||
|
svgContainer.appendChild(svg);
|
||||||
|
});
|
||||||
|
xhr.send();
|
||||||
|
|
||||||
|
const width = 2560;
|
||||||
|
const height = 1280;
|
||||||
|
const svgResolution = 360 / width;
|
||||||
|
svgContainer.style.width = width + 'px';
|
||||||
|
svgContainer.style.height = height + 'px';
|
||||||
|
svgContainer.style.transformOrigin = 'top left';
|
||||||
|
svgContainer.className = 'svg-layer';
|
||||||
|
|
||||||
|
map.addLayer(new Layer({
|
||||||
|
render: function(frameState) {
|
||||||
|
const scale = svgResolution / frameState.viewState.resolution;
|
||||||
|
const center = frameState.viewState.center;
|
||||||
|
const size = frameState.size;
|
||||||
|
const cssTransform = composeCssTransform(
|
||||||
|
size[0] / 2, size[1] / 2,
|
||||||
|
scale, scale,
|
||||||
|
frameState.viewState.rotation,
|
||||||
|
-center[0] / svgResolution - width / 2, center[1] / svgResolution - height / 2);
|
||||||
|
svgContainer.style.transform = cssTransform;
|
||||||
|
svgContainer.style.opacity = this.getOpacity();
|
||||||
|
return svgContainer;
|
||||||
|
}
|
||||||
|
}));
|
||||||
@@ -74,6 +74,12 @@
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||||
}
|
}
|
||||||
|
.ol-overlaycontainer, .ol-overlaycontainer-stopevent {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.ol-overlaycontainer > *, .ol-overlaycontainer-stopevent > * {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
.ol-selectable {
|
.ol-selectable {
|
||||||
-webkit-touch-callout: default;
|
-webkit-touch-callout: default;
|
||||||
-webkit-user-select: text;
|
-webkit-user-select: text;
|
||||||
|
|||||||
@@ -210,6 +210,24 @@ export function compose(transform, dx1, dy1, sx, sy, angle, dx2, dy2) {
|
|||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a composite transform given an initial translation, scale, rotation, and
|
||||||
|
* final translation (in that order only, not commutative). The resulting transform
|
||||||
|
* string can be applied as `transform` porperty of an HTMLElement's style.
|
||||||
|
* @param {number} dx1 Initial translation x.
|
||||||
|
* @param {number} dy1 Initial translation y.
|
||||||
|
* @param {number} sx Scale factor x.
|
||||||
|
* @param {number} sy Scale factor y.
|
||||||
|
* @param {number} angle Rotation (in counter-clockwise radians).
|
||||||
|
* @param {number} dx2 Final translation x.
|
||||||
|
* @param {number} dy2 Final translation y.
|
||||||
|
* @return {string} The composite css transform.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
export function composeCssTransform(dx1, dy1, sx, sy, angle, dx2, dy2) {
|
||||||
|
return toString(compose(create(), dx1, dy1, sx, sy, angle, dx2, dy2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invert the given transform.
|
* Invert the given transform.
|
||||||
|
|||||||
Reference in New Issue
Block a user