Merge pull request #8499 from ahocevar/focus

Round center in viewState to pixels
This commit is contained in:
Andreas Hocevar
2018-08-16 16:41:15 +02:00
committed by GitHub
23 changed files with 175 additions and 218 deletions

View File

@@ -1,5 +1,15 @@
## Upgrade notes
### Next version
#### Removal of the `snapToPixel` option for `ol/style/Image` subclasses
The `snapToPixel` option has been removed, and the `getSnapToPixel` and `setSnapToPixel` methods are deprecated.
The renderer now snaps to integer pixels when no interaction or animation is running to get crisp rendering. During interaction or animation, it does not snap to integer pixels to avoid jitter.
When rendering with the Immediate API, symbols will no longer be snapped to integer pixels. To get crisp images, set `context.imageSmoothingEnabled = false` before rendering with the Immediate API, and `context.imageSmoothingEnabled = true` afterwards.
### v5.1.0
#### Geometry constructor and `setCoordinates` no longer accept `null` coordinates

View File

@@ -22,7 +22,6 @@ const map = new Map({
const imageStyle = new Style({
image: new CircleStyle({
radius: 5,
snapToPixel: false,
fill: new Fill({color: 'yellow'}),
stroke: new Stroke({color: 'red', width: 1})
})
@@ -31,7 +30,6 @@ const imageStyle = new Style({
const headInnerImageStyle = new Style({
image: new CircleStyle({
radius: 2,
snapToPixel: false,
fill: new Fill({color: 'blue'})
})
});
@@ -39,7 +37,6 @@ const headInnerImageStyle = new Style({
const headOuterImageStyle = new Style({
image: new CircleStyle({
radius: 5,
snapToPixel: false,
fill: new Fill({color: 'black'})
})
});

View File

@@ -65,7 +65,6 @@ function flash(feature) {
const style = new Style({
image: new CircleStyle({
radius: radius,
snapToPixel: false,
stroke: new Stroke({
color: 'rgba(255, 0, 0, ' + opacity + ')',
width: 0.25 + opacity

View File

@@ -94,7 +94,6 @@ const styles = {
'geoMarker': new Style({
image: new CircleStyle({
radius: 7,
snapToPixel: false,
fill: new Fill({color: 'black'}),
stroke: new Stroke({
color: 'white', width: 2

View File

@@ -1,7 +1,7 @@
---
layout: example.html
title: Street Labels
shortdesc: Render street names with a custom render.
shortdesc: Render street names.
docs: >
Example showing the use of a text style with `placement: 'line'` to render text along a path.
tags: "vector, label, streets"

View File

@@ -1179,19 +1179,12 @@ class PluggableMap extends BaseObject {
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
layerStates[getUid(layerStatesArray[i].layer)] = layerStatesArray[i];
}
viewState = view.getState();
let focus = this.focus_;
if (!focus) {
focus = viewState.center;
const pixelResolution = viewState.resolution / this.pixelRatio_;
focus[0] = Math.round(focus[0] / pixelResolution) * pixelResolution;
focus[1] = Math.round(focus[1] / pixelResolution) * pixelResolution;
}
viewState = view.getState(this.pixelRatio_);
frameState = /** @type {module:ol/PluggableMap~FrameState} */ ({
animate: false,
coordinateToPixelTransform: this.coordinateToPixelTransform_,
extent: extent,
focus: focus,
focus: this.focus_ ? this.focus_ : viewState.center,
index: this.frameIndex_++,
layerStates: layerStates,
layerStatesArray: layerStatesArray,

View File

@@ -894,16 +894,21 @@ class View extends BaseObject {
}
/**
* @param {number} pixelRatio Pixel ratio for center rounding.
* @return {module:ol/View~State} View state.
*/
getState() {
getState(pixelRatio) {
const center = /** @type {module:ol/coordinate~Coordinate} */ (this.getCenter());
const projection = this.getProjection();
const resolution = /** @type {number} */ (this.getResolution());
const pixelResolution = resolution / pixelRatio;
const rotation = this.getRotation();
return (
/** @type {module:ol/View~State} */ ({
center: center.slice(),
center: [
Math.round(center[0] / pixelResolution) * pixelResolution,
Math.round(center[1] / pixelResolution) * pixelResolution
],
projection: projection !== undefined ? projection : null,
resolution: resolution,
rotation: rotation,

View File

@@ -54,6 +54,11 @@ class DragPan extends PointerInteraction {
*/
this.lastPointersCount_;
/**
* @type {boolean}
*/
this.panning_ = false;
/**
* @private
* @type {module:ol/events/condition~Condition}
@@ -76,6 +81,10 @@ class DragPan extends PointerInteraction {
* @this {module:ol/interaction/DragPan}
*/
function handleDragEvent(mapBrowserEvent) {
if (!this.panning_) {
this.panning_ = true;
this.getMap().getView().setHint(ViewHint.INTERACTING, 1);
}
const targetPointers = this.targetPointers;
const centroid = centroidFromPointers(targetPointers);
if (targetPointers.length == this.lastPointersCount_) {
@@ -128,7 +137,10 @@ function handleUpEvent(mapBrowserEvent) {
easing: easeOut
});
}
view.setHint(ViewHint.INTERACTING, -1);
if (this.panning_) {
this.panning_ = false;
view.setHint(ViewHint.INTERACTING, -1);
}
return false;
} else {
if (this.kinetic_) {
@@ -152,9 +164,6 @@ function handleDownEvent(mapBrowserEvent) {
const map = mapBrowserEvent.map;
const view = map.getView();
this.lastCentroid = null;
if (!this.handlingDownUpSequence) {
view.setHint(ViewHint.INTERACTING, 1);
}
// stop any current animation
if (view.getAnimating()) {
view.setCenter(mapBrowserEvent.frameState.viewState.center);

View File

@@ -88,12 +88,6 @@ class CanvasImageReplay extends CanvasReplay {
*/
this.scale_ = undefined;
/**
* @private
* @type {boolean|undefined}
*/
this.snapToPixel_ = undefined;
/**
* @private
* @type {number|undefined}
@@ -131,14 +125,14 @@ class CanvasImageReplay extends CanvasReplay {
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
this.scale_ * this.pixelRatio, this.snapToPixel_, this.width_
this.scale_ * this.pixelRatio, this.width_
]);
this.hitDetectionInstructions.push([
CanvasInstruction.DRAW_IMAGE, myBegin, myEnd, this.hitDetectionImage_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
this.scale_, this.snapToPixel_, this.width_
this.scale_, this.width_
]);
this.endGeometry(pointGeometry, feature);
}
@@ -161,14 +155,14 @@ class CanvasImageReplay extends CanvasReplay {
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
this.scale_ * this.pixelRatio, this.snapToPixel_, this.width_
this.scale_ * this.pixelRatio, this.width_
]);
this.hitDetectionInstructions.push([
CanvasInstruction.DRAW_IMAGE, myBegin, myEnd, this.hitDetectionImage_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
this.scale_, this.snapToPixel_, this.width_
this.scale_, this.width_
]);
this.endGeometry(multiPointGeometry, feature);
}
@@ -190,7 +184,6 @@ class CanvasImageReplay extends CanvasReplay {
this.originY_ = undefined;
this.rotateWithView_ = undefined;
this.rotation_ = undefined;
this.snapToPixel_ = undefined;
this.width_ = undefined;
}
@@ -215,7 +208,6 @@ class CanvasImageReplay extends CanvasReplay {
this.rotateWithView_ = imageStyle.getRotateWithView();
this.rotation_ = imageStyle.getRotation();
this.scale_ = imageStyle.getScale();
this.snapToPixel_ = imageStyle.getSnapToPixel();
this.width_ = size[0];
}
}

View File

@@ -156,12 +156,6 @@ class CanvasImmediateRenderer extends VectorContext {
*/
this.imageScale_ = 0;
/**
* @private
* @type {boolean}
*/
this.imageSnapToPixel_ = false;
/**
* @private
* @type {number}
@@ -261,12 +255,8 @@ class CanvasImmediateRenderer extends VectorContext {
rotation += this.viewRotation_;
}
for (let i = 0, ii = pixelCoordinates.length; i < ii; i += 2) {
let x = pixelCoordinates[i] - this.imageAnchorX_;
let y = pixelCoordinates[i + 1] - this.imageAnchorY_;
if (this.imageSnapToPixel_) {
x = Math.round(x);
y = Math.round(y);
}
const x = pixelCoordinates[i] - this.imageAnchorX_;
const y = pixelCoordinates[i + 1] - this.imageAnchorY_;
if (rotation !== 0 || this.imageScale_ != 1) {
const centerX = x + this.imageAnchorX_;
const centerY = y + this.imageAnchorY_;
@@ -856,7 +846,6 @@ class CanvasImmediateRenderer extends VectorContext {
this.imageRotateWithView_ = imageStyle.getRotateWithView();
this.imageRotation_ = imageStyle.getRotation();
this.imageScale_ = imageStyle.getScale() * this.pixelRatio_;
this.imageSnapToPixel_ = imageStyle.getSnapToPixel();
this.imageWidth_ = imageSize[0];
}
}

View File

@@ -533,6 +533,7 @@ class CanvasReplay extends VectorContext {
* @param {Object<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
* @param {Array<*>} instructions Instructions array.
* @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
* @param {function((module:ol/Feature|module:ol/render/Feature)): T|undefined} featureCallback Feature callback.
* @param {module:ol/extent~Extent=} opt_hitExtent Only check features that intersect this
* extent.
@@ -544,6 +545,7 @@ class CanvasReplay extends VectorContext {
transform,
skippedFeaturesHash,
instructions,
snapToPixel,
featureCallback,
opt_hitExtent
) {
@@ -672,14 +674,13 @@ class CanvasReplay extends VectorContext {
const rotateWithView = /** @type {boolean} */ (instruction[11]);
let rotation = /** @type {number} */ (instruction[12]);
const scale = /** @type {number} */ (instruction[13]);
const snapToPixel = /** @type {boolean} */ (instruction[14]);
const width = /** @type {number} */ (instruction[15]);
const width = /** @type {number} */ (instruction[14]);
let padding, backgroundFill, backgroundStroke;
if (instruction.length > 16) {
padding = /** @type {Array<number>} */ (instruction[16]);
backgroundFill = /** @type {boolean} */ (instruction[17]);
backgroundStroke = /** @type {boolean} */ (instruction[18]);
padding = /** @type {Array<number>} */ (instruction[15]);
backgroundFill = /** @type {boolean} */ (instruction[16]);
backgroundStroke = /** @type {boolean} */ (instruction[17]);
} else {
padding = defaultPadding;
backgroundFill = backgroundStroke = false;
@@ -853,11 +854,12 @@ class CanvasReplay extends VectorContext {
* @param {number} viewRotation View rotation.
* @param {Object<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
* @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
*/
replay(context, transform, viewRotation, skippedFeaturesHash) {
replay(context, transform, viewRotation, skippedFeaturesHash, snapToPixel) {
this.viewRotation_ = viewRotation;
this.replay_(context, transform,
skippedFeaturesHash, this.instructions, undefined, undefined);
skippedFeaturesHash, this.instructions, snapToPixel, undefined, undefined);
}
/**
@@ -883,7 +885,7 @@ class CanvasReplay extends VectorContext {
) {
this.viewRotation_ = viewRotation;
return this.replay_(context, transform, skippedFeaturesHash,
this.hitDetectionInstructions, opt_featureCallback, opt_hitExtent);
this.hitDetectionInstructions, true, opt_featureCallback, opt_hitExtent);
}
/**

View File

@@ -353,6 +353,7 @@ class CanvasReplayGroup extends ReplayGroup {
* @param {module:ol/transform~Transform} transform Transform.
* @param {number} viewRotation View rotation.
* @param {Object<string, boolean>} skippedFeaturesHash Ids of features to skip.
* @param {boolean} snapToPixel Snap point symbols and test to integer pixel.
* @param {Array<module:ol/render/ReplayType>=} opt_replayTypes Ordered replay types to replay.
* Default is {@link module:ol/render/replay~ORDER}
* @param {Object<string, module:ol/render/canvas~DeclutterGroup>=} opt_declutterReplays Declutter replays.
@@ -362,6 +363,7 @@ class CanvasReplayGroup extends ReplayGroup {
transform,
viewRotation,
skippedFeaturesHash,
snapToPixel,
opt_replayTypes,
opt_declutterReplays
) {
@@ -393,7 +395,7 @@ class CanvasReplayGroup extends ReplayGroup {
declutter.push(replay, transform.slice(0));
}
} else {
replay.replay(context, transform, viewRotation, skippedFeaturesHash);
replay.replay(context, transform, viewRotation, skippedFeaturesHash, snapToPixel);
}
}
}
@@ -486,8 +488,9 @@ export function getCircleArray(radius) {
* @param {!Object<string, Array<*>>} declutterReplays Declutter replays.
* @param {CanvasRenderingContext2D} context Context.
* @param {number} rotation Rotation.
* @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
*/
export function replayDeclutter(declutterReplays, context, rotation) {
export function replayDeclutter(declutterReplays, context, rotation, snapToPixel) {
const zs = Object.keys(declutterReplays).map(Number).sort(numberSafeCompareFunction);
const skippedFeatureUids = {};
for (let z = 0, zz = zs.length; z < zz; ++z) {
@@ -495,7 +498,7 @@ export function replayDeclutter(declutterReplays, context, rotation) {
for (let i = 0, ii = replayData.length; i < ii;) {
const replay = replayData[i++];
const transform = replayData[i++];
replay.replay(context, transform, rotation, skippedFeatureUids);
replay.replay(context, transform, rotation, skippedFeatureUids, snapToPixel);
}
}
}

View File

@@ -337,7 +337,7 @@ class CanvasTextReplay extends CanvasReplay {
this.instructions.push([CanvasInstruction.DRAW_IMAGE, begin, end,
label, (anchorX - this.textOffsetX_) * pixelRatio, (anchorY - this.textOffsetY_) * pixelRatio,
this.declutterGroup_, label.height, 1, 0, 0, this.textRotateWithView_, this.textRotation_,
1, true, label.width,
1, label.width,
textState.padding == defaultPadding ?
defaultPadding : textState.padding.map(function(p) {
return p * pixelRatio;
@@ -347,7 +347,7 @@ class CanvasTextReplay extends CanvasReplay {
this.hitDetectionInstructions.push([CanvasInstruction.DRAW_IMAGE, begin, end,
label, (anchorX - this.textOffsetX_) * pixelRatio, (anchorY - this.textOffsetY_) * pixelRatio,
this.declutterGroup_, label.height, 1, 0, 0, this.textRotateWithView_, this.textRotation_,
1 / pixelRatio, true, label.width, textState.padding,
1 / pixelRatio, label.width, textState.padding,
!!textState.backgroundFill, !!textState.backgroundStroke
]);
}

View File

@@ -158,11 +158,13 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
replayContext.translate(drawOffsetX, drawOffsetY);
}
const viewHints = frameState.viewHints;
const snapToPixel = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
const width = frameState.size[0] * pixelRatio;
const height = frameState.size[1] * pixelRatio;
rotateAtOffset(replayContext, -rotation,
width / 2, height / 2);
replayGroup.replay(replayContext, transform, rotation, skippedFeatureUids);
replayGroup.replay(replayContext, transform, rotation, skippedFeatureUids, snapToPixel);
if (vectorSource.getWrapX() && projection.canWrapX() &&
!containsExtent(projectionExtent, extent)) {
let startX = extent[0];
@@ -173,7 +175,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
--world;
offsetX = worldWidth * world;
transform = this.getTransform(frameState, offsetX);
replayGroup.replay(replayContext, transform, rotation, skippedFeatureUids);
replayGroup.replay(replayContext, transform, rotation, skippedFeatureUids, snapToPixel);
startX += worldWidth;
}
world = 0;
@@ -182,7 +184,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
++world;
offsetX = worldWidth * world;
transform = this.getTransform(frameState, offsetX);
replayGroup.replay(replayContext, transform, rotation, skippedFeatureUids);
replayGroup.replay(replayContext, transform, rotation, skippedFeatureUids, snapToPixel);
startX -= worldWidth;
}
}

View File

@@ -4,6 +4,7 @@
import {getUid} from '../../util.js';
import LayerType from '../../LayerType.js';
import TileState from '../../TileState.js';
import ViewHint from '../../ViewHint.js';
import {createCanvasContext2D} from '../../dom.js';
import {listen, unlisten} from '../../events.js';
import EventType from '../../events/EventType.js';
@@ -341,6 +342,8 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
if (declutterReplays) {
this.declutterTree_.clear();
}
const viewHints = frameState.viewHints;
const snapToPixel = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);
const tiles = this.renderedTiles;
const tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
const clips = [];
@@ -390,14 +393,14 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
context.clip();
}
}
replayGroup.replay(context, transform, rotation, {}, replayTypes, declutterReplays);
replayGroup.replay(context, transform, rotation, {}, snapToPixel, replayTypes, declutterReplays);
context.restore();
clips.push(currentClip);
zs.push(currentZ);
}
}
if (declutterReplays) {
replayDeclutter(declutterReplays, context, rotation);
replayDeclutter(declutterReplays, context, rotation, snapToPixel);
}
if (rotation) {
rotateAtOffset(context, rotation,
@@ -466,7 +469,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
scaleTransform(transform, pixelScale, -pixelScale);
translateTransform(transform, -tileExtent[0], -tileExtent[3]);
const replayGroup = sourceTile.getReplayGroup(layer, tile.tileCoord.toString());
replayGroup.replay(context, transform, 0, {}, replays);
replayGroup.replay(context, transform, 0, {}, true, replays);
}
}
}

View File

@@ -9,10 +9,6 @@ import RegularShape from '../style/RegularShape.js';
* @typedef {Object} Options
* @property {module:ol/style/Fill} [fill] Fill style.
* @property {number} radius Circle radius.
* @property {boolean} [snapToPixel=true] If `true` integral numbers of pixels are used as the X and Y pixel coordinate
* when drawing the circle in the output canvas. If `false` fractional numbers may be used. Using `true` allows for
* "sharp" rendering (no blur), while using `false` allows for "accurate" rendering. Note that accuracy is important if
* the circle's position is animated. Without it, the circle may jitter noticeably.
* @property {module:ol/style/Stroke} [stroke] Stroke style.
* @property {module:ol/style/AtlasManager} [atlasManager] The atlas manager to use for this circle.
* When using WebGL it is recommended to use an atlas manager to avoid texture switching. If an atlas manager is given,
@@ -37,7 +33,6 @@ class CircleStyle extends RegularShape {
points: Infinity,
fill: options.fill,
radius: options.radius,
snapToPixel: options.snapToPixel,
stroke: options.stroke,
atlasManager: options.atlasManager
});
@@ -55,7 +50,6 @@ class CircleStyle extends RegularShape {
fill: this.getFill() ? this.getFill().clone() : undefined,
stroke: this.getStroke() ? this.getStroke().clone() : undefined,
radius: this.getRadius(),
snapToPixel: this.getSnapToPixel(),
atlasManager: this.atlasManager_
});
style.setOpacity(this.getOpacity());

View File

@@ -38,10 +38,6 @@ import ImageStyle from '../style/Image.js';
* `top-left` or `top-right`. Default is `top-left`.
* @property {number} [opacity=1] Opacity of the icon.
* @property {number} [scale=1] Scale.
* @property {boolean} [snapToPixel=true] If `true` integral numbers of pixels are used as the X and Y pixel coordinate
* when drawing the icon in the output canvas. If `false` fractional numbers may be used. Using `true` allows for
* "sharp" rendering (no blur), while using `false` allows for "accurate" rendering. Note that accuracy is important if
* the icon's position is animated. Without it, the icon may jitter noticeably.
* @property {boolean} [rotateWithView=false] Whether to rotate the icon with the view.
* @property {number} [rotation=0] Rotation in radians (positive rotation clockwise).
* @property {module:ol/size~Size} [size] Icon size in pixel. Can be used together with `offset` to define the
@@ -85,17 +81,10 @@ class Icon extends ImageStyle {
const rotateWithView = options.rotateWithView !== undefined ?
options.rotateWithView : false;
/**
* @type {boolean}
*/
const snapToPixel = options.snapToPixel !== undefined ?
options.snapToPixel : true;
super({
opacity: opacity,
rotation: rotation,
scale: scale,
snapToPixel: snapToPixel,
rotateWithView: rotateWithView
});
@@ -230,7 +219,6 @@ class Icon extends ImageStyle {
size: this.size_ !== null ? this.size_.slice() : undefined,
opacity: this.getOpacity(),
scale: this.getScale(),
snapToPixel: this.getSnapToPixel(),
rotation: this.getRotation(),
rotateWithView: this.getRotateWithView()
});

View File

@@ -9,7 +9,6 @@
* @property {boolean} rotateWithView
* @property {number} rotation
* @property {number} scale
* @property {boolean} snapToPixel
*/
@@ -27,208 +26,200 @@ class ImageStyle {
constructor(options) {
/**
* @private
* @type {number}
*/
* @private
* @type {number}
*/
this.opacity_ = options.opacity;
/**
* @private
* @type {boolean}
*/
* @private
* @type {boolean}
*/
this.rotateWithView_ = options.rotateWithView;
/**
* @private
* @type {number}
*/
* @private
* @type {number}
*/
this.rotation_ = options.rotation;
/**
* @private
* @type {number}
*/
* @private
* @type {number}
*/
this.scale_ = options.scale;
/**
* @private
* @type {boolean}
*/
this.snapToPixel_ = options.snapToPixel;
}
/**
* Get the symbolizer opacity.
* @return {number} Opacity.
* @api
*/
* Get the symbolizer opacity.
* @return {number} Opacity.
* @api
*/
getOpacity() {
return this.opacity_;
}
/**
* Determine whether the symbolizer rotates with the map.
* @return {boolean} Rotate with map.
* @api
*/
* Determine whether the symbolizer rotates with the map.
* @return {boolean} Rotate with map.
* @api
*/
getRotateWithView() {
return this.rotateWithView_;
}
/**
* Get the symoblizer rotation.
* @return {number} Rotation.
* @api
*/
* Get the symoblizer rotation.
* @return {number} Rotation.
* @api
*/
getRotation() {
return this.rotation_;
}
/**
* Get the symbolizer scale.
* @return {number} Scale.
* @api
*/
* Get the symbolizer scale.
* @return {number} Scale.
* @api
*/
getScale() {
return this.scale_;
}
/**
* Determine whether the symbolizer should be snapped to a pixel.
* @return {boolean} The symbolizer should snap to a pixel.
* @api
*/
* This method is deprecated and always returns false.
* @return {boolean} false.
* @deprecated
* @api
*/
getSnapToPixel() {
return this.snapToPixel_;
return false;
}
/**
* Get the anchor point in pixels. The anchor determines the center point for the
* symbolizer.
* @abstract
* @return {Array<number>} Anchor.
*/
* Get the anchor point in pixels. The anchor determines the center point for the
* symbolizer.
* @abstract
* @return {Array<number>} Anchor.
*/
getAnchor() {}
/**
* Get the image element for the symbolizer.
* @abstract
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} Image element.
*/
* Get the image element for the symbolizer.
* @abstract
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} Image element.
*/
getImage(pixelRatio) {}
/**
* @abstract
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} Image element.
*/
* @abstract
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} Image element.
*/
getHitDetectionImage(pixelRatio) {}
/**
* @abstract
* @return {module:ol/ImageState} Image state.
*/
* @abstract
* @return {module:ol/ImageState} Image state.
*/
getImageState() {}
/**
* @abstract
* @return {module:ol/size~Size} Image size.
*/
* @abstract
* @return {module:ol/size~Size} Image size.
*/
getImageSize() {}
/**
* @abstract
* @return {module:ol/size~Size} Size of the hit-detection image.
*/
* @abstract
* @return {module:ol/size~Size} Size of the hit-detection image.
*/
getHitDetectionImageSize() {}
/**
* Get the origin of the symbolizer.
* @abstract
* @return {Array<number>} Origin.
*/
* Get the origin of the symbolizer.
* @abstract
* @return {Array<number>} Origin.
*/
getOrigin() {}
/**
* Get the size of the symbolizer (in pixels).
* @abstract
* @return {module:ol/size~Size} Size.
*/
* Get the size of the symbolizer (in pixels).
* @abstract
* @return {module:ol/size~Size} Size.
*/
getSize() {}
/**
* Set the opacity.
*
* @param {number} opacity Opacity.
* @api
*/
* Set the opacity.
*
* @param {number} opacity Opacity.
* @api
*/
setOpacity(opacity) {
this.opacity_ = opacity;
}
/**
* Set whether to rotate the style with the view.
*
* @param {boolean} rotateWithView Rotate with map.
* @api
*/
* Set whether to rotate the style with the view.
*
* @param {boolean} rotateWithView Rotate with map.
* @api
*/
setRotateWithView(rotateWithView) {
this.rotateWithView_ = rotateWithView;
}
/**
* Set the rotation.
*
* @param {number} rotation Rotation.
* @api
*/
* Set the rotation.
*
* @param {number} rotation Rotation.
* @api
*/
setRotation(rotation) {
this.rotation_ = rotation;
}
/**
* Set the scale.
*
* @param {number} scale Scale.
* @api
*/
* Set the scale.
*
* @param {number} scale Scale.
* @api
*/
setScale(scale) {
this.scale_ = scale;
}
/**
* Set whether to snap the image to the closest pixel.
*
* @param {boolean} snapToPixel Snap to pixel?
* @api
*/
setSnapToPixel(snapToPixel) {
this.snapToPixel_ = snapToPixel;
}
* This method is deprecated and does nothing.
* @param {boolean} snapToPixel Snap to pixel?
* @deprecated
* @api
*/
setSnapToPixel(snapToPixel) {}
/**
* @abstract
* @param {function(this: T, module:ol/events/Event)} listener Listener function.
* @param {T} thisArg Value to use as `this` when executing `listener`.
* @return {module:ol/events~EventsKey|undefined} Listener key.
* @template T
*/
* @abstract
* @param {function(this: T, module:ol/events/Event)} listener Listener function.
* @param {T} thisArg Value to use as `this` when executing `listener`.
* @return {module:ol/events~EventsKey|undefined} Listener key.
* @template T
*/
listenImageChange(listener, thisArg) {}
/**
* Load not yet loaded URI.
* @abstract
*/
* Load not yet loaded URI.
* @abstract
*/
load() {}
/**
* @abstract
* @param {function(this: T, module:ol/events/Event)} listener Listener function.
* @param {T} thisArg Value to use as `this` when executing `listener`.
* @template T
*/
* @abstract
* @param {function(this: T, module:ol/events/Event)} listener Listener function.
* @param {T} thisArg Value to use as `this` when executing `listener`.
* @template T
*/
unlistenImageChange(listener, thisArg) {}
}

View File

@@ -20,10 +20,6 @@ import ImageStyle from '../style/Image.js';
* @property {number} [radius1] Outer radius of a star.
* @property {number} [radius2] Inner radius of a star.
* @property {number} [angle=0] Shape's angle in radians. A value of 0 will have one of the shape's point facing up.
* @property {boolean} [snapToPixel=true] If `true` integral numbers of pixels are used as the X and Y pixel coordinate
* when drawing the shape in the output canvas. If `false` fractional numbers may be used. Using `true` allows for
* "sharp" rendering (no blur), while using `false` allows for "accurate" rendering. Note that accuracy is important if
* the shape's position is animated. Without it, the shape may jitter noticeably.
* @property {module:ol/style/Stroke} [stroke] Stroke style.
* @property {number} [rotation=0] Rotation in radians (positive rotation clockwise).
* @property {boolean} [rotateWithView=false] Whether to rotate the shape with the view.
@@ -58,12 +54,6 @@ class RegularShape extends ImageStyle {
* @param {module:ol/style/RegularShape~Options} options Options.
*/
constructor(options) {
/**
* @type {boolean}
*/
const snapToPixel = options.snapToPixel !== undefined ?
options.snapToPixel : true;
/**
* @type {boolean}
*/
@@ -74,8 +64,7 @@ class RegularShape extends ImageStyle {
opacity: 1,
rotateWithView: rotateWithView,
rotation: options.rotation !== undefined ? options.rotation : 0,
scale: 1,
snapToPixel: snapToPixel
scale: 1
});
/**
@@ -185,7 +174,6 @@ class RegularShape extends ImageStyle {
radius: this.getRadius(),
radius2: this.getRadius2(),
angle: this.getAngle(),
snapToPixel: this.getSnapToPixel(),
stroke: this.getStroke() ? this.getStroke().clone() : undefined,
rotation: this.getRotation(),
rotateWithView: this.getRotateWithView(),

View File

@@ -280,7 +280,6 @@ describe('ol.rendering.layer.Tile', function() {
evt.element.on('render', function(e) {
e.vectorContext.setImageStyle(new CircleStyle({
radius: 5,
snapToPixel: false,
fill: new Fill({color: 'yellow'}),
stroke: new Stroke({color: 'red', width: 1})
}));

View File

@@ -91,8 +91,7 @@ describe('ol.style.Circle', function() {
stroke: new Stroke({
color: '#319FD3'
}),
radius: 5,
snapToPixel: false
radius: 5
});
original.setOpacity(0.5);
original.setScale(1.5);
@@ -101,7 +100,6 @@ describe('ol.style.Circle', function() {
expect(original.getOpacity()).to.eql(clone.getOpacity());
expect(original.getRadius()).to.eql(clone.getRadius());
expect(original.getScale()).to.eql(clone.getScale());
expect(original.getSnapToPixel()).to.eql(clone.getSnapToPixel());
expect(original.getStroke().getColor()).to.eql(clone.getStroke().getColor());
});

View File

@@ -61,7 +61,6 @@ describe('ol.style.Icon', function() {
offsetOrigin: 'bottom-left',
opacity: 0.5,
scale: 2,
snapToPixel: false,
rotation: 4,
size: [10, 12]
});
@@ -82,7 +81,6 @@ describe('ol.style.Icon', function() {
expect(original.getOpacity()).to.eql(clone.getOpacity());
expect(original.getRotation()).to.eql(clone.getRotation());
expect(original.getRotateWithView()).to.eql(clone.getRotateWithView());
expect(original.getSnapToPixel()).to.eql(clone.getSnapToPixel());
const original2 = new Icon({
src: src

View File

@@ -121,7 +121,6 @@ describe('ol.style.RegularShape', function() {
radius: 4,
radius2: 6,
angle: 1,
snapToPixel: false,
stroke: new Stroke({
color: '#319FD3'
}),
@@ -140,7 +139,6 @@ describe('ol.style.RegularShape', function() {
expect(original.getRotation()).to.eql(clone.getRotation());
expect(original.getRotateWithView()).to.eql(clone.getRotateWithView());
expect(original.getScale()).to.eql(clone.getScale());
expect(original.getSnapToPixel()).to.eql(clone.getSnapToPixel());
expect(original.getStroke().getColor()).to.eql(clone.getStroke().getColor());
});