- 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/
我正在尝试获取从过去的 startposition/location 到当前移动的 currentposition/location 的距离(以米为单位)。 我确实有工作正常的currentposit
所以我有一堆绝对覆盖的 div。用户通过在叠加层上拖动来创建方形 div。如果您要创建一个 div,然后放大和缩小,div 会保持在同一位置,因为它对叠加层是绝对的,如前所述。 然而问题就出在这里。您
我想找到 View 在显示屏幕上的位置。 为此,我使用了 view.getLeft() 、view.getBottom() 、view.getRight() 等方法> , view.getTop()。
我有一个看起来像这样的 View 层次结构(基于其他答案和 Apple 的使用 UIScrollView 的高级 AutoLayout 指南): ScrollView 所需的2 个步骤是: 为 Scr
所以我有一个名为 MARKS 的表,我有这些列 STUDENT_ID, CLASSFORM_NAME, ACADEMIC_YEAR, TERM, SUBJECT_NAME, TOTAL_MARKS
我有一个问题我无法理解,请帮助: 我开发了带有图像的 html 页面,并使用 jQuery UI 帮助使它们可拖动,我将这些图像位置设置为相对位置并给出了左侧和顶部像素,这是页面的链接 http://
我正在尝试创建一个 CSS 动画,它在 sprite 表中循环播放 16 个图像,给人一种幽灵“漂浮”的错觉。动画通过在 background-position 位置之间移动以显示不同状态的幽灵来实现
我正在创建这个网站的 WebView https://nearxt.com/打开时询问位置但是当我使用此链接在 flutter 中创建 webview 时那么它就无法定位我还在应用程序中定义了位置,但
我正在以编程方式创建一个需要跨越 2 个屏幕的窗口。正在创建的窗口的大小是正确的,但窗口大约从第一个屏幕的一半开始。我可以将它拖回第一个屏幕的开头,NSWindow 非常适合。 我只需要知道在窗口的起
位置“/”的匹配叶路由没有元素。这意味着默认情况下它将呈现一个空值,从而导致一个“空”页面 //App.js File import { BrowserRouter as Router, Routes
我有一个运行 Ubuntu 和 Apache 的 VPS 例如,假设地址是:5.5.5.5 在 VPS 上,我有一个名为 eggdrop 的用户(除了我的 root 用户)。 用户 eggdrop 有
我有一个 JLabel与 ImageIcon ,我使用 setIcon() JLabel中的函数. ImageIcon然后上来,坐在我的JLabel 的文字左侧.是否有可能拥有 ImageIcon在文
我的图中有节点,它们的 xlabels 位于它们的左上方。我怎样才能改变这个位置?我希望 xlabels 正好位于节点本身的旁边。 最佳答案 xlp是你想要的属性,但它没有做任何事情。 你不能改变位置
我对基本的 VIM 功能有疑问:(我尝试谷歌搜索但找不到答案) 如何列出所有自定义功能。(我做了 :function 并且不能找到我的自定义函数) 如何获得自定义函数列表中的函数(或它们的存储位置)。
我是 PHP 的新手,虽然我一直在搜索,但我不知道该怎么做。 我知道可以使用 Location("some page") 进行重定向。我还读到,只要没有向用户显示任何内容,它就可以工作。 我想做的是:
如果在 jgrowl.css 中位置更改为“center”,我如何将其覆盖为默认值,即“top-right” $.jGrowl(data, { header: 'data', an
我需要根据用户是否滑动屏幕顶部、屏幕中间或屏幕底部来触发不同的事件。我正在尝试找出最好/最简单的方法来做到这一点,因为我很确定没有办法从 UISwipeGestureRecognizer 获取位置。
我需要枚举用delphi编写的外部应用程序中使用的类 ,因此我需要访问VMT表以获取该信息,但是我找不到任何有关如何在exe(由delphi生成)文件中找到VMT(虚拟方法表)的位置(地址)的文档。
在 D2010 (unicode) 中是否有像 Pos 这样不区分大小写的类似函数? 我知道我可以使用 Pos(AnsiUpperCase(FindString), AnsiUpperCase(Sou
我正在尝试为我的reveal.js 演示文稿制作一个标题,该标题会粘贴在屏幕顶部。标题中的内容在每张幻灯片的基础上都是动态的,因此我必须将标记放在 section 标记中。 显然,如果标记在 sect
我是一名优秀的程序员,十分优秀!