今天我想要實現一個功能:當使用者搜尋特定節點後,自動將該節點置中到畫面中央。聽起來很簡單,對吧?就像 Google Maps 那樣,點擊一個地點就能自動移動到那裡。
但這個看似簡單的功能,卻讓我陷入了座標系統的地獄...
我發現了幾個不同的座標系統在同時運作:
zoomInner
的 translate
和 scale
#graph
容器的尺寸和位置// 我嘗試的各種計算方式
const nodeX = bbox.x + bbox.width / 2; // SVG 座標
const nodeY = bbox.y + bbox.height / 2;
// 嘗試轉換到螢幕座標
const scaledX = nodeX * scale;
const scaledY = nodeY * scale;
// 嘗試計算移動距離
const moveX = containerCenterX - scaledX;
const moveY = containerCenterY - scaledY;
但這些計算總是會有微妙的偏移,讓我懷疑人生。
function centerNode(nodeId) {
const bbox = node.getBBox();
const moveX = containerCenterX - nodeX;
const moveY = containerCenterY - nodeY;
// 結果:總是偏右邊
}
function centerNode(nodeId) {
const rect = node.getBoundingClientRect();
const containerRect = graph.getBoundingClientRect();
// 結果:座標完全錯亂
}
function centerNode(nodeId) {
// 先設定縮放為 100%
state.scalePct = 100;
applyZoom(100);
// 然後再置中
// 結果:還是有偏移
}
最後我決定移除所有縮放功能,固定使用 100% 縮放,但問題依然存在。
這些差異讓座標轉換變得極其複雜。
經過無數次的嘗試,我決定採用一個更實用的方案:讓使用者直接拖曳 SVG 來移動地圖。
// 拖曳 SVG 本身
document.addEventListener('mousedown', function(e) {
if (e.target.closest('svg')) {
startDrag(e);
}
});
// 避免在節點上啟動拖曳
if (e.target.closest('g.node')) {
return; // 不啟動拖曳
}
這個方案雖然不是自動置中,但至少讓使用者能夠手動將想要的節點移到畫面中央。
我深刻體會到不同座標系統之間的轉換是多麼複雜。每個系統都有自己的原點、單位和方向。
縮放比例會影響所有座標計算,即使設定為 100%,仍然可能有微妙的差異。
不同瀏覽器對 SVG 和 CSS Transform 的處理可能有細微差異。
在 SVG 上處理滑鼠事件需要考慮事件冒泡、座標轉換等問題。
function centerNode(nodeId) {
const bbox = node.getBBox();
const moveX = containerCenterX - bbox.x;
const moveY = containerCenterY - bbox.y;
zoomInner.style.transform = `translate(${moveX}px, ${moveY}px)`;
}
function centerNode(nodeId) {
const scale = state.scalePct / 100;
const scaledX = bbox.x * scale;
const scaledY = bbox.y * scale;
// 複雜的計算...
}
// 讓使用者直接拖曳 SVG
document.addEventListener('mousedown', function(e) {
if (e.target.closest('svg') && !e.target.closest('g.node')) {
startDrag(e);
}
});
今天的開發確實是「徒勞無功」的,我沒有實現自動置中功能。但是,這個過程讓我深刻理解了:
有時候,承認某個功能太複雜,改用更簡單的方案,也是一種智慧。今天的「失敗」讓我學會了:
雖然今天沒有做出成果,但這個嘗試又嘗試的過程,本身就是一種收穫。在程式設計的路上,失敗和成功一樣重要,甚至更重要,因為失敗教會我們更多。
明天,我會帶著今天的經驗,繼續前進。也許下次遇到類似的問題時,我會更早地選擇更簡單的解決方案,而不是陷入座標系統的地獄中。
沒有做出成果,也是一種成果。什麼收穫都沒有,也是一種收穫。
Day 24 完成。座標系統的地獄,讓我學會了謙遜,也讓我學會了選擇。