我有一个带有工具提示和画笔的类,我使用的是 d3 版本 4,我的代码如下
var allData = [{
value: 10,
time: 1613579385
}, {
value: 15,
time: 1613492985
}, {
value: 20,
time: 1613406585
}, {
value: 30,
time: 1613320185
}, {
value: 10,
time: 1613589385
}, {
value: 15,
time: 1613482985
}, {
value: 20,
time: 1613486585
}, {
value: 30,
time: 1613380185
}
]
var margin = {
top: 20,
right: 10,
bottom: 50,
left: 50
};
var width = 600, height = 600;
var colors = ['#c0485c', '#4682b4'];
var svg = d3.select("body")
.append('svg')
.attr('class', 'ellipse')
.attr('width', width + margin.left + margin.right + 100)
.attr('height', height + margin.top + margin.bottom);
var gElement = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
var xScale = d3.scaleTime().range([margin.left, width]);
var yScale = d3.scaleLinear().range([height, margin.bottom]);
xScale.domain(d3.extent(allData, (d) => new Date(d.time * 1000)));
yScale.domain(d3.extent(allData, (d) => d.value));
var xAxis = gElement.append('g')
.attr('class', 'axis axis--x')
.attr('transform', 'translate(0,' + (height) + ')')
.call(d3.axisBottom(xScale));
gElement.append('text')
.attr('transform', 'translate(' + (width / 2) + ' ,' + (height + margin.top + 20) + ')')
.style('text-anchor', 'middle').text('time');
var yAxis = gElement.append('g')
.attr('class', 'axis axis--y')
.attr('transform', 'translate(' + (margin.left) + ',0)')
.call(d3.axisLeft(yScale));
// text label for the y axis
gElement.append('text')
.attr('transform', 'rotate(-90)')
.attr('x', 0 - (height / 2)).attr('dy', '1em')
.style('text-anchor', 'middle').text('Unit');
var circleCx = (d) => xScale(d && d.time ? new Date(d.time * 1000) : new Date(0));
var circleCy = (d) => yScale(d && d.value ? d.value : 0);
var clip = gElement.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("x", margin.left)
.attr("y", margin.bottom);
var circles = gElement.append('g')
.attr("clip-path", "url(#clip)");
var focus = gElement.append('g')
.attr('class', 'tooltip')
.style('display', 'none');
focus.append('rect')
.attr('class', 'tooltip-box')
.attr('width', 300)
.attr('height', 60);
focus.append('text').attr('class', 'tooltip-date');
focus.append('text').attr('class', 'tooltip-value');
focus.append('circle')
.attr('class', 'tooltip-point')
.style('stroke', 'white')
.style('stroke-width', '.5')
.attr('r', 6);
function onMouseOver(data) {
if (!data || !data.time) {
return;
}
focus.style('display', null);
focus.select('circle.tooltip-point').attr('transform', `translate(${xScale(new Date(data.time * 1000))},${yScale(data.value)})`);
const translateX = xScale(new Date(data.time * 1000));
const translateY = yScale(data.value);
focus.select('rect.tooltip-box')
.attr('transform', `translate(${translateX}, ${translateY})`)
.attr('x', 2)
.attr('y', -2.5);
focus.select('text.tooltip-date')
.attr('transform', `translate(${translateX}, ${translateY})`)
.attr('dx', 10)
.attr('dy', 30)
.text(`Date: ${new Date(data.time * 1000)}`);
focus.select('text.tooltip-value')
.attr('transform', `translate(${translateX}, ${translateY})`)
.attr('dx', 10)
.attr('dy', 45)
.text(`Value: ${data.value}`);
}
function onMouseOut() {
focus.style('display', 'none')
}
var points = circles.selectAll(`.circle-data`)
.data(allData)
.enter()
.append('circle') // enter append
.attr('class', `circle-data`)
.attr('stroke', 'blue')
.attr('r', '3') // radius
.attr('cx', circleCx)
.attr('cy', circleCy)
function applyZoom() {
var brush = d3.brushX()
.extent([[margin.left, margin.bottom], [width, height]])
.on("end", () => {
const extent = d3.event.selection;
if (extent) {
xScale.domain([xScale.invert(extent[0]), xScale.invert(extent[1])]);
circles.select(".brush").call(brush.move, null) // This remove the grey brush area as soon as the selection has been done
}
xAxis.transition().duration(1000).call(d3.axisBottom(this.xScale))
circles.selectAll('.circle-data')
.transition()
.duration(1000)
.attr('cx', circleCx)
.attr('cy', circleCy)
});
circles.append("g")
.attr("class", "brush")
.call(brush)
svg.on("dblclick", () => {
xScale.domain(d3.extent(allData, (d) => new Date(d.time * 1000)));
xAxis.transition().call(d3.axisBottom(xScale));
d3.selectAll('circle')
.transition()
.attr('cx', circleCx)
.attr('cy', circleCy)
});
}
applyZoom();
gElement.selectAll('.brush')
.on('mouseover', onMouseOver)
.on('mouseout', onMouseOut);
当我可以通过选择 svg 进行缩放时不显示工具提示。缩放有效,但不能与工具提示一起使用。如果我删除 zoom ,则工具提示正常工作。注释掉 applyZoom 方法提供了一个有效的工具提示。
完整代码可在小提琴中找到:https://jsfiddle.net/edayan/9chrn536/1/