Move gradient and pattern fills with the view
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
## Upgrade notes
|
## Upgrade notes
|
||||||
|
|
||||||
|
#### `ol.style.Fill` with `CanvasGradient` or `CanvasPattern`
|
||||||
|
|
||||||
|
Previously, gradients and patterns were aligned with the canvas, so they did not
|
||||||
|
move and rotate with the map. This was changed to a more expected behavior by anchoring the fill to the map origin (usually at map coordinate `[0, 0]`).
|
||||||
|
|
||||||
#### `goog.DEBUG` define was renamed to `ol.DEBUG`
|
#### `goog.DEBUG` define was renamed to `ol.DEBUG`
|
||||||
|
|
||||||
As last step in the removal of the dependency on Google Closure Library, the `goog.DEBUG` compiler define was renamed to `ol.DEBUG`. Please change accordingly in your custom build configuration json files.
|
As last step in the removal of the dependency on Google Closure Library, the `goog.DEBUG` compiler define was renamed to `ol.DEBUG`. Please change accordingly in your custom build configuration json files.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
goog.require('ol.Map');
|
goog.require('ol.Map');
|
||||||
goog.require('ol.View');
|
goog.require('ol.View');
|
||||||
goog.require('ol.format.GeoJSON');
|
goog.require('ol.format.GeoJSON');
|
||||||
|
goog.require('ol.has');
|
||||||
goog.require('ol.layer.Vector');
|
goog.require('ol.layer.Vector');
|
||||||
goog.require('ol.proj');
|
goog.require('ol.proj');
|
||||||
goog.require('ol.source.Vector');
|
goog.require('ol.source.Vector');
|
||||||
@@ -8,14 +9,22 @@ goog.require('ol.style.Fill');
|
|||||||
goog.require('ol.style.Stroke');
|
goog.require('ol.style.Stroke');
|
||||||
goog.require('ol.style.Style');
|
goog.require('ol.style.Style');
|
||||||
|
|
||||||
// Will contain ol.Style instances key by country.
|
var canvas = document.createElement('canvas');
|
||||||
var styleLookup = {};
|
var context = canvas.getContext('2d');
|
||||||
|
|
||||||
|
// Gradient and pattern are in canvas pixel space, so we adjust for the
|
||||||
|
// renderer's pixel ratio
|
||||||
|
var pixelRatio = ol.has.DEVICE_PIXEL_RATIO;
|
||||||
|
|
||||||
// Generate a rainbow gradient
|
// Generate a rainbow gradient
|
||||||
var gradient = (function() {
|
function gradient(feature, resolution) {
|
||||||
var canvas = document.createElement('canvas');
|
var extent = feature.getGeometry().getExtent();
|
||||||
var context = canvas.getContext('2d');
|
// Gradient starts on the left edge of each feature, and ends on the right.
|
||||||
var grad = context.createLinearGradient(0,0,1000,0);
|
// Coordinate origin is [0, 0], so we just divide by resolution and multiply
|
||||||
|
// with pixelRatio to match the renderer's pixel coordinate system.
|
||||||
|
var grad = context.createLinearGradient(
|
||||||
|
extent[0] / resolution * pixelRatio, 0,
|
||||||
|
extent[2] / 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');
|
||||||
@@ -24,33 +33,35 @@ var gradient = (function() {
|
|||||||
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
|
// Generate a canvasPattern with two circles on white background
|
||||||
var pattern = (function() {
|
var pattern = (function() {
|
||||||
var canvas = document.createElement('canvas');
|
canvas.width = 11 * pixelRatio;
|
||||||
var context = canvas.getContext('2d');
|
canvas.height = 11 * pixelRatio;
|
||||||
canvas.width = 11;
|
// white background
|
||||||
canvas.height = 11;
|
context.fillStyle = 'white';
|
||||||
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
// 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, 5, 4, 0, 2 * Math.PI);
|
context.arc(5 * pixelRatio, 5 * pixelRatio, 4 * pixelRatio, 0, 2 * Math.PI);
|
||||||
context.fill();
|
context.fill();
|
||||||
|
// inner circle
|
||||||
context.fillStyle = 'rgb(55, 0, 170)';
|
context.fillStyle = 'rgb(55, 0, 170)';
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
context.arc(5, 5, 2, 0, 2 * Math.PI);
|
context.arc(5 * pixelRatio, 5 * pixelRatio, 2 * pixelRatio, 0, 2 * Math.PI);
|
||||||
context.fill();
|
context.fill();
|
||||||
return context.createPattern(canvas, 'repeat');
|
return context.createPattern(canvas, 'repeat');
|
||||||
}());
|
}());
|
||||||
|
|
||||||
// Generate a background style that all features will reuse
|
// Generate style for gradient or pattern fill
|
||||||
var backgroundStyle = new ol.style.Style({
|
var fill = new ol.style.Fill();
|
||||||
|
var style = new ol.style.Style({
|
||||||
|
fill: fill,
|
||||||
stroke: new ol.style.Stroke({
|
stroke: new ol.style.Stroke({
|
||||||
color: '#333',
|
color: '#333',
|
||||||
width: 2
|
width: 2
|
||||||
}),
|
|
||||||
fill: new ol.style.Fill({
|
|
||||||
color: '#fff'
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -58,33 +69,14 @@ var backgroundStyle = new ol.style.Style({
|
|||||||
* The styling function for the vector layer, will return an array of styles
|
* The styling function for the vector layer, will return an array of styles
|
||||||
* which either contains the aboove gradient or pattern.
|
* which either contains the aboove gradient or pattern.
|
||||||
*
|
*
|
||||||
* @param {ol.Feature} feature the feature to style.
|
* @param {ol.Feature} feature The feature to style.
|
||||||
* @return {Array<ol.style.Style>} the styles to use for the feature.
|
* @param {number} resolution Resolution.
|
||||||
|
* @return {ol.style.Style} The style to use for the feature.
|
||||||
*/
|
*/
|
||||||
var getStackedStyle = function(feature) {
|
var getStackedStyle = function(feature, resolution) {
|
||||||
var id = feature.getId();
|
var id = feature.getId();
|
||||||
if (!styleLookup[id]) {
|
fill.setColor(id > 'J' ? gradient(feature, resolution) : pattern);
|
||||||
var patternOrGradient;
|
return style;
|
||||||
if (id > 'J') { // some shall get the gradient, others the pattern.
|
|
||||||
patternOrGradient = gradient;
|
|
||||||
} else {
|
|
||||||
patternOrGradient = pattern;
|
|
||||||
}
|
|
||||||
// Store the style in the lookup, next call will just return the stored
|
|
||||||
// style for the feature.
|
|
||||||
styleLookup[id] = [
|
|
||||||
// 1. Use the common background style
|
|
||||||
// (white fill and blackish stroke)
|
|
||||||
backgroundStyle,
|
|
||||||
// 2. On top of that, draw the pattern or gradient
|
|
||||||
new ol.style.Style({
|
|
||||||
fill: new ol.style.Fill({
|
|
||||||
color: patternOrGradient
|
|
||||||
})
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return styleLookup[id];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a vector layer that makes use of the style function above…
|
// Create a vector layer that makes use of the style function above…
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function() {
|
|||||||
var miterLimit = state.miterLimit;
|
var miterLimit = state.miterLimit;
|
||||||
if (fillStyle !== undefined && state.currentFillStyle != fillStyle) {
|
if (fillStyle !== undefined && state.currentFillStyle != fillStyle) {
|
||||||
this.instructions.push(
|
this.instructions.push(
|
||||||
[ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle]);
|
[ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle, typeof fillStyle != 'string']);
|
||||||
state.currentFillStyle = state.fillStyle;
|
state.currentFillStyle = state.fillStyle;
|
||||||
}
|
}
|
||||||
if (strokeStyle !== undefined) {
|
if (strokeStyle !== undefined) {
|
||||||
|
|||||||
@@ -58,6 +58,12 @@ ol.render.canvas.Replay = function(tolerance, maxExtent, resolution, overlaps) {
|
|||||||
*/
|
*/
|
||||||
this.resolution = resolution;
|
this.resolution = resolution;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.alignFill_ = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {Array.<*>}
|
* @type {Array.<*>}
|
||||||
@@ -185,6 +191,19 @@ ol.render.canvas.Replay.prototype.beginGeometry = function(geometry, feature) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ol.render.canvas.Replay.prototype.fill_ = function(context, transform, rotation) {
|
||||||
|
if (this.alignFill_) {
|
||||||
|
context.translate(transform[4], transform[5]);
|
||||||
|
context.rotate(rotation);
|
||||||
|
}
|
||||||
|
context.fill();
|
||||||
|
if (this.alignFill_) {
|
||||||
|
context.rotate(-rotation);
|
||||||
|
context.translate(-transform[4], -transform[5]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @param {CanvasRenderingContext2D} context Context.
|
* @param {CanvasRenderingContext2D} context Context.
|
||||||
@@ -250,7 +269,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
|||||||
break;
|
break;
|
||||||
case ol.render.canvas.Instruction.BEGIN_PATH:
|
case ol.render.canvas.Instruction.BEGIN_PATH:
|
||||||
if (pendingFill > batchSize) {
|
if (pendingFill > batchSize) {
|
||||||
context.fill();
|
this.fill_(context, transform, viewRotation);
|
||||||
pendingFill = 0;
|
pendingFill = 0;
|
||||||
}
|
}
|
||||||
if (pendingStroke > batchSize) {
|
if (pendingStroke > batchSize) {
|
||||||
@@ -429,7 +448,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
|||||||
if (batchSize) {
|
if (batchSize) {
|
||||||
pendingFill++;
|
pendingFill++;
|
||||||
} else {
|
} else {
|
||||||
context.fill();
|
this.fill_(context, transform, viewRotation);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
break;
|
break;
|
||||||
@@ -467,8 +486,10 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
|||||||
ol.colorlike.isColorLike(instruction[1]),
|
ol.colorlike.isColorLike(instruction[1]),
|
||||||
'2nd instruction should be a string, ' +
|
'2nd instruction should be a string, ' +
|
||||||
'CanvasPattern, or CanvasGradient');
|
'CanvasPattern, or CanvasGradient');
|
||||||
|
this.alignFill_ = instruction[2];
|
||||||
|
|
||||||
if (pendingFill) {
|
if (pendingFill) {
|
||||||
context.fill();
|
this.fill_(context, transform, viewRotation);
|
||||||
pendingFill = 0;
|
pendingFill = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +555,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pendingFill) {
|
if (pendingFill) {
|
||||||
context.fill();
|
this.fill_(context, transform, viewRotation);
|
||||||
}
|
}
|
||||||
if (pendingStroke) {
|
if (pendingStroke) {
|
||||||
context.stroke();
|
context.stroke();
|
||||||
|
|||||||
Reference in New Issue
Block a user