With newer versions of d3.js, there's no interpolate()
function on the line generator (reference: "Interpolate" is not a function), so I somewhat modified Alvin K's answer as shown in the code below (Typescript). In particular, the code is used to simulate a hover effect on an SVG text.
const group = d3.select(/* your node */)
group
.append("rect")
.attr("stroke", "none")
.attr("fill", "none")
group
.append("text")
.call((node) => {
node.on("mouseenter", function(this: any) {
const rect = this.getBBox()
d3.select(this.parentNode)
.select("rect")
.attr("x", rect.x - offset)
.attr("y", rect.y - offset)
.attr("width", rect.width + offset * 2)
.attr("height", rect.height + offset * 2)
.style("stroke-width", 1)
.style("stroke", "black")
.style("stroke-dasharray", "4")
.style("fill", "none");
})
node.on("mouseleave", function(this: any) {
d3.select(this.parentNode)
.select("rect")
.style("stroke", "none")
})
})
PS: it's not necessary to use call()
on the selection, you could just call on()
directly, however in my actual code, I refactored the callback into a class method.
var offset = 5
onload();
function onload() {
var svg = d3.select("body")
.append("svg")
.attr("width", 200)
.attr("height", 200)
const group = svg
.append("g")
.attr("transform", "translate(10, 40)")
group
.append("rect")
.attr("stroke", "none")
.attr("fill", "none")
group
.append("text")
.attr("fill", "black")
.attr("font-weight", 600)
.attr("font-size", "16px")
.text("HOVER ON ME")
.call((node) => {
node.on("mouseenter", function() {
const rect = this.getBBox()
d3.select(this.parentNode)
.select("rect")
.attr("x", rect.x - offset)
.attr("y", rect.y - offset)
.attr("width", rect.width + offset * 2)
.attr("height", rect.height + offset * 2)
.style("stroke-width", 1)
.style("stroke", "black")
.style("stroke-dasharray", "4")
.style("fill", "none");
})
node.on("mouseleave", function() {
d3.select(this.parentNode)
.select("rect")
.style("stroke", "none")
})
})
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>