Merge pull request #9525 from jahow/custom-render-fn
Support a custom render function for the Layer class
This commit is contained in:
@@ -1,132 +1,12 @@
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import Layer from '../src/ol/layer/Layer';
|
||||
import {assign} from '../src/ol/obj';
|
||||
import {toLonLat} from '../src/ol/proj';
|
||||
import SourceState from '../src/ol/source/State';
|
||||
import {Stroke, Style} from '../src/ol/style.js';
|
||||
import VectorLayer from '../src/ol/layer/Vector.js';
|
||||
import VectorSource from '../src/ol/source/Vector.js';
|
||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||
|
||||
class Mapbox extends Layer {
|
||||
|
||||
/**
|
||||
* @param {import('../src/ol/layer/Layer').Options} options Layer options.
|
||||
*/
|
||||
constructor(options) {
|
||||
const baseOptions = assign({}, options);
|
||||
super(baseOptions);
|
||||
|
||||
this.baseOptions = baseOptions;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type boolean
|
||||
*/
|
||||
this.loaded = false;
|
||||
|
||||
this.initMap();
|
||||
}
|
||||
|
||||
initMap() {
|
||||
const map = this.map_;
|
||||
const view = map.getView();
|
||||
const center = toLonLat(view.getCenter(), view.getProjection());
|
||||
|
||||
const options = assign(this.baseOptions, {
|
||||
attributionControl: false,
|
||||
boxZoom: false,
|
||||
center,
|
||||
container: map.getTargetElement(),
|
||||
doubleClickZoom: false,
|
||||
dragPan: false,
|
||||
dragRotate: false,
|
||||
interactive: false,
|
||||
keyboard: false,
|
||||
pitchWithRotate: false,
|
||||
scrollZoom: false,
|
||||
touchZoomRotate: false,
|
||||
zoom: view.getZoom() - 1
|
||||
});
|
||||
|
||||
this.mbmap = new mapboxgl.Map(options);
|
||||
|
||||
this.mbmap.on('load', function() {
|
||||
this.loaded = true;
|
||||
this.map_.render();
|
||||
this.mbmap.getContainer().querySelector('.mapboxgl-control-container').remove();
|
||||
}.bind(this));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @inheritDoc
|
||||
*/
|
||||
render(frameState) {
|
||||
const map = this.map_;
|
||||
const view = map.getView();
|
||||
|
||||
// adjust view parameters in mapbox
|
||||
const rotation = frameState.viewState.rotation;
|
||||
if (rotation) {
|
||||
this.mbmap.rotateTo(-rotation * 180 / Math.PI, {
|
||||
animate: false
|
||||
});
|
||||
}
|
||||
const center = toLonLat(view.getCenter(), view.getProjection());
|
||||
const zoom = view.getZoom() - 1;
|
||||
this.mbmap.jumpTo({
|
||||
center: center,
|
||||
zoom: zoom,
|
||||
animate: false
|
||||
});
|
||||
|
||||
// cancel the scheduled update & trigger synchronous redraw
|
||||
// see https://github.com/mapbox/mapbox-gl-js/issues/7893#issue-408992184
|
||||
// NOTE: THIS MIGHT BREAK WHEN UPDATING MAPBOX
|
||||
if (this.mbmap._frame) {
|
||||
this.mbmap._frame.cancel();
|
||||
this.mbmap._frame = null;
|
||||
}
|
||||
this.mbmap._render();
|
||||
|
||||
return this.mbmap.getCanvas();
|
||||
}
|
||||
|
||||
setVisible(visible) {
|
||||
super.setVisible(visible);
|
||||
|
||||
const canvas = this.mbmap.getCanvas();
|
||||
canvas.style.display = visible ? 'block' : 'none';
|
||||
}
|
||||
|
||||
setOpacity(opacity) {
|
||||
super.setOpacity(opacity);
|
||||
const canvas = this.mbmap.getCanvas();
|
||||
canvas.style.opacity = opacity;
|
||||
}
|
||||
|
||||
setZIndex(zindex) {
|
||||
super.setZIndex(zindex);
|
||||
const canvas = this.mbmap.getCanvas();
|
||||
canvas.style.zIndex = zindex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getSourceState() {
|
||||
return this.loaded ? SourceState.READY : SourceState.UNDEFINED;
|
||||
}
|
||||
|
||||
setMap(map) {
|
||||
this.map_ = map;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const style = new Style({
|
||||
stroke: new Stroke({
|
||||
color: '#319FD3',
|
||||
@@ -154,11 +34,71 @@ const map = new Map({
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
// init Mapbox object
|
||||
|
||||
const view = map.getView();
|
||||
const center = toLonLat(view.getCenter(), view.getProjection());
|
||||
const key = 'ER67WIiPdCQvhgsUjoWK';
|
||||
const mbLayer = new Mapbox({
|
||||
map: map,
|
||||
|
||||
const mbMap = new mapboxgl.Map({
|
||||
style: 'https://maps.tilehosting.com/styles/bright/style.json?key=' + key,
|
||||
attributionControl: false,
|
||||
boxZoom: false,
|
||||
center: center,
|
||||
container: map.getTargetElement(),
|
||||
doubleClickZoom: false,
|
||||
dragPan: false,
|
||||
dragRotate: false,
|
||||
interactive: false,
|
||||
keyboard: false,
|
||||
pitchWithRotate: false,
|
||||
scrollZoom: false,
|
||||
touchZoomRotate: false,
|
||||
zoom: view.getZoom() - 1
|
||||
});
|
||||
|
||||
|
||||
// init OL layers
|
||||
|
||||
const mbLayer = new Layer({
|
||||
container: map.getTarget(),
|
||||
style: 'https://maps.tilehosting.com/styles/bright/style.json?key=' + key
|
||||
render: function(frameState) {
|
||||
const canvas = mbMap.getCanvas();
|
||||
const view = map.getView();
|
||||
|
||||
const visible = mbLayer.getVisible();
|
||||
canvas.style.display = visible ? 'block' : 'none';
|
||||
|
||||
const opacity = mbLayer.getOpacity();
|
||||
canvas.style.opacity = opacity;
|
||||
|
||||
// adjust view parameters in mapbox
|
||||
const rotation = frameState.viewState.rotation;
|
||||
if (rotation) {
|
||||
mbMap.rotateTo(-rotation * 180 / Math.PI, {
|
||||
animate: false
|
||||
});
|
||||
}
|
||||
const center = toLonLat(view.getCenter(), view.getProjection());
|
||||
const zoom = view.getZoom() - 1;
|
||||
mbMap.jumpTo({
|
||||
center: center,
|
||||
zoom: zoom,
|
||||
animate: false
|
||||
});
|
||||
|
||||
// cancel the scheduled update & trigger synchronous redraw
|
||||
// see https://github.com/mapbox/mapbox-gl-js/issues/7893#issue-408992184
|
||||
// NOTE: THIS MIGHT BREAK WHEN UPDATING MAPBOX
|
||||
if (mbMap._frame) {
|
||||
mbMap._frame.cancel();
|
||||
mbMap._frame = null;
|
||||
}
|
||||
mbMap._render();
|
||||
|
||||
return canvas;
|
||||
}
|
||||
});
|
||||
|
||||
map.addLayer(mbLayer);
|
||||
|
||||
@@ -10,6 +10,10 @@ import {assign} from '../obj.js';
|
||||
import RenderEventType from '../render/EventType.js';
|
||||
import SourceState from '../source/State.js';
|
||||
|
||||
/**
|
||||
* @typedef {function(import("../PluggableMap.js").FrameState):HTMLElement} RenderFunction
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
@@ -29,6 +33,8 @@ import SourceState from '../source/State.js';
|
||||
* the source can be set by calling {@link module:ol/layer/Layer#setSource layer.setSource(source)} after
|
||||
* construction.
|
||||
* @property {import("../PluggableMap.js").default} [map] Map.
|
||||
* @property {RenderFunction} [render] Render function. Takes the frame state as input and is expected to return an
|
||||
* HTML element. Will overwrite the default rendering for the layer.
|
||||
*/
|
||||
|
||||
|
||||
@@ -47,8 +53,10 @@ import SourceState from '../source/State.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Base class from which all layer types are derived. This should only be instantiated
|
||||
* in the case where a custom layer is be added to the map with a custom `render` function.
|
||||
* Such a function can be specified in the `options` object, and is expected to return an HTML element.
|
||||
*
|
||||
* A visual representation of raster or vector map data.
|
||||
* Layers group together those properties that pertain to how the data is to be
|
||||
* displayed, irrespective of the source of that data.
|
||||
@@ -64,6 +72,7 @@ import SourceState from '../source/State.js';
|
||||
* @fires import("../render/Event.js").RenderEvent#postrender
|
||||
*
|
||||
* @template {import("../source/Source.js").default} SourceType
|
||||
* @api
|
||||
*/
|
||||
class Layer extends BaseLayer {
|
||||
/**
|
||||
@@ -100,6 +109,11 @@ class Layer extends BaseLayer {
|
||||
*/
|
||||
this.renderer_ = null;
|
||||
|
||||
// Overwrite default render method with a custom one
|
||||
if (options.render) {
|
||||
this.render = options.render;
|
||||
}
|
||||
|
||||
if (options.map) {
|
||||
this.setMap(options.map);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,8 @@ class CompositeMapRenderer extends MapRenderer {
|
||||
this.children_.length = 0;
|
||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||
const layerState = layerStatesArray[i];
|
||||
if (!visibleAtResolution(layerState, viewResolution) || layerState.sourceState != SourceState.READY) {
|
||||
if (!visibleAtResolution(layerState, viewResolution) ||
|
||||
(layerState.sourceState != SourceState.READY && layerState.sourceState != SourceState.UNDEFINED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,16 @@ describe('ol.layer.Layer', function() {
|
||||
layer.dispose();
|
||||
});
|
||||
|
||||
it('accepts a custom render function', function() {
|
||||
let called = false;
|
||||
const layer = new Layer({
|
||||
render: function() {
|
||||
called = true;
|
||||
}
|
||||
});
|
||||
layer.render();
|
||||
expect(called).to.eql(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('visibleAtResolution', function() {
|
||||
|
||||
Reference in New Issue
Block a user