d3.js - d3.js 拆分组,应用旋转和平移并计算新的平移坐标
问题描述
给定一个应用了平移和旋转变换的组中的初始矩形,我想用相同的旋转分割给定的矩形,并且考虑到旋转的平移。
下面是一个代码示例,试图解释我试图实现的目标。
我相信我只需要计算每个新矩形的平移 x,y 吗?
//Draw initial svg
const svg = d3.select('body').append('svg').attr('width', 1000).attr('height', 1000)
// Data for the initial group with one rectangle inside
const groupData = {width: 200, height: 100, translateX: 200, translateY: 150, rotation: 45}
//Create the initial group
let group1 = svg.append('g').attr('id', 'group1')
//Append a rect to the initial group, translate and rotate
group1.append('rect').attr('width', groupData.width).attr('height', groupData.height).attr('fill', 'blue')
group1.attr('transform', `translate(${groupData.translateX}, ${groupData.translateY}) rotate(${groupData.rotation}, ${groupData.width / 2}, ${groupData.height / 2})`)
// Attempt to split the initial group in equal parts based on the number of rows and columns from below
const splitGroupData = {
rows: 2,
columns: 2
}
//Extract the data
const {rows, columns} = splitGroupData
// Create row and column array to dynamically split the initial group based on the split data
const rowArray = [...Array(+rows).keys()]
const columnArray = [...Array(+columns).keys()]
//creates a rect inside the group 1 to split into 2 rows and 2 columns
rowArray.forEach(row => {
columnArray.forEach( column => {
let newRect = group1
.append("rect")
.attr("width", groupData.width / columns)
.attr("height", groupData.height / rows)
.attr("x", (groupData.width / +columns) * column)
.attr("y", (groupData.height / +rows) * row)
.attr("stroke", "red")
.attr("fill", "transparent");
})
})
// Trying to recreate the same rect as above but within their own group and can't figure how to calculate the right translation
rowArray.forEach(row => {
columnArray.forEach( column => {
let newGroup = svg.append('g').attr('id', `group${column}${row}`)
newGroup.append('rect')
.attr('width', groupData.width / columns)
.attr('height', groupData.height / rows)
.attr('fill', 'orange')
const cx = groupData.width / 2;
const cy = groupData.height / 2;
let tmpX = groupData.translateX + (groupData.width / +columns) * column;
let tmpY = groupData.translateY + (groupData.height / +rows) * row;
tmpX = tmpX - cx;
tmpY = tmpY - cy;
const pointX =
tmpX * Math.cos((groupData.rotation * Math.PI) / 180) -
tmpY * Math.sin((groupData.rotation * Math.PI) / 180);
const pointY =
tmpX * Math.sin((groupData.rotation * Math.PI) / 180) +
tmpY * Math.cos((groupData.rotation * Math.PI) / 180);
newGroup.attr('transform', `translate(${groupData.translateX + pointX}, ${groupData.translateY + pointY}) rotate(${groupData.rotation}, ${groupData.width / columns / 2}, ${groupData.height / rows / 2})`)
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
编辑:现在我可以将每个新矩形定位在正确的位置上。在代码片段的示例中,我只想让所有 4 个矩形都覆盖初始矩形。
解决方案
好的,所以我在多次手动测试后想通了。不确定它是否是最有效的公式,但至少它有效!希望它可以帮助遇到同样情况的人!
//Draw initial svg
const svg = d3.select('body').append('svg').attr('width', 1000).attr('height', 1000)
// Data for the initial group with one rectangle inside
const groupData = {width: 200, height: 100, translateX: 200, translateY: 150, rotation: 45}
//Create the initial group
let group1 = svg.append('g').attr('id', 'group1')
//Append a rect to the initial group, translate and rotate
group1.append('rect').attr('width', groupData.width).attr('height', groupData.height).attr('fill', 'blue')
group1.attr('transform', `translate(${groupData.translateX}, ${groupData.translateY}) rotate(${groupData.rotation}, ${groupData.width / 2}, ${groupData.height / 2})`)
const rows = 3
const columns = 2
// Create row and column array to dynamically split the initial group based on the rows and columns numbers
const rowArray = [...Array(+rows).keys()]
const columnArray = [...Array(+columns).keys()]
rowArray.forEach(row => {
columnArray.forEach( column => {
let newGroup = svg.append('g').attr('id', `group${column}${row}`)
newGroup.append('rect')
.attr('width', groupData.width / columns)
.attr('height', groupData.height / rows)
.attr('fill', 'orange')
const cx = groupData.translateX + (groupData.width / columns / 2) * (columns - 1);
const cy = groupData.translateY + (groupData.height / rows / 2) * (rows - 1);
const tmpX = groupData.translateX + (groupData.width / columns) * column - cx;
const tmpY = groupData.translateY + (groupData.height / rows) * row - cy;
const pointX = tmpX * Math.cos((groupData.rotation * Math.PI) / 180) - tmpY * Math.sin((groupData.rotation * Math.PI) / 180) + cx;
const pointY = tmpX * Math.sin((groupData.rotation * Math.PI) / 180) + tmpY * Math.cos((groupData.rotation * Math.PI) / 180) + cy;
newGroup.attr('transform', `translate(${groupData.rotation != 0 ? pointX : groupData.translateX + (groupData.width / columns) * column}, ${groupData.rotation != 0 ? pointY : groupData.translateY + (groupData.height / rows) * row}) rotate(${groupData.rotation}, ${groupData.width / columns / 2}, ${groupData.height / rows / 2})`)
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
推荐阅读
- java - 事务中的更改子集有时在提交后不久不可见
- javascript - 从 JSON 数据(嵌套对象)计算球队的赛季目标
- javascript - XMLHttpRequest 未发送
- svn - 无法连接到磁盘 URL file:/// 处的 Subversion 存储库
- excel - 倒数计时器失败
- python - 迭代日期,计算每 24 小时的平均值
- google-chrome - 无法从 CHROME 获取 Gravitee API 网关响应,但能够从 POSTMAN 获取
- php - Ajax 请求不执行(完全是幽灵)
- angular - 在组件的方法中创建的对象的 TypeScript 测试属性
- sql - SQL 无法将 Varchar 转换为数值 - 转换失败错误