草庐IT

javascript - 在 Canvas 图中显示工具提示

coder 2024-05-11 原文

我正在使用 html5 canvas 元素绘制一个图形,其中的点表示 here 中的各个点。 .

我想在鼠标悬停的不同点上显示不同的工具提示。要显示为工具提示的文本将由用户提供。

我试过但无法弄清楚如何将工具提示添加到图中的各个点。我用来显示点的代码是..

// Draw the dots
c.fillStyle = '#333';

for (var i = 0; i < data.values.length; i++) {
  c.beginPath();
  c.arc(getXPixel(data.values[i].X), getYPixel(data.values[i].Y), 4, 0, Math.PI * 2, true);
  c.fill();
}

我应该在此代码中添加什么,以便我能够将用户输入显示为工具提示?

最佳答案

您可以在用户移到图表的数据点上时显示工具提示

此工具提示只是第二个 Canvas ,它从链接的文本框中绘制文本并将其自身定位在数据点上方。

首先,您创建一个数组来保存每个数据点的工具提示信息。

    var dots = [];

对于每个工具提示,您将需要:

  • 数据点的 x/y 坐标,
  • 数据点的半径,
  • 您要从中获取提示的文本框的 ID。
  • 您还需要 rXr,它始终 == 半径的平方(在 HitTest 期间需要)

这是创建要存储在点[]中的工具提示信息的代码

    // define tooltips for each data point

    for(var i = 0; i < data.values.length; i ++) {
        dots.push({
            x: getXPixel(data.values[i].X),
            y: getYPixel(data.values[i].Y),
            r: 4,
            rXr: 16,
            tip: "#text"+(i+1)
        });
    }

然后您设置一个查看点数组的 mousemove 处理程序。如果用户在任何 data=dot 内移动,则会显示工具提示:

    // request mousemove events

    $("#graph").mousemove(function(e){handleMouseMove(e);});

    // show tooltip when mouse hovers over dot
    function handleMouseMove(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // Put your mousemove stuff here
      var hit = false;
      for (var i = 0; i < dots.length; i++) {
          var dot = dots[i];
          var dx = mouseX - dot.x;
          var dy = mouseY - dot.y;
          if (dx * dx + dy * dy < dot.rXr) {
              tipCanvas.style.left = (dot.x) + "px";
              tipCanvas.style.top = (dot.y - 40) + "px";
              tipCtx.clearRect(0, 0, tipCanvas.width, tipCanvas.height);
              tipCtx.fillText($(dot.tip).val(), 5, 15);
              hit = true;
          }
      }
      if (!hit) { tipCanvas.style.left = "-200px"; }
    }

[已编辑以适合您的代码]

这是代码和 fiddle :http://jsfiddle.net/m1erickson/yLBjM/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; margin-top:35px; }
    #wrapper{position:relative; width:300px; height:150px;}
    canvas{border:1px solid red;}
    #tip{background-color:white; border:1px solid blue; position:absolute; left:-200px; top:100px;}
</style>

<script>
$(function(){

    var graph = document.getElementById("graph");
    var ctx = graph.getContext("2d");
    var tipCanvas = document.getElementById("tip");
    var tipCtx = tipCanvas.getContext("2d");

    var canvasOffset = $("#graph").offset();
    var offsetX = canvasOffset.left;
    var offsetY = canvasOffset.top;

    var graph;
    var xPadding = 30;
    var yPadding = 30;

    // Notice I changed The X values
    var data = { values:[
        { X: 0, Y: 12 },
        { X: 2, Y: 28 },
        { X: 3, Y: 18 },
        { X: 4, Y: 34 },
        { X: 5, Y: 40 },
        { X: 6, Y: 80 },
        { X: 7, Y: 80 }
    ]};

    // define tooltips for each data point
    var dots = [];
    for(var i = 0; i < data.values.length; i ++) {
        dots.push({
            x: getXPixel(data.values[i].X),
            y: getYPixel(data.values[i].Y),
            r: 4,
            rXr: 16,
            color: "red",
            tip: "#text"+(i+1)
        });
    }

    // request mousemove events
    $("#graph").mousemove(function(e){handleMouseMove(e);});

    // show tooltip when mouse hovers over dot
    function handleMouseMove(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // Put your mousemove stuff here
      var hit = false;
      for (var i = 0; i < dots.length; i++) {
          var dot = dots[i];
          var dx = mouseX - dot.x;
          var dy = mouseY - dot.y;
          if (dx * dx + dy * dy < dot.rXr) {
              tipCanvas.style.left = (dot.x) + "px";
              tipCanvas.style.top = (dot.y - 40) + "px";
              tipCtx.clearRect(0, 0, tipCanvas.width, tipCanvas.height);
              tipCtx.fillText($(dot.tip).val(), 5, 15);
              hit = true;
          }
      }
      if (!hit) { tipCanvas.style.left = "-200px"; }
    }

//不变的代码如下

    // Returns the max Y value in our data list
    function getMaxY() {
        var max = 0;

        for(var i = 0; i < data.values.length; i ++) {
            if(data.values[i].Y > max) {
                max = data.values[i].Y;
            }
        }

        max += 10 - max % 10;
        return max;
    }

    // Returns the max X value in our data list
    function getMaxX() {
        var max = 0;

        for(var i = 0; i < data.values.length; i ++) {
            if(data.values[i].X > max) {
                max = data.values[i].X;
            }
        }

        // omited
      //max += 10 - max % 10;
        return max;
    }

    // Return the x pixel for a graph point
    function getXPixel(val) {
        // uses the getMaxX() function
        return ((graph.width - xPadding) / (getMaxX() + 1)) * val + (xPadding * 1.5);
        // was
      //return ((graph.width - xPadding) / getMaxX()) * val + (xPadding * 1.5);
    }

    // Return the y pixel for a graph point
    function getYPixel(val) {
        return graph.height - (((graph.height - yPadding) / getMaxY()) * val) - yPadding;
    }

        graph = document.getElementById("graph");
        var c = graph.getContext('2d');            

        c.lineWidth = 2;
        c.strokeStyle = '#333';
        c.font = 'italic 8pt sans-serif';
        c.textAlign = "center";

        // Draw the axises
        c.beginPath();
        c.moveTo(xPadding, 0);
        c.lineTo(xPadding, graph.height - yPadding);
        c.lineTo(graph.width, graph.height - yPadding);
        c.stroke();

        // Draw the X value texts
        var myMaxX = getMaxX();
        for(var i = 0; i <= myMaxX; i ++) {
            // uses data.values[i].X
            c.fillText(i, getXPixel(i), graph.height - yPadding + 20);
        }
        /* was
        for(var i = 0; i < data.values.length; i ++) {
            // uses data.values[i].X
            c.fillText(data.values[i].X, getXPixel(data.values[i].X), graph.height - yPadding + 20);
        }
        */

        // Draw the Y value texts
        c.textAlign = "right"
        c.textBaseline = "middle";

        for(var i = 0; i < getMaxY(); i += 10) {
            c.fillText(i, xPadding - 10, getYPixel(i));
        }

        c.strokeStyle = '#f00';

        // Draw the line graph
        c.beginPath();
        c.moveTo(getXPixel(data.values[0].X), getYPixel(data.values[0].Y));
        for(var i = 1; i < data.values.length; i ++) {
            c.lineTo(getXPixel(data.values[i].X), getYPixel(data.values[i].Y));
        }
        c.stroke();

        // Draw the dots
        c.fillStyle = '#333';

        for(var i = 0; i < data.values.length; i ++) {  
            c.beginPath();
            c.arc(getXPixel(data.values[i].X), getYPixel(data.values[i].Y), 4, 0, Math.PI * 2, true);
            c.fill();
        }


}); // end $(function(){});
</script>

</head>

<body>
    <div id="wrapper">
        <canvas id="graph" width=300 height=150></canvas>
        <canvas id="tip" width=100 height=25></canvas>
    </div>
    <br><br>
    <input type="text" id="text1" value="text 1"/><br><br>
    <input type="text" id="text2" value="text 2"/><br><br>
    <input type="text" id="text3" value="text 3"/><br><br>
    <input type="text" id="text4" value="text 4"/><br><br>
    <input type="text" id="text5" value="text 5"/><br><br>
    <input type="text" id="text6" value="text 6"/><br><br>
    <input type="text" id="text7" value="text 7"/><br><br>
</body>
</html>

关于javascript - 在 Canvas 图中显示工具提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17064913/

有关javascript - 在 Canvas 图中显示工具提示的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  4. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  5. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

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

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

  7. ruby-on-rails - 复数 for fields_for has_many 关联未显示在 View 中 - 2

    目前,Itembelongs_toCompany和has_manyItemVariants。我正在尝试使用嵌套的fields_for通过Item表单添加ItemVariant字段,但是使用:item_variants不显示该表单。只有当我使用单数时才会显示。我检查了我的关联,它们似乎是正确的,这可能与嵌套在公司下的项目有关,还是我遗漏了其他东西?提前致谢。注意:下面的代码片段中省略了不相关的代码。编辑:不知道这是否相关,但我正在使用CanCan进行身份验证。routes.rbresources:companiesdoresources:itemsenditem.rbclassItemi

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

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

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

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

  10. ruby-on-rails - 在 Flash 警报 Rails 3 中显示错误消息 - 2

    如果我在模型中设置验证消息validates:name,:presence=>{:message=>'Thenamecantbeblank.'}我如何让该消息显示在闪光警报中,这是我迄今为止尝试过的方法defcreate@message=Message.new(params[:message])if@message.valid?ContactMailer.send_mail(@message).deliverredirect_to(root_path,:notice=>"Thanksforyourmessage,Iwillbeintouchsoon")elseflash[:error]

随机推荐