Align patterns and gradients to a grid
This commit is contained in:
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
### Next release
|
### Next release
|
||||||
|
|
||||||
|
#### `ol/style/Fill` with `CanvasGradient` or `CanvasPattern`
|
||||||
|
|
||||||
|
The origin for gradients and patterns has changed from the top-left corner of the extent of the geometry being filled to 512 css pixel increments from map coordinate `[0, 0]`. This allows repeat patterns to be aligned properly with vector tiles. For seamless repeat patterns, width and height of the pattern image must be a factor of two (2, 4, 8, ..., 512).
|
||||||
|
|
||||||
#### Removal of the renderer option for maps
|
#### Removal of the renderer option for maps
|
||||||
|
|
||||||
The `renderer` option has been removed from the `Map` constructor. The purpose of this change is to avoid bundling code in your application that you do not need. Previously, code for both the Canvas and WebGL renderers was included in all applications - even though most people only use one renderer. The `Map` constructor now gives you a Canvas (2D) based renderer. If you want to try the WebGL renderer, you can import the constructor from `ol/WebGLMap`.
|
The `renderer` option has been removed from the `Map` constructor. The purpose of this change is to avoid bundling code in your application that you do not need. Previously, code for both the Canvas and WebGL renderers was included in all applications - even though most people only use one renderer. The `Map` constructor now gives you a Canvas (2D) based renderer. If you want to try the WebGL renderer, you can import the constructor from `ol/WebGLMap`.
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ layout: example.html
|
|||||||
title: Styling feature with CanvasGradient or CanvasPattern
|
title: Styling feature with CanvasGradient or CanvasPattern
|
||||||
shortdesc: Example showing the countries vector layer styled with patterns and gradients.
|
shortdesc: Example showing the countries vector layer styled with patterns and gradients.
|
||||||
docs: >
|
docs: >
|
||||||
First this example creates a reusable [`CanvasPattern`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern)
|
This example creates a [`CanvasPattern`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern)
|
||||||
and a [`CanvasGradient`](https://developer.mozilla.org/en/docs/Web/API/CanvasGradient). The countries are loaded from
|
and a [`CanvasGradient`](https://developer.mozilla.org/en/docs/Web/API/CanvasGradient). The countries are loaded from
|
||||||
a GeoJSON file. A style function determines for each country whether to use a fill with the pregenerated
|
a GeoJSON file. A style function determines for each country whether to use a fill with the
|
||||||
CanvasGradient (rainbow colors) or a CanvasPattern (repeating stacked circles).
|
CanvasGradient (rainbow colors) or a CanvasPattern (repeating stacked circles). **Note**: For seamless repeat patterns,
|
||||||
|
image width and height of the pattern image must be a factor of two (2, 4, 8, ..., 512).
|
||||||
tags: "canvas, gradient, pattern, style"
|
tags: "canvas, gradient, pattern, style"
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import Map from '../src/ol/Map.js';
|
import Map from '../src/ol/Map.js';
|
||||||
import View from '../src/ol/View.js';
|
import View from '../src/ol/View.js';
|
||||||
import {getWidth} from '../src/ol/extent.js';
|
|
||||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||||
import {DEVICE_PIXEL_RATIO} from '../src/ol/has.js';
|
import {DEVICE_PIXEL_RATIO} from '../src/ol/has.js';
|
||||||
import VectorLayer from '../src/ol/layer/Vector.js';
|
import VectorLayer from '../src/ol/layer/Vector.js';
|
||||||
@@ -16,14 +15,8 @@ const context = canvas.getContext('2d');
|
|||||||
const pixelRatio = DEVICE_PIXEL_RATIO;
|
const pixelRatio = DEVICE_PIXEL_RATIO;
|
||||||
|
|
||||||
// Generate a rainbow gradient
|
// Generate a rainbow gradient
|
||||||
function gradient(feature, resolution) {
|
const gradient = (function() {
|
||||||
const extent = feature.getGeometry().getExtent();
|
const grad = context.createLinearGradient(0, 0, 512 * pixelRatio, 0);
|
||||||
// Gradient starts on the left edge of each feature, and ends on the right.
|
|
||||||
// Coordinate origin is the top-left corner of the extent of the geometry, so
|
|
||||||
// we just divide the geometry's extent width by resolution and multiply with
|
|
||||||
// pixelRatio to match the renderer's pixel coordinate system.
|
|
||||||
const grad = context.createLinearGradient(0, 0,
|
|
||||||
getWidth(extent) / resolution * pixelRatio, 0);
|
|
||||||
grad.addColorStop(0, 'red');
|
grad.addColorStop(0, 'red');
|
||||||
grad.addColorStop(1 / 6, 'orange');
|
grad.addColorStop(1 / 6, 'orange');
|
||||||
grad.addColorStop(2 / 6, 'yellow');
|
grad.addColorStop(2 / 6, 'yellow');
|
||||||
@@ -32,24 +25,24 @@ function gradient(feature, resolution) {
|
|||||||
grad.addColorStop(5 / 6, 'blue');
|
grad.addColorStop(5 / 6, 'blue');
|
||||||
grad.addColorStop(1, 'purple');
|
grad.addColorStop(1, 'purple');
|
||||||
return grad;
|
return grad;
|
||||||
}
|
})();
|
||||||
|
|
||||||
// Generate a canvasPattern with two circles on white background
|
// Generate a canvasPattern with two circles on white background
|
||||||
const pattern = (function() {
|
const pattern = (function() {
|
||||||
canvas.width = 11 * pixelRatio;
|
canvas.width = 8 * pixelRatio;
|
||||||
canvas.height = 11 * pixelRatio;
|
canvas.height = 8 * pixelRatio;
|
||||||
// white background
|
// white background
|
||||||
context.fillStyle = 'white';
|
context.fillStyle = 'white';
|
||||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
// outer circle
|
// outer circle
|
||||||
context.fillStyle = 'rgba(102, 0, 102, 0.5)';
|
context.fillStyle = 'rgba(102, 0, 102, 0.5)';
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
context.arc(5 * pixelRatio, 5 * pixelRatio, 4 * pixelRatio, 0, 2 * Math.PI);
|
context.arc(4 * pixelRatio, 4 * pixelRatio, 3 * pixelRatio, 0, 2 * Math.PI);
|
||||||
context.fill();
|
context.fill();
|
||||||
// inner circle
|
// inner circle
|
||||||
context.fillStyle = 'rgb(55, 0, 170)';
|
context.fillStyle = 'rgb(55, 0, 170)';
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
context.arc(5 * pixelRatio, 5 * pixelRatio, 2 * pixelRatio, 0, 2 * Math.PI);
|
context.arc(4 * pixelRatio, 4 * pixelRatio, 1.5 * pixelRatio, 0, 2 * Math.PI);
|
||||||
context.fill();
|
context.fill();
|
||||||
return context.createPattern(canvas, 'repeat');
|
return context.createPattern(canvas, 'repeat');
|
||||||
}());
|
}());
|
||||||
@@ -69,12 +62,11 @@ const style = new Style({
|
|||||||
* which either contains the aboove gradient or pattern.
|
* which either contains the aboove gradient or pattern.
|
||||||
*
|
*
|
||||||
* @param {module:ol/Feature~Feature} feature The feature to style.
|
* @param {module:ol/Feature~Feature} feature The feature to style.
|
||||||
* @param {number} resolution Resolution.
|
|
||||||
* @return {module:ol/style/Style} The style to use for the feature.
|
* @return {module:ol/style/Style} The style to use for the feature.
|
||||||
*/
|
*/
|
||||||
const getStackedStyle = function(feature, resolution) {
|
const getStackedStyle = function(feature) {
|
||||||
const id = feature.getId();
|
const id = feature.getId();
|
||||||
fill.setColor(id > 'J' ? gradient(feature, resolution) : pattern);
|
fill.setColor(id > 'J' ? gradient : pattern);
|
||||||
return style;
|
return style;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -94,7 +86,7 @@ const map = new Map({
|
|||||||
],
|
],
|
||||||
target: 'map',
|
target: 'map',
|
||||||
view: new View({
|
view: new View({
|
||||||
center: fromLonLat([7, 52]),
|
center: fromLonLat([16, 48]),
|
||||||
zoom: 3
|
zoom: 3
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
+3
-2
@@ -8,8 +8,9 @@ import {toString} from './color.js';
|
|||||||
* A type accepted by CanvasRenderingContext2D.fillStyle
|
* A type accepted by CanvasRenderingContext2D.fillStyle
|
||||||
* or CanvasRenderingContext2D.strokeStyle.
|
* or CanvasRenderingContext2D.strokeStyle.
|
||||||
* Represents a color, pattern, or gradient. The origin for patterns and
|
* Represents a color, pattern, or gradient. The origin for patterns and
|
||||||
* gradients as fill style is the top-left corner of the extent of the geometry
|
* gradients as fill style is an increment of 512 css pixels from map coordinate
|
||||||
* being filled.
|
* `[0, 0]`. For seamless repeat patterns, width and height of the pattern image
|
||||||
|
* must be a factor of two (2, 4, 8, ..., 512).
|
||||||
*
|
*
|
||||||
* @typedef {string|CanvasPattern|CanvasGradient} ColorLike
|
* @typedef {string|CanvasPattern|CanvasGradient} ColorLike
|
||||||
* @api
|
* @api
|
||||||
|
|||||||
@@ -456,8 +456,9 @@ CanvasReplay.prototype.beginGeometry = function(geometry, feature) {
|
|||||||
*/
|
*/
|
||||||
CanvasReplay.prototype.fill_ = function(context) {
|
CanvasReplay.prototype.fill_ = function(context) {
|
||||||
if (this.fillOrigin_) {
|
if (this.fillOrigin_) {
|
||||||
const origin = applyTransform(this.renderedTransform_, this.fillOrigin_.slice());
|
const origin = applyTransform(this.renderedTransform_, [0, 0]);
|
||||||
context.translate(origin[0], origin[1]);
|
const repeatSize = 512 * this.pixelRatio;
|
||||||
|
context.translate(origin[0] % repeatSize, origin[1] % repeatSize);
|
||||||
context.rotate(this.viewRotation_);
|
context.rotate(this.viewRotation_);
|
||||||
}
|
}
|
||||||
context.fill();
|
context.fill();
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.7 KiB |
Reference in New Issue
Block a user