jjzjj

javascript - D3.js:折线图 - 工具提示和悬停垂直线

coder 2024-07-19 原文

我一直在研究使用 D3.js 构建的交互式折线图。悬停一次我希望工具提示显示为一条垂直线。垂直线很好,但是,我遇到了与工具提示相关的问题。工具提示位置不在图表上,我只得到第一个数据元素。

这是我的代码:

 margin = {
                    top: 20,
                    right: 20,
                    bottom: 20,
                    left: 50
                };
        var width = Math.max(250, Math.min(700, d3.select("#content").width- margin.left - margin.right)),
                    height = 500;

        var vis = d3.select("#line_chart").append("svg")
                            .attr("width", width + margin.left + margin.right)
                            .attr("height", height + margin.top + margin.bottom);

        max_x = 0, max_y = 0, min = 100;

        d3.csv("line.csv", function(error, data) {


                for(i=0; i < data.length; i++){
                    max_y = Math.max(max_y, data[i].number);
                    max_x = Math.max(max_x, data[i].class);
                    min = Math.min(min, data[i].class);
                }


                    xScale = d3.scale.linear().range([margin.left, width - margin.right]).domain([min, max_x]),

                    yScale = d3.scale.linear().range([height - margin.top, margin.bottom]).domain([0, max_y]),

                    xAxis = d3.svg.axis()
                    .scale(xScale),

                    yAxis = d3.svg.axis()
                    .scale(yScale)
                    .orient("left");

                vis.append("svg:g")
                    .attr("class", "x axis")
                    .attr("transform", "translate(0," + (height - margin.bottom) + ")")
                    .call(xAxis);

                vis.append("svg:g")
                    .attr("class", "y axis")
                    .attr("transform", "translate(" + (margin.left) + ",0)")
                    .call(yAxis);

                var lineGen = d3.svg.line()
                    .x(function(d) {
                        return xScale(d.class);
                    })
                    .y(function(d) {
                        return yScale(d.number);
                    })
                    .interpolate("basis");

                var pth = vis.append('svg:path')
                    .attr('d', lineGen(data))
                    .attr('stroke', '#000')
                    .attr('stroke-width', 3.5)
                    .attr('fill', 'none');

                var totalLength = pth.node().getTotalLength();

                pth
                  .attr("stroke-dasharray", totalLength + " " + totalLength)
                  .attr("stroke-dashoffset", totalLength)
                  .transition()
                    .duration(2400)
                    .ease("linear")
                    .attr("stroke-dashoffset", 0);

                //Line chart mouse over 
                var hoverLineGroup = vis.append("g")
                                    .attr("class", "hover-line");

                var hoverLine = hoverLineGroup
                    .append("line")
                        .attr("stroke", "#000")
                        .attr("x1", 10).attr("x2", 10) 
                        .attr("y1", 0).attr("y2", height); 

                var hoverTT = hoverLineGroup.append('text')
                   .attr("class", "hover-tex capo")
                   .attr('dy', "0.35em");

                var cle = hoverLineGroup.append("circle")
                    .attr("r", 4.5);

                var hoverTT2 = hoverLineGroup.append('text')

                   .attr("class", "hover-text capo")
                   .attr('dy', "0.35em");

                hoverLineGroup.style("opacity", 1e-6);

                var rectHover = vis.append("rect")
                  .data(data)
                  .attr("class", "overlay")
                  .attr("width", width)
                  .attr("height", height);

                rectHover  
                    .on("mouseout", hoverMouseOff)
                    .on("mousemove", hoverMouseOn);

                function hoverMouseOn(d) {

                      var mouse_x = d3.mouse(this)[0];
                      var mouse_y = d3.mouse(this)[1];
                      var graph_y = yScale.invert(mouse_y);
                      var graph_x = xScale.invert(mouse_x);

                      hoverTT.text("Marks: " + Math.round(graph_x * 100)/100); 
                      hoverTT.attr('x', mouse_x + 10);
                      hoverTT.attr('y', yScale(d.class));


                      hoverTT2.text("Frequency: " + Math.round(d.number * 100)/100)
                        .attr('x', mouse_x + 10)
                        .attr('y', yScale(d.class) +15);

                      cle
                        .attr('x', mouse_x)
                        .attr('y', mouse_y);


                      hoverLine.attr("x1", mouse_x).attr("x2", mouse_x)
                      hoverLineGroup.style("opacity", 1);

                }

                function hoverMouseOff() {
                        hoverLineGroup.style("opacity", 1e-6);
                };

            });
        }

数据:

class,number
25,1
30,7
35,11
45,13
50,21
55,23
60,30
65,41
75,39
80,24
85,14
90,4
95,8
100,2

我无法弄清楚问题是什么。

我该如何解决这个问题?

提前致谢。

编辑:这是工作代码:https://jsfiddle.net/kan83q0m/1/

最佳答案

在您的 hoverMouseOn 方法中,变量 d 未定义。您需要使用 d3.bisector 来查找最近的数据点,如下所示:

var bisectDate = d3.bisector(function(d) { return d.class; }).left;

var mouseDate = xScale.invert(mouse_x);
var i = bisectDate(data, mouseDate);

var d0 = data[i - 1]
var d1 = data[i];
var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;

此外,我将 mousemove 监听器放在“vis”而不是“rectHover”上:

        vis  
            .on("mouseout", hoverMouseOff)
            .on("mousemove", hoverMouseOn);

并使用 d.number 而不是 d.class 作为 y 值。如果您希望工具提示始终在线,请 gets a bit more complicated . Here's a working fiddle.

将工具提示放在鼠标坐标处可能会更容易 like in this fiddle.

关于javascript - D3.js:折线图 - 工具提示和悬停垂直线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42433779/

有关javascript - D3.js:折线图 - 工具提示和悬停垂直线的更多相关文章

  1. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  2. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  3. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  4. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  5. ruby - 在 Ruby 中,垂直线是什么? - 2

    1.upto(9){|x|printx}为什么这行不通?{printx|x}}y呢? 最佳答案 它用于传递给您的block的参数。即在您的示例中,upto将使用1到9中的每个数字调用您的block,当前值可作为x获得。block参数可以有任何名称,就像方法参数一样。例如1.upto(9){|num|putsnum是有效的。就像一个方法的参数一样,一个block也可以有多个参数。例如hash.each_pair{|key,value|puts"#{key}is#{value}"} 关于ru

  6. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  7. ruby - 使用 Ruby 开发工具包将文件上传到 Amazon S3 - 2

    我正在尝试上传文件。一个简单的hello.txt。我正在关注文档,但无法将其上传到我的存储桶。#STARTAWSCLIENTs3=Aws::S3::Resource.newbucket=s3.bucket(BUCKET_NAME)begins3.buckets[BUCKET_NAME].objects[KEY].write(:file=>FILE_NAME)puts"Uploadingfile#{FILE_NAME}tobucket#{BUCKET_NAME}."bucket.objects.eachdo|obj|puts"#{obj.key}=>#{obj.etag}"endresc

  8. ruby-on-rails - Assets 管道损坏 : Not compiling on the fly css and js files - 2

    我开始了一个新的Rails3.2.5项目,Assets管道不再工作了。CSS和Javascript文件不再编译。这是尝试生成Assets时日志的输出:StartedGET"/assets/application.css?body=1"for127.0.0.1at2012-06-1623:59:11-0700Servedasset/application.css-200OK(0ms)[2012-06-1623:59:11]ERRORNoMethodError:undefinedmethod`each'fornil:NilClass/Users/greg/.rbenv/versions/1

  9. ruby-on-rails - Rails - 理解 application.js 和 application.css - 2

    rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:

  10. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

随机推荐