使用d3js计算二次SVG连接器的中点和曲线路径 [英] Using d3js to calculate midpoints and curve path for quadratic SVG connectors

查看:217
本文介绍了使用d3js计算二次SVG连接器的中点和曲线路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图显示从左侧矩形到右侧矩形的连接.两侧的矩形是根据JSON中的值动态构建的. 目前,我在矩形的左右两端放置了空的div,并以此为参考来获取x,y坐标,并以此绘制了二次SVG曲线. 在完成这项工作的同时,我想知道是否可以改善计算曲线路径的方式.

I am trying to show connections from rectangles on left to rectangles on right. The rectangles on both sides are dynamically constructed based on values in JSON. Currently I have placed empty divs on left and right end side of rectangles and using this as reference to obtain x,y co-ordinates and used this to draw a quadratic SVG curve. While this does the job , i wanted to know if i could improve the way i calculate the curve path.

SVG曲线的计算基于此处的答案 https://stackoverflow.com/a/49286885/9924482 . 这行得通,但我想知道d3js是否可以在给定两个点的情况下自动构建连接器.如果可以计算出中点,我确信连接会比我的计算更平滑.

Calculation of SVG curve is based on the answer found here https://stackoverflow.com/a/49286885/9924482. This works but I wanted to know if d3js could automatically construct a connector given two points.If it could calculate the midpoint i am sure the connections would be smoother than my calculation.

function x() {
    var p1x = parseFloat(document.getElementById("au").getAttribute("cx"));
    var p1y = parseFloat(document.getElementById("au").getAttribute("cy"));
    var p2x = parseFloat(document.getElementById("sl").getAttribute("cx"));
    var p2y = parseFloat(document.getElementById("sl").getAttribute("cy"));

    // mid-point of line:
    var mpx = (p2x + p1x) * 0.5;
    var mpy = (p2y + p1y) * 0.5;

    // angle of perpendicular to line:
    var theta = Math.atan2(p2y - p1y, p2x - p1x) - Math.PI / 2;

    // distance of control point from mid-point of line:
    var offset = 30;

    // location of control point:
    var c1x = mpx + offset * Math.cos(theta);
    var c1y = mpy + offset * Math.sin(theta);

    // show where the control point is:
    var c1 = document.getElementById("cp");
    c1.setAttribute("cx", c1x);
    c1.setAttribute("cy", c1y);

    // construct the command to draw a quadratic curve
    var curve = "M" + p1x + " " + p1y + " Q " + c1x + " " + c1y + " " + p2x + " " + p2y;
    var curveElement = document.getElementById("curve");
    curveElement.setAttribute("d", curve);
}

推荐答案

目前尚不清楚您要多少个控制点.如果要创建带有拐点的链接,最舒适的解决方案是使用D3

It's not clear in your question how many control points you want. If you want to create links with an inflection point, the most comfortable solution is using D3 link generators.

例如,假设您有以下数据:

For instance, suppose you have this data:

const data = [{x: 20, y: 20}, {x: 280, y: 130}];

您可以使用这样的链接生成器:

You can use a link generator like this:

const linkGenerator = d3.linkHorizontal()
  .x(d => d.x)
  .y(d => d.y)
  .source(d => d[0])
  .target(d => d[1]);

这是一个演示:

const data = [{
  x: 20,
  y: 20
}, {
  x: 280,
  y: 130
}];
const svg = d3.select("svg");
const linkGenerator = d3.linkHorizontal()
  .x(d => d.x)
  .y(d => d.y)
  .source(d => d[0])
  .target(d => d[1]);
const circles = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("r", 10)
  .attr("cx", d => d.x)
  .attr("cy", d => d.y);
const link = svg.append("path")
  .style("fill", "none")
  .style("stroke", "black")
  .attr("d", linkGenerator(data))

<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>

这是另一个带有随机数据的演示:

And here another demo, with random data:

const svg = d3.select("svg");
const linkGenerator = d3.linkHorizontal()
  .x(d => d.x)
  .y(d => d.y)
  .source(d => d[0])
  .target(d => d[1]);
draw();
d3.select("button").on("click", draw);

function draw() {
  const data = [{
    x: 20,
    y: 20 + Math.random() * 110
  }, {
    x: 280,
    y: 20 + Math.random() * 110
  }];
  const circles = svg.selectAll("circle")
    .data(data);
  circles.enter()
    .append("circle")
    .merge(circles)
    .attr("r", 10)
    .attr("cx", d => d.x)
    .attr("cy", d => d.y);
  const link = svg.selectAll("path")
    .data([data]);
  link.enter()
    .append("path")
    .style("fill", "none")
    .style("stroke", "black")
    .merge(link)
    .attr("d", linkGenerator(data))
};

<script src="https://d3js.org/d3.v5.min.js"></script>
<button>Change data</button>
<br>
<svg></svg>

这篇关于使用d3js计算二次SVG连接器的中点和曲线路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆