js html5 绘制折线图

效果:

测试页面

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    
    <br/>
    <textarea id="ttJsonStr"  rows="5" cols="100">[{
        "x": "12",
        "y": "13",
        "value": "315"
    },
    {
        "x": "31",
        "y": "41",
        "value": "6498"
    },
    {
        "x": "78",
        "y": "13",
        "value": "156"
    },
    {
        "x": "23",
        "y": "30",
        "value": "123"
    },
    {
        "x": "1",
        "y": "34",
        "value": "331"
    },
    {
        "x": "50",
        "y": "3",
        "value": "123"
    },
    {
        "x": "13",
        "y": "20",
        "value": "85678"
    }]</textarea>
      <button type="button" id="btnDrawChart" onclick="drawChart()">click</button><br/>
      <canvas id="myCanvas" width="500" height="300"></canvas>
</body>

</html>

script:

<script>
    
    function drawChart() {
        
        xInterval = 10;
        yInterval = 10;
        let rawData = JSON.parse(document.getElementById('ttJsonStr').value);
        data =[];
        for (let item of rawData) {
            data.push({ x:item.x, y:item.y, value:item.value })
        }

        let canvas = document.getElementById('myCanvas');

        // 1. 创建画布对象
        let context = canvas.getContext("2d");
        // 2. 获取画布的宽度和高度
        const WIDTH = canvas.width;
        const HEIGHT = canvas.height;
        // 3. 定义坐标轴相对画布的内边距
        var padding = 20;//初始化内边距
        var paddingLeft = 60;//至少大于绘制文字的宽度
        var paddingBottom = 30;//至少大于绘制文字的高度

        // 4. 定义绘制坐标轴的关键点的坐标值
        var axisYStart = {// y轴的起点坐标值
            x: paddingLeft,
            y: padding
        };
        var origin = {// 原点坐标值(x轴与y轴相交点)
            x: paddingLeft,
            y: HEIGHT - paddingBottom
        };
        var axisXStart = {// x轴的起点坐标值
            x: WIDTH - padding,
            y: HEIGHT - paddingBottom
        };
        // 5. 绘制坐标轴
        context.beginPath();
        context.moveTo(axisYStart.x, axisYStart.y);
        context.lineTo(origin.x, origin.y);
        context.lineTo(axisXStart.x, axisXStart.y);
        context.stroke();
        // 6. 绘制坐标轴的箭头
        context.beginPath();
        context.moveTo(axisYStart.x - 5, axisYStart.y + 10);
        context.lineTo(axisYStart.x, axisYStart.y);
        context.lineTo(axisYStart.x + 5, axisYStart.y + 10);
        context.stroke();

        context.beginPath();
        context.moveTo(axisXStart.x - 10, axisXStart.y - 5);
        context.lineTo(axisXStart.x, axisXStart.y);
        context.lineTo(axisXStart.x - 10, axisXStart.y + 5);
        context.stroke();

        // 定义折点的x轴值
        var pointsX = [];

        // 7. 绘制坐标轴的刻度(x轴的月份和y轴的金额)
        // x轴刻度
        var month = {
            x: paddingLeft,
            y: HEIGHT - paddingBottom
        }
        //计算x轴刻度
        data.sort(function (a, b) { return a.x - b.x });
        let xIntervalCount = Math.ceil(data[data.length - 1].x / xInterval);
        let xIntervalLen = (axisXStart.x - origin.x) / xIntervalCount;
        // 设置字体
        context.font = "14px 微软雅黑";
        // 设置垂直对齐
        context.textBaseline = "top";
        //标注x坐标刻度
        let xStart = origin.x + xIntervalLen;
        let interval = this.xInterval;
        for (let i = 1; i <= xIntervalCount; i++) {
            context.fillText(interval, xStart, origin.y);
            // 改变每次绘制的x坐标轴的值
            xStart += xIntervalLen;
            interval += this.xInterval;
        }

        //计算y轴刻度
        this.data.sort(function (a, b) { return a.y - b.y });
        let yIntervalCount = Math.ceil(this.data[this.data.length - 1].y / this.yInterval);
        let yIntervalLen = (axisXStart.y - axisYStart.y) / yIntervalCount;
        // 设置垂直对齐
        context.textAlign = "right";
        //标注y坐标刻度
        let yStart = origin.y - xIntervalLen;
        interval = this.yInterval;
        for (let i = 1; i <= yIntervalCount; i++) {
            context.fillText(interval, origin.x, yStart);
            // 改变每次绘制的x坐标轴的值
            yStart -= yIntervalLen;
            interval += yInterval;
        }
        context.fillText("0,0", origin.x, origin.y);
        context.stroke();

        //8.绘制折线
        this.data.sort(function (a, b) { return a.x - b.x });
        context.textAlign ="left";
        context.textBaseline = "bottom";
        for(let i=0;i<this.data.length;i++){
            
            let pointX=origin.x+this.data[i].x/this.xInterval*xIntervalLen;
            let pointY=origin.y-this.data[i].y/this.yInterval*yIntervalLen;
            if(i==0)
            {
                context.moveTo(pointX,pointY);
            }
            else{
                context.lineTo(pointX,pointY);
            }
            context.fillText(this.data[i].value, pointX, pointY);
        }
        context.stroke();
    }

</script>
原文地址:https://www.cnblogs.com/lvjianwei/p/8193582.html