d3开发SVG图例时如何让text相对对应rect独立旋转
D3图例文本独立旋转问题修复
问题现象
使用D3编写横向排列的10格图例组件时,预期将每个单元格对应的文本标签放在单元格上方,呈向右轻微倾斜的排布;添加旋转配置后所有文本被识别为整体成排旋转,未和绑定的单元格一一对应独立旋转。
附初始问题代码:
<svg preserveAspectRatio="xMinYMin meet" viewBox={`0 0 800 70`}> <g transform={`translate(${[dms.marginTop, dms.marginLeft].join(',')})`}> <g> {range(10).map((d) => ( <> <rect key={`${d}_legendCell`} width={cellSize - 1.5} height={cellSize - 1.5} fill={colorScale(Number(legendBands(String(d))) + interval)} x={d * cellSize} ></rect> <text key={`${d}_legendLabel`} fontWeight="300" fontSize="12" width="100" y={cellSize * d} transform="rotate(290)" dy=".85rem" > {Number(legendBands(String(d))).toFixed(1)} </text> </> ))} </g> </g> </svg>
问题根因
- SVG的
rotate()变换默认以SVG坐标系原点(0,0)为旋转中心,仅传入角度参数时,所有元素都会绕全局原点旋转,自然出现整体偏移错位 - 代码中使用空Fragment包裹单元格和文本,没有将每一组「单元格+对应标签」做独立分组,全局坐标计算容易混乱
- 文本定位逻辑错误:矩形是横向排布,仅x坐标随索引偏移,y坐标统一为0;初始代码给文本设置
y={cellSize * d},会让文本沿纵向错位排布 - 旋转角度设置错误:290度旋转接近完全竖排,不符合「向右轻微倾斜」的预期
修复方案
核心调整3处即可实现预期效果:
- 元素分组调整:用独立的
<g>标签替换空Fragment,包裹每一组rect和text,每组先通过translate平移到对应单元格的横向位置,组内元素使用局部坐标系定位,减少全局坐标计算误差 - 旋转参数补全:调用
rotate(角度, 旋转中心x, 旋转中心y)时,传入文本自身的定位坐标作为旋转中心,让每个文本绕自身中心点旋转,而非绕全局原点 - 定位与样式修正:修正文本的x/y坐标到对应单元格的上方居中位置,添加
text-anchor: middle让文本居中对齐,调整旋转角度为-30~-40度区间即可实现向右轻微倾斜的效果
修复后代码参考:
<svg preserveAspectRatio="xMinYMin meet" viewBox={`0 0 800 70`}> <g transform={`translate(${dms.marginTop}, ${dms.marginLeft})`}> {range(10).map((d) => ( // 每组单元格+标签单独分组,统一平移到对应横向位置 <g key={d} transform={`translate(${d * cellSize}, 0)`}> <rect width={cellSize - 1.5} height={cellSize - 1.5} fill={colorScale(Number(legendBands(String(d))) + interval)} x={0} /> <text fontWeight="300" fontSize="12" // 文本定位到单元格水平居中、上方6px位置 x={(cellSize - 1.5) / 2} y={-6} text-anchor="middle" // 指定旋转中心为文本自身坐标,绕自身旋转-35度实现右倾斜 transform={`rotate(-35, ${(cellSize - 1.5) / 2}, -6)`} > {Number(legendBands(String(d))).toFixed(1)} </text> </g> ))} </g> </svg>
内容的提问来源于stack exchange,提问作者Kraken
相关产品推荐
相关产品推荐

