Merge pull request #4278 from ahocevar/css-box
Use DOM instead of map canvas for ol.render.Box
This commit is contained in:
@@ -2,6 +2,35 @@
|
||||
|
||||
### v3.11.0
|
||||
|
||||
#### `ol.interaction.DragBox` and `ol.interaction.DragZoom` changes
|
||||
|
||||
Styling is no longer done with `ol.Style`, but with pure CSS. The `style` constructor option is no longer required, and no longer available. Instead, there is a `className` option for the CSS selector. The default for `ol.interaction.DragBox` is `ol-dragbox`, and `ol.interaction.DragZoom` uses `ol-dragzoom`. If you previously had
|
||||
```js
|
||||
new ol.interaction.DragZoom({
|
||||
style: new ol.style.Style({
|
||||
stroke: new ol.style.Stroke({
|
||||
color: 'red',
|
||||
width: 3
|
||||
}),
|
||||
fill: new ol.style.Fill({
|
||||
color: [255, 255, 255, 0.4]
|
||||
})
|
||||
})
|
||||
});
|
||||
```
|
||||
you'll now just need
|
||||
```js
|
||||
new ol.interaction.DragZoom();
|
||||
```
|
||||
but with additional css:
|
||||
```css
|
||||
.ol-dragzoom {
|
||||
border-color: red;
|
||||
border-width: 3px;
|
||||
background-color: rgba(255,255,255,0.4);
|
||||
}
|
||||
```
|
||||
|
||||
### v3.10.0
|
||||
|
||||
#### `ol.layer.Layer` changes
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
.ol-box {
|
||||
box-sizing: border-box;
|
||||
border-radius: 2px;
|
||||
border: 2px solid blue;
|
||||
}
|
||||
|
||||
.ol-mouse-position {
|
||||
top: 8px;
|
||||
|
||||
4
examples/box-selection.css
Normal file
4
examples/box-selection.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.ol-dragbox {
|
||||
background-color: rgba(255,255,255,0.4);
|
||||
border-color: rgba(100,150,0,1);
|
||||
}
|
||||
@@ -8,9 +8,6 @@ goog.require('ol.layer.Tile');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.source.OSM');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.style.Fill');
|
||||
goog.require('ol.style.Stroke');
|
||||
goog.require('ol.style.Style');
|
||||
|
||||
|
||||
var vectorSource = new ol.source.Vector({
|
||||
@@ -44,15 +41,7 @@ var selectedFeatures = select.getFeatures();
|
||||
|
||||
// a DragBox interaction used to select features by drawing boxes
|
||||
var dragBox = new ol.interaction.DragBox({
|
||||
condition: ol.events.condition.platformModifierKeyOnly,
|
||||
style: new ol.style.Style({
|
||||
fill: new ol.style.Fill({
|
||||
color: [255, 255, 255, 0.4]
|
||||
}),
|
||||
stroke: new ol.style.Stroke({
|
||||
color: [100, 150, 0, 1]
|
||||
})
|
||||
})
|
||||
condition: ol.events.condition.platformModifierKeyOnly
|
||||
});
|
||||
|
||||
map.addInteraction(dragBox);
|
||||
|
||||
@@ -2281,13 +2281,21 @@ olx.interaction.DragAndDropOptions.prototype.projection;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{condition: (ol.events.ConditionType|undefined),
|
||||
* style: ol.style.Style}}
|
||||
* @typedef {{className: (string|undefined),
|
||||
* condition: (ol.events.ConditionType|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.DragBoxOptions;
|
||||
|
||||
|
||||
/**
|
||||
* CSS class name for styling the box. The default is `ol-dragbox`.
|
||||
* @type {string|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.DragBoxOptions.prototype.className;
|
||||
|
||||
|
||||
/**
|
||||
* A function that takes an {@link ol.MapBrowserEvent} and returns a boolean
|
||||
* to indicate whether that event should be handled.
|
||||
@@ -2298,14 +2306,6 @@ olx.interaction.DragBoxOptions;
|
||||
olx.interaction.DragBoxOptions.prototype.condition;
|
||||
|
||||
|
||||
/**
|
||||
* Style for the box.
|
||||
* @type {ol.style.Style}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.DragBoxOptions.prototype.style;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{kinetic: (ol.Kinetic|undefined)}}
|
||||
* @api
|
||||
@@ -2374,14 +2374,22 @@ olx.interaction.DragRotateOptions.prototype.duration;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{condition: (ol.events.ConditionType|undefined),
|
||||
* duration: (number|undefined),
|
||||
* style: (ol.style.Style|undefined)}}
|
||||
* @typedef {{className: (string|undefined),
|
||||
* condition: (ol.events.ConditionType|undefined),
|
||||
* duration: (number|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.DragZoomOptions;
|
||||
|
||||
|
||||
/**
|
||||
* CSS class name for styling the box. The default is `ol-dragzoom`.
|
||||
* @type {string|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.DragZoomOptions.prototype.className;
|
||||
|
||||
|
||||
/**
|
||||
* A function that takes an {@link ol.MapBrowserEvent} and returns a boolean
|
||||
* to indicate whether that event should be handled.
|
||||
@@ -2400,14 +2408,6 @@ olx.interaction.DragZoomOptions.prototype.condition;
|
||||
olx.interaction.DragZoomOptions.prototype.duration;
|
||||
|
||||
|
||||
/**
|
||||
* Style for the box.
|
||||
* @type {ol.style.Style|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.DragZoomOptions.prototype.style;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{clickTolerance: (number|undefined),
|
||||
* features: (ol.Collection.<ol.Feature>|undefined),
|
||||
@@ -5995,7 +5995,7 @@ olx.style.TextOptions.prototype.rotation;
|
||||
|
||||
|
||||
/**
|
||||
* Text content.
|
||||
* Text content.
|
||||
* @type {string|undefined}
|
||||
* @api
|
||||
*/
|
||||
@@ -6003,7 +6003,7 @@ olx.style.TextOptions.prototype.text;
|
||||
|
||||
|
||||
/**
|
||||
* Text alignment. Possible values: 'left', 'right', 'center', 'end' or 'start'.
|
||||
* Text alignment. Possible values: 'left', 'right', 'center', 'end' or 'start'.
|
||||
* Default is 'start'.
|
||||
* @type {string|undefined}
|
||||
* @api
|
||||
@@ -6012,7 +6012,7 @@ olx.style.TextOptions.prototype.textAlign;
|
||||
|
||||
|
||||
/**
|
||||
* Text base line. Possible values: 'bottom', 'top', 'middle', 'alphabetic',
|
||||
* Text base line. Possible values: 'bottom', 'top', 'middle', 'alphabetic',
|
||||
* 'hanging', 'ideographic'. Default is 'alphabetic'.
|
||||
* @type {string|undefined}
|
||||
* @api
|
||||
|
||||
@@ -93,17 +93,11 @@ ol.interaction.DragBox = function(opt_options) {
|
||||
|
||||
var options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Style}
|
||||
*/
|
||||
var style = options.style ? options.style : null;
|
||||
|
||||
/**
|
||||
* @type {ol.render.Box}
|
||||
* @private
|
||||
*/
|
||||
this.box_ = new ol.render.Box(style);
|
||||
this.box_ = new ol.render.Box(options.className || 'ol-dragbox');
|
||||
|
||||
/**
|
||||
* @type {ol.Pixel}
|
||||
|
||||
@@ -6,8 +6,6 @@ goog.require('ol.easing');
|
||||
goog.require('ol.events.condition');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.interaction.DragBox');
|
||||
goog.require('ol.style.Stroke');
|
||||
goog.require('ol.style.Style');
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +15,9 @@ goog.require('ol.style.Style');
|
||||
* normally combined with an {@link ol.events.condition} that limits
|
||||
* it to when a key, shift by default, is held down.
|
||||
*
|
||||
* To change the style of the box, use CSS and the `.ol-dragzoom` selector, or
|
||||
* your custom one configured with `className`.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.interaction.DragBox}
|
||||
* @param {olx.interaction.DragZoomOptions=} opt_options Options.
|
||||
@@ -34,20 +35,9 @@ ol.interaction.DragZoom = function(opt_options) {
|
||||
*/
|
||||
this.duration_ = options.duration !== undefined ? options.duration : 200;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Style}
|
||||
*/
|
||||
var style = options.style ?
|
||||
options.style : new ol.style.Style({
|
||||
stroke: new ol.style.Stroke({
|
||||
color: [0, 0, 255, 1]
|
||||
})
|
||||
});
|
||||
|
||||
goog.base(this, {
|
||||
condition: condition,
|
||||
style: style
|
||||
className: options.className || 'ol-dragzoom'
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
@@ -4,18 +4,30 @@ goog.provide('ol.render.Box');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.render.EventType');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
* @param {ol.style.Style} style Style.
|
||||
* @param {string} className CSS class name.
|
||||
*/
|
||||
ol.render.Box = function(style) {
|
||||
ol.render.Box = function(className) {
|
||||
|
||||
/**
|
||||
* @type {ol.geom.Polygon}
|
||||
* @private
|
||||
*/
|
||||
this.geometry_ = null;
|
||||
|
||||
/**
|
||||
* @type {HTMLDivElement}
|
||||
* @private
|
||||
*/
|
||||
this.element_ = /** @type {HTMLDivElement} */ (document.createElement('div'));
|
||||
this.element_.style.position = 'absolute';
|
||||
this.element_.className = 'ol-box ' + className;
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -23,12 +35,6 @@ ol.render.Box = function(style) {
|
||||
*/
|
||||
this.map_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.events.Key}
|
||||
*/
|
||||
this.postComposeListenerKey_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Pixel}
|
||||
@@ -41,27 +47,68 @@ ol.render.Box = function(style) {
|
||||
*/
|
||||
this.endPixel_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.geom.Polygon}
|
||||
*/
|
||||
this.geometry_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.style.Style}
|
||||
*/
|
||||
this.style_ = style;
|
||||
|
||||
};
|
||||
goog.inherits(ol.render.Box, goog.Disposable);
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @return {ol.geom.Polygon} Geometry.
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.Box.prototype.createGeometry_ = function() {
|
||||
ol.render.Box.prototype.disposeInternal = function() {
|
||||
this.setMap(null);
|
||||
goog.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.render.Box.prototype.render_ = function() {
|
||||
var startPixel = this.startPixel_;
|
||||
var endPixel = this.endPixel_;
|
||||
goog.asserts.assert(startPixel, 'this.startPixel_ must be truthy');
|
||||
goog.asserts.assert(endPixel, 'this.endPixel_ must be truthy');
|
||||
var px = 'px';
|
||||
var style = this.element_.style;
|
||||
style.left = Math.min(startPixel[0], endPixel[0]) + px;
|
||||
style.top = Math.min(startPixel[1], endPixel[1]) + px;
|
||||
style.width = Math.abs(endPixel[0] - startPixel[0]) + px;
|
||||
style.height = Math.abs(endPixel[1] - startPixel[1]) + px;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
*/
|
||||
ol.render.Box.prototype.setMap = function(map) {
|
||||
if (this.map_) {
|
||||
this.map_.getViewport().removeChild(this.element_);
|
||||
var style = this.element_.style;
|
||||
style.left = style.top = style.width = style.height = 'inherit';
|
||||
}
|
||||
this.map_ = map;
|
||||
if (this.map_) {
|
||||
this.map_.getViewport().appendChild(this.element_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Pixel} startPixel Start pixel.
|
||||
* @param {ol.Pixel} endPixel End pixel.
|
||||
*/
|
||||
ol.render.Box.prototype.setPixels = function(startPixel, endPixel) {
|
||||
this.startPixel_ = startPixel;
|
||||
this.endPixel_ = endPixel;
|
||||
this.createOrUpdateGeometry();
|
||||
this.render_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates or updates the cached geometry.
|
||||
*/
|
||||
ol.render.Box.prototype.createOrUpdateGeometry = function() {
|
||||
goog.asserts.assert(this.startPixel_,
|
||||
'this.startPixel_ must be truthy');
|
||||
goog.asserts.assert(this.endPixel_,
|
||||
@@ -78,33 +125,11 @@ ol.render.Box.prototype.createGeometry_ = function() {
|
||||
var coordinates = pixels.map(this.map_.getCoordinateFromPixel, this.map_);
|
||||
// close the polygon
|
||||
coordinates[4] = coordinates[0].slice();
|
||||
return new ol.geom.Polygon([coordinates]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.render.Box.prototype.disposeInternal = function() {
|
||||
this.setMap(null);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.render.Event} event Event.
|
||||
* @private
|
||||
*/
|
||||
ol.render.Box.prototype.handleMapPostCompose_ = function(event) {
|
||||
var geometry = this.geometry_;
|
||||
goog.asserts.assert(geometry, 'geometry should be defined');
|
||||
var style = this.style_;
|
||||
goog.asserts.assert(style, 'style must be truthy');
|
||||
// use drawAsync(Infinity) to draw above everything
|
||||
event.vectorContext.drawAsync(Infinity, function(render) {
|
||||
render.setFillStrokeStyle(style.getFill(), style.getStroke());
|
||||
render.setTextStyle(style.getText());
|
||||
render.drawPolygonGeometry(geometry, null);
|
||||
});
|
||||
if (!this.geometry_) {
|
||||
this.geometry_ = new ol.geom.Polygon([coordinates]);
|
||||
} else {
|
||||
this.geometry_.setCoordinates([coordinates]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -114,45 +139,3 @@ ol.render.Box.prototype.handleMapPostCompose_ = function(event) {
|
||||
ol.render.Box.prototype.getGeometry = function() {
|
||||
return this.geometry_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.render.Box.prototype.requestMapRenderFrame_ = function() {
|
||||
if (this.map_ && this.startPixel_ && this.endPixel_) {
|
||||
this.map_.render();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
*/
|
||||
ol.render.Box.prototype.setMap = function(map) {
|
||||
if (this.postComposeListenerKey_) {
|
||||
goog.events.unlistenByKey(this.postComposeListenerKey_);
|
||||
this.postComposeListenerKey_ = null;
|
||||
this.map_.render();
|
||||
this.map_ = null;
|
||||
}
|
||||
this.map_ = map;
|
||||
if (this.map_) {
|
||||
this.postComposeListenerKey_ = goog.events.listen(
|
||||
map, ol.render.EventType.POSTCOMPOSE, this.handleMapPostCompose_, false,
|
||||
this);
|
||||
this.requestMapRenderFrame_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Pixel} startPixel Start pixel.
|
||||
* @param {ol.Pixel} endPixel End pixel.
|
||||
*/
|
||||
ol.render.Box.prototype.setPixels = function(startPixel, endPixel) {
|
||||
this.startPixel_ = startPixel;
|
||||
this.endPixel_ = endPixel;
|
||||
this.geometry_ = this.createGeometry_();
|
||||
this.requestMapRenderFrame_();
|
||||
};
|
||||
|
||||
@@ -43,6 +43,14 @@ describe('ol.interaction.DragZoom', function() {
|
||||
var instance = new ol.interaction.DragZoom();
|
||||
expect(instance).to.be.an(ol.interaction.DragZoom);
|
||||
});
|
||||
it('sets "ol-dragzoom" as box className', function() {
|
||||
var instance = new ol.interaction.DragZoom();
|
||||
expect(instance.box_.element_.className).to.be('ol-box ol-dragzoom');
|
||||
});
|
||||
it('sets a custom box className', function() {
|
||||
var instance = new ol.interaction.DragZoom({className: 'test-dragzoom'});
|
||||
expect(instance.box_.element_.className).to.be('ol-box test-dragzoom');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
65
test/spec/ol/render/box.test.js
Normal file
65
test/spec/ol/render/box.test.js
Normal file
@@ -0,0 +1,65 @@
|
||||
goog.provide('ol.test.render.Box');
|
||||
|
||||
describe('ol.render.Box', function() {
|
||||
|
||||
var box, map, target;
|
||||
|
||||
beforeEach(function() {
|
||||
box = new ol.render.Box('test-box');
|
||||
|
||||
target = document.createElement('div');
|
||||
document.body.appendChild(target);
|
||||
|
||||
map = new ol.Map({
|
||||
target: target,
|
||||
view: new ol.View({
|
||||
center: [0, 0],
|
||||
zoom: 0
|
||||
})
|
||||
});
|
||||
map.renderSync();
|
||||
box.setMap(map);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
goog.dispose(map);
|
||||
document.body.removeChild(target);
|
||||
});
|
||||
|
||||
describe('Constructor', function() {
|
||||
it('creates an absolutely positioned DIV with a className', function() {
|
||||
expect(box.element_).to.be.a(HTMLDivElement);
|
||||
expect(box.element_.style.position).to.be('absolute');
|
||||
expect(box.element_.className).to.be('ol-box test-box');
|
||||
expect(box.element_.style.position).to.be('absolute');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setPixels()', function() {
|
||||
it('applies correct styles for a box', function() {
|
||||
box.setPixels([1, 2], [4, 8]);
|
||||
expect(box.element_.style.left).to.be('1px');
|
||||
expect(box.element_.style.top).to.be('2px');
|
||||
expect(box.element_.style.width).to.be('3px');
|
||||
expect(box.element_.style.height).to.be('6px');
|
||||
});
|
||||
it('applies correct styles for a flipped box', function() {
|
||||
box.setPixels([4, 8], [1, 2]);
|
||||
expect(box.element_.style.left).to.be('1px');
|
||||
expect(box.element_.style.top).to.be('2px');
|
||||
expect(box.element_.style.width).to.be('3px');
|
||||
expect(box.element_.style.height).to.be('6px');
|
||||
});
|
||||
it('creates a polygon geometry', function() {
|
||||
expect(box.getGeometry()).to.be(null);
|
||||
box.setPixels([1, 2], [3, 4]);
|
||||
expect(box.getGeometry()).to.be.a(ol.geom.Polygon);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.render.Box');
|
||||
Reference in New Issue
Block a user