d3.js实现坐标轴与文本位置同步旋转、矩形保持不旋转问题求解
实现方案
要实现坐标轴旋转后矩形位置同步偏移但矩形本身不旋转,核心思路是手动计算每个刻度点旋转后的坐标,将矩形容器平移到该坐标,矩形内部相对容器定位,不做旋转处理即可。
核心改动说明
- 统一管理旋转参数,提前将角度转为弧度并计算对应三角函数值
- 通过二维旋转公式,以坐标轴的变换原点
(0,5)为旋转中心,计算每个刻度点旋转后的坐标 - 矩形、文本仅相对自身父容器定位,不需要加旋转属性,即可保持原有朝向
完整实现代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
test() function test() { var width = 800 var height = 600 var margin = 20 // 统一配置旋转角度 const rotateAngle = 30 const rotateRad = rotateAngle * Math.PI / 180 const cos = Math.cos(rotateRad) const sin = Math.sin(rotateRad) // 旋转原点和坐标轴保持一致 const rotateOriginX = 0 const rotateOriginY = 5 var svg = d3.select('body').append('svg') .attr('width',width).attr('height',height) .style('border','1px solid red') var g = svg.append('g') .attr("transform", `translate(${margin}, ${margin})`) var data = [ {pos:0,name:'A'}, {pos:2,name:'B'}, {pos:12,name:'C'}, {pos:15,name:'D'}, {pos:20,name:'E'}, {pos:23,name:'F'}, {pos:26,name:'G'}, ]; var xranges = data.map(function(d){ return d.pos }) var scalelinear = d3.scaleLinear() .domain([d3.min(xranges), d3.max(xranges)]) .range([0, width-2*margin]); var scalepoint = d3.scalePoint() .domain(xranges) .range([0, width-2*margin]); var scale = scalepoint var x_axis = d3.axisTop() .scale(scale) g.append("g") .call(x_axis) .attr("transform", `translate(${rotateOriginX}, ${rotateOriginY}) rotate(${rotateAngle})`) var iw = 48 var ih = 80 var g1 = g.selectAll(null) .data(data).enter() .append('g') .attr("transform", d => { // 原始刻度坐标 const originX = scale(d.pos) const originY = 0 // 计算旋转后的坐标 const relativeX = originX - rotateOriginX const relativeY = originY - rotateOriginY const rotatedX = rotateOriginX + relativeX * cos - relativeY * sin const rotatedY = rotateOriginY + relativeX * sin + relativeY * cos return `translate(${rotatedX}, ${rotatedY})` }) g1.append('rect') .attr('x', -iw/2) .attr('y', 0) .attr('width', iw) .attr('height', ih) .attr('fill','none') .attr('stroke','black') g1.append('text') .attr('x', 0) .attr('y', ih/2) .text(d => d.name) .attr('text-anchor','middle') .attr('fill','none') .attr('stroke','black') }
内容的提问来源于stack exchange,提问作者lucky1928
相关产品推荐
相关产品推荐

