Align patterns and gradients to a grid
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
### 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
|
||||
|
||||
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
|
||||
shortdesc: Example showing the countries vector layer styled with patterns and gradients.
|
||||
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
|
||||
a GeoJSON file. A style function determines for each country whether to use a fill with the pregenerated
|
||||
CanvasGradient (rainbow colors) or a CanvasPattern (repeating stacked circles).
|
||||
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). **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"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {getWidth} from '../src/ol/extent.js';
|
||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||
import {DEVICE_PIXEL_RATIO} from '../src/ol/has.js';
|
||||
import VectorLayer from '../src/ol/layer/Vector.js';
|
||||
@@ -16,14 +15,8 @@ const context = canvas.getContext('2d');
|
||||
const pixelRatio = DEVICE_PIXEL_RATIO;
|
||||
|
||||
// Generate a rainbow gradient
|
||||
function gradient(feature, resolution) {
|
||||
const extent = feature.getGeometry().getExtent();
|
||||
// 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);
|
||||
const gradient = (function() {
|
||||
const grad = context.createLinearGradient(0, 0, 512 * pixelRatio, 0);
|
||||
grad.addColorStop(0, 'red');
|
||||
grad.addColorStop(1 / 6, 'orange');
|
||||
grad.addColorStop(2 / 6, 'yellow');
|
||||
@@ -32,24 +25,24 @@ function gradient(feature, resolution) {
|
||||
grad.addColorStop(5 / 6, 'blue');
|
||||
grad.addColorStop(1, 'purple');
|
||||
return grad;
|
||||
}
|
||||
})();
|
||||
|
||||
// Generate a canvasPattern with two circles on white background
|
||||
const pattern = (function() {
|
||||
canvas.width = 11 * pixelRatio;
|
||||
canvas.height = 11 * pixelRatio;
|
||||
canvas.width = 8 * pixelRatio;
|
||||
canvas.height = 8 * pixelRatio;
|
||||
// white background
|
||||
context.fillStyle = 'white';
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
// outer circle
|
||||
context.fillStyle = 'rgba(102, 0, 102, 0.5)';
|
||||
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();
|
||||
// inner circle
|
||||
context.fillStyle = 'rgb(55, 0, 170)';
|
||||
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();
|
||||
return context.createPattern(canvas, 'repeat');
|
||||
}());
|
||||
@@ -69,12 +62,11 @@ const style = new Style({
|
||||
* which either contains the aboove gradient or pattern.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
const getStackedStyle = function(feature, resolution) {
|
||||
const getStackedStyle = function(feature) {
|
||||
const id = feature.getId();
|
||||
fill.setColor(id > 'J' ? gradient(feature, resolution) : pattern);
|
||||
fill.setColor(id > 'J' ? gradient : pattern);
|
||||
return style;
|
||||
};
|
||||
|
||||
@@ -94,7 +86,7 @@ const map = new Map({
|
||||
],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: fromLonLat([7, 52]),
|
||||
center: fromLonLat([16, 48]),
|
||||
zoom: 3
|
||||
})
|
||||
});
|
||||
|
||||
@@ -8,8 +8,9 @@ import {toString} from './color.js';
|
||||
* A type accepted by CanvasRenderingContext2D.fillStyle
|
||||
* or CanvasRenderingContext2D.strokeStyle.
|
||||
* 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
|
||||
* being filled.
|
||||
* gradients as fill style is an increment of 512 css pixels from map coordinate
|
||||
* `[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
|
||||
* @api
|
||||
|
||||
@@ -456,8 +456,9 @@ CanvasReplay.prototype.beginGeometry = function(geometry, feature) {
|
||||
*/
|
||||
CanvasReplay.prototype.fill_ = function(context) {
|
||||
if (this.fillOrigin_) {
|
||||
const origin = applyTransform(this.renderedTransform_, this.fillOrigin_.slice());
|
||||
context.translate(origin[0], origin[1]);
|
||||
const origin = applyTransform(this.renderedTransform_, [0, 0]);
|
||||
const repeatSize = 512 * this.pixelRatio;
|
||||
context.translate(origin[0] % repeatSize, origin[1] % repeatSize);
|
||||
context.rotate(this.viewRotation_);
|
||||
}
|
||||
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