Canvas 绘制折线统计图

我们只要不是要去用 canvas 做游戏,能做到 让 数据 可视图形化 即可,下面是 canvas 绘制折线统计图的练习

<canvas width="600" height="400" id="cas" style='border: 1px solid black;'></canvas>
<script>
    var cas = document.getElementById( 'cas' );
    var ctx = cas.getContext( '2d' );   // 获取绘图对象

    /*---- 绘制坐标系 ----*/
    // 坐标系在 canvas 中的 padding
    var padding = 30;
    // 坐标系原点
    var x0 = padding,   // 在正方向 padding
        y0 = cas.height - padding; // 左下角 高度-padding
    // 箭头高宽
    var arrowHeight = 20,   // 箭头高度
        arrowWidth = 10;    // 箭头宽度
    // 坐标系最大 x,坐标系最大 y
    var maxX = cas.width - padding * 2 - arrowHeight,
        maxY = cas.height - padding * 2 - arrowHeight;

    // 绘制 坐标系 两个轴
    ctx.moveTo( x0, y0 ); // 从 原点开始
    ctx.lineTo( x0 + maxX + arrowHeight, y0 );  // 绘制 x 轴
    ctx.moveTo( x0, y0 ); // 从 原点开始
    ctx.lineTo( x0, y0 - maxY - arrowHeight ); // 绘制 y 轴 由于 方向是反的,所以要加 负号
    ctx.stroke();    // 连点成线,绘制路径

    // 绘制 坐标系 箭头
    ctx.beginPath();
    // 绘制 x 轴 箭头
    ctx.moveTo( x0 + maxX + arrowHeight, y0 ); // x 轴右顶点开始
    ctx.lineTo( x0 + maxX, y0 - arrowWidth / 2 ); // 箭头上半边线, 由于是反的,上半边是减
    ctx.lineTo( x0 + maxX + arrowHeight / 2, y0 ); // 回 一半
    ctx.lineTo( x0 + maxX, y0 + arrowWidth / 2 ); // 箭头下半边线顶点
    ctx.closePath(); // 闭合路径 绘制出下半边线
    // 绘制 y 轴 箭头
    ctx.moveTo( x0, padding ); // y 轴 上顶点开始
    ctx.lineTo( x0 - arrowWidth / 2, padding + arrowHeight ); // 箭头左半边
    ctx.lineTo( x0, padding + arrowHeight / 2 ); // 回一半
    ctx.lineTo( x0 + arrowWidth / 2, padding + arrowHeight ); // 箭头右半边 顶点
    ctx.closePath(); // 闭合路径 绘制出右半边线
    ctx.fill(); // 填充路径

    /*-----  绘制坐标系点 ------*/
    var data1 = [ [ 10, 20 ], [ 15, 13 ], [ 17, 30 ], [ 30, 10 ], [ 20, 15 ] ];
    var data3 = []; // 用于存储计算之后的坐标
    // 排序
    // 由于 要进行 连线,所以要先进行排序, 这里冒泡一下
    var flag = true; // 定义 flag 看 有没有 排完
    for ( var i = 0; i < data1.length - 1; i++ ) {  // 排 length - 1 趟
        for( var j = 0; j < data1.length - 1 - i; j++ ) { // 每 排完一趟,每趟 就少排一次
            if ( data1[ j ][ 0 ] > data1[ j + 1][ 0 ] ) {   // 如果 大于,那就换
                var t = data1[ j ];
                data1[ j ] = data1[ j + 1 ];
                data1[ j + 1 ] = t;
                flag = false;  // 交换了 说明没排好
            }
        }
        if ( flag ) break; // 一趟下来,没进行交换,说明已经排好,退出
        flag = true; // 否则没排完,置为 ture
    }

    // 计算出最大值,和比例
    var dataMaxX = Math.max.apply( null, data1.map( function( v ) { return v[ 0 ]; } ) );
    var dataMaxY = Math.max.apply( null, data1.map( function( v ) { return v[ 1 ]; } ) );

    // 使用循环绘制点
    ctx.beginPath();
    ctx.fillStyle = 'blue'; // 设置画笔颜色

    for( var i = 0; i < data1.length; i++ ) {
        // 每个是 点边长 为 8 的矩形
        var tmpX = data1[ i ][ 0 ]; // 基准点 x 坐标
        var tmpY = data1[ i ][ 1 ]; // 基准点 y 坐标
        // 按比例 缩放
        tmpX = tmpX * maxX / dataMaxX;
        tmpY = tmpY * maxY / dataMaxY;
        // 转换坐标基准,以 x0 y0 为基准
        tmpX = tmpX + x0;
        tmpY = y0 - tmpY;

        data3.push( [ tmpX, tmpY ] ); // 将计算好的坐标点存放到数组中

        // 绘制点
        ctx.moveTo( tmpX - 4, tmpY - 4 );
        ctx.lineTo( tmpX + 4, tmpY - 4 );
        ctx.lineTo( tmpX + 4, tmpY + 4 );
        ctx.lineTo( tmpX - 4, tmpY + 4 );
        ctx.closePath();
    }
    ctx.fill(); // 绘制出四个点

    /*---- 连线 -----*/
    ctx.beginPath(); // 开启路径
    ctx.strokeStyle = 'blue'; // 换个颜色
    data3.forEach( function( v, i ) {
        ctx [ [ 'moveTo', 'lineTo' ][ i==0?0:1 ] ]( v[ 0 ], v[ 1 ] );
    });
    ctx.stroke(); // 绘制

</script>

最终绘制出来的结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值