当前位置: 移动技术网 > IT编程>网页制作>Html5 > 【带着canvas去流浪】(1)绘制柱状图

【带着canvas去流浪】(1)绘制柱状图

2019年03月11日  | 移动技术网IT编程  | 我要评论

目录

示例代码托管在:http://www.github.com/dashnowords/blogs

博客园地址:

华为云社区地址:

一. 任务说明

使用原生canvasapi绘制柱状图。(柱状图截图来自于百度echarts官方示例库)

二. 重点提示

柱状图或许是最容易实现的图表类型了,矩形的部分直接使用fillrect()来绘制即可,为了将坐标轴标签文字绘制在小分割线中间,需要用measuretext()来测量文本的宽度,然后进行相应的偏移,否则直接绘制的话文字的左边界会和直线相对齐。其他部分都是一些基本api的使用,希望各位小伙伴通过做练习来熟悉这些api的用法。

三. 示例代码

提示:代码中将个别图表参数直接写在了函数里(也就是所谓的“魔鬼数字”),这种做法是不提倡的,因为它违反了开发的基本原则之一“开放封闭原则”。如果你使用过echarts图表库就会发现,图表中几乎所有要素都可以通过参数来定制,此处只需要关注canvasapi的实现方法即可。

/**
 * 获取canvas绘图上下文
 * @type {[type]}
 */
const canvas = document.getelementbyid('canvas');
const context = canvas.getcontext('2d');

//绘图配置
let options = {
        chartzone:[50,50,1000,700],//标识绘图区域
        yaxislabel:['0','100','200','300','400'],//标示y轴坐标
        ymax:400,//y轴最大值
        xaxislabel:['mon','tue','wed','thu','fri','sat','sun'],//x轴坐标
        data:[10,50,200,330,390,320,220],//柱状图数据
        barstyle:{
            width:70,//柱状图宽度
            color:'#1abc9c'//柱状图颜色
        }
    }

/*echarts使用时,会调用实例方法echartsinstance.setoptions(options)来启动绘图*/
drawbarchart(options);

/**
 * 绘制柱状图
 */
function drawbarchart(options) {
    drawaxis(options); //绘制坐标轴
    drawylabels(options); //绘制y轴坐标
    drawxlabels(options); //绘制x轴坐标
    //drawdata(options);//绘制柱状图
    drawdatagradient(options);//绘制渐变色柱状图
}

/**
 * 绘制坐标轴
 */
function drawaxis(options) {
    let chartzone = options.chartzone;
    context.strokewidth = 4;
    context.strokestyle = '#353535';
    context.moveto(chartzone[0],chartzone[1]);
    context.lineto(chartzone[0],chartzone[3]); //y轴总高从50到700
    context.lineto(chartzone[2],chartzone[3]); //x轴总长从50到1000
    context.stroke();
}

/**
 * 绘制y轴坐标
 */
function drawylabels(options) {
    let labels = options.yaxislabel;
    let ylength = (options.chartzone[3] - options.chartzone[1])*0.98;
    let gap = ylength / (labels.length - 1);
    
    labels.foreach(function (label, index) {
        //绘制坐标文字
        let offset = context.measuretext(label).width + 20;
        context.strokestyle = '#eaeaea';
        context.font = '16px';
        context.filltext(label, options.chartzone[0] - offset ,options.chartzone[3] - index * gap);
        //绘制小间隔
        context.beginpath();
        context.strokestyle = '#353535';
        context.moveto(options.chartzone[0] - 10, options.chartzone[3] - index * gap);
        context.lineto(options.chartzone[0], options.chartzone[3] - index * gap);
        context.stroke();
        //绘制辅助线
        context.beginpath();
        context.strokestyle = '#eaeaea';
        context.strokewidth = 2;
        context.moveto(options.chartzone[0], options.chartzone[3] - index * gap);
        context.lineto(options.chartzone[2], options.chartzone[3] - index * gap);
        context.stroke();
    });
}

/**
 * 绘制x轴坐标
 */
function drawxlabels(options) {
    let labels = options.xaxislabel;
    let xlength = (options.chartzone[2] - options.chartzone[0])*0.96;
    let gap = xlength / labels.length;
    
    labels.foreach(function (label, index) {
        //绘制坐标文字
        let offset = context.measuretext(label).width;
        context.strokestyle = '#eaeaea';
        context.font = '18px';
        context.filltext(label, options.chartzone[0] + (index + 1) * gap - offset ,options.chartzone[3] + 20);
        //绘制小间隔
        context.beginpath();
        context.strokestyle = '#353535';
        context.moveto(options.chartzone[0] + (index + 1) * gap - offset / 2 ,options.chartzone[3]);
        context.lineto(options.chartzone[0] + (index + 1) * gap - offset / 2,options.chartzone[3]+5);
        context.stroke();
        //存储偏移量
        options.offsetxlabel = offset / 2;
    });
}

/**
 * 绘制数据
 */
function drawdata(options) {
    let data = options.data;
    let xlength = (options.chartzone[2] - options.chartzone[0])*0.96;
    let ylength = (options.chartzone[3] - options.chartzone[1])*0.98;
    let gap = xlength / options.xaxislabel.length;

    //绘制矩形
    data.foreach(function (item, index) {
        context.fillstyle = options.barstyle.color || '#1abc9c'; //02bad4
        let x0 = options.chartzone[0] + (index + 1) * gap - options.barstyle.width / 2 - options.offsetxlabel;
        let height = item / options.ymax * (options.chartzone[3] - options.chartzone[1])*0.98;
        let y0 =  options.chartzone[3] - height;
        let width = options.barstyle.width;
        context.fillrect(x0,y0,width,height);
    });
}

/**
 * 绘制线性渐变色柱状图
 */
function drawdatagradient(options) {
    let data = options.data;
    let xlength = (options.chartzone[2] - options.chartzone[0])*0.96;
    let ylength = (options.chartzone[3] - options.chartzone[1])*0.98;
    let gap = xlength / options.xaxislabel.length;
    //创建渐变色
    let fillstylegradient = context.createlineargradient(50,50,50,700);
        fillstylegradient.addcolorstop(0, options.barstyle.color);
        fillstylegradient.addcolorstop(1, 'rgba(1,176,241,0.6)');

    //绘制矩形
    data.foreach(function (item, index) {
        context.fillstyle = fillstylegradient;
        let x0 = options.chartzone[0] + (index + 1) * gap - options.barstyle.width / 2 - options.offsetxlabel;
        let height = item / options.ymax * (options.chartzone[3] - options.chartzone[1])*0.98;
        let y0 =  options.chartzone[3] - height;
        let width = options.barstyle.width;
        context.fillrect(x0,y0,width,height);
    });
}

浏览器中可查看效果:

四. 思考题

如果希望在坐标轴末端加一个箭头,需要怎么做呢?

/*x轴箭头示例*/
//1.options中增加箭头颜色和大小的设置
let options = {
    //...
    axisarrow:{
            size:2,
            color:'#da5961'
        }
}
//箭头绘制函数

/**
 * x轴绘制箭头
 */
function drawarrow(options) {
    let factor = options.axisarrow.size;//获取箭头大小因子
    context.save();//保存当前设置的绘图上下文
    context.translate(options.chartzone[2], options.chartzone[3]);//移动坐标系原点至x轴末端
    context.beginpath();//开始绘制箭头
    context.moveto(0,0);//移动至新原点
    context.lineto(2 * factor,-3 * factor);
    context.lineto(10 * factor,0);
    context.lineto(2 * factor, 3 * factor);
    context.lineto(0,0);
    context.globalalpha = 0.7; //设置填充色透明度
    context.fillstyle = options.axisarrow.color;//获取箭头颜色
    context.fill();//填充箭头路径
    context.restore();//恢复绘图上下文样式设置
}        

箭头效果:

y轴的箭头请自行完成即可。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网