- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在创建饼图。
悬停段时,我想显示自定义 html 工具提示 ...
从一开始,我一直在使用 d3.event.pageX
和 d3.event.pageY
来计算工具提示位置。
但现在我想在饼图的中心点显示工具提示
所以,我在悬停时计算质心
var centroid = arcs.pie.centroid(d);
var left = centroid[0];
var top = centroid[1];
并相应地分配tooltip的左、右位置
tooltip.style("left", (left) + "px")
.style("top", (top) + "px");
这仅在图表大小时有效,但我也希望图表能够响应
所以,我已经在 svg 上分配了 viewbox 属性
var svg = d3.select(selector)
.append('svg')
.attr("viewBox", "0 0 " + attrs.svgWidth + " " + attrs.svgHeight)
.attr("preserveAspectRatio", "xMidYMid meet")
问题来了:
调整窗口大小时,图表会相应缩放,但工具提示位置不在段中心。
如何将此工具提示移动到正确的位置?
我正在寻找“无插件”解决方案。
查看 codepen
最佳答案
这里需要进行计算。首先,在获得质心后,您需要取消转换它,因为它们处于 g
转换中(并且您的 div 需要定位到顶部/左侧)。然后,您可以简单地获取 svg
的当前/实际宽度/高度,并按其与初始非 View 框宽度/高度的比例缩放位置。
var centroid = arcs.pie.centroid(d),
svgDim = svg.node().getBoundingClientRect();
var left = (centroid[0] + dynamic.marginLeft) * (svgDim.width/attrs.svgWidth),
top = (centroid[1] + dynamic.marginTop) * (svgDim.height/attrs.svgHeight);
完整运行代码如下:
function packData(p) {
var data = p;
var result = {
title: data.datasets[0].label,
data: []
};
data.labels.forEach(function(v) {
result.data.push({
label: v
});
});
result.data.forEach(function(v, i) {
v.value = data.datasets[0].data[i];
if (data.datasets[0].backgroundColor) {
v.backgroundColor = data.datasets[0].backgroundColor[i];
}
if (data.extras) {
for (var attrname in data.extras[i]) {
v[attrname] = data.extras[i][attrname];
}
}
});
return result;
}
var svg;
function drawD3JsPie(selector) {
var info = packData({
labels: ["Niger", "Cameroon", "Georgia", "Spain", "United States", "Singapore", "Qatar"],
datasets: [{
label: 'GDP Per Capita in $ (2015)',
data: [1080, 3144, 9630, 34819, 55805, 85253, 132099],
backgroundColor: ["#FF6384", "#36A2EB", "#FFCE56", "#AA6384", "#2CA21B", "#678E86", "#FFAE86"]
}]
});
var data = info.data;
// ######## hard coded and dynamically calculated attributes #######
var attrs = {
svgWidth: 600,
svgHeight: 600,
marginLeft: 4,
marginBottom: 20,
marginRight: 4,
marginTop: 20,
textColor: '#7f7777',
fontSize: '13px',
pieStroke: 'white',
pieStrokeWidth: 3,
titleText: info.title,
hoverColorImpact: 1,
animationDuration: 1200,
animationEase: 'out',
titleHeight: 30,
tooltipTextColor: 'white',
tooltipBackgroundColor: 'black',
}
var dynamic = {}
dynamic.chartWidth = attrs.svgWidth - attrs.marginLeft - attrs.marginRight
dynamic.chartHeight = attrs.svgHeight - attrs.marginTop - attrs.marginBottom - attrs.titleHeight;
dynamic.pieOuterRadius = Math.min(dynamic.chartWidth, dynamic.chartHeight) / 2;
dynamic.chartTopMargin = attrs.marginTop + attrs.titleHeight;
dynamic.marginLeft = attrs.marginLeft + dynamic.pieOuterRadius;
dynamic.marginTop = dynamic.chartTopMargin + dynamic.pieOuterRadius;
// ############## SCALES #########
// ############## ARCS ###############
var arcs = {}
arcs.pie = d3.arc()
.outerRadius(dynamic.pieOuterRadius - 10)
.innerRadius(0);
// ########## layouts #######
var layouts = {};
layouts.pie = d3.pie()
.sort(null)
.value(function(d) {
return d.value;
});
//############### STARTUP ANIMATIONS ###############
var tweens = {}
tweens.pieIn = function(endData) {
var startData = {
startAngle: 0,
endAngle: 0
};
var interpolation = d3.interpolate(startData, endData);
return function(currentData) {
return arcs.pie(interpolation(currentData));
}
};
// ########### RESPONSIVE SVG DRAWING ##############
svg = d3.select(selector)
.append('svg')
.attr("viewBox", "0 0 " + attrs.svgWidth + " " + attrs.svgHeight)
.attr("preserveAspectRatio", "xMidYMid meet")
// ################# CHART CONTENT DRAWING ###############
var chart = svg.append('g')
.attr('width', dynamic.chartWidth)
.attr('height', dynamic.chartHeight)
.attr('transform', 'translate(' + (dynamic.marginLeft) + ',' + (dynamic.marginTop) + ')');
var pieArcs = chart.selectAll('.arc')
.data(layouts.pie(data))
.enter()
.append("g")
.attr("class", "arc");
pieArcs.append("path")
//.attr("d", arcs.pie)
.attr('stroke-width', attrs.pieStrokeWidth)
.attr('stroke', attrs.pieStroke)
.attr("fill", function(d) {
return d.data.backgroundColor;
})
.transition()
.duration(1000)
.attrTween("d", tweens.pieIn);
// ################ ADDING TOOLTIP ##################
var div = d3.select(selector)
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", 'absolute')
.style("text-align", 'left')
.style("font", '12px sans-serif')
.style("background", attrs.tooltipBackgroundColor)
.style("padding", '5px')
.style("color", attrs.tooltipTextColor)
.style("border", '0px')
.style("border-radius", '4px')
.style("pointer-events", 'none')
d3.selectAll('.arc')
.on("mouseover", function(d, i) {
var centroid = arcs.pie.centroid(d),
svgDim = svg.node().getBoundingClientRect();
var left = (centroid[0] + dynamic.marginLeft) * (svgDim.width / attrs.svgWidth),
top = (centroid[1] + dynamic.marginTop) * (svgDim.height / attrs.svgHeight);
d3.select(this)
.append('circle')
.style('fill', 'steelblue')
.attr("transform", "translate(" + centroid + ")")
.attr("r", 10);
var buffer = d.value.toString().length;
if (i > data.length / 2) {
buffer = -buffer - 180;
} else {
buffer *= 4;
}
div.transition()
.duration(100)
.style("opacity", .9);
div.html("<b>" + attrs.titleText + "</b><br/>" + d.data.label + ' : ' + d.data.value)
.style("left", (left) + "px")
.style("top", (top) + "px");
var currPath = d3.select(this).select('path');
var darkenedColor = d3.rgb(currPath.attr('fill')).darker(attrs.hoverColorImpact);
currPath.attr('fill', darkenedColor);
})
.on("mouseout", function(d) {
div.transition()
.duration(200)
.style("opacity", 0);
var currPath = d3.select(this).select('path');
var changedColor = d3.rgb(currPath.attr('fill')).darker(-attrs.hoverColorImpact);
currPath.attr('fill', changedColor);
});
}
drawD3JsPie("#d3JsPie");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
<div style='height:50%;width:50%'id="d3JsPie"></div>
关于d3.js - D3,tooltip位置,应用viewBox时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40708196/
我有一个多行的 Google LineChart。这些点不共享相同的 X 值,所以我必须以某种方式格式化我的数据以使其工作: var data = google.visualization.array
如何在某些 View 上显示工具提示/提示? 例如,在按钮上。 最佳答案 感谢两位 Andrew和 Sorin为解决方向。所提出的解决方案大多有效,但是当我使用它们时,它们完全弄乱了布局。事实证明,工
我在 DataGridView 上使用 winforms ToolTip 类(不是 datagridview 的工具提示,因为我需要自定义格式。) 然后我在 DataGridView 的 CellMo
我有两个工具提示,一个在外部元素上,另一个在内部元素上,如下所示: 如何在显示内部工具提示时删除外部工具提示? Here's a Fiddle 代码非常标准,但请记住,有时 v-tooltip像模式一
是的,这个问题已经被问过here在 SO。 问题是该问题的解决方案是隐藏工具提示,我真的需要删除而不是隐藏它。 我正在使用我制作的几个函数向我的表单中的几个控件添加工具提示。 有两个函数,一个是设置T
我的方法是使用特定的工具提示格式配置图表: Highcharts.chart('container', { tooltip: { formatter: function
我正在尝试在带有 Datagrid 的 WPF 窗体的单元格上设置工具提示。这行得通,但我不希望它在没有弹出文本可显示的单元格中弹出。 我在这里看到过类似的问题,但我无法让这些解决方案发挥作用。 这是
Angular 2 (2.0.0-rc.4)我使用 Bootstrap 的 Tooltip,Tooltip 需要在准备好后执行 javascript: $(function () { $('[da
目前我正在尝试将 ToolTip 的 IsOpen 属性绑定(bind)到我的支持 View 模型的属性。此外,绑定(bind)模式设置为“OneWayToSource”。 这是应用于 TreeVie
我应该关注以下 HTML 验证错误吗? …rel="tooltip" data-placement="bottom" data-original-title="Permalink">
我有一组数据,正在以散点图形式绘制。当我将鼠标悬停在其中一个圆圈上时,我希望它弹出数据(例如 x、y 值,也许更多)。这是我尝试使用的: vis.selectAll("circle") .dat
http://jsfiddle.net/Margo/yKG7X/1/我正在使用工具提示功能,就像 fiddle 一样。 $("#placeholder").bind("plothover",
当前的 Android YouTube 应用程序为导航用户界面提供了有用的提示。例如:当用户第一次在播放视频时切换选项卡时,会弹出一个带有箭头的小“工具提示”,上面写着“您也可以通过左右滑动来切换选项
我正在为我的项目使用 NVD3 库,并编写了以下代码。 var chart = nv.models.lineChart() .useInteractiveGuideline(t
我正在显示 jQuery UI Tooltip悬停时,就在我的元素中间。但是当将鼠标悬停在工具提示上时,工具提示本身就会消失。 (传播问题) 元素: 带有工具提示: 因此,当我将鼠标悬停在工具提示本身
我正在尝试使用从以下内容中找到的 .tooltip():Jquery-ui tooltip 。我拥有的是一个 Rails 应用程序,它在表格中包含一些信息。在单独的牢房中。目前,您可以通过单击单元格来
我使用 Highcharts 创建了一个图表。 工具提示在 FF 和 IE 中工作正常,但在 chorme 中,文本超出了框架。 我尝试使用 HTML tooltip: { //Tr
长话短说:我有一个窗口,在列表框中显示一堆图表。当鼠标悬停在图表上(使用 LineSeries)时,数据点后面有一条线(捕捉到数据点位置)。在那条线附近,我将展示一个由弹出窗口制成的工具提示,其中显示
现在使用 nv.d3 示例中的 stackedAreaChart(),当您将鼠标悬停在时间序列中的某个点上时,您会得到一个工具提示。 我垂直对齐了 3 个时间序列。如果鼠标悬停在其中任何一个点上,我希
我创建了一个具有两个数据集的 Chart JS 2 图。 当我将鼠标悬停在一行上时,我只会得到当前行的数据,但我也想查看另一行的数据。 如何在工具提示中添加特定日期的所有数据? 最佳答案 要在工具提示
我是一名优秀的程序员,十分优秀!