Javascript 如何在图形的悬停转折点上显示Y轴值

Javascript 如何在图形的悬停转折点上显示Y轴值,javascript,jquery,html,canvas,graph,Javascript,Jquery,Html,Canvas,Graph,我正在使用java脚本和画布制作一个图形。下面是JSFIDLE链接 我想显示悬停气泡(转折点)上的值,如 8月1日价格2100 java脚本 var CanvasChart = function () { var ctx; var margin = { top: 40, left: 75, right: 0, bottom: 75 }; var chartHeight, chartWidth, yMax, xMax, data; var maxYValue =

我正在使用java脚本和画布制作一个图形。下面是JSFIDLE链接

我想显示悬停气泡(转折点)上的值,如

8月1日价格2100

java脚本

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);
        });
var CanvasChart=函数(){
var-ctx;
var-margin={top:40,left:75,right:0,bottom:75};
var chartHeight、chartWidth、yMax、xMax、数据;
var maxYValue=0;
var比率=0;
var renderType={lines:'lines',points:'points'};
var render=函数(canvasId,dataObj){
数据=数据对象;
getMaxDataYValue();
var canvas=document.getElementById(canvasId);
chartHeight=canvas.getAttribute('height');
chartWidth=canvas.getAttribute('width');
xMax=图表宽度-(margin.left+margin.right);
yMax=图表高度-(margin.top+margin.bottom);
比率=yMax/maxYValue;
ctx=canvas.getContext(“2d”);
renderChart();
};
var renderChart=函数(){
renderBackground();
renderText();
renderLinesAndLabels();
//根据客户端提供的renderType类型呈现数据
如果(data.renderTypes==undefined | | data.renderTypes==null)data.renderTypes=[renderType.lines];
对于(var i=0;imaxYValue)maxYValue=data.dataPoints[i].y;
}
};
var renderBackground=函数(){
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='#6A6A';
};
var renderText=函数(){
var labelFont=(data.labelFont!=null)?data.labelFont:'20pt Arial';
ctx.font=labelFont;
ctx.textAlign=“中心”;
//头衔
var txtSize=ctx.measureText(data.title);
ctx.fillText(data.title,(chartWidth/2),(margin.top/2));
//X轴文本
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.旋转(-Math.PI/2);
ctx.font=labelFont;
ctx.fillText(data.yLabel,(yMax/2)*-1,margin.left/4);
ctx.restore();
};
var renderLinesAndLabels=函数(){
//垂直指导线
var yInc=yMax/data.dataPoints.length;
var-yPos=0;
var yLabelInc=(maxYValue*比率)/data.dataPoints.length;
var xInc=getXInc();
var xPos=margin.left;
对于(var i=0;i=14)?txtSize.width:10)-7,yPos+4);
//x轴标签
txt=data.dataPoints[i].x;
txtSize=ctx.measureText(txt);
ctx.fillText(txt、xPos、yMax+(margin.bottom/3));
xPos+=xInc;
}
//垂直线
抽绳(margin.left、margin.top、margin.left、yMax,‘黑色’);
//水平线
抽绳(左边距,yMax,xMax,yMax,'黑色');
};
var renderData=函数(类型){
var xInc=getXInc();
var prevX=0,
prevY=0;
对于(var i=0;i0&&type==renderType.lines){
//画连接线
抽绳(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,'白色');
ctx.beginPath();
ctx.fillStyle=radgrad;
//渲染圆
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=函数(){
返回Math.round(xMax/data.dataPoints.length)-1;
};
var drawLine=函数(startX、startY、endX、endY、strokeStyle、线宽){
如果(strokeStyle!=null)ctx.strokeStyle=strokeStyle;
如果(线宽!=null)ctx.lineWidth=lineWidth;
ctx.beginPath();
ctx.moveTo(startX,startY);
ctx.lineTo(endX,endY);
ctx.stroke();
ctx.closePath();
};
返回{
renderType:renderType,
渲染:渲染
};
} ();
$(文档).ready(函数(){
var dataDef={title:“美国人口图表”,
xLabel:'日期',
伊拉贝尔:“价格”,
拉贝尔丰:'19pt
<body style="margin-left:50px;margin-top:50px;">
<canvas id="canvas" width="500" height="300"></canvas>