我一直在尝试使此示例SVG foreignObject tooltips in D3与D3v4一起使用。我已经花了几个小时没有成功。
它是d3v4,似乎在.attr
的对象参数上令人cho目结舌,因此我将它们压扁了。现在它在下面的行上失败了
var foHeight = div[0][0].getBoundingClientRect().height;
错误“无法读取未定义的属性'0'”
当用户运行下面的代码并滚动到紫色圆圈上时,将发生错误。这与d3v4的选择如何变化有关吗?
有小费吗?
var margin = {
top: 20,
right: 10,
bottom: 20,
left: 10
};
var width = 800 - margin.left - margin.right;
var height = 480 - margin.top - margin.bottom;
var svg = d3.select('body')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
svg.append('rect')
.attr('width', width * 0.8)
.attr('height', height * 0.8)
.attr('x', width * 0.1)
.attr('y', height * 0.1)
.attr('fill', '#F8F8F8');
var foWidth = 300;
var anchor = {
'w': width / 3,
'h': height / 3
};
var t = 50,
k = 15;
var tip = {
'w': (3 / 4 * t),
'h': k
};
svg.append('circle')
.attr('r', 50)
.attr('cx', anchor.w)
.attr('cy', anchor.h)
.attr('fill', '#7413E8')
.attr('opacity', 0.35)
.on('mouseover', function() {
var fo = svg.append('foreignObject')
.attr('x', anchor.w - tip.w)
.attr('y', anchor.h + tip.h)
.attr('width', foWidth)
.attr('class', 'svg-tooltip');
var div = fo.append('xhtml:div')
.append('div')
.attr('class', 'tooltip');
div.append('p')
.attr('class', 'lead')
.html('Holmes was certainly not a difficult man to live with.');
div.append('p')
.html('He was quiet in his ways, and his habits were regular. It was rare for him to be up after ten at night, and he had invariably breakfasted and gone out before I rose in the morning.');
var foHeight = div[0][0].getBoundingClientRect().height;
fo.attr({
'height': foHeight
});
svg.insert('polygon', '.svg-tooltip')
.attr({
'points': "0,0 0," + foHeight + " " + foWidth + "," + foHeight + " " + foWidth + ",0 " + (t) + ",0 " + tip.w + "," + (-tip.h) + " " + (t / 2) + ",0",
'height': foHeight + tip.h,
'width': foWidth,
'fill': '#D8D8D8',
'opacity': 0.75,
'transform': 'translate(' + (anchor.w - tip.w) + ',' + (anchor.h + tip.h) + ')'
});
})
.on('mouseout', function() {
svg.selectAll('.svg-tooltip').remove();
svg.selectAll('polygon').remove();
});
svg {
display: block;
margin: 0 auto;
}
.svg-tooltip {
pointer-events: none;
}
.tooltip {
padding: 10px;
color: #4A22FF;
}
.lead {
font-style: italic;
}
p {
margin: 5px 0px;
}
polygon {
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js" integrity="sha256-aYYnqVVhAJ4lDammP4Qybmxg3/HVpA7/sNSCntyCyu4=" crossorigin="anonymous"></script>
<head>
<meta charset='utf-8'>
<title>
SVG foreignObject tooltips in D3
</title>
</head>
<body>
</body>
</html>
最佳答案
在D3 v3中,选择项曾经是数组。在V4中不再存在:现在它们是对象。
changelog说:
选择不再使用原型链注入来子类化Array;它们现在是普通对象,可以提高性能。
让我们展示一下。在D3 v3中...
console.log(d3.select("body"))
<script src="https://d3js.org/d3.v3.min.js"></script>
现在在D3 v4中:
console.log(d3.select("body"))
<script src="https://d3js.org/d3.v4.min.js"></script>
因此,由于选择不再是数组,因此:
div[0]
... 不管用。
这里的解决方案很简单,只需使用
node()
即可获取DOM元素:var foHeight = div.node().getBoundingClientRect().height;
这是您所做的更改的代码:
var margin = {
top: 20,
right: 10,
bottom: 20,
left: 10
};
var width = 800 - margin.left - margin.right;
var height = 480 - margin.top - margin.bottom;
var svg = d3.select('body')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
svg.append('rect')
.attr('width', width * 0.8)
.attr('height', height * 0.8)
.attr('x', width * 0.1)
.attr('y', height * 0.1)
.attr('fill', '#F8F8F8');
var foWidth = 300;
var anchor = {
'w': width / 3,
'h': height / 3
};
var t = 50,
k = 15;
var tip = {
'w': (3 / 4 * t),
'h': k
};
svg.append('circle')
.attr('r', 50)
.attr('cx', anchor.w)
.attr('cy', anchor.h)
.attr('fill', '#7413E8')
.attr('opacity', 0.35)
.on('mouseover', function() {
var fo = svg.append('foreignObject')
.attr('x', anchor.w - tip.w)
.attr('y', anchor.h + tip.h)
.attr('width', foWidth)
.attr('class', 'svg-tooltip');
var div = fo.append('xhtml:div')
.append('div')
.attr('class', 'tooltip');
div.append('p')
.attr('class', 'lead')
.html('Holmes was certainly not a difficult man to live with.');
div.append('p')
.html('He was quiet in his ways, and his habits were regular. It was rare for him to be up after ten at night, and he had invariably breakfasted and gone out before I rose in the morning.');
var foHeight = div.node().getBoundingClientRect().height;
fo.attr({
'height': foHeight
});
svg.insert('polygon', '.svg-tooltip')
.attr({
'points': "0,0 0," + foHeight + " " + foWidth + "," + foHeight + " " + foWidth + ",0 " + (t) + ",0 " + tip.w + "," + (-tip.h) + " " + (t / 2) + ",0",
'height': foHeight + tip.h,
'width': foWidth,
'fill': '#D8D8D8',
'opacity': 0.75,
'transform': 'translate(' + (anchor.w - tip.w) + ',' + (anchor.h + tip.h) + ')'
});
})
.on('mouseout', function() {
svg.selectAll('.svg-tooltip').remove();
svg.selectAll('polygon').remove();
});
svg {
display: block;
margin: 0 auto;
}
.svg-tooltip {
pointer-events: none;
}
.tooltip {
padding: 10px;
color: #4A22FF;
}
.lead {
font-style: italic;
}
p {
margin: 5px 0px;
}
polygon {
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js" integrity="sha256-aYYnqVVhAJ4lDammP4Qybmxg3/HVpA7/sNSCntyCyu4=" crossorigin="anonymous"></script>
<head>
<meta charset='utf-8'>
<title>
SVG foreignObject tooltips in D3
</title>
</head>
<body>
</body>
</html>
关于javascript - 有关获取“foreignObject” d3v3示例以在d3v4中工作的问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47342164/