如何在图的悬停转折点上显示Y轴值 [英] How To Show Y-axis value, on hover turning point of graph

查看:336
本文介绍了如何在图的悬停转折点上显示Y轴值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用java脚本和画布创建图形。以下是jsfiddle链接






  • 创建一个div作为工具提示(工具提示div)。

  • 最初隐藏工具提示div。

  • 收听mousemove事件。

  • 在mousemove处理程序中,点击测试鼠标是否在任何数据点内。

  • 如果鼠标在数据点内,


    1. 在工具提示div中设置所需的文本,

    2. 使用CSS在数据点上移动工具提示div,

    3. 显示工具提示div。




以下是注释代码和演示



 maxYValue)maxYValue = data.dataPoints [i] .y ; }}; var renderBackground = function(){var lingrad = ctx.createLinearGradient(margin.left,margin.top,xMax  -  margin.right,yMax); lingrad.addColorStop(0.0,'#ffffff'); lingrad.addColorStop(0.2,'#fff'); lingrad.addColorStop(0.8,'#fff'); lingrad.addColorStop(1,'#ffffff'); ctx.fillStyle = lingrad; ctx.fillRect(margin.left,margin.top,xMax  -  margin.left,yMax  -  margin.top); ctx.fillStyle ='#6A6A6A'; }; var renderText = function(){var labelFont =(data.labelFont!= null)? data.labelFont:'20pt Arial'; ctx.font = labelFont; ctx.textAlign =center; // Title var txtSize = ctx.measureText(data.title); ctx.fillText(data.title,(chartWidth / 2),(margin.top / 2)); // X-axis text txtSize = ctx.measureText(data.xLabel); ctx.fillText(data.xLabel,margin.left +(xMax / 2) - (txtSize.width / 2),yMax +(margin.bottom / 1.2)); // Y轴文本ctx.save(); ctx.rotate(-Math.PI / 2); ctx.font = labelFont; ctx.fillText(data.yLabel,(yMax / 2)* -1,margin.left / 4); ctx.restore(); }; var renderLinesAndLabels = function(){//垂直向导var yInc = yMax / data.dataPoints.length; var yPos = 0; var yLabelInc =(maxYValue * ratio)/ data.dataPoints.length; var xInc = getXInc(); var xPos = margin.left; for(var i = 0; i  

  body {background-color:ivory; } #canvas {border:1px solid red; margin:0 auto; }  

 < script src =https:// ajax .googleapis.com / ajax / libs / jquery / 1.9.1 / jquery.min.js>< / script>< canvas id =canvaswidth = 300 height = 300& code> 


I am making a graph using java script and canvas. below is the jsfiddle link

http://jsfiddle.net/ghan_123/n0r796ae/

I want to show values on hover bubble(turning points) like

price 2100 on 1-aug

java script

var CanvasChart = function () {
    var ctx;
    var margin = { top: 40, left: 75, right: 0, bottom: 75 };
    var chartHeight, chartWidth, yMax, xMax, data;
    var maxYValue = 0;
    var ratio = 0;
    var renderType = { lines: 'lines', points: 'points' };

    var render = function(canvasId, dataObj) {
        data = dataObj;
        getMaxDataYValue();
        var canvas = document.getElementById(canvasId);
        chartHeight = canvas.getAttribute('height');
        chartWidth = canvas.getAttribute('width');
        xMax = chartWidth - (margin.left + margin.right);
        yMax = chartHeight - (margin.top + margin.bottom);
        ratio = yMax / maxYValue;
        ctx = canvas.getContext("2d");
        renderChart();
    };

    var renderChart = function () {
        renderBackground();
        renderText();
        renderLinesAndLabels();

        //render data based upon type of renderType(s) that client supplies
        if (data.renderTypes == undefined || data.renderTypes == null) data.renderTypes = [renderType.lines];
        for (var i = 0; i < data.renderTypes.length; i++) {
            renderData(data.renderTypes[i]);
        }
    };

    var getMaxDataYValue = function () {
        for (var i = 0; i < data.dataPoints.length; i++) {
            if (data.dataPoints[i].y > maxYValue) maxYValue = data.dataPoints[i].y;
        }
    };

    var renderBackground = function() {
        var lingrad = ctx.createLinearGradient(margin.left, margin.top, xMax - margin.right, yMax);
        lingrad.addColorStop(0.0, '#ffffff');
        lingrad.addColorStop(0.2, '#fff');
        lingrad.addColorStop(0.8, '#fff');
        lingrad.addColorStop(1, '#ffffff');
        ctx.fillStyle = lingrad;
        ctx.fillRect(margin.left, margin.top, xMax - margin.left, yMax - margin.top);
        ctx.fillStyle = '#6A6A6A';
    };

    var renderText = function() {
        var labelFont = (data.labelFont != null) ? data.labelFont : '20pt Arial';
        ctx.font = labelFont;
        ctx.textAlign = "center";

        //Title
        var txtSize = ctx.measureText(data.title);
        ctx.fillText(data.title, (chartWidth / 2), (margin.top / 2));

        //X-axis text
        txtSize = ctx.measureText(data.xLabel);
        ctx.fillText(data.xLabel, margin.left + (xMax / 2) - (txtSize.width / 2), yMax + (margin.bottom / 1.2));

        //Y-axis text
        ctx.save();
        ctx.rotate(-Math.PI / 2);
        ctx.font = labelFont;
        ctx.fillText(data.yLabel, (yMax / 2) * -1, margin.left / 4);
        ctx.restore();
    };

    var renderLinesAndLabels = function () {
        //Vertical guide lines
        var yInc = yMax / data.dataPoints.length;
        var yPos = 0;
        var yLabelInc = (maxYValue * ratio) / data.dataPoints.length;
        var xInc = getXInc();
        var xPos = margin.left;
        for (var i = 0; i < data.dataPoints.length; i++) {
            yPos += (i == 0) ? margin.top : yInc;
            //Draw horizontal lines
            drawLine(margin.left, yPos, xMax, yPos, '#E8E8E8');

            //y axis labels
            ctx.font = (data.dataPointFont != null) ? data.dataPointFont : '10pt Calibri';
            var txt = Math.round(maxYValue - ((i == 0) ? 0 : yPos / ratio));
            var txtSize = ctx.measureText(txt);
            ctx.fillText(txt, margin.left - ((txtSize.width >= 14) ? txtSize.width : 10) - 7, yPos + 4);

            //x axis labels
            txt = data.dataPoints[i].x;
            txtSize = ctx.measureText(txt);
            ctx.fillText(txt, xPos, yMax + (margin.bottom / 3));
            xPos += xInc;
        }

        //Vertical line
        drawLine(margin.left, margin.top, margin.left, yMax, 'black');

        //Horizontal Line
        drawLine(margin.left, yMax, xMax, yMax, 'black');
    };

    var renderData = function(type) {
        var xInc = getXInc();
        var prevX = 0, 
            prevY = 0;

        for (var i = 0; i < data.dataPoints.length; i++) {
            var pt = data.dataPoints[i];
            var ptY = (maxYValue - pt.y) * ratio;
            if (ptY < margin.top) ptY = margin.top;
            var ptX = (i * xInc) + margin.left;

            if (i > 0 && type == renderType.lines) {
                //Draw connecting lines
                drawLine(ptX, ptY, prevX, prevY, '#309FB2', 2);
            }

            if (type == renderType.points) {
                var radgrad = ctx.createRadialGradient(ptX, ptY, 8, ptX - 5, ptY - 5, 0);
                radgrad.addColorStop(0, '#309FB2');
                radgrad.addColorStop(0.9, 'White');
                ctx.beginPath();
                ctx.fillStyle = radgrad;
                //Render circle
                ctx.arc(ptX, ptY, 8, 0, 2 * Math.PI, false)
                ctx.fill();
                ctx.lineWidth = 1;
                ctx.strokeStyle = '#000';
                ctx.stroke();
                ctx.closePath();
            }

            prevX = ptX;
            prevY = ptY;
        }
    };

    var getXInc = function() {
        return Math.round(xMax / data.dataPoints.length) - 1;
    };

    var drawLine = function(startX, startY, endX, endY, strokeStyle, lineWidth) {
        if (strokeStyle != null) ctx.strokeStyle = strokeStyle;
        if (lineWidth != null) ctx.lineWidth = lineWidth;
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.lineTo(endX, endY);
        ctx.stroke();
        ctx.closePath();
    };

    return {
        renderType: renderType,
        render: render
    };
} ();


$(document).ready(function () {
            var dataDef = { title: "US Population Chart",
                            xLabel: 'Date', 
                            yLabel: 'Price',
                            labelFont: '19pt Arial', 
                            dataPointFont: '10pt Arial',
                            renderTypes: [CanvasChart.renderType.lines, CanvasChart.renderType.points],
                            dataPoints: [{ x: '1-aug', y: 2100 }, 
                                         { x: '2-aug', y: 2000 },
                                         { x: '3-aug', y: 2200 },
                                         { x: '4-aug', y: 1800 },
                                         { x: '5-aug', y: 1500 },
                                         { x: '6-aug', y: 3000 },

                                                                ]
                           };
            CanvasChart.render('canvas', dataDef);
        });

HTML part

<body style="margin-left:50px;margin-top:50px;">
<canvas id="canvas" width="500" height="300"></canvas>

解决方案

Here's a simple way to use a plain-old DIV as a tooltip.

  • Create a div to use as the tooltip (the tooltip-div).
  • Initially hide the tooltip-div.
  • Listen for mousemove events.
  • In the mousemove handler, hit-test if the mouse is inside any data point.
  • If the mouse is inside a data point,

    1. Set the desired text in the tooltip-div,
    2. Use CSS to move the tooltip-div over the data point,
    3. Show the tooltip-div.

Here's annotated code and a Demo:

var CanvasChart = function () {
  var ctx;
  var margin = { top: 40, left: 75, right: 0, bottom: 75 };
  var chartHeight, chartWidth, yMax, xMax, data;
  var maxYValue = 0;
  var ratio = 0;
  var renderType = { lines: 'lines', points: 'points' };

  // addition
  var dataXY=[];

  var render = function(canvasId, dataObj) {
    data = dataObj;
    getMaxDataYValue();
    var canvas = document.getElementById(canvasId);
    chartHeight = canvas.getAttribute('height');
    chartWidth = canvas.getAttribute('width');
    xMax = chartWidth - (margin.left + margin.right);
    yMax = chartHeight - (margin.top + margin.bottom);
    ratio = yMax / maxYValue;
    ctx = canvas.getContext("2d");
    renderChart();
  };

  var renderChart = function () {
    renderBackground();
    renderText();
    renderLinesAndLabels();

    //render data based upon type of renderType(s) that client supplies
    if (data.renderTypes == undefined || data.renderTypes == null) data.renderTypes = [renderType.lines];
    for (var i = 0; i < data.renderTypes.length; i++) {
      renderData(data.renderTypes[i]);
    }
  };

  var getMaxDataYValue = function () {
    for (var i = 0; i < data.dataPoints.length; i++) {
      if (data.dataPoints[i].y > maxYValue) maxYValue = data.dataPoints[i].y;
    }
  };

  var renderBackground = function() {
    var lingrad = ctx.createLinearGradient(margin.left, margin.top, xMax - margin.right, yMax);
    lingrad.addColorStop(0.0, '#ffffff');
    lingrad.addColorStop(0.2, '#fff');
    lingrad.addColorStop(0.8, '#fff');
    lingrad.addColorStop(1, '#ffffff');
    ctx.fillStyle = lingrad;
    ctx.fillRect(margin.left, margin.top, xMax - margin.left, yMax - margin.top);
    ctx.fillStyle = '#6A6A6A';
  };

  var renderText = function() {
    var labelFont = (data.labelFont != null) ? data.labelFont : '20pt Arial';
    ctx.font = labelFont;
    ctx.textAlign = "center";

    //Title
    var txtSize = ctx.measureText(data.title);
    ctx.fillText(data.title, (chartWidth / 2), (margin.top / 2));

    //X-axis text
    txtSize = ctx.measureText(data.xLabel);
    ctx.fillText(data.xLabel, margin.left + (xMax / 2) - (txtSize.width / 2), yMax + (margin.bottom / 1.2));

    //Y-axis text
    ctx.save();
    ctx.rotate(-Math.PI / 2);
    ctx.font = labelFont;
    ctx.fillText(data.yLabel, (yMax / 2) * -1, margin.left / 4);
    ctx.restore();
  };

  var renderLinesAndLabels = function () {
    //Vertical guide lines
    var yInc = yMax / data.dataPoints.length;
    var yPos = 0;
    var yLabelInc = (maxYValue * ratio) / data.dataPoints.length;
    var xInc = getXInc();
    var xPos = margin.left;
    for (var i = 0; i < data.dataPoints.length; i++) {
      yPos += (i == 0) ? margin.top : yInc;
      //Draw horizontal lines
      drawLine(margin.left, yPos, xMax, yPos, '#E8E8E8');

      //y axis labels
      ctx.font = (data.dataPointFont != null) ? data.dataPointFont : '10pt Calibri';
      var txt = Math.round(maxYValue - ((i == 0) ? 0 : yPos / ratio));
      var txtSize = ctx.measureText(txt);
      ctx.fillText(txt, margin.left - ((txtSize.width >= 14) ? txtSize.width : 10) - 7, yPos + 4);

      //x axis labels
      txt = data.dataPoints[i].x;
      txtSize = ctx.measureText(txt);
      ctx.fillText(txt, xPos, yMax + (margin.bottom / 3));
      xPos += xInc;
    }

    //Vertical line
    drawLine(margin.left, margin.top, margin.left, yMax, 'black');

    //Horizontal Line
    drawLine(margin.left, yMax, xMax, yMax, 'black');
  };

  var renderData = function(type) {
    var xInc = getXInc();
    var prevX = 0, 
        prevY = 0;

    // addition
    dataXY.length=0;

    for (var i = 0; i < data.dataPoints.length; i++) {
      var pt = data.dataPoints[i];
      var ptY = (maxYValue - pt.y) * ratio;
      if (ptY < margin.top) ptY = margin.top;
      var ptX = (i * xInc) + margin.left;

      if (i > 0 && type == renderType.lines) {
        //Draw connecting lines
        drawLine(ptX, ptY, prevX, prevY, '#309FB2', 2);
      }

      if (type == renderType.points) {
        var radgrad = ctx.createRadialGradient(ptX, ptY, 8, ptX - 5, ptY - 5, 0);
        radgrad.addColorStop(0, '#309FB2');
        radgrad.addColorStop(0.9, 'White');
        ctx.beginPath();
        ctx.fillStyle = radgrad;
        //Render circle
        ctx.arc(ptX, ptY, 8, 0, 2 * Math.PI, false)
        ctx.fill();
        ctx.lineWidth = 1;
        ctx.strokeStyle = '#000';
        ctx.stroke();
        ctx.closePath();
        // addition
        dataXY.push({cx:ptX,cy:ptY,r:8,tipText:'Price='+pt.y+' on '+pt.x});
      }

      prevX = ptX;
      prevY = ptY;
    }
  };

  var getXInc = function() {
    return Math.round(xMax / data.dataPoints.length) - 1;
  };

  var drawLine = function(startX, startY, endX, endY, strokeStyle, lineWidth) {
    if (strokeStyle != null) ctx.strokeStyle = strokeStyle;
    if (lineWidth != null) ctx.lineWidth = lineWidth;
    ctx.beginPath();
    ctx.moveTo(startX, startY);
    ctx.lineTo(endX, endY);
    ctx.stroke();
    ctx.closePath();
  };

  return {
    renderType: renderType,
    render: render,  // added comma

    // addition
    dataXY: dataXY
  };
} ();
//
// end CanvasChart
/////////////////////////////



// addition
var CanvasTooltip=(function(){
  // ctor
  function CanvasTooltip(canvasId,targets){
    var that=this;
    this.$canvas=$("#"+canvasId);
    this.targets=targets;
    this.openTooltipIndex=-1;
    // add tip elements
    this.init();
    this.$tip=$('#canvasTip').hide();
    // eventing
    this.offsetX,this.offsetY;
    this.reOffset();
    this.$canvas.on('mousemove',function(e){ that.handleMouseMove(e); });
    $(window).on('scroll',function(e){ that.reOffset(); });
  }

  CanvasTooltip.prototype.reOffset=function(){
    var BB=this.$canvas[0].getBoundingClientRect();
    this.offsetX=BB.left;
    this.offsetY=BB.top;    
  };

  CanvasTooltip.prototype.init=function(){
    this.$canvas.wrap('<div id="canvasTipWrapper"></div>');
    $('#canvasTipWrapper').css({'position':'relative'});
    $('<div id="canvasTip"></div>')
    .css({
      'position':'absolute', 
      'border':'1px solid gray',
      'border-left-width':'7px',
      'border-left-color':'maroon',
      'margin-bottom':'20px',
      'background':'rgba(255,255,255,1.00)',
      'padding-left':'5px',
      'padding-right':'5px',
      'max-width':'150px'
    })
    .appendTo('#canvasTipWrapper');    
  };

  CanvasTooltip.prototype.handleMouseMove =function(e){
    e.preventDefault();
    e.stopPropagation();
    var mouseX=parseInt(e.clientX-this.offsetX);
    var mouseY=parseInt(e.clientY-this.offsetY);
    // hit-test each target
    var hit=-1;
    for(var i=0;i<this.targets.length;i++){
      var t=this.targets[i];
      if(t.cx){
        var dx=mouseX-t.cx;
        var dy=mouseY-t.cy;
        var r=t.r;
        if(dx*dx+dy*dy<r*r){
          hit=i;
          if(hit!==this.openTooltipIndex){
            // configure & open the tooltip
            this.openTooltipIndex=hit;
            this.$tip
            .text(t.tipText)
            .css({left:t.cx,top:t.cy-t.r-10-this.$tip.height()})
            .show();
          }
        }
      }
    }
    // hide the tip if no target was hit
    if(hit==-1 && this.openTooltipIndex!==-1){
      this.$tip.hide();
      this.openTooltipIndex=-1;
    }
  }

  return(CanvasTooltip);

})(); // end CanvasTooltip
//
// end CanvasTooltip
////////////////////////////


var dataDef = { title: "US Population Chart",
               xLabel: 'Date', 
               yLabel: 'Price',
               labelFont: '19pt Arial', 
               dataPointFont: '10pt Arial',
               renderTypes: [CanvasChart.renderType.lines, CanvasChart.renderType.points],
               dataPoints: [{ x: '1-aug', y: 2100 }, 
                            { x: '2-aug', y: 2000 },
                            { x: '3-aug', y: 2200 },
                            { x: '4-aug', y: 1800 },
                            { x: '5-aug', y: 1500 },
                            { x: '6-aug', y: 3000 },

                           ]
                            };
                            CanvasChart.render('canvas', dataDef);

                            // addition
                            var tooltip=new CanvasTooltip('canvas',CanvasChart.dataXY);

body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="canvas" width=300 height=300></canvas>

这篇关于如何在图的悬停转折点上显示Y轴值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆