标记去掉圆点,改为带左箭头的便签指向坐标
This commit is contained in:
+42
-37
@@ -36,15 +36,16 @@ function sphericalAreaKm2(polys) {
|
|||||||
return area * R * R;
|
return area * R * R;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成便签 canvas:黄色圆角底 + 黑色加粗文字(整张图,背景与文字完美对齐)
|
// 生成便签 canvas:黄底圆角 + 左侧箭头 + 黑色加粗文字(整张图,箭头尖端指向坐标)
|
||||||
function makeStickyNote(text, fontSize) {
|
function makeStickyNote(text, fontSize, selected = false) {
|
||||||
const padX = 14, padY = 8, radius = 8, S = 2; // S: 2x 超采样,文字更清晰
|
const padX = 14, padY = 8, radius = 8, arrowW = 12, arrowH = 16, S = 2; // S: 2x 超采样
|
||||||
const font = `bold ${fontSize}px "Noto Serif SC", "Songti SC", "STSong", "SimSun", Georgia, serif`;
|
const font = `bold ${fontSize}px "Noto Serif SC", "Songti SC", "STSong", "SimSun", Georgia, serif`;
|
||||||
const m = document.createElement('canvas');
|
const m = document.createElement('canvas');
|
||||||
const mctx = m.getContext('2d');
|
const mctx = m.getContext('2d');
|
||||||
mctx.font = font;
|
mctx.font = font;
|
||||||
const textW = mctx.measureText(text).width;
|
const textW = mctx.measureText(text).width;
|
||||||
const w = Math.max(1, Math.ceil(textW + padX * 2));
|
const bodyW = Math.max(1, Math.ceil(textW + padX * 2));
|
||||||
|
const w = arrowW + bodyW;
|
||||||
const h = Math.ceil(fontSize + padY * 2);
|
const h = Math.ceil(fontSize + padY * 2);
|
||||||
const c = document.createElement('canvas');
|
const c = document.createElement('canvas');
|
||||||
c.width = w * S;
|
c.width = w * S;
|
||||||
@@ -52,20 +53,38 @@ function makeStickyNote(text, fontSize) {
|
|||||||
const ctx = c.getContext('2d');
|
const ctx = c.getContext('2d');
|
||||||
ctx.scale(S, S);
|
ctx.scale(S, S);
|
||||||
|
|
||||||
// 黄色圆角底 + 阴影
|
// 阴影
|
||||||
ctx.shadowColor = 'rgba(0, 0, 0, 0.20)';
|
ctx.shadowColor = 'rgba(0, 0, 0, 0.20)';
|
||||||
ctx.shadowBlur = 5;
|
ctx.shadowBlur = 5;
|
||||||
ctx.shadowOffsetY = 2;
|
ctx.shadowOffsetY = 2;
|
||||||
|
|
||||||
|
// 箭头 + 圆角矩形一体化路径(箭头尖端在左侧 x=0,指向坐标)
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.moveTo(radius, 0);
|
ctx.moveTo(0, h / 2); // 箭头尖端
|
||||||
ctx.arcTo(w, 0, w, h, radius);
|
ctx.lineTo(arrowW, h / 2 - arrowH / 2); // 箭头上沿
|
||||||
ctx.arcTo(w, h, 0, h, radius);
|
ctx.lineTo(arrowW, radius); // 左边缘上部
|
||||||
ctx.arcTo(0, h, 0, 0, radius);
|
ctx.arcTo(arrowW, 0, arrowW + radius, 0, radius); // 左上圆角
|
||||||
ctx.arcTo(0, 0, w, 0, radius);
|
ctx.lineTo(w - radius, 0); // 上边
|
||||||
ctx.closePath();
|
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 = '#FFF9A6';
|
ctx.fillStyle = '#FFF9A6';
|
||||||
ctx.fill();
|
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.shadowColor = 'transparent';
|
||||||
ctx.shadowBlur = 0;
|
ctx.shadowBlur = 0;
|
||||||
@@ -74,7 +93,7 @@ function makeStickyNote(text, fontSize) {
|
|||||||
ctx.font = font;
|
ctx.font = font;
|
||||||
ctx.textBaseline = 'middle';
|
ctx.textBaseline = 'middle';
|
||||||
ctx.textAlign = 'center';
|
ctx.textAlign = 'center';
|
||||||
ctx.fillText(text, w / 2, h / 2 + 1);
|
ctx.fillText(text, arrowW + bodyW / 2, h / 2 + 1);
|
||||||
|
|
||||||
return { canvas: c, scale: 1 / S };
|
return { canvas: c, scale: 1 / S };
|
||||||
}
|
}
|
||||||
@@ -186,42 +205,28 @@ export class CesiumGlobe {
|
|||||||
|
|
||||||
_buildMarkers() {
|
_buildMarkers() {
|
||||||
const viewer = this.viewer;
|
const viewer = this.viewer;
|
||||||
const gold = Cesium.Color.fromCssColorString('#e0c46a');
|
|
||||||
const ink = Cesium.Color.fromCssColorString('#14100d');
|
|
||||||
|
|
||||||
ENTRIES.forEach((entry, i) => {
|
ENTRIES.forEach((entry, i) => {
|
||||||
|
// 便签:黄底黑字 + 左侧箭头指向坐标(整张图)
|
||||||
|
const noteNormal = makeStickyNote(entry.name, 19, false);
|
||||||
|
const noteSelected = makeStickyNote(entry.name, 19, true);
|
||||||
|
|
||||||
const entity = viewer.entities.add({
|
const entity = viewer.entities.add({
|
||||||
position: Cesium.Cartesian3.fromDegrees(entry.lng, entry.lat),
|
|
||||||
point: {
|
|
||||||
pixelSize: 10, // 标记宽一点
|
|
||||||
color: gold, // 金色圆形
|
|
||||||
outlineColor: ink, // 外侧 1px 黑边
|
|
||||||
outlineWidth: 1,
|
|
||||||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
|
||||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
||||||
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 1e7),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
entity.entryIndex = i;
|
|
||||||
|
|
||||||
// 便签:黄底黑字(整张图,贴到圆点右侧)
|
|
||||||
const note = makeStickyNote(entry.name, 19);
|
|
||||||
const noteEntity = viewer.entities.add({
|
|
||||||
position: Cesium.Cartesian3.fromDegrees(entry.lng, entry.lat),
|
position: Cesium.Cartesian3.fromDegrees(entry.lng, entry.lat),
|
||||||
billboard: {
|
billboard: {
|
||||||
image: note.canvas,
|
image: noteNormal.canvas,
|
||||||
scale: note.scale,
|
scale: noteNormal.scale,
|
||||||
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
|
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
|
||||||
verticalOrigin: Cesium.VerticalOrigin.CENTER,
|
verticalOrigin: Cesium.VerticalOrigin.CENTER,
|
||||||
pixelOffset: new Cesium.Cartesian2(12, 0),
|
pixelOffset: new Cesium.Cartesian2(0, 0),
|
||||||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
||||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||||
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 1e7),
|
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 1e7),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
entity.entryIndex = i;
|
||||||
|
|
||||||
this.markers.push({ entity, index: i });
|
this.markers.push({ entity, noteNormal, noteSelected, index: i });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,9 +388,9 @@ export class CesiumGlobe {
|
|||||||
setSelected(index) {
|
setSelected(index) {
|
||||||
this.selected = index;
|
this.selected = index;
|
||||||
if (!this.viewer) return;
|
if (!this.viewer) return;
|
||||||
this.markers.forEach(({ entity, index: i }) => {
|
this.markers.forEach(({ entity, noteNormal, noteSelected, index: i }) => {
|
||||||
const on = i === index;
|
const on = i === index;
|
||||||
entity.point.outlineWidth = on ? 3 : 1; // 选中加粗黑圈,不放大
|
entity.billboard.image = on ? noteSelected.canvas : noteNormal.canvas; // 选中加黑边
|
||||||
});
|
});
|
||||||
this.viewer.scene.requestRender();
|
this.viewer.scene.requestRender();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user