专栏首页Devops专栏Canvas 绘制折线图 - 使用prototype属性构建对象

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

需求

前面的几篇文章介绍了如何绘制网格图、坐标系、坐标系中的点,那么本篇章将这些步骤方法,以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

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

构建对象的具体代码

<!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>

浏览器显示效果如下:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Canvas绘制从黑到白的渐变矩形

    Canvas绘制一条线条可以使用strokeStyle方法来绘制线条的颜色。但是却是绘制一条直线的。 示例如下:

    Devops海洋的渔夫
  • JavaScript 变量

    JavaScript 是一种弱类型语言,javascript的变量类型由它的值来决定。 定义变量需要用关键字 var

    Devops海洋的渔夫
  • Canvas绘制坐标系

    原点坐标的 x = space 原点坐标的 y = CanvasHeight - space

    Devops海洋的渔夫
  • js模块化例子

    最近在看一本书,里面提到js的模块化,觉得很有必要,所以记录下来 Game.js

    黒之染
  • h5小游戏——HitRocket

    一.游戏介绍 游戏介绍: 不断有携带字母炸弹的火箭撞向地面,请根据火箭身上的字母敲击键盘,每一次对应的敲击会击落携带该字母的火箭并使得分加一,每一架火箭撞到地...

    lonelydawn
  • 基础篇章:关于 React Native 之 Modal 组件的讲解

    (友情提示:RN学习,从最基础的开始,大家不要嫌弃太基础,会的同学请自行略过,希望不要耽误已经会的同学的宝贵时间) Modal是模态视图,它的作用是可以用来覆盖...

    非著名程序员
  • 【被玩坏的博客园】之canvas装饰博客园侧边栏

    用户1749219
  • 【被玩坏的博客园】之canvas装饰博客园侧边栏

    用户1749219
  • 使用普拉特分析法解析极为复杂的算术表达式

    望月从良
  • 移动端吸顶fixbar解决方案

    在IOS端,使用 position: sticky 这个属性,使用类似于 position: relative 和 position: absolute 的...

    Tiffany_c4df

扫码关注云+社区

领取腾讯云代金券