gpt4 book ai didi

javascript - d3.js voronoi 事件。当光标正好位于点上方时,鼠标悬停似乎消失

转载 作者:行者123 更新时间:2023-12-03 01:21:43 31 4
gpt4 key购买 nike

请问我在这里做错了什么?我想在鼠标进入关联的 voronoi 单元时增加点的大小,但是当鼠标完全高于该点时,该点会恢复到其原始大小;我尝试了 mouseovermousemove 事件,但没有成功。代码片段,你可以放大,你就能看到我刚才描述的内容。非常感谢!

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">

<title>Chart</title>


<!-- Reference minified version of D3 -->
<script src='https://d3js.org/d3.v4.min.js' type='text/javascript'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
</head>

<body>
<style>
.grid line {
stroke: #ddd;
}
</style>


<div id='scatter-plot'>
<svg width="700" height="500">
</svg>
</div>


<script>

var data = [];
for (let i = 0; i < 200; i++) {
data.push({
x: Math.random(),
y: Math.random(),
dotNum: i,
})
}

renderChart(data)




function renderChart(data) {

var totalWidth = 920,
totalHeight = 480;

var margin = {
top: 10,
left: 50,
bottom: 30,
right: 0
}

var width = totalWidth - margin.left - margin.right,
height = totalHeight - margin.top - margin.bottom;

// inner chart dimensions, where the dots are plotted
// var width = width - margin.left - margin.right;
// var height = height - margin.top - margin.bottom;

var tsn = d3.transition().duration(200);

// radius of points in the scatterplot
var pointRadius = 2;

var extent = {
x: d3.extent(data, function (d) {return d.x}),
y: d3.extent(data, function (d) {return d.y}),
};

var scale = {
x: d3.scaleLinear().range([0, width]),
y: d3.scaleLinear().range([height, 0]),
};

var axis = {
x: d3.axisBottom(scale.x).ticks(xTicks).tickSizeOuter(0),
y: d3.axisLeft(scale.y).ticks(yTicks).tickSizeOuter(0),
};

var gridlines = {
x: d3.axisBottom(scale.x).tickFormat("").tickSize(height),
y: d3.axisLeft(scale.y).tickFormat("").tickSize(-width),
}


var colorScale = d3.scaleLinear().domain([0, 1]).range(['#06a', '#06a']);

// select the root container where the chart will be added
var container = d3.select('#scatter-plot');

var zoom = d3.zoom()
.scaleExtent([1, 20])
.on("zoom", zoomed);

var tooltip = d3.select("body").append("div")
.attr("id", "tooltip")
.style("opacity", 0);

// initialize main SVG
var svg = container.select('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(zoom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// Clip path
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);


// Heatmap dots
var dotsGroup = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("g");

//Create X axis
var renderXAxis = svg.append("g")
.attr("class", "x axis")

//Create Y axis
var renderYAxis = svg.append("g")
.attr("class", "y axis")


// set up axis generating functions
var xTicks = Math.round(width / 50);
var yTicks = Math.round(height / 50);


function updateScales(data, scale){
scale.x.domain([extent.x[0], extent.x[1]]).nice(),
scale.y.domain([extent.y[0], extent.y[1]]).nice()
}

function zoomed() {
d3.event.transform.x = d3.event.transform.x;
d3.event.transform.y = d3.event.transform.y;

// update: rescale x axis
renderXAxis.call(axis.x.scale(d3.event.transform.rescaleX(scale.x)));
renderYAxis.call(axis.y.scale(d3.event.transform.rescaleX(scale.y)));


dotsGroup.attr("transform", d3.event.transform);
}

// add the overlay on top of everything to take the mouse events
dotsGroup.append('rect')
.attr('class', 'overlay')
.attr('width', width)
.attr('height', height)
.style('fill', 'red')
.style('opacity', 0)
.on('mouseover', mouseMoveHandler)
.on('mouseleave', () => {
// hide the highlight circle when the mouse leaves the chart
highlight(null);
});

renderPlot(data);

function renderPlot(data){
updateScales(data, scale);

svg.select('.y.axis')
.attr("transform", "translate(" + -pointRadius + " 0)" )
.call(axis.y);

var h = height + pointRadius;
svg.select('.x.axis')
.attr("transform", "translate(0, " + h + ")")
.call(axis.x);

svg.append("g")
.attr("class", "grid")
.call(gridlines.x);

svg.append("g")
.attr("class", "grid")
.call(gridlines.y);


//Do the chart
var update = dotsGroup.selectAll("circle").data(data)

update
.enter()
.append('circle')
.attr('r', pointRadius)
.attr('cx', d => scale.x(d.x))
.attr('cy', d => scale.y(d.y))
.attr('fill', d => colorScale(d.y))
};


// create a voronoi diagram
var voronoiDiagram = d3.voronoi()
.x(d => scale.x(d.x))
.y(d => scale.y(d.y))
.size([width, height])(data);


// add a circle for indicating the highlighted point
dotsGroup.append('circle')
.attr('class', 'highlight-circle')
.attr('r', pointRadius*2) // increase the size if highlighted
.style('fill', 'red')
.style('display', 'none');

// callback to highlight a point
function highlight(d) {
// no point to highlight - hide the circle and the tooltip
if (!d) {
d3.select('.highlight-circle').style('display', 'none');
//tooltip.style("opacity",0);
// otherwise, show the highlight circle at the correct position
} else {
d3.select('.highlight-circle')
.style('display', '')
.style('stroke', colorScale(d.y))
.attr('cx', scale.x(d.x))
.attr('cy', scale.y(d.y));
}
}

// callback for when the mouse moves across the overlay
function mouseMoveHandler() {
// get the current mouse position
var [mx, my] = d3.mouse(this);

var site = voronoiDiagram.find(mx, my);

// highlight the point if we found one, otherwise hide the highlight circle
highlight(site && site.data);


for (let i = 0; i < site.data.dotNum; i++) {
//do something....
}

}




}




</script>
</body>

</html>

最佳答案

  • 您必须在圆圈和突出显示圆圈之后绘制覆盖矩形。如果没有,则将鼠标悬停在圆圈上会生成鼠标离开事件,并且您会看到突出显示圆圈闪烁
  • 使用mousemove事件而不是mouseover,这是一种mouse-enter事件
  • 我添加了逻辑,仅在点更改时更新突出显示
  • 缩放和平移时网格不会更新(未修复)
  • 即使在overlay上移动时,仍然存在mouseleave事件 - 它们是由网格线引起的。将点组移到网格线组之后

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">

<title>Chart</title>


<!-- Reference minified version of D3 -->
<script src='https://d3js.org/d3.v4.min.js' type='text/javascript'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
</head>

<body>
<style>
.grid line { stroke: #ddd; }
</style>

<div id='scatter-plot'>
<svg width="700" height="500">
</svg>
</div>

<script>

var data = [];
for (let i = 0; i < 200; i++) {
data.push({
x: Math.random(),
y: Math.random(),
dotNum: i,
})
}
renderChart(data);

function renderChart(data) {

var totalWidth = 920,
totalHeight = 480;

var margin = {
top: 10,
left: 50,
bottom: 30,
right: 0
}

var width = totalWidth - margin.left - margin.right,
height = totalHeight - margin.top - margin.bottom;

// inner chart dimensions, where the dots are plotted
// var width = width - margin.left - margin.right;
// var height = height - margin.top - margin.bottom;

var tsn = d3.transition().duration(200);

// radius of points in the scatterplot
var pointRadius = 2;

var extent = {
x: d3.extent(data, function (d) {return d.x}),
y: d3.extent(data, function (d) {return d.y}),
};

var scale = {
x: d3.scaleLinear().range([0, width]),
y: d3.scaleLinear().range([height, 0]),
};

var axis = {
x: d3.axisBottom(scale.x).ticks(xTicks).tickSizeOuter(0),
y: d3.axisLeft(scale.y).ticks(yTicks).tickSizeOuter(0),
};

var gridlines = {
x: d3.axisBottom(scale.x).tickFormat("").tickSize(height),
y: d3.axisLeft(scale.y).tickFormat("").tickSize(-width),
}

var colorScale = d3.scaleLinear().domain([0, 1]).range(['#06a', '#06a']);

// select the root container where the chart will be added
var container = d3.select('#scatter-plot');

var zoom = d3.zoom()
.scaleExtent([1, 20])
.on("zoom", zoomed);

var tooltip = d3.select("body").append("div")
.attr("id", "tooltip")
.style("opacity", 0);

// initialize main SVG
var svg = container.select('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(zoom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// Clip path
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);

//Create X axis
var renderXAxis = svg.append("g")
.attr("class", "x axis")

//Create Y axis
var renderYAxis = svg.append("g")
.attr("class", "y axis")

// set up axis generating functions
var xTicks = Math.round(width / 50);
var yTicks = Math.round(height / 50);

function updateScales(data, scale){
scale.x.domain([extent.x[0], extent.x[1]]).nice(),
scale.y.domain([extent.y[0], extent.y[1]]).nice()
}

function zoomed() {
d3.event.transform.x = d3.event.transform.x;
d3.event.transform.y = d3.event.transform.y;

// update: rescale x axis
renderXAxis.call(axis.x.scale(d3.event.transform.rescaleX(scale.x)));
renderYAxis.call(axis.y.scale(d3.event.transform.rescaleX(scale.y)));

dotsGroup.attr("transform", d3.event.transform);
}

var dotsGroup;
renderPlot(data);

function renderPlot(data){
updateScales(data, scale);

svg.select('.y.axis')
.attr("transform", "translate(" + -pointRadius + " 0)" )
.call(axis.y);

var h = height + pointRadius;
svg.select('.x.axis')
.attr("transform", "translate(0, " + h + ")")
.call(axis.x);

svg.append("g")
.attr("class", "grid")
.call(gridlines.x);

svg.append("g")
.attr("class", "grid")
.call(gridlines.y);

dotsGroup = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("g");

//Do the chart
var update = dotsGroup.selectAll("circle").data(data)

update
.enter()
.append('circle')
.attr('r', pointRadius)
.attr('cx', d => scale.x(d.x))
.attr('cy', d => scale.y(d.y))
.attr('fill', d => colorScale(d.y))
};

// create a voronoi diagram
var voronoiDiagram = d3.voronoi()
.x(d => scale.x(d.x))
.y(d => scale.y(d.y))
.size([width, height])(data);

// add a circle for indicating the highlighted point
dotsGroup.append('circle')
.attr('class', 'highlight-circle')
.attr('r', pointRadius*2) // increase the size if highlighted
.style('fill', 'red')
.style('display', 'none');

// add the overlay on top of everything to take the mouse events
dotsGroup.append('rect')
.attr('class', 'overlay')
.attr('width', width)
.attr('height', height)
.style('fill', 'red')
.style('opacity', 0)
.on('mousemove', mouseMoveHandler)
.on('mouseleave', () => {
// hide the highlight circle when the mouse leaves the chart
console.log('mouse leave');
highlight(null);
});

var prevHighlightDotNum = null;
// callback to highlight a point
function highlight(d) {
// no point to highlight - hide the circle and the tooltip
if (!d) {
d3.select('.highlight-circle').style('display', 'none');
prevHighlightDotNum = null;
//tooltip.style("opacity",0);
// otherwise, show the highlight circle at the correct position
} else {
if (prevHighlightDotNum !== d.dotNum) {
d3.select('.highlight-circle')
.style('display', '')
.style('stroke', colorScale(d.y))
.attr('cx', scale.x(d.x))
.attr('cy', scale.y(d.y));
prevHighlightDotNum = d.dotNum;
}
}
}

// callback for when the mouse moves across the overlay
function mouseMoveHandler() {
// get the current mouse position
var [mx, my] = d3.mouse(this);

var site = voronoiDiagram.find(mx, my);

//console.log('site', site);
// highlight the point if we found one, otherwise hide the highlight circle
highlight(site && site.data);

for (let i = 0; i < site.data.dotNum; i++) {
//do something....
}
}
}
</script>
</body>

</html>

关于javascript - d3.js voronoi 事件。当光标正好位于点上方时,鼠标悬停似乎消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51736979/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com