Tune camera and timeline controls, add globe fly-to
- Clamp binder/timeline zoom ranges and disable OrbitControls zoom, using custom smooth zoom instead - Disable middle/right mouse buttons; reduce rotate speed - Fly camera to picked marker on globe click - Rebuild leather surfaces with a regular grid for smooth curvature - Refine suede and kraft paper textures, punch real page holes - Reposition axis, time labels, and detail card; speed up iris fade
This commit is contained in:
+14
-13
@@ -7,6 +7,8 @@ export const TIMELINE_SPREAD = 6.2; // 横轴范围 ±6.2(超出视口,可
|
||||
|
||||
const CARD_FLOAT = 0.14; // 选中时上浮高度
|
||||
const NAME_Y = 0.42; // 主题标签基准高度(活页上方)
|
||||
const AXIS_Y = -0.40; // 时间轴基线高度
|
||||
const TIME_Y = -0.56; // 时间标签高度(轴下方)
|
||||
|
||||
function cardX(i, n) {
|
||||
return (i / (n - 1)) * 2 * TIMELINE_SPREAD - TIMELINE_SPREAD;
|
||||
@@ -24,27 +26,21 @@ export class Timeline {
|
||||
|
||||
_buildLine() {
|
||||
const n = ENTRIES.length;
|
||||
const min = cardX(0, n) - 0.4;
|
||||
const max = cardX(n - 1, n) + 0.4;
|
||||
// 轴线向两侧延伸足够远(并关闭雾化),滚动到边缘也不见端点,视觉上无限长
|
||||
const extent = 50;
|
||||
|
||||
const lineMat = new THREE.LineBasicMaterial({ color: 0xc9a227, transparent: true, opacity: 0.7 });
|
||||
const lineMat = new THREE.LineBasicMaterial({ color: 0xc9a227, transparent: true, opacity: 0.7, fog: false });
|
||||
const lineGeo = new THREE.BufferGeometry().setFromPoints([
|
||||
new THREE.Vector3(min, -0.85, 0), new THREE.Vector3(max, -0.85, 0),
|
||||
new THREE.Vector3(-extent, AXIS_Y, 0), new THREE.Vector3(extent, AXIS_Y, 0),
|
||||
]);
|
||||
this.group.add(new THREE.Line(lineGeo, lineMat));
|
||||
|
||||
const glowMat = new THREE.LineBasicMaterial({ color: 0xe0c46a, transparent: true, opacity: 0.22 });
|
||||
const glowGeo = new THREE.BufferGeometry().setFromPoints([
|
||||
new THREE.Vector3(min, -0.855, -0.03), new THREE.Vector3(max, -0.855, -0.03),
|
||||
]);
|
||||
this.group.add(new THREE.Line(glowGeo, glowMat));
|
||||
|
||||
// 刻度:向上指向卡片、向下指向时间标签
|
||||
const tickMat = new THREE.LineBasicMaterial({ color: 0xc9a227, transparent: true, opacity: 0.5 });
|
||||
ENTRIES.forEach((e, i) => {
|
||||
const x = cardX(i, n);
|
||||
const g = new THREE.BufferGeometry().setFromPoints([
|
||||
new THREE.Vector3(x, -0.98, 0), new THREE.Vector3(x, -0.7, 0),
|
||||
new THREE.Vector3(x, AXIS_Y - 0.14, 0), new THREE.Vector3(x, AXIS_Y + 0.12, 0),
|
||||
]);
|
||||
this.group.add(new THREE.Line(g, tickMat));
|
||||
});
|
||||
@@ -73,12 +69,12 @@ export class Timeline {
|
||||
card.add(outline);
|
||||
|
||||
// 活页上方:主题(常显,随选中上浮,超宽居中换行)
|
||||
const name = makeTextSprite(entry.name, { fontSize: 17, color: '#e8d9b4', scale: 0.13, maxWidth: 1.0 });
|
||||
const name = makeTextSprite(entry.name, { fontSize: 17, color: '#e8d9b4', scale: 0.12, maxWidth: 0.9 });
|
||||
name.position.set(x, NAME_Y, 0);
|
||||
|
||||
// 轴下方:时间(常显,固定不动)
|
||||
const time = makeTextSprite(entry.time, { fontSize: 13, color: '#c9a227', scale: 0.11 });
|
||||
time.position.set(x, -1.06, 0);
|
||||
time.position.set(x, TIME_Y, 0);
|
||||
|
||||
this.group.add(card, name, time);
|
||||
this.cards.push({ card, outline, name, nameBaseY: NAME_Y, index: i });
|
||||
@@ -94,4 +90,9 @@ export class Timeline {
|
||||
c.name.position.y = c.nameBaseY + (on ? CARD_FLOAT : 0);
|
||||
});
|
||||
}
|
||||
|
||||
// 返回某张卡片在时间轴组内的横向坐标(用于点击后居中)
|
||||
getCardX(index) {
|
||||
return cardX(index, ENTRIES.length);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user