d3.event 的 x 和 y 坐标在显示工具提示时不正确 [英] d3.event's x and y coordinates are incorrect while showing tooltip

查看:22
本文介绍了d3.event 的 x 和 y 坐标在显示工具提示时不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在水平条形图上显示工具提示.如果我向下滚动页面,此工具提示将无法正常工作.

如果条形图在视图中并且不需要滚动,这可以正常工作.但是如果我在图表上方添加更多元素,当我向下滚动时,工具提示会从鼠标指针升高.

请帮助我解决这个问题.

代码如下:

//忽略测试数据var 出生数据 = [{年份":1967,"month": "一月",出生":31502},{年份":1967,"month": "二月",出生":26703},{年份":1967,"month": "三月",出生":28853},{年份":1967,"month": "四月",出生":26958},{年份":1967,"月": "五月",出生":28591},{年份":1967,"month": "六月",出生":29545},{年份":1967,"month": "七月",出生":30086},{年份":1967,"month": "八月",出生":30947},{年份":1967,"month": "九月",出生":32338},{年份":1967,"month": "十月",出生":32296},{年份":1967,"month": "十一月",出生":30326},{年份":1967,"month": "十二月",出生":28994}]//d3 代码var minYear = d3.min(birthData, function(d) {返回 d.year;});var maxYear = d3.max(birthData, function(d) {返回 d.year;});无功宽度= 600;变量高度 = 600;var barPadding = 30;var numBars = 12;var barWidth = 10;var maxBirths = d3.max(birthData, function(d) {返回 d. 出生;});var xScale = d3.scaleLinear().domain([0, maxBirths]).range([0, 宽度]);var tooltip = d3.select('body').append('div').classed('tooltip', true);var g = d3.select('svg').attr('宽度', 宽度).attr('身高', 身高).selectAll('g').data(birthData.filter(function(d) {返回 d.year === minYear;})).进入().append('g').attr('transform', 'translate(40, 40)');g.append('rect').attr('宽度', 函数(d) {返回 xScale(maxBirths);}).attr('高度', barWidth).attr('x', 0).attr('y', function(d, i) {返回 (barWidth + barPadding) * i;}).attr('填充', '灰色');g.append('rect').attr('宽度', 函数(d) {返回 xScale(d.births);}).attr('高度', barWidth).attr('x', 0).attr('y', function(d, i) {返回 (barWidth + barPadding) * i;}).attr('填充', '蓝色').classed('原始', 真);g.append('文本').attr('x', 0).attr('y', function(d, i) {返回 (barWidth + barPadding) * i;}).text(function(d) {返回 d.month;});g.on('mousemove', showToolTip).on('mouseout', hideToolTip).on('touchstart', showToolTip).on('touchend', hideToolTip);函数隐藏工具提示(){工具提示.style('不透明度', 0);}功能 showToolTip(d) {工具提示.style('不透明度', 1).style('left', d3.event.x + 'px').style('top', d3.event.y + 'px').text(d.month + ': ' + d.births)};

svg,输入 {边距:0 自动 10px;显示:块;}.工具提示{不透明度:0;位置:绝对;指针事件:无;背景颜色:浅蓝色;边框:8px 纯蓝色;边框半径:8px;填充:15px;}

<html lang="zh-cn"><头><meta charset="UTF-8"><title>D3 出生图</title><link rel="stylesheet" href="style.css"><身体><div style="height: 200px; width: 200px"><h2>仪表板</h2>

</svg><script src="https://d3js.org/d3.v5.js"></script></html>

解决方案

使用 d3 代替 d3.event.xd3.event.y.event.pageXd3.event.pageY.event.pageX:

<块引用>

返回鼠标被点击时相对于整个文档左边缘的 X(水平)坐标(以像素为单位).这包括文档中当前不可见的任何部分.

pageY 也是如此.

这是您的更改代码:

//忽略测试数据var 出生数据 = [{年份":1967,"month": "一月",出生":31502},{年份":1967,"month": "二月",出生":26703},{年份":1967,"month": "三月",出生":28853},{年份":1967,"month": "四月",出生":26958},{年份":1967,"月": "五月",出生":28591},{年份":1967,"month": "六月",出生":29545},{年份":1967,"month": "七月",出生":30086},{年份":1967,"month": "八月",出生":30947},{年份":1967,"month": "九月",出生":32338},{年份":1967,"month": "十月",出生":32296},{年份":1967,"month": "十一月",出生":30326},{年份":1967,"month": "十二月",出生":28994}]//d3 代码var minYear = d3.min(birthData, function(d) {返回 d.year;});var maxYear = d3.max(birthData, function(d) {返回 d.year;});var 宽度 = 600;变量高度 = 600;var barPadding = 30;var numBars = 12;var barWidth = 10;var maxBirths = d3.max(birthData, function(d) {返回 d. 出生;});var xScale = d3.scaleLinear().domain([0, maxBirths]).range([0, 宽度]);var tooltip = d3.select('body').append('div').classed('tooltip', true);var g = d3.select('svg').attr('宽度', 宽度).attr('身高', 身高).selectAll('g').data(birthData.filter(function(d) {返回 d.year === minYear;})).进入().append('g').attr('transform', 'translate(40, 40)');g.append('rect').attr('宽度', 函数(d) {返回 xScale(maxBirths);}).attr('高度', barWidth).attr('x', 0).attr('y', function(d, i) {返回 (barWidth + barPadding) * i;}).attr('填充', '灰色');g.append('rect').attr('宽度', 函数(d) {返回 xScale(d.births);}).attr('高度', barWidth).attr('x', 0).attr('y', function(d, i) {返回 (barWidth + barPadding) * i;}).attr('填充', '蓝色').classed('原始', 真);g.append('文本').attr('x', 0).attr('y', function(d, i) {返回 (barWidth + barPadding) * i;}).text(function(d) {返回 d.month;});g.on('mousemove', showToolTip).on('mouseout', hideToolTip).on('touchstart', showToolTip).on('touchend', hideToolTip);函数隐藏工具提示(){工具提示.style('不透明度', 0);}功能 showToolTip(d) {工具提示.style('不透明度', 1).style('left', d3.event.pageX + 'px').style('top', d3.event.pageY + 'px').text(d.month + ': ' + d.births)};

svg,输入 {边距:0 自动 10px;显示:块;}.工具提示{不透明度:0;位置:绝对;指针事件:无;背景颜色:浅蓝色;边框:8px 纯蓝色;边框半径:8px;填充:15px;}

<html lang="zh-cn"><头><meta charset="UTF-8"><title>D3 出生图</title><link rel="stylesheet" href="style.css"><身体><div style="height: 200px; width: 200px"><h2>仪表板</h2>

</svg><script src="https://d3js.org/d3.v5.js"></script></html>

I am trying to display a tooltip on the horizontal bar chart. This tooltip does not work properly if I scroll down the page a bit.

This works fine if the bar chart is in view and there is no need to scroll. But if I add more elements above the chart, as I scroll down tooltip goes higher from the mouse pointer.

Please help me in resolving this issue.

Here is the code:

//Ignore test data
var birthData = [{
    "year": 1967,
    "month": "January",
    "births": 31502
  },
  {
    "year": 1967,
    "month": "February",
    "births": 26703
  },
  {
    "year": 1967,
    "month": "March",
    "births": 28853
  },
  {
    "year": 1967,
    "month": "April",
    "births": 26958
  },
  {
    "year": 1967,
    "month": "May",
    "births": 28591
  },
  {
    "year": 1967,
    "month": "June",
    "births": 29545
  },
  {
    "year": 1967,
    "month": "July",
    "births": 30086
  },
  {
    "year": 1967,
    "month": "August",
    "births": 30947
  },
  {
    "year": 1967,
    "month": "September",
    "births": 32338
  },
  {
    "year": 1967,
    "month": "October",
    "births": 32296
  },
  {
    "year": 1967,
    "month": "November",
    "births": 30326
  },
  {
    "year": 1967,
    "month": "December",
    "births": 28994
  }
]

//d3 code
var minYear = d3.min(birthData, function(d) {
  return d.year;
});
var maxYear = d3.max(birthData, function(d) {
  return d.year;
});
var width = 600;
var height = 600;
var barPadding = 30;
var numBars = 12;
var barWidth = 10;

var maxBirths = d3.max(birthData, function(d) {
  return d.births;
});

var xScale = d3.scaleLinear()
  .domain([0, maxBirths])
  .range([0, width]);

var tooltip = d3.select('body').append('div').classed('tooltip', true);

var g = d3.select('svg')
  .attr('width', width)
  .attr('height', height)
  .selectAll('g')
  .data(birthData.filter(function(d) {
    return d.year === minYear;
  }))
  .enter()
  .append('g')
  .attr('transform', 'translate(40, 40)');

g.append('rect')
  .attr('width', function(d) {
    return xScale(maxBirths);
  })
  .attr('height', barWidth)
  .attr('x', 0)
  .attr('y', function(d, i) {
    return (barWidth + barPadding) * i;
  }).attr('fill', 'grey');

g.append('rect')
  .attr('width', function(d) {
    return xScale(d.births);
  })
  .attr('height', barWidth)
  .attr('x', 0)
  .attr('y', function(d, i) {
    return (barWidth + barPadding) * i;
  }).attr('fill', 'blue')
  .classed('original', true);

g.append('text')
  .attr('x', 0)
  .attr('y', function(d, i) {
    return (barWidth + barPadding) * i;
  })
  .text(function(d) {
    return d.month;
  });

g.on('mousemove', showToolTip)
  .on('mouseout', hideToolTip)
  .on('touchstart', showToolTip)
  .on('touchend', hideToolTip);


function hideToolTip() {
  tooltip
    .style('opacity', 0);
}

function showToolTip(d) {
  tooltip
    .style('opacity', 1)
    .style('left', d3.event.x + 'px')
    .style('top', d3.event.y + 'px')
    .text(d.month + ': ' + d.births)
};

svg,
input {
  margin: 0 auto 10px;
  display: block;
}

.tooltip {
  opacity: 0;
  position: absolute;
  pointer-events: none;
  background-color: lightblue;
  border: 8px solid blue;
  border-radius: 8px;
  padding: 15px;
}

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

<head>
  <meta charset="UTF-8">
  <title>D3 Birth Chart</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div style="height: 200px; width: 200px">
    <h2>Dashboard</h2>
  </div>
  <svg>
  </svg>
  <script src="https://d3js.org/d3.v5.js"></script>
</body>

</html>

解决方案

Instead of d3.event.x and d3.event.y use d3.event.pageX and d3.event.pageY. event.pageX:

returns the X (horizontal) coordinate (in pixels) at which the mouse was clicked, relative to the left edge of the entire document. This includes any portion of the document not currently visible.

The same goes for pageY.

Here is your code with that change:

//Ignore test data
var birthData = [{
    "year": 1967,
    "month": "January",
    "births": 31502
  },
  {
    "year": 1967,
    "month": "February",
    "births": 26703
  },
  {
    "year": 1967,
    "month": "March",
    "births": 28853
  },
  {
    "year": 1967,
    "month": "April",
    "births": 26958
  },
  {
    "year": 1967,
    "month": "May",
    "births": 28591
  },
  {
    "year": 1967,
    "month": "June",
    "births": 29545
  },
  {
    "year": 1967,
    "month": "July",
    "births": 30086
  },
  {
    "year": 1967,
    "month": "August",
    "births": 30947
  },
  {
    "year": 1967,
    "month": "September",
    "births": 32338
  },
  {
    "year": 1967,
    "month": "October",
    "births": 32296
  },
  {
    "year": 1967,
    "month": "November",
    "births": 30326
  },
  {
    "year": 1967,
    "month": "December",
    "births": 28994
  }
]

//d3 code
var minYear = d3.min(birthData, function(d) {
  return d.year;
});
var maxYear = d3.max(birthData, function(d) {
  return d.year;
});
var width = 600;
var height = 600;
var barPadding = 30;
var numBars = 12;
var barWidth = 10;

var maxBirths = d3.max(birthData, function(d) {
  return d.births;
});

var xScale = d3.scaleLinear()
  .domain([0, maxBirths])
  .range([0, width]);

var tooltip = d3.select('body').append('div').classed('tooltip', true);

var g = d3.select('svg')
  .attr('width', width)
  .attr('height', height)
  .selectAll('g')
  .data(birthData.filter(function(d) {
    return d.year === minYear;
  }))
  .enter()
  .append('g')
  .attr('transform', 'translate(40, 40)');

g.append('rect')
  .attr('width', function(d) {
    return xScale(maxBirths);
  })
  .attr('height', barWidth)
  .attr('x', 0)
  .attr('y', function(d, i) {
    return (barWidth + barPadding) * i;
  }).attr('fill', 'grey');

g.append('rect')
  .attr('width', function(d) {
    return xScale(d.births);
  })
  .attr('height', barWidth)
  .attr('x', 0)
  .attr('y', function(d, i) {
    return (barWidth + barPadding) * i;
  }).attr('fill', 'blue')
  .classed('original', true);

g.append('text')
  .attr('x', 0)
  .attr('y', function(d, i) {
    return (barWidth + barPadding) * i;
  })
  .text(function(d) {
    return d.month;
  });

g.on('mousemove', showToolTip)
  .on('mouseout', hideToolTip)
  .on('touchstart', showToolTip)
  .on('touchend', hideToolTip);


function hideToolTip() {
  tooltip
    .style('opacity', 0);
}

function showToolTip(d) {
  tooltip
    .style('opacity', 1)
    .style('left', d3.event.pageX + 'px')
    .style('top', d3.event.pageY + 'px')
    .text(d.month + ': ' + d.births)
};

svg,
input {
  margin: 0 auto 10px;
  display: block;
}

.tooltip {
  opacity: 0;
  position: absolute;
  pointer-events: none;
  background-color: lightblue;
  border: 8px solid blue;
  border-radius: 8px;
  padding: 15px;
}

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

<head>
  <meta charset="UTF-8">
  <title>D3 Birth Chart</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div style="height: 200px; width: 200px">
    <h2>Dashboard</h2>
  </div>
  <svg>
  </svg>
  <script src="https://d3js.org/d3.v5.js"></script>
</body>

</html>

这篇关于d3.event 的 x 和 y 坐标在显示工具提示时不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆