我正在使用D3完成一个简单的散点图项目。我正在使用D3 tip在鼠标悬停时在图表上显示有关主题的更多信息。
目前,提示会显示主题位于图表上主题的位置。
但是,无论何时触发提示,我都希望将我的提示放在图表右下角的固定位置。
我试图在CSS中修改d3-tip
类,但无论我尝试什么,它似乎被覆盖,并且提示的top
和left
位置总是在鼠标的任何地方碰巧是。
以下是我的项目的Codepen,您可以在其中找到主题所在位置的提示:http://codepen.io/alanbuchanan/pen/RryBVQ
如何确保我的小费显示在图表右下角的固定位置?
使用Javascript:
var w = 600;
var h = 700;
var margin = {top: 70, bottom: 90, left: 110, right: 70};
var nameMargin = 2;
var chartWidth = w - margin.left - margin.right;
var chartHeight = h - margin.top - margin.bottom;
var url = 'https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/cyclist-data.json';
var svg = d3.select('body')
.append('svg')
.attr('width', w + margin.right)
.attr('height', h)
.style('background-color', '#eeeeee')
.style('border-radius', '10px')
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
var formatMinutes = d => {
d -= 2210
var mins = Math.floor(d / 60)
var secs = d - mins * 60
return mins + ':' + secs
};
// Scales
var x = d3.scale.linear()
.domain([
2390 + 5,
2210
])
.range([0, chartWidth]);
var y = d3.scale.linear()
.domain([1, 35 + 1])
.range([0, chartHeight]);
// Axes
var xAxis = d3.svg.axis()
.scale(x)
.orient('bottom')
.ticks(7)
.tickFormat(formatMinutes);
var yAxis = d3.svg.axis()
.scale(y)
.orient('left')
.ticks(10);
var getFlag = nat => {
switch (nat) {
// Deal with odd cases
case 'GER': nat = "DE"; break;
case 'SUI': nat = "CH"; break;
case 'UKR': nat = "UA"; break;
case 'POR': nat = "PT"; break;
default: break;
}
return nat.substr(0, 2).toLowerCase();
};
$.getJSON(url, data => {
console.log(data)
var tip = d3.tip()
.attr('class', 'd3-tip')
.html(d => {
return `<h4><span class="flag-icon flag-icon-` + getFlag(d.Nationality) + `"></span> ${d.Name}</h4>
<h5>Time: ${d.Time} in ${d.Year}</h5>
<p>${d.Doping || 'No allegations'}</p>`
});
// Add data from JSON
svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', d => x(d.Seconds))
.attr('cy', d => y(d.Place))
.attr('r', '2')
.style('width', '4px')
.style('height', '10px');
svg.call(tip);
var createLink = d => {
return `window.location='${d.URL}`
};
var text = svg.selectAll('text')
.data(data)
.enter()
.append('text')
.attr('x', d => x(d.Seconds - nameMargin))
.attr('y', d => y(d.Place))
.attr("dy", ".35em")
.text(d => d.Name)
.attr('class', 'rider-name')
.attr('class', d => d.Doping.length === 0 ? 'noAllegations' : 'hasAllegations')
.on('click', (d) => location.href = d.URL)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
svg.append('g')
.attr('class', 'axis')
.attr('transform', `translate(0, ${chartHeight})`)
.call(xAxis);
svg.append('g')
.attr('class', 'axis')
.call(yAxis);
// Axis labels
svg.append('text')
.attr('class', 'label')
.attr('text-anchor', 'middle')
.attr('x', chartWidth / 2)
.attr('y', chartHeight + 50)
.text('Mins and secs behind best time');
svg.append('text')
.attr('class', 'label')
.attr('text-anchor', 'middle')
.attr('y', 0 - margin.left)
.attr('x', 0 - (chartHeight / 2))
.attr('dy', '3.9em')
.attr('transform', 'rotate(-90)')
.text('Place');
// Title
var title = svg.append('text')
.attr('class', 'title')
.attr('x', chartWidth / 2)
.attr('y', 0 - (margin.top / 2))
.attr('text-anchor', 'middle')
.text('Doping in Professional Bicycle Racing: 35 Fastest times up Alpe d\'Huez')
.style('font-size', '16px')
.style('font-weight', 'bold');
});
CSS:
@import url(https://fonts.googleapis.com/css?family=Raleway:400,100);
$font: 'Raleway', sans-serif;
$font-light: 100;
$font-med: 400;
$green: #416600;
$red: #b40000;
body {
background-color: #DADADA;
position: relative;
font-family: $font;
}
.axis path,
.axis line {
fill: none;
stroke: gray;
shape-rendering: crispEdges;
}
.d3-tip {
width: 200px;
}
svg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, 10%);
border: 1px solid $red;
box-shadow: 3px 3px 15px #888888;
}
h4, h5 {
margin: 0;
}
text {
cursor: pointer;
}
.noAllegations {
fill: $green;
}
.hasAllegations {
fill: $red;
}
.title {
cursor: initial;
fill: $red;
}
.noAllegations, .hasAllegations {
text-transform: uppercase;
font-weight: $font-med;
font-size: 12px;
}
circle {
fill: black;
}
.label {
cursor: initial;
}