重写选中便签的黑边为干净的外描边
This commit is contained in:
+39
-37
@@ -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);
|
||||
|
||||
// 阴影
|
||||
const ox = B, oy = B; // 形状整体内缩 B,给黑边留空间
|
||||
|
||||
// 箭头 + 圆角矩形一体化路径(箭头尖端在 (ox, oy + h/2),指向坐标)
|
||||
ctx.beginPath();
|
||||
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;
|
||||
|
||||
// 箭头 + 圆角矩形一体化路径(箭头尖端在左侧 x=0,指向坐标)
|
||||
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.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`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-13
@@ -47,7 +47,6 @@ html, body {
|
||||
pointer-events: auto;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
transform: translateY(-50%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -66,27 +65,25 @@ html, body {
|
||||
background: #0c0906; opacity: 0; transition: opacity 0.18s ease;
|
||||
}
|
||||
|
||||
/* 加载界面 */
|
||||
/* 加载界面:OS1 3D 加载环 */
|
||||
#loading {
|
||||
position: fixed; inset: 0; z-index: 1000;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||||
gap: 26px;
|
||||
background: #14100d;
|
||||
transition: opacity 0.6s ease;
|
||||
}
|
||||
#loading.hidden { opacity: 0; pointer-events: none; }
|
||||
.loading-box { display: flex; flex-direction: column; align-items: center; gap: 18px; }
|
||||
.spinner {
|
||||
width: 54px; height: 54px;
|
||||
border: 3px solid rgba(201, 162, 39, 0.22);
|
||||
border-top-color: #c9a227;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.9s linear infinite;
|
||||
#loading-canvas {
|
||||
width: 500px; height: 500px;
|
||||
max-width: 88vw; max-height: 88vw;
|
||||
}
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
#loading-canvas canvas { width: 100%; height: 100%; display: block; }
|
||||
.loading-text {
|
||||
font-family: var(--serif);
|
||||
font-size: 14px; letter-spacing: 0.3em;
|
||||
color: rgba(230, 216, 182, 0.7);
|
||||
font-size: 13px;
|
||||
letter-spacing: 0.2em;
|
||||
color: rgba(224, 196, 106, 0.8);
|
||||
}
|
||||
|
||||
/* 顶部标题 */
|
||||
|
||||
Reference in New Issue
Block a user