Skip to content

Commit 0ddf3d9

Browse files
committed
Moved over to basic canvas rendering for circles to fix stroke position.
Also `circle-blur` is now possible so I added that also.
1 parent 206396b commit 0ddf3d9

File tree

1 file changed

+54
-24
lines changed

1 file changed

+54
-24
lines changed

src/stylefunction.js

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ Copyright 2016-present ol-mapbox-style contributors
44
License: https://raw.githubusercontent.com/openlayers/ol-mapbox-style/master/LICENSE
55
*/
66

7-
import Circle from 'ol/style/Circle.js';
87
import Fill from 'ol/style/Fill.js';
98
import Icon from 'ol/style/Icon.js';
109
import RenderFeature from 'ol/render/Feature.js';
@@ -1140,40 +1139,71 @@ export function stylefunction(
11401139
functionCache,
11411140
featureState
11421141
);
1142+
1143+
const circleBlur = getValue(
1144+
layer,
1145+
'paint',
1146+
'circle-blur',
1147+
zoom,
1148+
f,
1149+
functionCache,
1150+
featureState
1151+
);
11431152
const cache_key =
11441153
circleRadius +
11451154
'.' +
11461155
circleStrokeColor +
11471156
'.' +
11481157
circleColor +
11491158
'.' +
1150-
circleStrokeWidth;
1151-
iconImg = iconImageCache[cache_key];
1152-
if (!iconImg) {
1153-
iconImg = new Circle({
1154-
radius: circleRadius,
1155-
stroke:
1156-
circleStrokeColor && circleStrokeWidth > 0
1157-
? new Stroke({
1158-
width: circleStrokeWidth,
1159-
color: circleStrokeColor,
1160-
})
1161-
: undefined,
1162-
fill: circleColor
1163-
? new Fill({
1164-
color: circleColor,
1165-
})
1166-
: undefined,
1167-
declutterMode: 'none',
1168-
});
1169-
iconImageCache[cache_key] = iconImg;
1170-
}
1171-
style.setImage(iconImg);
1159+
circleStrokeWidth +
1160+
'.' +
1161+
circleBlur;
1162+
11721163
text = style.getText();
11731164
style.setText(undefined);
11741165
style.setGeometry(undefined);
11751166
style.setZIndex(index);
1176-
hasImage = true;
1167+
style.setRenderer(([x, y], renderOpts) => {
1168+
const r = circleRadius * renderOpts.pixelRatio;
1169+
const sw = circleStrokeWidth * renderOpts.pixelRatio;
1170+
const cb = circleBlur * renderOpts.pixelRatio;
1171+
1172+
const w = r * 2 + sw * 2 + sw / 2 + cb * 2;
1173+
const h = r * 2 + sw * 2 + sw / 2 + cb * 2;
1174+
1175+
let bitmap = iconImageCache[cache_key];
1176+
if (!bitmap) {
1177+
const offscreenBuffer = new OffscreenCanvas(w, h);
1178+
const ctx = offscreenBuffer.getContext('2d');
1179+
1180+
if (cb !== 0) {
1181+
ctx.filter = `blur(${cb}px)`;
1182+
}
1183+
1184+
const ox = w / 2;
1185+
const oy = h / 2;
1186+
1187+
ctx.save();
1188+
ctx.beginPath();
1189+
ctx.arc(ox, oy, r, 0, 2 * Math.PI);
1190+
ctx.fillStyle = circleColor;
1191+
ctx.fill();
1192+
ctx.restore();
1193+
1194+
ctx.save();
1195+
ctx.beginPath();
1196+
ctx.arc(ox, oy, r + sw / 2, 0, 2 * Math.PI);
1197+
ctx.strokeStyle = circleStrokeColor;
1198+
ctx.lineWidth = sw;
1199+
ctx.stroke();
1200+
ctx.restore();
1201+
ctx.restore();
1202+
bitmap = offscreenBuffer.transferToImageBitmap();
1203+
iconImageCache[cache_key] = bitmap;
1204+
}
1205+
renderOpts.context.drawImage(bitmap, x - w / 2, y - h / 2);
1206+
});
11771207
}
11781208

11791209
let label, font, textLineHeight, textSize, letterSpacing, maxTextWidth;

0 commit comments

Comments
 (0)