zoukankan      html  css  js  c++  java
  • canvas绘制经典折线图(一)

    最终效果图如下:

    实现步骤如下:注-引用了jQuery

    HTML代码

    <!doctype html>
    <html lang="en">
     <head>
      <meta charset="UTF-8">
      <meta name="Generator" content="EditPlus®">
      <meta name="Author" content="">
      <meta name="Keywords" content="">
      <meta name="Description" content="">
      <title>canvas绘制折线图</title>
      <script src="scripts/jquery-1.11.3.js"></script>
      <script src="scripts/recordPaint.js"></script>
      <style>
        
      </style>
     </head>
     <script>
        $(function(){
             /*
                 * 定义绘制折线图的关键数据(12个月的消费记录-金额)
                 * 封装函数专门用于绘制折线图
                   recordPaint(Elem,Data)方法
                   * Elem - 表示<canvas>元素
                   * Data - 表示关键数据
              */
             var datas = [1200,2000,3000,500,200,800,1800,2200,2600,1000,600,300];
             recordPaint($("#recordCvs")[0],datas);
        });
     </script>
     <body>
        <div id="recordContent">
            <canvas id="recordCvs" width="600" height="400"></canvas>
        </div>
     </body>
    </html>

    JS代码:即HTML中引用的外部JS文件<script src="scripts/recordPaint.js"></script>

    /**
     * Created by walker on 2015/11/26.
     * 定义recordPaint()方法
     */
    function recordPaint(Elem,Data){
        // 1. 创建画布对象
        var context = Elem.getContext('2d');
        // 2. 获取画布的宽度和高度
        const WIDTH = Elem.width;
        const HEIGHT = Elem.height;
        // 3. 定义坐标轴相对画布的内边距
        var padding = 20;//初始化内边距
        var paddingLeft = 60;//至少大于绘制文字的宽度
        var paddingBottom = 30;//至少大于绘制文字的高度
        // 4. 定义绘制坐标轴的关键点的坐标值
        var axisY = {// y轴的起点坐标值
            x : paddingLeft,
            y : padding
        };
        var origin = {// 原点坐标值(x轴与y轴相交点)
            x : paddingLeft,
            y : HEIGHT - paddingBottom
        };
        var axisX = {
            x : WIDTH - padding,
            y : HEIGHT - paddingBottom
        };
        // 5. 绘制坐标轴
        context.beginPath();
        context.moveTo(axisY.x,axisY.y);
        context.lineTo(origin.x,origin.y);
        context.lineTo(axisX.x,axisX.y);
        context.stroke();
        // 6. 绘制坐标轴的箭头
        context.beginPath();
        context.moveTo(axisY.x-5,axisY.y+10);
        context.lineTo(axisY.x,axisY.y);
        context.lineTo(axisY.x+5,axisY.y+10);
        context.stroke();
    
        context.beginPath();
        context.moveTo(axisX.x-10,axisX.y-5);
        context.lineTo(axisX.x,axisX.y);
        context.lineTo(axisX.x-10,axisX.y+5);
        context.stroke();
    
        // 定义折点的x轴值
        var pointsX = [];
    
        // 7. 绘制坐标轴的刻度(x轴的月份和y轴的金额)
        // x轴的月份
        var month = {
            x : paddingLeft,
            y : HEIGHT - paddingBottom
        }
        // 设置字体
        context.font = "14px 微软雅黑";
        // 设置垂直对齐
        context.textBaseline = "top";
        for(var i=1;i<=12;i++){
            pointsX[pointsX.length] = month.x;
            // 绘制月份信息
            context.fillText(i+"月",month.x,month.y);
            // 改变每次绘制的x坐标轴的值
            month.x += (axisX.x - origin.x)/12;
        }
    
        // 绘制y轴的金额
        // 从众多的关键金额中,取到最高金额
        /*
        var datas = [];
        for(index in Data){
            datas[datas.length] = Data[index];
        }
        function sortNumber(a,b){
            return a - b;
        }
        var max = datas.sort(sortNumber)[datas.length-1];
        */
        var max = Math.max.apply(Math,Data);
    
        var moneyY = (origin.y - axisY.y)/(max/500+1);
    
        // 定义绘制的坐标值
        var money = {
            x : axisY.x - 5,
            y : axisY.y + moneyY,
            jin : max
        }
        // 设置水品对齐
        context.textAlign = "right";
        // 遍历"最高值/间隔"次
        for(var i=0;i<max/500;i++){
            // 绘制金额
            context.fillText(money.jin+"元",money.x,money.y);
            // y轴向下移动(增加)
            money.y += moneyY;
            // 金额每次减500
            money.jin -= 500;
        }
    
        /*
          绘制折线
          * 12个折点的x轴值,对应12个月文字的x轴值
          * 折点的y轴值等于原点的y轴值-折点到原点的距离
            * 折点到原点的距离 = (3000点的y到原点的y的长度)*当前金额/3000
         */
        context.beginPath();
        for(var i=0;i<Data.length;i++){
            // 获取折点的x和y值
            var pointY = origin.y - (origin.y - (axisY.y + moneyY))*Data[i]/max;
            var pointX = pointsX[i];
            // 绘制折线
            if(i == 0){
                context.textAlign = "left";
                //context.textBaseline = "bottom";
                context.moveTo(pointX,pointY);
            }else{
                context.textAlign = "center";
                context.textBaseline = "bottom";
                context.lineTo(pointX,pointY);
            }
            // 绘制折点的金额
            context.fillText(Data[i],pointX,pointY);
        }
        context.stroke();
        // 绘制12个折点的圆
        for(var i=0;i<Data.length;i++){
            // 获取折点的x和y值
            var pointY = origin.y - (origin.y - (axisY.y + moneyY))*Data[i]/max;
            var pointX = pointsX[i];
            // 绘制圆
            context.fillStyle = "red";
            context.beginPath();
            context.arc(pointX,pointY,3,0,Math.PI*2);
            context.fill();
        }
    
    }
    

      总结:每个拐点的坐标值要清晰

  • 相关阅读:
    Construction构造函数
    映射验证
    映射设置
    条件映射
    映射前和映射后的操作
    AutoMapper 5.0-升级指南
    Bootstrap Tree View
    MiniProfiler使用笔记
    关于添加数据自定义编号格式问题
    【Postgresql】数据库函数
  • 原文地址:https://www.cnblogs.com/-walker/p/5022688.html
Copyright © 2011-2022 走看看