Compare commits

..
25 Commits
Author SHA1 Message Date
fukunee db8b14705d README:补充 Cesium 地理视图精要说明 2026-09-19 17:53:17 +08:00
fukunee f11dcb0ea5 词条便签逆时针旋转45°(绕箭头尖),命中测试改用实际矩形 2026-09-19 17:44:32 +08:00
fukunee 6d46d51685 词条便签整体缩小,圆角更小 2026-09-19 17:41:14 +08:00
fukunee 4cfeb7cba0 撤回:恢复箭头平滑曲线 2026-09-19 17:40:47 +08:00
fukunee 929e55c32f 箭头改回直角三角(无圆角) 2026-09-19 17:40:17 +08:00
fukunee 847d361431 便签文字左移2px 2026-09-19 17:39:24 +08:00
fukunee 30e2f562bc 便签:箭头曲线直接平滑过渡到长边,消除小拐角 2026-09-19 17:38:24 +08:00
fukunee 46c6d2f34a 便签箭头用二次贝塞尔曲线平滑过渡到主体 2026-09-19 17:36:33 +08:00
fukunee d327ab5bc1 便签:箭头加大、圆角更小更方 2026-09-19 17:34:51 +08:00
fukunee 0215fa71d4 便签形状:更圆角、指向箭头更小更简洁 2026-09-19 17:33:15 +08:00
fukunee d0732a9ac3 国家/城市字号再调大;城市最大距离增至2.5e6 2026-09-19 17:32:07 +08:00
fukunee 52b09f5049 标签字号再调大;国家名最大距离恢复1e7 2026-09-19 17:30:55 +08:00
fukunee 63777b83ce 标签样式改为 FILL_AND_OUTLINE,使黑边生效 2026-09-19 17:30:05 +08:00
fukunee 46f6681b6a 国家名:字号调大、黑边黄字、最大显示距离6e6 2026-09-19 17:29:24 +08:00
fukunee 3522ece7b3 城市名:字号13px、黑边黄字、最大显示距离2e6 2026-09-19 17:28:47 +08:00
fukunee 1fd386b6cf 便签贴附:失败点降级重试(12/8/4)尽量补全 2026-09-19 17:24:40 +08:00
fukunee 10b2b77887 便签贴附:等待地形provider就绪后再采样 2026-09-19 17:23:15 +08:00
fukunee d4e0999506 便签地形采样改用固定层级 sampleTerrain,并输出贴附数量日志 2026-09-19 17:19:46 +08:00
fukunee 0e150f09df 便签地形贴附改用 sampleTerrainMostDetailed 2026-09-19 17:15:46 +08:00
fukunee 5b71877ae3 便签锚点贴到地形表面,修复放大旋转时的漂移 2026-09-19 17:12:56 +08:00
fukunee 89d51a7f59 便签不拦截事件:滚轮/右键穿透,左键改为canvas命中选中 2026-09-19 17:10:07 +08:00
fukunee 9df646c91c 中键回正改为天底+北朝上(不恢复原视角) 2026-09-19 17:07:49 +08:00
fukunee d02e7da220 关闭光照/大气辉光,地形回到2.0 2026-09-19 17:04:30 +08:00
fukunee 6256098a94 丢弃 ESRI 灰色'Map data not yet available'错误瓦片,回退父级放大 2026-09-19 17:03:38 +08:00
fukunee 174f162565 右键不自动回正,改为中键回正(保留动画) 2026-09-19 16:58:36 +08:00
3 changed files with 205 additions and 59 deletions
+41 -13
View File
@@ -8,7 +8,19 @@
| --- | --- |
| **活页本** | 皮革封面 + 金属活页环 + 20 张双面活页,翻页动画、纸张弯曲、堆叠阴影 |
| **时间轴** | 20 张活页沿金色时间轴一字排开,选中卡片上浮并显示年代 |
| **地理** | 点阵地球 + 经纬网 + 事件标记 + 相邻事件间的金色大圆航线,缓慢自转 |
| **地理** | Cesium 三维地球:卫星影像 + 真实地形 + 国界/城市标注 + 词条便签标记 |
## 地理视图(Cesium)
地理视图使用 **Cesium**(懒加载,进入该视图才加载脚本),免费、无需 Ion token:
- **影像/地形**:ESRI World Imagery 卫星影像(限制 ±85°)+ Esri World Elevation 3D 真实地形。
- **国界**:Natural Earth 50m,黑色单线。
- **国家/城市名**:Natural Earth + GeoNames 中文名,黑边黄字(`FILL_AND_OUTLINE`),按距离淡出,背面经深度测试隐藏。
- **词条便签**:DOM 覆盖层(非 billboard),贴地形高度,逆时针 45° 斜放、平滑曲线箭头;未选中金底黑字带黑边,选中黑底金字。
- **交互**:左键旋转、滚轮缩放(500 m ~ 8000 km)、右键原生 tilt(松手不回正)、中键回正(flyTo 动画)。
- **画质**:按设备像素比渲染(高分屏清晰)、FXAA + MSAA、地形 `maximumScreenSpaceError=2.0`。
- **兜底**:丢弃 ESRI 灰色 "Map data not yet available" 错误瓦片,自动回退父级放大。
## 技术要点
@@ -18,6 +30,18 @@
- **双面活页**:正面用 `FrontSide`、背面用 `BackSide`(内容预先水平镜像),配合纸张柔性弯曲,翻页时自然显露背面素描。
- 数据(`src/data/entries.js`)包含 20 条真实历史里程碑,含经纬度与分类(人 / 事 / 物)。
## 性能优化(已完成)
- **纹理懒加载 + LRU**:页面 / 卡片纹理按需生成,引用计数 + LRU 释放(上限 40 页),启动只为可见窗口生成;时间轴卡片用独立低分辨率纹理池(256×358)。
- **按需渲染**:静止时停止重绘,动画 / 交互 / 状态变化时才渲染(含页面 z 过渡的 `isSettling` 判定)。
- **几何降级**:栈内页用极简几何(2 三角形),顶层 / 翻页页才用高分段;封面皮革曲面、活页环、铆钉均降低分段;时间轴卡片 24×6 → 12×3。
- **双面材质合并**:页面正反面合并为单 mesh(`gl_FrontFacing` 双纹理),draw call 减半;活页孔用 alphaTest 免透明排序。
- **Cesium 懒加载 + 后台预载**:首屏不加载 6MB 脚本,首帧后后台预载,地理按钮就绪前在循环切换中自动跳过。
- **地理数据 primitive 化**:7342 城市点/标签与约 240 国家名标签由 entity 改为 `PointPrimitiveCollection` / `LabelCollection`。
- **渲染分辨率**:DPR 上限 1.5、Cesium 关闭超采样、页面纹理关闭 mipmap、anisotropy 8→4。
- **射线检测节流**:hover 合帧到渲染循环,只测可见窗口对象(binder 当前页 ±1、时间轴可视窗口)。
- **gzip**:Nginx 开启 gzip(含 `application/octet-stream`),geojson 3MB→1MB、城市 641KB→182KB。
## 运行
```bash
@@ -71,6 +95,7 @@ curl -s -o /dev/null -w "%{http_code}\n" https://hist.fukun.net/
## 操作
- **拖动** 旋转视角,**滚轮** 缩放
- 地理视图:**左键拖拽** 旋转、**滚轮** 缩放、**右键拖拽** 倾斜环视(松手不回正)、**中键** 回正
- **← →** 或底部按钮 翻页(翻面查看背面素描)
- 点击 活页 / 时间轴卡片 / 地球标记 选中词条
- 顶部按钮或按键 **1 / 2 / 3** 切换 活页本 / 时间轴 / 地理 视图
@@ -79,18 +104,18 @@ curl -s -o /dev/null -w "%{http_code}\n" https://hist.fukun.net/
```
src/
main.js 入口
core/App.js 编排器:渲染、灯光、相机、视图切换、拾取
scene/Binder.js 活页本(封面、环、双面活页、翻页动画)
scene/Timeline.js 时间轴视图
scene/Globe.js 地理视图(点阵地球、弧线、标记)
textures/pages.js 纸张 + 登记卡/素描两面纹理
textures/sketch.js 程序化素描生成器
data/entries.js 历史词条数据
data/worldMap.js 简化大陆轮廓
ui/overlay.js HTML 覆盖层
utils/ 缓动 / 文字精灵
scripts/ 截图与验证辅助(开发用)
main.js 入口
core/App.js 编排器:渲染、灯光、相机、视图切换、拾取
scene/binder.js 活页本(封面、环、双面活页、翻页动画)
scene/timeline.js 时间轴视图
scene/CesiumGlobe.js 地理视图(Cesium 地球、国界、城市、词条便签)
textures/pages.js 纸张 + 登记卡/素描两面纹理
textures/sketch.js 程序化素描生成器
data/entries.js 历史词条数据
ui/overlay.js HTML 覆盖层
ui/loading.js 加载遮罩
utils/ 缓动 / 文字精灵
scripts/ 截图与验证辅助(开发用)
```
## TODO / 后续规划
@@ -100,3 +125,6 @@ scripts/ 截图与验证辅助(开发用)
- [ ] **时间轴时期划分**:时间轴轴线上标注中西方历史时期刻度(如中国朝代:夏商周 / 秦汉 / 隋唐 / 宋元明清;西方:古典时代 / 中世纪 / 文艺复兴 / 启蒙运动 / 工业革命等),作为背景衬托。
- [ ] **词条插入时间轴**:词条按其 `timeNumeric` 真实时间位置插入时间轴(当前为等距排列),使时期刻度与词条位置相互对应。
- [ ] **词条结构考究与排版优化**:重新审视 `entries.js` 数据模型(补充年代精度、文明圈、影响、关键词等字段),并优化登记卡正面排版(信息层级、留白、装饰细节)。
- [ ] **性能进一步优化**:继续排查渲染 / 显存 / 加载瓶颈(已做:纹理懒加载、按需渲染、几何降级、双面材质、gzip 等)。
- [ ] **边界测试修复**:尾页(第一页 / 最后一页)前后的边界情况,在地理视图与时间轴视图存在 bug,待修。
- [ ] **时间轴清晰度**:时间轴视图当前偏模糊,需排查(可能是卡片低分辨率纹理 256×358 或渲染分辨率导致)。
+164 -44
View File
@@ -55,7 +55,7 @@ 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, B = 2; // S: 2x 超采样,B: 边框预留
const padX = 7, padY = 4, radius = 2, arrowW = 11, 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');
@@ -77,16 +77,15 @@ function makeStickyNote(text, fontSize, selected = false) {
// 箭头 + 圆角矩形一体化路径(箭头尖端在 (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.quadraticCurveTo(ox + arrowW * 0.7, oy, ox + arrowW, oy);
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.lineTo(ox + arrowW, oy + h);
// 下侧:一条曲线从下边缘平滑过渡回尖端(起点水平切线)
ctx.quadraticCurveTo(ox + arrowW * 0.7, oy + h, ox, oy + h / 2);
ctx.closePath();
if (selected) {
@@ -117,7 +116,7 @@ function makeStickyNote(text, fontSize, selected = false) {
ctx.font = font;
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.fillText(text, ox + arrowW + bodyW / 2, oy + h / 2 + 1);
ctx.fillText(text, ox + arrowW + bodyW / 2 - 2, oy + h / 2 + 1);
return { canvas: c, scale: 1 / S, width: cw, height: ch, tipX: B, tipY: B + h / 2 };
}
@@ -203,8 +202,8 @@ export class CesiumGlobe {
scene.skyBox.show = false;
scene.sun.show = false;
scene.moon.show = false;
scene.globe.enableLighting = true; // 地形法线明暗 + 水面高光/波纹
scene.globe.showGroundAtmosphere = true; // 地平线大气辉光
scene.globe.enableLighting = false;
scene.globe.showGroundAtmosphere = false;
scene.globe.baseColor = Cesium.Color.fromCssColorString('#d9e6f0'); // 冰盖浅色:影像/地形未覆盖的南北极区域显示为冰盖,而非黑洞
// 相机交互:限制滚轮缩放范围,避免过近/过远
@@ -228,11 +227,12 @@ export class CesiumGlobe {
},
];
// 阻止右键弹出浏览器菜单
// 阻止右键弹出浏览器菜单;阻止中键触发浏览器自动滚动
scene.canvas.addEventListener('contextmenu', (e) => e.preventDefault());
scene.canvas.addEventListener('mousedown', (e) => { if (e.button === 1) e.preventDefault(); });
// 精细化渲染:高清 + 精细地形
scene.globe.maximumScreenSpaceError = 1.0; // 更精细的地形起伏
scene.globe.maximumScreenSpaceError = 2.0; // 地形细分
scene.globe.tileCacheSize = 600; // 更大的瓦片缓存,减少细节刷新
scene.fxaa = true; // 后处理抗锯齿(MSAA 默认已 4x)
viewer.useBrowserRecommendedResolution = false; // 按设备像素比渲染,高分屏清晰
@@ -240,10 +240,45 @@ export class CesiumGlobe {
scene.maximumRenderTimeChange = Infinity; // 配合 requestRenderMode:静止时停止重绘,大幅省电省帧
// 卫星影像
// 检测 ESRI "Map data not yet available" 灰色错误瓦片并丢弃,自动回退父级放大
const discardNotAvailableTile = {
_canvas: document.createElement('canvas'),
_ctx: null,
isReady() {
return true;
},
shouldDiscardImage(image) {
try {
if (!this._ctx) {
this._ctx = this._canvas.getContext('2d', { willReadFrequently: true });
}
this._canvas.width = 8;
this._canvas.height = 8;
this._ctx.drawImage(image, 0, 0, 8, 8);
const d = this._ctx.getImageData(0, 0, 8, 8).data;
let gray = 0;
let total = 0;
for (let i = 0; i < d.length; i += 4) {
const r = d[i];
const g = d[i + 1];
const b = d[i + 2];
const mx = Math.max(r, g, b);
const mn = Math.min(r, g, b);
if (mx - mn < 15 && r > 110 && r < 240) gray++;
total++;
}
return total > 0 && gray / total > 0.92;
} catch (e) {
return false;
}
},
};
const imagery = new Cesium.UrlTemplateImageryProvider({
url: IMAGERY_URL,
credit: 'Imagery © Esri, Maxar, Earthstar Geographics',
maximumLevel: 19,
tileDiscardPolicy: discardNotAvailableTile,
});
const imageryLayer = new Cesium.ImageryLayer(imagery, {
// 卫星影像不覆盖极区(约 ±85° 外返回黑块),限制范围让极区用冰盖底色
@@ -263,6 +298,7 @@ export class CesiumGlobe {
viewer.clock.shouldAnimate = false;
this._buildMarkers();
this._clampMarkersToTerrain();
this._setupPick();
this._setupRightRestore();
this._loadBoundaries();
@@ -288,9 +324,11 @@ export class CesiumGlobe {
_buildMarkers() {
ENTRIES.forEach((entry, i) => {
const position = Cesium.Cartesian3.fromDegrees(entry.lng, entry.lat);
const noteNormal = makeStickyNote(entry.name, 16, false);
const noteSelected = makeStickyNote(entry.name, 16, true);
const noteNormal = makeStickyNote(entry.name, 14, false);
const noteSelected = makeStickyNote(entry.name, 14, true);
this.markers.push({
lng: entry.lng,
lat: entry.lat,
position,
r2: Cesium.Cartesian3.magnitudeSquared(position),
noteNormal,
@@ -301,6 +339,64 @@ export class CesiumGlobe {
this._initMarkerLayer();
}
// 把便签锚点贴到地形表面(否则在椭球面高度 0 上,放大旋转时会飘)
async _clampMarkersToTerrain() {
const scene = this.viewer.scene;
if (!scene) return;
// 等待地形 provider 就绪(setTerrain 是异步的,调用时 provider 可能还没准备好)
let tp = scene.terrainProvider;
if (!tp) {
tp = await new Promise((resolve) => {
const started = Date.now();
const poll = () => {
const p = scene.terrainProvider;
if (p) { resolve(p); return; }
if (Date.now() - started > 30000) { resolve(undefined); return; }
setTimeout(poll, 500);
};
poll();
});
}
if (!tp) {
console.warn('[CesiumGlobe] 地形 provider 未就绪,便签保持椭球面高度');
return;
}
const cartos = this.markers.map((m) =>
Cesium.Cartographic.fromDegrees(m.lng, m.lat),
);
try {
// 固定层级 15(约 30m):ArcGIS 高程服务无 availability,不用 sampleTerrainMostDetailed
await Cesium.sampleTerrain(tp, 15, cartos);
} catch (err) {
console.warn('[CesiumGlobe] 地形高度采样失败:', err);
}
// 失败的点逐级降级重试(更粗的层级更容易成功)
for (const level of [12, 8, 4]) {
const retry = cartos.filter((c) => c.height == null || !isFinite(c.height));
if (retry.length === 0) break;
try {
await Cesium.sampleTerrain(tp, level, retry);
} catch (err) {
break;
}
}
let clamped = 0;
for (let i = 0; i < this.markers.length; i++) {
const h = cartos[i] && cartos[i].height;
if (h != null && isFinite(h)) {
const m = this.markers[i];
m.position = Cesium.Cartesian3.fromDegrees(m.lng, m.lat, h);
m.r2 = Cesium.Cartesian3.magnitudeSquared(m.position);
clamped++;
}
}
console.log(`[CesiumGlobe] 便签已贴附地形:${clamped}/${this.markers.length}`);
}
// 便签用 DOM 覆盖层渲染:始终在城市/国家名上层,且缩放到最近也不会漂移
_initMarkerLayer() {
const container = document.getElementById('cesium-container');
@@ -319,11 +415,11 @@ export class CesiumGlobe {
m.tipY = m.noteNormal.tipY;
m.normalUrl = m.noteNormal.canvas.toDataURL();
m.selectedUrl = m.noteSelected.canvas.toDataURL();
m.screenX = -1e9;
m.screenY = -1e9;
el.style.backgroundImage = `url("${m.normalUrl}")`;
el.addEventListener('click', (e) => {
e.stopPropagation();
this.onPick?.(m.index);
});
el.style.transform = 'rotate(-45deg)';
el.style.transformOrigin = `${m.tipX}px ${m.tipY}px`;
this._markerLayer.appendChild(el);
}
@@ -351,48 +447,68 @@ export class CesiumGlobe {
el.style.display = 'block';
el.style.opacity = '1';
el.style.left = `${win.x - m.tipX}px`;
el.style.top = `${win.y - m.tipY}px`;
m.screenX = win.x - m.tipX;
m.screenY = win.y - m.tipY;
el.style.left = `${m.screenX}px`;
el.style.top = `${m.screenY}px`;
}
}
_setupPick() {
const viewer = this.viewer;
// 移除 Viewer 默认的单击选中与双击“追踪实体”:否则双击后会锁定相机(定住)
// 标记便签已改为 DOM 覆盖层,点击由 DOM 元素自行处理
// 移除 Viewer 默认的单击选中与双击“追踪实体”
viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
// 便签层 pointer-events:none 后,左键通过 canvas 命中测试选中便签
viewer.screenSpaceEventHandler.setInputAction((movement) => {
const x = movement.position.x;
const y = movement.position.y;
const canvasRect = viewer.canvas.getBoundingClientRect();
for (const m of this.markers) {
const el = m.el;
if (!el || el.style.display === 'none') continue;
const r = el.getBoundingClientRect();
if (
x >= r.left - canvasRect.left && x <= r.right - canvasRect.left &&
y >= r.top - canvasRect.top && y <= r.bottom - canvasRect.top
) {
this.onPick?.(m.index);
break;
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
// 右键原生 tilt 松开后自动回位:按下记录相机状态,松开恢复(并清掉 tilt 惯性余力)
// 右键原生 tilt:按下记录位置;松开不回正。中键:回正到“不倾斜不旋转”(天底 + 北朝上)
_setupRightRestore() {
const scene = this.viewer.scene;
const camera = this.viewer.camera;
const handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
this._rightRestore = null;
this._rightHome = null;
handler.setInputAction(() => {
camera.cancelFlight(); // 取消可能仍在进行的回正动画
this._rightRestore = {
position: Cesium.Cartesian3.clone(camera.position),
direction: Cesium.Cartesian3.clone(camera.direction),
up: Cesium.Cartesian3.clone(camera.up),
};
this._rightHome = Cesium.Cartesian3.clone(camera.position);
}, Cesium.ScreenSpaceEventType.RIGHT_DOWN);
handler.setInputAction(() => {
if (!this._rightRestore) return;
const s = this._rightRestore;
this._rightRestore = null;
// 松开右键:只清掉 tilt 惯性余力,不回正
const tiltState = scene.screenSpaceCameraController._lastInertiaTiltMovement;
if (tiltState) tiltState.inertiaEnabled = false;
// 回正改用 flyTo 渐变,而不是瞬间 setView
}, Cesium.ScreenSpaceEventType.RIGHT_UP);
handler.setInputAction(() => {
// 中键:回正(天底 + 北朝上,保持原注视点)
if (!this._rightHome) return;
const pos = this._rightHome;
this._rightHome = null;
camera.flyTo({
destination: s.position,
orientation: { direction: s.direction, up: s.up },
destination: pos,
orientation: { heading: 0, pitch: Cesium.Math.toRadians(-90), roll: 0 },
duration: 0.5,
});
}, Cesium.ScreenSpaceEventType.RIGHT_UP);
}, Cesium.ScreenSpaceEventType.MIDDLE_DOWN);
this._rightRestoreHandler = handler;
}
@@ -441,13 +557,15 @@ export class CesiumGlobe {
let cname = props.NAME_ZH || props.NAME;
if (cname === '中华民国') cname = '中国台湾';
if (cname && props.LABEL_X != null && props.LABEL_Y != null) {
const fontSize = areaKm2 > 5e6 ? 22 : areaKm2 > 1.5e6 ? 15 : areaKm2 > 3e5 ? 12 : 10;
const fontSize = areaKm2 > 5e6 ? 28 : areaKm2 > 1.5e6 ? 21 : areaKm2 > 3e5 ? 18 : 16;
countryLabels.add({
position: Cesium.Cartesian3.fromDegrees(props.LABEL_X, props.LABEL_Y),
text: cname,
font: `bold ${fontSize}px "Noto Serif SC", "Songti SC", "STSong", "SimSun", Georgia, serif`,
fillColor: black,
style: Cesium.LabelStyle.FILL,
fillColor: textGold,
outlineColor: black,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: 1000, // 1km 内不深度测试(近处不消失),远处仍遮挡背面
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 1e7),
@@ -491,8 +609,8 @@ export class CesiumGlobe {
const scene = this.viewer.scene;
const textGold = Cesium.Color.fromCssColorString('#e0c46a');
const black = Cesium.Color.fromCssColorString('#14100d');
const ddc = new Cesium.DistanceDisplayCondition(0, 4e6);
const tdc = new Cesium.NearFarScalar(2e6, 1.0, 4e6, 0.0);
const ddc = new Cesium.DistanceDisplayCondition(0, 2.5e6);
const tdc = new Cesium.NearFarScalar(1.25e6, 1.0, 2.5e6, 0.0);
let cities = [];
try {
@@ -522,9 +640,11 @@ export class CesiumGlobe {
labels.add({
position,
text: c.name,
font: 'bold 11px "Noto Serif SC", "Songti SC", "STSong", "SimSun", Georgia, serif',
fillColor: black,
style: Cesium.LabelStyle.FILL,
font: 'bold 17px "Noto Serif SC", "Songti SC", "STSong", "SimSun", Georgia, serif',
fillColor: textGold,
outlineColor: black,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -6),
-2
View File
@@ -44,10 +44,8 @@ html, body {
}
.marker-note {
position: absolute;
pointer-events: auto;
background-repeat: no-repeat;
background-size: 100% 100%;
cursor: pointer;
}
/* 气氛遮罩 */