Below code try to link two circles from border to border. Drag event only take effect when click on circle border, I would like it work in circle area as well ( more easy to be dragged).
demo()
function demo() {
function dragstarted(event,d) {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(event,d) {
d.fx = event.x;
d.fy = event.y;
}
function dragended(event,d) {
// if (!event.active) simulation.alphaTarget(0);
// d.fx = null;
// d.fy = null;
}
var data = {
"nodes":[{
"id":1,
"influence": 1
},{
"id": 2,
"influence": 2
}],
"links":[{
"source": 1,
"target": 2,
"weight": 3
}]
}
var width = 200
var height = 200
const simulation = d3.forceSimulation(data.nodes)
.force('charge', d3.forceManyBody().strength(-100))
.force('link', d3.forceLink(data.links).id(d => d.id)
.distance(150))
.force('center', d3.forceCenter(width/2, height/2))
const svg = d3.select('body')
.append("svg")
.attr("viewBox", [0,0,width,height]);
var path = ['M',2,6,'L',2,2,10,6,2,10,'z'].join(' ')
svg
.append('defs')
.append('marker')
.attr('id', 'arr1')
.attr('viewBox', [0, 0, 12, 12])
.attr('refX', 10)
.attr('refY', 6)
.attr('markerWidth', 12)
.attr('markerHeight', 12)
.attr('orient', 'auto-start-reverse')
.append('path')
.attr('d',path)
.attr('stroke', 'black')
.attr('fill','black')
var r = 35
const node = svg.selectAll('circle')
.data(data.nodes)
.enter()
.append('circle')
.attr('r', r)
.attr('stroke','black')
.attr('stroke-width',4)
.attr('fill', 'none')
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
const link = svg
.selectAll('path.link')
.data(data.links)
.enter()
.append('line')
.attr('stroke', 'black')
.attr('fill', 'none');
simulation.on('tick', () => {
node.attr('cx', d => d.x);
node.attr('cy', d => d.y);
link.attr('x1', d => {
var sx = d.source.x
var sy = d.source.y
var tx = d.target.x
var ty = d.target.y
var dx = tx - sx
var dy = ty - sy
var length = Math.sqrt((dx * dx) (dy * dy))
var x = r*dx/length
var y = r*dy/length
d.source.bx = sx x
d.source.by = sy y
d.target.bx = tx - x
d.target.by = ty - y
return d.source.bx
})
.attr('y1',d => d.source.by)
.attr('x2',d => d.target.bx)
.attr('y2',d => d.target.by)
link.attr('marker-end', 'url(#arr1)')
});
}
<script src="https://unpkg.com/[email protected]/dist/d3.min.js"></script>
CodePudding user response:
Your fill
is set to none
, therefore you have to set the adequate value to pointer-events
, like all
. The problem is that the default pointer-events
value is visiblePainted
, in which, as the MDN explains:
The element can only be the target of a pointer event when [...] the
fill
property is set to a value other thannone
.
For a more detailed list have a look at MDN here: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
Here's your code setting pointer-events
to all
:
demo()
function demo() {
function dragstarted(event,d) {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(event,d) {
d.fx = event.x;
d.fy = event.y;
}
function dragended(event,d) {
// if (!event.active) simulation.alphaTarget(0);
// d.fx = null;
// d.fy = null;
}
var data = {
"nodes":[{
"id":1,
"influence": 1
},{
"id": 2,
"influence": 2
}],
"links":[{
"source": 1,
"target": 2,
"weight": 3
}]
}
var width = 200
var height = 200
const simulation = d3.forceSimulation(data.nodes)
.force('charge', d3.forceManyBody().strength(-100))
.force('link', d3.forceLink(data.links).id(d => d.id)
.distance(150))
.force('center', d3.forceCenter(width/2, height/2))
const svg = d3.select('body')
.append("svg")
.attr("viewBox", [0,0,width,height]);
var path = ['M',2,6,'L',2,2,10,6,2,10,'z'].join(' ')
svg
.append('defs')
.append('marker')
.attr('id', 'arr1')
.attr('viewBox', [0, 0, 12, 12])
.attr('refX', 10)
.attr('refY', 6)
.attr('markerWidth', 12)
.attr('markerHeight', 12)
.attr('orient', 'auto-start-reverse')
.append('path')
.attr('d',path)
.attr('stroke', 'black')
.attr('fill','black')
var r = 35
const node = svg.selectAll('circle')
.data(data.nodes)
.enter()
.append('circle')
.attr('r', r)
.attr('stroke','black')
.attr('stroke-width',4)
.attr('fill', 'none')
.attr("pointer-events", "all")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
const link = svg
.selectAll('path.link')
.data(data.links)
.enter()
.append('line')
.attr('stroke', 'black')
.attr('fill', 'none');
simulation.on('tick', () => {
node.attr('cx', d => d.x);
node.attr('cy', d => d.y);
link.attr('x1', d => {
var sx = d.source.x
var sy = d.source.y
var tx = d.target.x
var ty = d.target.y
var dx = tx - sx
var dy = ty - sy
var length = Math.sqrt((dx * dx) (dy * dy))
var x = r*dx/length
var y = r*dy/length
d.source.bx = sx x
d.source.by = sy y
d.target.bx = tx - x
d.target.by = ty - y
return d.source.bx
})
.attr('y1',d => d.source.by)
.attr('x2',d => d.target.bx)
.attr('y2',d => d.target.by)
link.attr('marker-end', 'url(#arr1)')
});
}
<script src="https://unpkg.com/[email protected]/dist/d3.min.js"></script>