Use geometry extent's top left corner as pattern/gradient origin

This commit is contained in:
Andreas Hocevar
2016-10-27 21:27:17 +02:00
parent 767bec4dc7
commit a2a2a53e08
6 changed files with 39 additions and 27 deletions

View File

@@ -1,5 +1,10 @@
## Upgrade notes ## Upgrade notes
#### `ol.style.Fill` with `CanvasGradient` or `CanvasPattern`
The origin for gradients and patterns has changed from `[0, 0]` to the top-left
corner of the extent of the geometry being filled.
### v3.19.0 ### v3.19.0
#### `ol.style.Fill` with `CanvasGradient` or `CanvasPattern` #### `ol.style.Fill` with `CanvasGradient` or `CanvasPattern`

View File

@@ -1,5 +1,6 @@
goog.require('ol.Map'); goog.require('ol.Map');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.extent');
goog.require('ol.format.GeoJSON'); goog.require('ol.format.GeoJSON');
goog.require('ol.has'); goog.require('ol.has');
goog.require('ol.layer.Vector'); goog.require('ol.layer.Vector');
@@ -20,11 +21,11 @@ var pixelRatio = ol.has.DEVICE_PIXEL_RATIO;
function gradient(feature, resolution) { function gradient(feature, resolution) {
var extent = feature.getGeometry().getExtent(); var extent = feature.getGeometry().getExtent();
// Gradient starts on the left edge of each feature, and ends on the right. // Gradient starts on the left edge of each feature, and ends on the right.
// Coordinate origin is [0, 0], so we just divide by resolution and multiply // Coordinate origin is the top-left corner of the extent of the geometry, so
// with pixelRatio to match the renderer's pixel coordinate system. // we just divide the geometry's extent width by resolution and multiply with
var grad = context.createLinearGradient( // pixelRatio to match the renderer's pixel coordinate system.
extent[0] / resolution * pixelRatio, 0, var grad = context.createLinearGradient(0, 0,
extent[2] / resolution * pixelRatio, 0); ol.extent.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');

View File

@@ -132,7 +132,7 @@ ol.render.canvas.PolygonReplay.prototype.drawCircle = function(circleGeometry, f
ol.DEBUG && console.assert(state.lineWidth !== undefined, ol.DEBUG && console.assert(state.lineWidth !== undefined,
'state.lineWidth should be defined'); 'state.lineWidth should be defined');
} }
this.setFillStrokeStyles_(); this.setFillStrokeStyles_(circleGeometry);
this.beginGeometry(circleGeometry, feature); this.beginGeometry(circleGeometry, feature);
// always fill the circle for hit detection // always fill the circle for hit detection
this.hitDetectionInstructions.push( this.hitDetectionInstructions.push(
@@ -182,7 +182,7 @@ ol.render.canvas.PolygonReplay.prototype.drawPolygon = function(polygonGeometry,
ol.DEBUG && console.assert(state.lineWidth !== undefined, ol.DEBUG && console.assert(state.lineWidth !== undefined,
'state.lineWidth should be defined'); 'state.lineWidth should be defined');
} }
this.setFillStrokeStyles_(); this.setFillStrokeStyles_(polygonGeometry);
this.beginGeometry(polygonGeometry, feature); this.beginGeometry(polygonGeometry, feature);
// always fill the polygon for hit detection // always fill the polygon for hit detection
this.hitDetectionInstructions.push( this.hitDetectionInstructions.push(
@@ -217,7 +217,7 @@ ol.render.canvas.PolygonReplay.prototype.drawMultiPolygon = function(multiPolygo
ol.DEBUG && console.assert(state.lineWidth !== undefined, ol.DEBUG && console.assert(state.lineWidth !== undefined,
'state.lineWidth should be defined'); 'state.lineWidth should be defined');
} }
this.setFillStrokeStyles_(); this.setFillStrokeStyles_(multiPolygonGeometry);
this.beginGeometry(multiPolygonGeometry, feature); this.beginGeometry(multiPolygonGeometry, feature);
// always fill the multi-polygon for hit detection // always fill the multi-polygon for hit detection
this.hitDetectionInstructions.push( this.hitDetectionInstructions.push(
@@ -332,8 +332,9 @@ ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyle = function(fillStyle
/** /**
* @private * @private
* @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
*/ */
ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function() { ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function(geometry) {
var state = this.state_; var state = this.state_;
var fillStyle = state.fillStyle; var fillStyle = state.fillStyle;
var strokeStyle = state.strokeStyle; var strokeStyle = state.strokeStyle;
@@ -342,9 +343,13 @@ ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function() {
var lineJoin = state.lineJoin; var lineJoin = state.lineJoin;
var lineWidth = state.lineWidth; var lineWidth = state.lineWidth;
var miterLimit = state.miterLimit; var miterLimit = state.miterLimit;
if (fillStyle !== undefined && state.currentFillStyle != fillStyle) { if (typeof fillStyle !== 'string' || fillStyle !== undefined && state.currentFillStyle != fillStyle) {
this.instructions.push( var fillInstruction = [ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle];
[ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle, typeof fillStyle != 'string']); if (typeof fillStyle !== 'string') {
var fillExtent = geometry.getExtent();
fillInstruction.push([fillExtent[0], fillExtent[3]]);
}
this.instructions.push(fillInstruction);
state.currentFillStyle = state.fillStyle; state.currentFillStyle = state.fillStyle;
} }
if (strokeStyle !== undefined) { if (strokeStyle !== undefined) {

View File

@@ -60,9 +60,9 @@ ol.render.canvas.Replay = function(tolerance, maxExtent, resolution, overlaps) {
/** /**
* @private * @private
* @type {boolean} * @type {ol.Coordinate}
*/ */
this.alignFill_ = false; this.fillOrigin_;
/** /**
* @private * @private
@@ -194,18 +194,17 @@ ol.render.canvas.Replay.prototype.beginGeometry = function(geometry, feature) {
/** /**
* @private * @private
* @param {CanvasRenderingContext2D} context Context. * @param {CanvasRenderingContext2D} context Context.
* @param {ol.Transform} transform Transform.
* @param {number} rotation Rotation. * @param {number} rotation Rotation.
*/ */
ol.render.canvas.Replay.prototype.fill_ = function(context, transform, rotation) { ol.render.canvas.Replay.prototype.fill_ = function(context, rotation) {
if (this.alignFill_) { if (this.fillOrigin_) {
context.translate(transform[4], transform[5]); var origin = ol.transform.apply(this.renderedTransform_, this.fillOrigin_.slice());
context.translate(origin[0], origin[1]);
context.rotate(rotation); context.rotate(rotation);
} }
context.fill(); context.fill();
if (this.alignFill_) { if (this.fillOrigin_) {
context.rotate(-rotation); context.setTransform.apply(context, this.resetTransform_);
context.translate(-transform[4], -transform[5]);
} }
}; };
@@ -275,7 +274,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) {
this.fill_(context, transform, viewRotation); this.fill_(context, viewRotation);
pendingFill = 0; pendingFill = 0;
} }
if (pendingStroke > batchSize) { if (pendingStroke > batchSize) {
@@ -452,7 +451,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
if (batchSize) { if (batchSize) {
pendingFill++; pendingFill++;
} else { } else {
this.fill_(context, transform, viewRotation); this.fill_(context, viewRotation);
} }
++i; ++i;
break; break;
@@ -490,10 +489,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]; this.fillOrigin_ = instruction[2];
if (pendingFill) { if (pendingFill) {
this.fill_(context, transform, viewRotation); this.fill_(context, viewRotation);
pendingFill = 0; pendingFill = 0;
} }
@@ -559,7 +558,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
} }
} }
if (pendingFill) { if (pendingFill) {
this.fill_(context, transform, viewRotation); this.fill_(context, viewRotation);
} }
if (pendingStroke) { if (pendingStroke) {
context.stroke(); context.stroke();

View File

@@ -121,7 +121,9 @@ ol.Color;
/** /**
* A type accepted by CanvasRenderingContext2D.fillStyle * A type accepted by CanvasRenderingContext2D.fillStyle
* or CanvasRenderingContext2D.strokeStyle. * or CanvasRenderingContext2D.strokeStyle.
* Represents a color, pattern, or gradient. * 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.
* *
* @typedef {string|CanvasPattern|CanvasGradient} * @typedef {string|CanvasPattern|CanvasGradient}
*/ */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB