D3ForceLayout: 配置的 center / centerX / x / y / radial 坐标及 radius 参数被默认值覆盖失效
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 75/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- d3, typescript
調査の方向性
マージ順序の問題は src/algorithm/d3-force/index.ts の getCenterOptions、getXForceOptions、getYForceOptions、getRadialOptions にあり、ユーザーオプションの後に assignDefined を通じてデフォルト値が展開されています。まずissueの再現スクリプトを実行し、重心が [350, 350] であること、radial.radius の値が 100 であることを確認してください。ユーザーが指定した center、centerX/centerY、force の x/y/radial 座標、radial.radius が反映され、未設定のレイアウトが変わらなければ完了です。
索引モデルが issue の本文から書いたものです。
説明
版本
@antv/layout:2.0.1(npmbeta),v5分支(62bb479)同样可复现- Node.js: 24
问题描述
D3ForceLayout 在合并配置时,默认值后置覆盖了用户传入的参数,导致以下自定义配置失效:
- 中心点配置失效:
center: { x, y }与文档推荐的快捷字段centerX/centerY均不生效,中心点始终固定为视口中心[width / 2, height / 2](且源码中未读取centerX/centerY)。 - 力的坐标被覆盖:中心力开启时(默认开启),
x: { x }、y: { y }、radial: { x, y }均会被中心点坐标覆盖。 - 径向半径被覆盖:
radial: { radius }始终被默认值100覆盖。
复现
const { D3ForceLayout } = require('@antv/layout');
const data = {
nodes: [{ id: 'a' }, { id: 'b' }, { id: 'c' }, { id: 'd' }],
edges: [
{ id: 'e1', source: 'a', target: 'b' },
{ id: 'e2', source: 'b', target: 'c' },
{ id: 'e3', source: 'c', target: 'd' },
],
};
const centroid = async (options) => {
const layout = new D3ForceLayout({ width: 700, height: 700, ...options });
await layout.execute(data);
let x = 0, y = 0, n = 0;
layout.forEachNode((node) => { x += node.x; y += node.y; n += 1; });
return [Math.round(x / n), Math.round(y / n)];
};
(async () => {
console.log(await centroid({ center: { x: 300, y: 200 } })); // 实际: [350, 350], 期望: [300, 200]
console.log(await centroid({ centerX: 300, centerY: 200 })); // 实际: [350, 350], 期望: [300, 200]
const layout = new D3ForceLayout({
width: 700,
height: 700,
x: { x: 100 },
radial: { x: 100, y: 100, radius: 50 },
});
await layout.execute(data);
console.log(layout.getForce('x').x()()); // 实际: 350, 期望: 100
console.log(layout.getForce('radial').x(), layout.getForce('radial').y()); // 实际: 350 350, 期望: 100 100
console.log(layout.getForce('radial').radius()()); // 实际: 100, 期望: 50
})();
问题原因
在 src/algorithm/d3-force/index.ts 中,getCenterOptions、getXForceOptions、getYForceOptions 和 getRadialOptions 合并配置时使用了如下写法:
return assignDefined({}, options.center || {}, {
x: viewport.width / 2,
y: viewport.height / 2,
strength: options.centerStrength,
});
默认值对象放在了用户配置对象之后,直接覆盖了用户传入的自定义值(如视口中心 width / 2、中心点坐标、radius: 100)。
修复建议
将默认值前置,调整合并顺序为:默认值 → force 对象 → 快捷字段。
这样仅在未配置时使用默认值,未配置相关参数的已有布局不受影响。我稍后会提交对应的修复 PR。
待确认问题
- 配置优先级:文档
d3-force-options说明为“两者混用时以 force 对象为准”,但当前代码实现中所有 getter(如manyBody与nodeStrength、center.strength与centerStrength)均为“快捷字段优先覆盖 force 对象”。PR 沿用了现有实现的约定,是否需要后续统一调整文档或实现? - 中心配置文档说明:同一文档的“通用配置”中提到“
D3ForceLayout中心相关配置不使用center,而是使用centerX/centerY”,但在“2D 扩展”章节和 TypeScript 类型定义中均支持center: false | { x?, y?, strength? }。该处文档说明是否需要同步修正?
- 主要言語
- TypeScript
- スター
- 280
- フォーク
- 61
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
antvis/layout のほかの issue
-
難易度 3/5 半日 初心者へのやさしさ 35/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
-
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
-
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
-
layout-gpu
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
oxidecomputer/skepsis#102 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
voidzero-dev/void#677 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
kunchenguid/gh-axi#247 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
lidge-jun/opencodex#8101 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信