High resolution icon
This commit is contained in:
BIN
examples/data/bigdot.png
Normal file
BIN
examples/data/bigdot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
66
examples/data/dot.svg
Normal file
66
examples/data/dot.svg
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="20"
|
||||
height="20"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="dot.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1533"
|
||||
inkscape:window-height="845"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="11.8"
|
||||
inkscape:cx="-35.042373"
|
||||
inkscape:cy="11.5"
|
||||
inkscape:window-x="67"
|
||||
inkscape:window-y="102"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g4"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<g
|
||||
id="g4"
|
||||
transform="translate(1.5,-1.5)">
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path822"
|
||||
cx="8.5"
|
||||
cy="11.5"
|
||||
r="8.5"
|
||||
inkscape:export-xdpi="400"
|
||||
inkscape:export-ydpi="400" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -1,7 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
||||
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<rect width="20" height="20" style="fill:#fff; stroke-width:4px; stroke:#000" />
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="20"
|
||||
height="20"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="square.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1533"
|
||||
inkscape:window-height="845"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="11.8"
|
||||
inkscape:cx="11.5"
|
||||
inkscape:cy="11.5"
|
||||
inkscape:window-x="67"
|
||||
inkscape:window-y="102"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg6" />
|
||||
<g
|
||||
id="g4"
|
||||
transform="matrix(0.85,0,0,0.85,1.5,1.5)"
|
||||
style="fill:#fefefe;fill-opacity:1;stroke:#000000;stroke-width:3.52941179;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
|
||||
<rect
|
||||
width="20"
|
||||
height="20"
|
||||
style="fill:#fefefe;fill-opacity:1;stroke:#000000;stroke-width:3.52941179;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect2"
|
||||
x="0"
|
||||
y="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 225 B After Width: | Height: | Size: 1.9 KiB |
@@ -19,12 +19,19 @@ const london = new Feature({
|
||||
const madrid = new Feature({
|
||||
geometry: new Point(fromLonLat([-3.683333, 40.4])),
|
||||
});
|
||||
const paris = new Feature({
|
||||
geometry: new Point(fromLonLat([2.353, 48.8566])),
|
||||
});
|
||||
const berlin = new Feature({
|
||||
geometry: new Point(fromLonLat([13.3884, 52.5169])),
|
||||
});
|
||||
|
||||
rome.setStyle(
|
||||
new Style({
|
||||
image: new Icon({
|
||||
color: '#8959A8',
|
||||
crossOrigin: 'anonymous',
|
||||
// For Internet Explorer 11
|
||||
imgSize: [20, 20],
|
||||
src: 'data/square.svg',
|
||||
}),
|
||||
@@ -36,7 +43,8 @@ london.setStyle(
|
||||
image: new Icon({
|
||||
color: '#4271AE',
|
||||
crossOrigin: 'anonymous',
|
||||
src: 'data/dot.png',
|
||||
src: 'data/bigdot.png',
|
||||
scale: 0.2,
|
||||
}),
|
||||
})
|
||||
);
|
||||
@@ -44,15 +52,37 @@ london.setStyle(
|
||||
madrid.setStyle(
|
||||
new Style({
|
||||
image: new Icon({
|
||||
color: [113, 140, 0],
|
||||
crossOrigin: 'anonymous',
|
||||
src: 'data/dot.png',
|
||||
src: 'data/bigdot.png',
|
||||
scale: 0.2,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
paris.setStyle(
|
||||
new Style({
|
||||
image: new Icon({
|
||||
color: '#8959A8',
|
||||
crossOrigin: 'anonymous',
|
||||
// For Internet Explorer 11
|
||||
imgSize: [20, 20],
|
||||
src: 'data/dot.svg',
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
berlin.setStyle(
|
||||
new Style({
|
||||
image: new Icon({
|
||||
crossOrigin: 'anonymous',
|
||||
// For Internet Explorer 11
|
||||
imgSize: [20, 20],
|
||||
src: 'data/dot.svg',
|
||||
}),
|
||||
})
|
||||
);
|
||||
const vectorSource = new VectorSource({
|
||||
features: [rome, london, madrid],
|
||||
features: [rome, london, madrid, paris, berlin],
|
||||
});
|
||||
|
||||
const vectorLayer = new VectorLayer({
|
||||
|
||||
@@ -320,6 +320,16 @@ class Icon extends ImageStyle {
|
||||
return this.iconImage_.getImage(pixelRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pixel ratio.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @return {number} The pixel ration of the image.
|
||||
* @api
|
||||
*/
|
||||
getPixelRatio(pixelRatio) {
|
||||
return this.iconImage_.getPixelRatio(pixelRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("../size.js").Size} Image size.
|
||||
*/
|
||||
|
||||
@@ -23,9 +23,9 @@ class IconImage extends EventTarget {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLImageElement|HTMLCanvasElement}
|
||||
* @type {Object<number, HTMLImageElement|HTMLCanvasElement>}
|
||||
*/
|
||||
this.hitDetectionImage_ = null;
|
||||
this.hitDetectionImage_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -39,9 +39,9 @@ class IconImage extends EventTarget {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLCanvasElement}
|
||||
* @type {Object<number, HTMLCanvasElement>}
|
||||
*/
|
||||
this.canvas_ = color ? document.createElement('canvas') : null;
|
||||
this.canvas_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -75,22 +75,18 @@ class IconImage extends EventTarget {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean|undefined}
|
||||
*/
|
||||
this.tainted_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D=} context A context with the image already drawn into.
|
||||
* @return {boolean} The image canvas is tainted.
|
||||
*/
|
||||
isTainted_(context) {
|
||||
isTainted_() {
|
||||
if (this.tainted_ === undefined && this.imageState_ === ImageState.LOADED) {
|
||||
if (!context) {
|
||||
context = createCanvasContext2D(1, 1);
|
||||
context.drawImage(this.image_, 0, 0);
|
||||
}
|
||||
const context = createCanvasContext2D(1, 1);
|
||||
context.drawImage(this.image_, 0, 0);
|
||||
try {
|
||||
context.getImageData(0, 0, 1, 1);
|
||||
this.tainted_ = false;
|
||||
@@ -125,10 +121,10 @@ class IconImage extends EventTarget {
|
||||
if (this.size_) {
|
||||
this.image_.width = this.size_[0];
|
||||
this.image_.height = this.size_[1];
|
||||
} else {
|
||||
this.size_ = [this.image_.width, this.image_.height];
|
||||
}
|
||||
this.size_ = [this.image_.width, this.image_.height];
|
||||
this.unlistenImage_();
|
||||
this.replaceColor_();
|
||||
this.dispatchChangeEvent_();
|
||||
}
|
||||
|
||||
@@ -137,7 +133,17 @@ class IconImage extends EventTarget {
|
||||
* @return {HTMLImageElement|HTMLCanvasElement} Image or Canvas element.
|
||||
*/
|
||||
getImage(pixelRatio) {
|
||||
return this.canvas_ ? this.canvas_ : this.image_;
|
||||
this.replaceColor_(pixelRatio);
|
||||
return this.canvas_[pixelRatio] ? this.canvas_[pixelRatio] : this.image_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @return {number} Image or Canvas element.
|
||||
*/
|
||||
getPixelRatio(pixelRatio) {
|
||||
this.replaceColor_(pixelRatio);
|
||||
return this.canvas_[pixelRatio] ? pixelRatio : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,18 +158,23 @@ class IconImage extends EventTarget {
|
||||
* @return {HTMLImageElement|HTMLCanvasElement} Image element.
|
||||
*/
|
||||
getHitDetectionImage(pixelRatio) {
|
||||
if (!this.hitDetectionImage_) {
|
||||
if (!this.hitDetectionImage_[pixelRatio]) {
|
||||
if (this.isTainted_()) {
|
||||
const usedPixelRatio = this.color_ ? pixelRatio : 1;
|
||||
const width = this.size_[0];
|
||||
const height = this.size_[1];
|
||||
const context = createCanvasContext2D(width, height);
|
||||
const context = createCanvasContext2D(
|
||||
Math.ceil(width * usedPixelRatio),
|
||||
Math.ceil(height * usedPixelRatio)
|
||||
);
|
||||
context.scale(usedPixelRatio, usedPixelRatio);
|
||||
context.fillRect(0, 0, width, height);
|
||||
this.hitDetectionImage_ = context.canvas;
|
||||
this.hitDetectionImage_[pixelRatio] = context.canvas;
|
||||
} else {
|
||||
this.hitDetectionImage_ = this.image_;
|
||||
this.hitDetectionImage_[pixelRatio] = this.image_;
|
||||
}
|
||||
}
|
||||
return this.hitDetectionImage_;
|
||||
return this.hitDetectionImage_[pixelRatio];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,20 +212,25 @@ class IconImage extends EventTarget {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @private
|
||||
*/
|
||||
replaceColor_() {
|
||||
if (!this.color_) {
|
||||
replaceColor_(pixelRatio) {
|
||||
if (!this.color_ || this.canvas_[pixelRatio]) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.canvas_.width = this.image_.width;
|
||||
this.canvas_.height = this.image_.height;
|
||||
const canvas = document.createElement('canvas');
|
||||
this.canvas_[pixelRatio] = canvas;
|
||||
|
||||
const ctx = this.canvas_.getContext('2d');
|
||||
canvas.width = Math.ceil(this.image_.width * pixelRatio);
|
||||
canvas.height = Math.ceil(this.image_.height * pixelRatio);
|
||||
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(pixelRatio, pixelRatio);
|
||||
ctx.drawImage(this.image_, 0, 0);
|
||||
|
||||
if (this.isTainted_(ctx)) {
|
||||
if (this.isTainted_()) {
|
||||
// If reading from the canvas throws a SecurityError the same effect can be
|
||||
// achieved with globalCompositeOperation.
|
||||
// This could be used as the default, but it is not fully supported by all
|
||||
@@ -226,19 +242,14 @@ class IconImage extends EventTarget {
|
||||
const c = this.color_;
|
||||
ctx.globalCompositeOperation = 'multiply';
|
||||
ctx.fillStyle = 'rgb(' + c[0] + ',' + c[1] + ',' + c[2] + ')';
|
||||
ctx.fillRect(0, 0, this.image_.width, this.image_.height);
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.globalCompositeOperation = 'destination-in';
|
||||
ctx.drawImage(this.image_, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
const imgData = ctx.getImageData(
|
||||
0,
|
||||
0,
|
||||
this.image_.width,
|
||||
this.image_.height
|
||||
);
|
||||
const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
const data = imgData.data;
|
||||
const r = this.color_[0] / 255.0;
|
||||
const g = this.color_[1] / 255.0;
|
||||
|
||||
Reference in New Issue
Block a user