I'm trying to add a bottom-to-top color gradient to my markers, but it's not working as I expected. I also don't quite agree with the radius * 3 but I didn't find another solution to let the circle look like a circle yet. Any ideas in how to fix this? Thank you.
const radius= 30;
const style = new Style({
image: new Circle({
radius: radius * 3,
fill: new Fill({
color: gradient(outerRadius, '#22C55E', '#4ADE80'),
}),
}),
});
function gradient(radius: number, color1: string, color2: string) {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const size = radius * 2;
canvas.width = size;
canvas.height = size;
const gradient = context.createLinearGradient(0, size, 0, 0);
gradient.addColorStop(0, color1);
gradient.addColorStop(1, color2);
context.fillStyle = gradient;
context.beginPath();
context.arc(radius, radius, radius, 0, 2 * Math.PI);
context.fill();
return context.createPattern(canvas, 'no-repeat');
}
The gray circle in the picture is correctly positioned and it's fill color is created by using
fill: new Fill({
color: 'rgb(52, 69, 76)'
})
But the gradient circle isn't:
Here's an example with two markers. A default one which is positioned correctly and a gradient one using the same coordinate. https://jsfiddle.net/zx36h7wy/1/
You do not have any control over the origin of the pattern when it is used as fill, in your case it looks like the point geometry is the top left of the pattern. You would have more control if you used your canvas as an icon
const radius = 30;
const style = new Style({
image: new Icon({
img: gradient(radius, '#22C55E', '#4ADE80'),
}),
});
function gradient(radius: number, color1: string, color2: string) {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const size = radius * 2;
canvas.width = size;
canvas.height = size;
const gradient = context.createLinearGradient(0, size, 0, 0);
gradient.addColorStop(0, color1);
gradient.addColorStop(1, color2);
context.fillStyle = gradient;
context.beginPath();
context.arc(radius, radius, radius, 0, 2 * Math.PI);
context.fill();
return canvas;
}
<html>
<head>
<style>
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/ol@v10.2.1/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v10.2.1/ol.css">
</head>
<body>
<div id="map" class="map"></div>
<script>
{
const Feature = ol.Feature;
const Map = ol.Map;
const OSM = ol.source.OSM;
const Point = ol.geom.Point;
const TileLayer = ol.layer.Tile;
const VectorLayer = ol.layer.Vector;
const VectorSource = ol.source.Vector;
const View = ol.View;
const {Icon, Style} = ol.style;
const radius = 30;
const style = new Style({
image: new Icon({
img: gradient(radius, '#00ff00', '#ff0000'),
}),
});
function gradient(radius, color1, color2) {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const size = radius * 2;
canvas.width = size;
canvas.height = size;
const gradient = context.createLinearGradient(0, size, 0, 0);
gradient.addColorStop(0, color1);
gradient.addColorStop(1, color2);
context.fillStyle = gradient;
context.beginPath();
context.arc(radius, radius, radius, 0, 2 * Math.PI);
context.fill();
return canvas;
}
new Map({
layers: [
new TileLayer({
source: new OSM(),
}),
new VectorLayer({
source: new VectorSource({
features: [
new Feature(new Point([0, 0])),
],
}),
style: style,
}),
],
target: 'map',
view: new View({
center: [0, 0],
zoom: 2,
}),
});
}
</script>
</body>
</html>