前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Canvas 绘制折线图 - 使用prototype属性构建对象

Canvas 绘制折线图 - 使用prototype属性构建对象

作者头像
Devops海洋的渔夫
发布2020-02-13 13:35:11
1.1K0
发布2020-02-13 13:35:11
举报
文章被收录于专栏:Devops专栏Devops专栏

需求

前面的几篇文章介绍了如何绘制网格图、坐标系、坐标系中的点,那么本篇章将这些步骤方法,以js原型面向对象的方式开发,编写出一个折线图的示例。

构建对象的思路

为了更加好方便地使用绘画折线图的方法,应该要将其各个绘制写成对应的对象方法。那么构建对象方法有很多种,本篇将使用prototype属性构建绘画折线图的对象。

如果需要构建一个绘画折线图的对象,基于前面几篇绘制网格图、坐标系、坐标系中的点,可以将其中的基本参数、基本方法都设置到这个绘画折线图的对象中。

定义内容如下:

  1. 构建一个绘制折线图的对象 LineChart
  2. LineChart对象首先要有绘制网格图、坐标系、坐标系中的点相关的基本参数,罗列如下: 2.1 画笔工具 var ctx = myCanvas.getContext('2d'); 2.2 绘制网格图需要的基本参数:网格大小 girdSize、Canvas的width、height 2.3 绘制坐标系需要的基本参数:坐标系箭头三角形大小 arrowSize、坐标系距离边界的间隙 space 2.4 绘制坐标系中点的基本参数:点的大小dotSize、点的坐标(应该由后台传参坐标,不应该写死。)
  3. LineChart对象除了基本参数,还要将各种绘制方法定义到对象中,如下: 3.1 绘制网格图的方法 drawGrid 3.2 绘制坐标系的方法 drawCoordinates 3.3 绘制坐标中点的方法 drawPoints 3.4 绘制将坐标点连成折线的方法 drawLinePath

好了,有了上面的定义内容,就可以开始下面的定义方法。

构建对象的具体代码

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas{
            border: 1px solid #cccccc;
            margin-top: 100px;
            margin-left: 100px;
        }
    </style>
    <script type="text/javascript">
        window.onload = function () {

            /*
            1. 构建一个绘制折线图的对象 LineChart
            2. LineChart对象首先要有绘制网格图、坐标系、坐标系中的点相关的基本参数,罗列如下:
                2.1 画笔工具 var ctx = myCanvas.getContext('2d');
                2.2 绘制网格图需要的基本参数:网格大小 girdSize、Canvas的width、height
                2.3 绘制坐标系需要的基本参数:坐标系箭头三角形大小 arrowSize、坐标系距离边界的间隙 space
                2.4 绘制坐标系中点的基本参数:点的大小dotSize、点的坐标(应该由后台传参坐标,不应该写死。)
            3. LineChart对象除了基本参数,还要将各种绘制方法定义到对象中,如下:
                3.1 绘制网格图的方法 drawGrid
                3.2 绘制坐标系的方法 drawCoordinates
                3.3 绘制坐标中点的方法 drawPoints
                3.4 绘制将坐标点连成折线的方法  drawLinePath
            */

            // 1. 定义绘制折线图对象
            var LineChart = function (ctx) {
                /*获取绘图工具*/
                this.ctx = ctx || document.querySelector('canvas').getContext('2d');
                /*画布的大小*/
                this.canvasWidth = this.ctx.canvas.width;
                this.canvasHeight = this.ctx.canvas.height;
                /*网格的大小*/
                this.gridSize = 10;
                /*坐标系的间距*/
                this.space = 20;
                /*坐标原点*/
                this.x0 = this.space;
                this.y0 = this.canvasHeight - this.space;
                /*箭头的大小*/
                this.arrowSize = 10;
                /*绘制点*/
                this.dotSize = 10;
                /*点的坐标 和数据有关系  数据可视化*/
            };

            // 2. 定义LineChart对象的初始化方法
            LineChart.prototype.init = function (data) {
                this.drawGrid(); // 绘制网格
                this.drawCoordinates(); // 绘制坐标系
                this.drawPoints(data); // 绘制点
                this.drawLinePath(data); // 绘制点与点之间折线的轨迹
            };

            // 2. 定义绘制网格的对象方法 drawGrid
            LineChart.prototype.drawGrid = function () {

                this.ctx.strokeStyle = "#ccc"; // 设置每个线条的颜色

                // 采用遍历的方式,绘画x轴的线条
                var xLineTotals = Math.floor(this.canvasHeight / this.gridSize); // 计算需要绘画的x轴条数
                for (var i = 0; i < xLineTotals; i++) {
                    // console.log(this.gridSize * i - 0.5);
                    // console.log(this.girdSize * i - 0.5);
                    this.ctx.beginPath(); // 开启路径,设置不同的样式
                    this.ctx.moveTo(0, this.gridSize * i - 0.5); // -0.5是为了解决像素模糊问题
                    this.ctx.lineTo(this.canvasWidth, this.gridSize * i - 0.5);
                    this.ctx.stroke();
                }

                // 采用遍历的方式,绘画y轴的线条
                var yLineTotals = Math.floor(this.canvasWidth / this.gridSize); // 计算需要绘画y轴的条数
                for (var j = 0; j < yLineTotals; j++) {
                    this.ctx.beginPath(); // 开启路径,设置不同的样式
                    this.ctx.moveTo(this.gridSize * j, 0);
                    this.ctx.lineTo(this.gridSize * j, this.canvasHeight);
                    this.ctx.stroke();
                }
            };

            // 3. 定义绘制坐标系方法
            LineChart.prototype.drawCoordinates = function () {

                // 计算坐标系y轴的最远坐标点(x1,y1)以及对应三角形的坐标点左边(x2,y2)\右边(x3,y3)
                var x1 = this.space;
                var y1 = this.space;

                var x2 = Math.floor(x1 - this.arrowSize/2);
                var y2 = Math.floor(y1 + this.arrowSize);

                var x3 = Math.floor(x1 + this.arrowSize/2);
                var y3 = Math.floor(y1 + this.arrowSize);

                // 绘画y轴的线条
                this.ctx.beginPath();
                this.ctx.beginPath();
                this.ctx.moveTo(this.x0,this.y0); // 原点
                this.ctx.lineTo(x1,y1); // y轴最远点

                // 绘画y轴三角形
                this.ctx.lineTo(x2,y2); // 三角形左边点
                this.ctx.lineTo(x3,y3); // 三角形右边点
                this.ctx.lineTo(x1,y1); // 回到y轴最远点

                // 填充以及描边y轴
                this.ctx.strokeStyle = "#000";
                this.ctx.fill();
                this.ctx.stroke();

                // 计算坐标系x轴的最远坐标点(x4,y4)以及对应三角形的坐标点上边(x5,y5)\下边(x6,y6)
                var x4 = this.canvasWidth - this.space;
                var y4 = this.canvasHeight - this.space;

                var x5 = Math.floor(x4 - this.arrowSize);
                var y5 = Math.floor(y4 - this.arrowSize/2);

                var x6 = Math.floor(x4 - this.arrowSize);
                var y6 = Math.floor(y4 + this.arrowSize/2);

                // 9.绘制x轴线条
                this.ctx.beginPath();
                this.ctx.moveTo(this.x0,this.y0); // 原点
                this.ctx.lineTo(x4,y4); // x轴最远点

                // 10.绘制三角形
                this.ctx.lineTo(x5,y5); // 三角形的上边
                this.ctx.lineTo(x6,y6); // 三角形的下边
                this.ctx.lineTo(x4,y4); // 回到x轴最远点

                // 11.填充以及描边
                this.ctx.strokeStyle = "#000";
                this.ctx.fill();
                this.ctx.stroke();
            };

            // 4. 定义绘制坐标系多点的方法
            LineChart.prototype.drawPoints = function (data) {

                /*
                1. 设置坐标点的中心圆点位置(x0,y0)
                2. 设置坐标点的大小  dotSize
                3. 计算坐标点的上下左右四角的点坐标
                */

                // 获取画笔ctx
                ctx = this.ctx;

                // 设置坐标点的大小  dotSize
                var dotSize = this.dotSize;

                // 4.遍历点的坐标,以及绘画点
                data.forEach(function (item,i) {
                    console.log("i = " + i + ", x = " + item.x + ", y = " + item.y);

                    // 1. 设置坐标点的中心圆点位置(x0,y0)
                    var x0 = item.x;
                    var y0 = item.y;
                    console.log("坐标点的重点原点位置 x0 = " + x0 + ", y0 = " + y0);

                    // 2.计算坐标点的上下左右四角的点坐标: 左上(x1,y1) 左下(x2,y2) 右上(x3,y3) 右下(x4,y4)

                    var x1 = Math.floor(x0 - dotSize/2);
                    var y1 = Math.floor(y0 - dotSize/2);

                    var x2 = Math.floor(x0 - dotSize/2);
                    var y2 = Math.floor(y0 + dotSize/2);

                    var x3 = Math.floor(x0 + dotSize/2);
                    var y3 = Math.floor(y0 - dotSize/2);

                    var x4 = Math.floor(x0 + dotSize/2);
                    var y4 = Math.floor(y0 + dotSize/2);

                    console.log("左上 x1 = " + x1 + ", y1 = " + y1);
                    console.log("左下 x2 = " + x2 + ", y2 = " + y2);
                    console.log("右上 x3 = " + x3 + ", y3 = " + y3);
                    console.log("右下 x4 = " + x4 + ", y4 = " + y4);

                    // 3.绘画坐标点

                    ctx.beginPath();
                    ctx.beginPath();
                    ctx.moveTo(x1,y1); // 左上点
                    ctx.lineTo(x2,y2); // 左下点
                    ctx.lineTo(x4,y4); // 右下点
                    ctx.lineTo(x3,y3); // 右上点
                    ctx.closePath();

                    // 4.填充以及描边y轴
                    ctx.fill();
                });
            };

            // 5. 定义绘制坐标系多点的折现
            LineChart.prototype.drawLinePath = function (data) {

                /*获取绘图工具*/
                var ctx = this.ctx;

                // 设置坐标系与边界的间隙大小
                var space = this.space;

                // 2. 获取Canvas的width、height
                var canvasWidth = this.canvasWidth;
                var canvasHeight = this.canvasHeight;

                // 3.计算坐标系的原点坐标(x0,y0)
                var x0 = this.space;
                var y0 = canvasHeight - space;

                /*
                遍历绘画多点连接的折线
                1. 第一个点与坐标系原点连成一条线
                2. 从第二个点开始与上一个点连成一条线,所以需要记录上一个点的坐标
                */

                // 记录上一个点坐标
                var prev_point_x = null;
                var prev_point_y = null;

                data.forEach(function (item,i) {
                    console.log("绘制折线: i = " + i + ", x = " + item.x + ", y = " + item.y);

                    if (i===0){
                        console.log("坐标系的原点坐标:x0 = " + x0 + ", y0 = " + y0);
                        console.log("第一个点的坐标: x = " + item.x + ", y = " + item.y);

                        // 第一个点与坐标系原点连成一条线
                        ctx.beginPath();
                        ctx.moveTo(x0,y0); // 坐标系原点
                        ctx.lineTo(item.x,item.y); // 第一个点
                        ctx.stroke();

                        // 记录当前的点为下一个点的坐标的出发点坐标
                        prev_point_x = item.x;
                        prev_point_y = item.y;

                    }else{ // 从第二个点开始与上一个点连成一条线,所以需要记录上一个点的坐标

                        ctx.beginPath();
                        ctx.moveTo(prev_point_x,prev_point_y); // 设置上一个点的坐标为出发点
                        ctx.lineTo(item.x, item.y); // 设置当前点为终点
                        ctx.stroke();

                        // 记录当前的点为下一个点的坐标的出发点坐标
                        prev_point_x = item.x;
                        prev_point_y = item.y;

                    }

                })

            };

            // 定义需要绘制的点坐标
            var points = [
                {
                    x: 30,
                    y: 80,
                },
                {
                    x: 40,
                    y: 120,
                },
                {
                    x: 100,
                    y: 200,
                },
                {
                    x: 150,
                    y: 300,
                },
                {
                    x: 250,
                    y: 100,
                },
                {
                    x: 300,
                    y: 200,
                },
                {
                    x: 350,
                    y: 50,
                }
            ];

            // 创建绘制折线图
            var linechart = new LineChart();
            linechart.init(points);
        }
    </script>
</head>
<body>
    <canvas id="myCanvas" width="600" height="400"></canvas>
</body>
</html>

浏览器显示效果如下:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 需求
    • 构建对象的思路
      • 构建对象的具体代码
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档