这里是D3的新手,并使用下面的代码处理图表。当用户将鼠标悬停在其中一个文本标签上时,我有一个名为“tip”的div,它显示(通过改变不透明度)。我无法正确定位。
我想要的是将它放在图表的左上角,让我们说x,y坐标为10,10。但我不知道如何得到那个坐标,因为它是一个div。有人可以帮帮我吗?
var url = "https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/cyclist-data.json";
d3.json(url, function(json) {
var data = json;
//Dimensions of the SVG container
var margin = {
top: 40,
right: 100,
bottom: 60,
left: 60
};
//inner width for the chart, within SVG element
var w = 1000 - margin.left - margin.right;
//inner height for the chart, within SVG element
var h = 800 - margin.top - margin.bottom;
var padding = 20;
//create SVG conratiner and append to DOM
var svg = d3.select("#chart")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var maxRank = d3.max(data, function(d) {
return d.Place;
});
var minSeconds = d3.min(data, function(d) {
return d.Seconds;
});
var maxSeconds = d3.max(data, function(d) {
return d.Seconds;
});
var formatTime = d3.timeFormat("%M:%S");
var formatSeconds = formatMinutes = function(d) {
return formatTime(new Date(2016, 0, 0, 0, 1, d));
};
var xScale = d3.scaleLinear()
.domain([maxSeconds + 5, minSeconds])
.range([0, w]);
var yScale = d3.scaleLinear()
.domain([0, maxRank + 2])
.range([0, h]);
var xAxis = d3.axisBottom()
.scale(xScale)
.ticks(10)
.tickFormat(formatMinutes)
var yAxis = d3.axisLeft()
.scale(yScale)
.ticks(10);
var tip = d3.select("#chart").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var circles = svg.selectAll("circle")
.data(data)
.enter()
.append("circle");
var circleAttributes = circles
.attr("cx", function(d) {
return xScale(d.Seconds);
})
.attr("cy", function(d) {
return yScale(d.Place);
})
.attr("r", 6)
.attr("class", "circles")
.attr("fill", function(d) {
if (d.Doping === "") {
return "#2c3e50";
} else {
return "#e74c3c";
}
});
var labels = svg.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d) {
return d.Name;
})
.attr("x", function(d) {
return xScale(d.Seconds) + 7;
})
.attr("y", function(d) {
return yScale(d.Place) + 4;
})
.attr("class", "labels")
.attr("font-family", "roboto slab")
.attr("font-size", "12px")
.attr("fill", "#2c3e50")
.on("mouseover", function(d) {
tip.transition()
.duration(200)
.style("opacity", 0.7);
tip.html("<span><strong>" + d.Name + "</strong><br/><i>Place: </i>" + d.Place + "<br/><i>Time: </i>" + d.Time + "<br/><i>Year: </i>" + d.Year + "<br/><i>Nationality: </i>" + d.Nationality + "<br/><i>Doping: </i>" + d.Doping + "</span>")
.style("left", (d3.event.pageX + 48) + "px")
.style("top", (d3.event.pageY + 48) + "px");
})
.on("mouseout", function(d) {
tip.transition()
.duration(200)
.style("opacity", 0);
});
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis);
svg.append("g")
.attr("class", "axis")
.call(yAxis)
})
答案 0 :(得分:5)
在我看来,这个问题(几乎)与D3.js无关。相反,这是一个CSS问题。
有一些不同的解决方案,我在这里建议的非常简单:只需设置容器div(带有chart
的div)相对位置......
#svgwrapper {
position: relative;
}
...以及工具提示div中的绝对位置,top
和left
为零:
.tooltip {
position: absolute;
top: 0 px;
left: 0 px;
}
此外,请不要忘记删除d3.event.pageX
和d3.event.pageY
,因为您的工具提示将始终显示在同一位置。
这是一个演示(悬停在圆圈上):
var tip = d3.select("#svgwrapper").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
d3.select("circle").on("mouseover", function(){
tip.html("Hello!")
.style("opacity", 1)
}).on("mouseout", function(){
tip.style("opacity", 0)
});
#svgwrapper {
border: 1px solid gray;
position: relative;
}
.tooltip {
position: absolute;
top: 0px;
left: 0px;
border: 1px solid gray;
border-radius: 2px;
padding: 4px;
background-color: tan;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</div>
<div id="svgwrapper">
<svg>
<circle cx="100" cy="100" r="20" fill="teal"></circle>
</svg>
</div>