Have high resolution regular shape

This commit is contained in:
Stéphane Brunner
2020-07-14 14:50:46 +02:00
parent 2dd9342a98
commit f2fe6e5957
5 changed files with 142 additions and 68 deletions

View File

@@ -32,6 +32,12 @@ class CanvasImageBuilder extends CanvasBuilder {
*/
this.image_ = null;
/**
* @private
* @type {number|undefined}
*/
this.imagePixelRatio_ = undefined;
/**
* @private
* @type {number|undefined}
@@ -136,17 +142,20 @@ class CanvasImageBuilder extends CanvasBuilder {
myEnd,
this.image_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_,
this.anchorY_,
this.anchorX_ * this.imagePixelRatio_,
this.anchorY_ * this.imagePixelRatio_,
this.declutterGroups_,
this.height_,
this.height_ * this.imagePixelRatio_,
this.opacity_,
this.originX_,
this.originY_,
this.rotateWithView_,
this.rotation_,
[this.scale_[0] * this.pixelRatio, this.scale_[1] * this.pixelRatio],
this.width_,
[
(this.scale_[0] * this.pixelRatio) / this.imagePixelRatio_,
(this.scale_[1] * this.pixelRatio) / this.imagePixelRatio_,
],
this.width_ * this.imagePixelRatio_,
]);
this.hitDetectionInstructions.push([
CanvasInstruction.DRAW_IMAGE,
@@ -154,17 +163,20 @@ class CanvasImageBuilder extends CanvasBuilder {
myEnd,
this.hitDetectionImage_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_,
this.anchorY_,
this.anchorX_ * this.imagePixelRatio_,
this.anchorY_ * this.imagePixelRatio_,
this.declutterGroups_,
this.height_,
this.height_ * this.imagePixelRatio_,
this.opacity_,
this.originX_,
this.originY_,
this.rotateWithView_,
this.rotation_,
this.scale_,
this.width_,
[
(this.scale_[0] * this.pixelRatio) / this.imagePixelRatio_,
(this.scale_[1] * this.pixelRatio) / this.imagePixelRatio_,
],
this.width_ * this.imagePixelRatio_,
]);
this.endGeometry(feature);
}
@@ -193,17 +205,20 @@ class CanvasImageBuilder extends CanvasBuilder {
myEnd,
this.image_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_,
this.anchorY_,
this.anchorX_ * this.imagePixelRatio_,
this.anchorY_ * this.imagePixelRatio_,
this.declutterGroups_,
this.height_,
this.height_ * this.imagePixelRatio_,
this.opacity_,
this.originX_,
this.originY_,
this.rotateWithView_,
this.rotation_,
[this.scale_[0] * this.pixelRatio, this.scale_[1] * this.pixelRatio],
this.width_,
[
(this.scale_[0] * this.pixelRatio) / this.imagePixelRatio_,
(this.scale_[1] * this.pixelRatio) / this.imagePixelRatio_,
],
this.width_ * this.imagePixelRatio_,
]);
this.hitDetectionInstructions.push([
CanvasInstruction.DRAW_IMAGE,
@@ -211,17 +226,20 @@ class CanvasImageBuilder extends CanvasBuilder {
myEnd,
this.hitDetectionImage_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_,
this.anchorY_,
this.anchorX_ * this.imagePixelRatio_,
this.anchorY_ * this.imagePixelRatio_,
this.declutterGroups_,
this.height_,
this.height_ * this.imagePixelRatio_,
this.opacity_,
this.originX_,
this.originY_,
this.rotateWithView_,
this.rotation_,
this.scale_,
this.width_,
[
(this.scale_[0] * this.pixelRatio) / this.imagePixelRatio_,
(this.scale_[1] * this.pixelRatio) / this.imagePixelRatio_,
],
this.width_ * this.imagePixelRatio_,
]);
this.endGeometry(feature);
}
@@ -236,6 +254,7 @@ class CanvasImageBuilder extends CanvasBuilder {
this.anchorY_ = undefined;
this.hitDetectionImage_ = null;
this.image_ = null;
this.imagePixelRatio_ = undefined;
this.height_ = undefined;
this.scale_ = undefined;
this.opacity_ = undefined;
@@ -254,9 +273,10 @@ class CanvasImageBuilder extends CanvasBuilder {
setImageStyle(imageStyle, declutterGroups) {
const anchor = imageStyle.getAnchor();
const size = imageStyle.getSize();
const hitDetectionImage = imageStyle.getHitDetectionImage(1);
const image = imageStyle.getImage(1);
const hitDetectionImage = imageStyle.getHitDetectionImage(this.pixelRatio);
const image = imageStyle.getImage(this.pixelRatio);
const origin = imageStyle.getOrigin();
this.imagePixelRatio_ = imageStyle.getPixelRatio(this.pixelRatio);
this.anchorX_ = anchor[0];
this.anchorY_ = anchor[1];
this.declutterGroups_ = declutterGroups;

View File

@@ -161,6 +161,14 @@ class ImageStyle {
return abstract();
}
/*
* Get the image pixel ratio.
* @param {number} pixelRatio Pixel ratio.
* */
getPixelRatio(pixelRatio) {
return 1;
}
/**
* @abstract
* @return {import("../ImageState.js").default} Image state.

View File

@@ -73,15 +73,15 @@ class RegularShape extends ImageStyle {
/**
* @private
* @type {HTMLCanvasElement}
* @type {Object<number, HTMLCanvasElement>}
*/
this.canvas_ = null;
this.canvas_ = {};
/**
* @private
* @type {HTMLCanvasElement}
* @type {Object<number, HTMLCanvasElement>}
*/
this.hitDetectionCanvas_ = null;
this.hitDetectionCanvas_ = {};
/**
* @private
@@ -205,20 +205,45 @@ class RegularShape extends ImageStyle {
/**
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLImageElement|HTMLCanvasElement} Image element.
* @return {HTMLCanvasElement} Image element.
*/
getHitDetectionImage(pixelRatio) {
return this.hitDetectionCanvas_;
if (!this.hitDetectionCanvas_[pixelRatio || 1]) {
const renderOptions = this.createRenderOptions();
this.createHitDetectionCanvas_(renderOptions, pixelRatio || 1);
}
return this.hitDetectionCanvas_[pixelRatio || 1];
}
/**
* Get the image icon.
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLImageElement|HTMLCanvasElement} Image or Canvas element.
* @return {HTMLCanvasElement} Image or Canvas element.
* @api
*/
getImage(pixelRatio) {
return this.canvas_;
if (!this.canvas_[pixelRatio || 1]) {
const renderOptions = this.createRenderOptions();
const context = createCanvasContext2D(
renderOptions.size * pixelRatio || 1,
renderOptions.size * pixelRatio || 1
);
this.draw_(renderOptions, context, 0, 0, pixelRatio || 1);
this.canvas_[pixelRatio || 1] = context.canvas;
}
return this.canvas_[pixelRatio || 1];
}
/*
* Get the image pixel ratio.
* @param {number} pixelRatio Pixel ratio.
* */
getPixelRatio(pixelRatio) {
return pixelRatio;
}
/**
@@ -312,9 +337,10 @@ class RegularShape extends ImageStyle {
unlistenImageChange(listener) {}
/**
* @returns {RenderOptions} The render options
* @protected
*/
render() {
createRenderOptions() {
let lineCap = defaultLineCap;
let lineJoin = defaultLineJoin;
let miterLimit = 0;
@@ -349,9 +375,9 @@ class RegularShape extends ImageStyle {
}
}
let size = 2 * (this.radius_ + strokeWidth) + 1;
const size = 2 * (this.radius_ + strokeWidth) + 1;
const renderOptions = {
return {
strokeStyle: strokeStyle,
strokeWidth: strokeWidth,
size: size,
@@ -361,18 +387,30 @@ class RegularShape extends ImageStyle {
lineJoin: lineJoin,
miterLimit: miterLimit,
};
}
const context = createCanvasContext2D(size, size);
this.canvas_ = context.canvas;
/**
* @protected
*/
render() {
const renderOptions = this.createRenderOptions();
const context = createCanvasContext2D(
renderOptions.size,
renderOptions.size
);
this.draw_(renderOptions, context, 0, 0, 1);
this.canvas_[1] = context.canvas;
// canvas.width and height are rounded to the closest integer
size = this.canvas_.width;
const size = context.canvas.width;
const imageSize = size;
const displacement = this.getDisplacement();
this.draw_(renderOptions, context, 0, 0);
this.createHitDetectionCanvas_(renderOptions);
this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size];
this.createHitDetectionCanvas_(renderOptions, 1);
this.anchor_ = [size / 2 - displacement[0], size / 2 + displacement[1]];
this.size_ = [size, size];
@@ -385,11 +423,13 @@ class RegularShape extends ImageStyle {
* @param {CanvasRenderingContext2D} context The rendering context.
* @param {number} x The origin for the symbol (x).
* @param {number} y The origin for the symbol (y).
* @param {number} pixelRatio The pixel ratio.
*/
draw_(renderOptions, context, x, y) {
draw_(renderOptions, context, x, y, pixelRatio) {
let i, angle0, radiusC;
// reset transform
context.setTransform(1, 0, 0, 1, 0, 0);
context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
// then move to (x, y)
context.translate(x, y);
@@ -448,10 +488,10 @@ class RegularShape extends ImageStyle {
/**
* @private
* @param {RenderOptions} renderOptions Render options.
* @param {number} pixelRatio The pixel ratio.
*/
createHitDetectionCanvas_(renderOptions) {
this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size];
this.hitDetectionCanvas_ = this.canvas_;
createHitDetectionCanvas_(renderOptions, pixelRatio) {
this.hitDetectionCanvas_[pixelRatio] = this.getImage(pixelRatio);
if (this.fill_) {
let color = this.fill_.getColor();
@@ -469,12 +509,12 @@ class RegularShape extends ImageStyle {
// if a transparent fill style is set, create an extra hit-detection image
// with a default fill style
const context = createCanvasContext2D(
renderOptions.size,
renderOptions.size
renderOptions.size * pixelRatio,
renderOptions.size * pixelRatio
);
this.hitDetectionCanvas_ = context.canvas;
this.hitDetectionCanvas_[pixelRatio] = context.canvas;
this.drawHitDetectionCanvas_(renderOptions, context, 0, 0);
this.drawHitDetectionCanvas_(renderOptions, context, 0, 0, pixelRatio);
}
}
}
@@ -485,10 +525,11 @@ class RegularShape extends ImageStyle {
* @param {CanvasRenderingContext2D} context The context.
* @param {number} x The origin for the symbol (x).
* @param {number} y The origin for the symbol (y).
* @param {number} pixelRatio The pixel ratio.
*/
drawHitDetectionCanvas_(renderOptions, context, x, y) {
drawHitDetectionCanvas_(renderOptions, context, x, y, pixelRatio) {
// reset transform
context.setTransform(1, 0, 0, 1, 0, 0);
context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
// then move to (x, y)
context.translate(x, y);