简体   繁体   中英

Draw line between rectangle from border to border

I would like to draw a line to connect two rectangle from border to border and pass through both rectangle center. currently, I can draw the line from center to center. I know if I fill the rectangle with white, then the line connection will looks like from border to border. but I do wish to keep rectangle transparent!

What's proper way to implement it?

 var svg = d3.select('body').append('svg').attr('width',800).attr('height',600).style('border','1px solid red').style('background-color','#e0e0e0') svg.append("defs").append("marker").attr("id","pointer").attr("markerWidth", 10).attr("markerHeight", 10).attr("orient","auto").attr("refY", 5).append("path").attr("d", "M 0 0 L 10 5 L 0 10 z") var data = [ { id:0, x:100, y:100, width:100, height:50, },{ id:1, x:200, y:200, width:100, height:50, } ] var links = [ { src:0, dest:1, } ] svg.selectAll(null).data(data).enter().append('rect').attr('x', d => dx - d.width/2).attr('y', d => dy - d.height/2).attr('width',d => d.width).attr('height', d => d.height).attr('fill','none').attr('stroke','black').attr('stroke-width',2) svg.selectAll(null).data(links).enter().append('line').attr('x1',d => data.find(e => e.id === d.src).x).attr('y1',d => data.find(e => e.id === d.src).y).attr('x2',d => data.find(e => e.id === d.dest).x).attr('y2',d => data.find(e => e.id === d.dest).y).attr('stroke','black').attr("marker-end","url(#pointer)");
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>

Use linkPath function:

 const first = {x: 50, y: 50, width: 40, height: 30}; const second = {x: 200, y: 110, width: 70, height: 40}; const third = {x: 80, y: 120, width: 50, height: 20}; const linkPath = (from, to) => { const dx = to.x - from.x; const dy = to.y - from.y; let fX, fY, tX, tY; const factor = dx > 0 ^ dy > 0; if (from.width / from.height > Math.abs(dx / dy)) { fX = from.x + from.height * dx / dy / 2 * (factor? -1: 1); fY = from.y + from.height / 2 * (factor? -1: 1); } else { fX = from.x + from.width / 2 * (factor? -1: 1); fY = from.y + from.width * dy / dx / 2 * (factor? -1: 1); } if (to.width / to.height > Math.abs(dx / dy)) { tX = to.x + to.height * dx / dy / 2 * (factor? 1: -1); tY = to.y + to.height / 2 * (factor? 1: -1); } else { tX = to.x + to.width / 2 * (factor? 1: -1); tY = to.y + to.width * dy / dx / 2 * (factor? 1: -1); } return {from: {x: fX, y: fY}, to: {x: tX, y: tY}}; }; const svg = d3.select('svg'); const drawRectangle = rect => svg.append('rect').attr('x', rect.x - rect.width / 2).attr('y', rect.y - rect.height / 2).attr('width', rect.width).attr('height', rect.height); const drawLink = (from, to) => { const path = linkPath(from, to); svg.append('line').attr('x1', path.from.x).attr('y1', path.from.y).attr('x2', path.to.x).attr('y2', path.to.y).attr('marker-end', 'url(#arrowhead)') } drawRectangle(first); drawRectangle(second); drawRectangle(third); drawLink(first, second); drawLink(first, third); drawLink(second, third);
 rect { fill: none; stroke: black; } line { stroke: black; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg width="300" height="200"> <defs> <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"> <polygon fill="black" points="0 0, 10 3.5, 0 7" /> </marker> </defs> </svg>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM