重写选中便签的黑边为干净的外描边
This commit is contained in:
+40
-38
@@ -53,8 +53,9 @@ function sphericalAreaKm2(polys) {
|
||||
}
|
||||
|
||||
// 生成便签 canvas:黄底圆角 + 左侧箭头 + 黑色加粗文字(整张图,箭头尖端指向坐标)
|
||||
// 选中态:先描粗边再填充,得到一条干净的 2px 外描边(四周预留 B 的 padding 防止裁切)
|
||||
function makeStickyNote(text, fontSize, selected = false) {
|
||||
const padX = 8, padY = 5, radius = 7, arrowW = 10, arrowH = 14, S = 2; // S: 2x 超采样
|
||||
const padX = 8, padY = 5, radius = 7, arrowW = 10, arrowH = 14, S = 2, B = 2; // S: 2x 超采样,B: 边框预留
|
||||
const font = `bold ${fontSize}px "Noto Serif SC", "Songti SC", "STSong", "SimSun", Georgia, serif`;
|
||||
const m = document.createElement('canvas');
|
||||
const mctx = m.getContext('2d');
|
||||
@@ -63,55 +64,54 @@ function makeStickyNote(text, fontSize, selected = false) {
|
||||
const bodyW = Math.max(1, Math.ceil(textW + padX * 2));
|
||||
const w = arrowW + bodyW;
|
||||
const h = Math.ceil(fontSize + padY * 2);
|
||||
const cw = w + B * 2;
|
||||
const ch = h + B * 2;
|
||||
const c = document.createElement('canvas');
|
||||
c.width = w * S;
|
||||
c.height = h * S;
|
||||
c.width = cw * S;
|
||||
c.height = ch * S;
|
||||
const ctx = c.getContext('2d');
|
||||
ctx.scale(S, S);
|
||||
|
||||
// 阴影
|
||||
ctx.shadowColor = 'rgba(0, 0, 0, 0.20)';
|
||||
ctx.shadowBlur = 5;
|
||||
ctx.shadowOffsetY = 2;
|
||||
const ox = B, oy = B; // 形状整体内缩 B,给黑边留空间
|
||||
|
||||
// 箭头 + 圆角矩形一体化路径(箭头尖端在左侧 x=0,指向坐标)
|
||||
// 箭头 + 圆角矩形一体化路径(箭头尖端在 (ox, oy + h/2),指向坐标)
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, h / 2); // 箭头尖端
|
||||
ctx.lineTo(arrowW, h / 2 - arrowH / 2); // 箭头上沿
|
||||
ctx.lineTo(arrowW, radius); // 左边缘上部
|
||||
ctx.arcTo(arrowW, 0, arrowW + radius, 0, radius); // 左上圆角
|
||||
ctx.lineTo(w - radius, 0); // 上边
|
||||
ctx.arcTo(w, 0, w, radius, radius); // 右上圆角
|
||||
ctx.lineTo(w, h - radius); // 右边
|
||||
ctx.arcTo(w, h, w - radius, h, radius); // 右下圆角
|
||||
ctx.lineTo(arrowW + radius, h); // 底边
|
||||
ctx.arcTo(arrowW, h, arrowW, h - radius, radius); // 左下圆角
|
||||
ctx.lineTo(arrowW, h / 2 + arrowH / 2); // 左边缘下部
|
||||
ctx.closePath(); // 闭合回箭头尖端
|
||||
ctx.moveTo(ox, oy + h / 2);
|
||||
ctx.lineTo(ox + arrowW, oy + h / 2 - arrowH / 2);
|
||||
ctx.lineTo(ox + arrowW, oy + radius);
|
||||
ctx.arcTo(ox + arrowW, oy, ox + arrowW + radius, oy, radius);
|
||||
ctx.lineTo(ox + w - radius, oy);
|
||||
ctx.arcTo(ox + w, oy, ox + w, oy + radius, radius);
|
||||
ctx.lineTo(ox + w, oy + h - radius);
|
||||
ctx.arcTo(ox + w, oy + h, ox + w - radius, oy + h, radius);
|
||||
ctx.lineTo(ox + arrowW + radius, oy + h);
|
||||
ctx.arcTo(ox + arrowW, oy + h, ox + arrowW, oy + h - radius, radius);
|
||||
ctx.lineTo(ox + arrowW, oy + h / 2 + arrowH / 2);
|
||||
ctx.closePath();
|
||||
|
||||
if (selected) {
|
||||
// 先描粗边,再填充盖住内侧一半 → 外露 2px 干净黑边
|
||||
ctx.strokeStyle = '#14100d';
|
||||
ctx.lineWidth = B * 2; // 4px,外露 2px
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.stroke();
|
||||
} else {
|
||||
// 非选中:柔和的投影
|
||||
ctx.shadowColor = 'rgba(0, 0, 0, 0.20)';
|
||||
ctx.shadowBlur = 5;
|
||||
ctx.shadowOffsetY = 2;
|
||||
}
|
||||
ctx.fillStyle = '#e0c46a';
|
||||
ctx.fill();
|
||||
|
||||
// 选中时加黑边
|
||||
if (selected) {
|
||||
ctx.shadowColor = 'transparent';
|
||||
ctx.shadowBlur = 0;
|
||||
ctx.shadowOffsetY = 0;
|
||||
ctx.strokeStyle = '#14100d';
|
||||
ctx.lineWidth = 3;
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
// 黑色加粗文字(无阴影)
|
||||
ctx.shadowColor = 'transparent';
|
||||
ctx.shadowBlur = 0;
|
||||
ctx.shadowOffsetY = 0;
|
||||
// 黑色加粗文字
|
||||
ctx.fillStyle = '#14100d';
|
||||
ctx.font = font;
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText(text, arrowW + bodyW / 2, h / 2 + 1);
|
||||
ctx.fillText(text, ox + arrowW + bodyW / 2, oy + h / 2 + 1);
|
||||
|
||||
return { canvas: c, scale: 1 / S, width: w, height: h };
|
||||
return { canvas: c, scale: 1 / S, width: cw, height: ch, tipX: B, tipY: B + h / 2 };
|
||||
}
|
||||
|
||||
export class CesiumGlobe {
|
||||
@@ -300,6 +300,8 @@ export class CesiumGlobe {
|
||||
el.style.height = `${m.noteNormal.height}px`;
|
||||
el.dataset.index = m.index;
|
||||
m.el = el;
|
||||
m.tipX = m.noteNormal.tipX; // 箭头尖相对元素左上角的偏移
|
||||
m.tipY = m.noteNormal.tipY;
|
||||
m.normalUrl = m.noteNormal.canvas.toDataURL();
|
||||
m.selectedUrl = m.noteSelected.canvas.toDataURL();
|
||||
el.style.backgroundImage = `url("${m.normalUrl}")`;
|
||||
@@ -335,8 +337,8 @@ export class CesiumGlobe {
|
||||
|
||||
el.style.display = 'block';
|
||||
el.style.opacity = String(opacity);
|
||||
el.style.left = `${win.x}px`;
|
||||
el.style.top = `${win.y}px`;
|
||||
el.style.left = `${win.x - m.tipX}px`;
|
||||
el.style.top = `${win.y - m.tipY}px`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user