canvas实现稍复杂的财务报表

7次阅读

共计 2289 个字符,预计需要花费 6 分钟才能阅读完成。



<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            /*#oCan{
                width: 1000px;
                height: 650px;
            }*/
        </style>
    </head>
    <body style="background-color:#fff">
        <canvas id="oCan" width="1600" height="650">            ~~~~</canvas>
        <script>
            var canvas = document.getElementById('oCan');
            let dateArr = [];
            let years = 2016;
            let month = 0;
            var startX = 100;
            var startY = 600;
            var ctx = canvas.getContext('2d');
            const salary = ['0','50k','100k','150k'];
            const data = [89815.85,65441.37,68983.43,80520.7,71360.8,71308.09,97843.1,74963.94,72430.98,81891.22,126140.22,57712.01,85631.15,
            68464.57,73150.3,91573.05,81404.2,76903.97,71145.33,81884.51,90759.47,80811.97,76918.84,99999.56];
            for(let i = 0 ; i<24;i++){
                ++month;
                month = transFromMonthType(month);
                dateArr.push(years + '-' + month);
                if(month === 12){
                    years++;
                    month = 0;
                }
            }
            function transFromMonthType (date) {if(date < 10){return "0" + date + ''}
                return date
            }
            console.log(dateArr);
            // 建立坐标系
            function create(){ctx.beginPath();
                // 轴线
                ctx.moveTo(startX,startY);
                ctx.lineTo(startX,0);
                ctx.moveTo(startX,startY);
                ctx.lineTo(1600,startY);
                ctx.strokeStyle="#ccc";
                ctx.stroke();
                ctx.closePath();
                
                ctx.beginPath();
                // 横线
                ctx.moveTo(startX,400);
                ctx.lineTo(1600,400);
                ctx.moveTo(startX,200);
                ctx.lineTo(1600,200);
                ctx.moveTo(startX,0);
                ctx.lineTo(1600,0);
                ctx.strokeStyle="#ccc";
                ctx.stroke();
                ctx.closePath();}
            // 填充横纵坐标
            function insert(){
                var x = 100;
                var y = 600;
                var offsetY = 600 * (1-(data[0]/150000));
                // 绘制横坐标
                ctx.moveTo(125,offsetY);
                ctx.fillText(data[0],110,offsetY-5);
                for(var i= 0; i <dateArr.length;i++){
                    ctx.textAlign="start";
                    ctx.fillText(dateArr[i],x,y+20);    
                    x += 50;
                    if(i > 0){offsetY = 600 * (1-(data[i]/150000));
                        ctx.textAlign="right";
                        ctx.fillText(data[i],x,offsetY-5);
                        buildLineChart(x,offsetY);
                    }
                    
                }
                x = 100;
                y = 600;
                // 绘制纵坐标
                for(let j = 0 ;j < salary.length;j++){
                    ctx.textAlign = 'center';
                    ctx.fillText(salary[j],x-40,y);
                    y -= 197;// 偏差问题,如果设置 200 那么 salary[3]的文本‘15k’就会被隐藏~~~~
                }
                
            }
            // 建立折线图
            function buildLineChart(x,y){
                let yet1 = y;
                ctx.lineTo(x-25,yet1);
                ctx.strokeStyle = "#3FA7DC";
                ctx.stroke();}
            
            
            insert();
            create();
            
        </script>
    </body>
</html>

整体思路:
1. 设计 y 轴价格和 x 轴日期区间。注意:此 demo 的价格区间只限于 0 <=price<150000; 超出的部分会被省略
2. 日期区间主要通过 for 循环将字符串日期推送到特定数组中,并调用特定函数来实现个位数加 0 操作。
3.create 方法主要用来创建 x 和 y 轴,以及特定数量的横线。利用
ctx.beginPath();
ctx.closePath();~~~~
实现开辟以及结束一个工作区,在工作区给线条改颜色。
4. 调用 insert()来设置和填充横纵坐标,以及通过 moveTo()开始一条路径 buildLineChart() 方法用来绘制折线图,具体通过 lineTo 方法连接这些线,然后就呈现成折线。

5. 此文章难点还是在于 lineTo 的 y 轴坐标问题,要让他和金额以及距离 canvas 对象原点 y 轴比例的问题。即纵坐标 offsetY = 600 * (1-(data[i]/150000));

正文完
 0