上一篇文章我已经说过数据准备好画图就非常简单了,如果你担心不回话好办,我给你个最简单的小例子,

你先练练。
![画图.png](http://upload-images.jianshu.io/upload_images/745192-27d69688f9b7fddd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

这个很简单吧,什么面向对象什么的都不用,你就先用最粗暴的方式撸出来。

然后,你在看下面我写的代码就容易了。最终效果图

![screenshot.png](http://upload-images.jianshu.io/upload_images/745192-60543c6edd1eb474.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

下面代码只有一个难点:

1.怎么算横轴、纵轴label坐标位置

其余就容易多了,有一个注意问题,我其实写复杂了各种位置都是动态算的,因为实际项目你用 写死的数值浏览器适配就会出问题。不说了上代码,先耐着性子敲一遍,然后在一点点研究。

```
/**
  此处可以写一些装13的东西
  尽可能用英文,不会可以自己百度,

例如:
  Author:leo lau
  desc:ni shishibushiwozuitengaideren ,ni weisha bushuo hua
**/
'use strict';
//模仿 http://echarts.baidu.com/demo.html#bar-gradient
window.onload = function(){
    var data = [
      {"label":"一月","value":getRandomInt(0,400)},
      {"label":"二月","value":getRandomInt(1,400)},
      {"label":"三月","value":getRandomInt(1,400)},
      {"label":"四月","value":getRandomInt(0,400)},
      {"label":"五月","value":getRandomInt(1,400)}
    ];

var targetId = 'div1';
    var cw = 600;
    var ch = 450;
    //为啥用面向对象方式,因为显得拽呗
    //
    function Bcharts(targetId,cw,ch,data){
      //基础信息
        var c = this;//为啥这么做?我懒,c = chart = this;
        c.configureChart(targetId,cw,ch,data);
        c.init();

}
    Bcharts.prototype.configureChart = function(targetId,cw,ch,data){
      var c = this;
      c.setCanvasParameters(targetId,cw,ch,data);
      c.setChartParameters(targetId,cw,ch,data);
    };
    Bcharts.prototype.setCanvasParameters = function(targetId,cw,ch,data){
      var c = this;
      c.id = targetId;
      c.cw = cw;
      c.ch = ch;
      c.data = data;
    };
    Bcharts.prototype.setChartParameters = function(targetId,cw,ch,data){
      var c = this;
      c.axeRadio = 10;//定义一个比例,为啥是10,看图大体是这个随便定的,别忒离谱就好
      c.horGap = (c.cw*c.axeRadio)/100;
      c.verGap = (c.ch*c.axeRadio)/100;
    //标识准备
      c.fontRadio = 3;//原因同上
      c.horFontSize = (c.cw*c.fontRadio)/100;
      c.verFontSize = (c.ch*c.fontRadio)/100;

};
    //初始化
    Bcharts.prototype.init = function(){
        var c = this;
        c.createCanvas();
        //这里只是把后台给你的数据整理好了,并不是图表直接能画的数据
        //比如最大值是234,其实我们要花240,不可能是不整齐的
        c.handleData();
        //所以需要处理数据
        c.prepareData();

//开画
        c.draw();

};
    Bcharts.prototype.createCanvas = function(){
        var c = this;
        var canvas = document.createElement('canvas');
        canvas.id = c.id + '-' + Math.random();
        canvas.width = c.cw;
        canvas.height = c.ch;
        document.getElementById(c.id).innerHTML = '';
        document.getElementById(c.id).appendChild(canvas);
        c.canvas = canvas;
        c.context = c.canvas.getContext('2d');
    };
    Bcharts.prototype.handleData = function(){
        //因为后台肯定给你标准的数组格式一堆,但是你没法直接用,得自己666一把
        var c = this;
        c.label = [];//这个数组放循环内容的名字,比如[一月,二月]
        c.values = [];//放值[200,45……]
        c.data.forEach(function(item){
          c.label.push(item.label);
          c.values.push(item.value);
        });
    };
    Bcharts.prototype.prepareData = function(){
        var c = this;
        c.itemNum = c.data.length;
        c.MaxValue = Math.max.apply(null,c.values);
        c.MinValue = Math.min.apply(null,c.values);
        //算坐标宽高
        c.horAxiWidth = c.cw - 2*c.horGap;
        c.verAxiWidth = c.ch - 2*c.verGap;

//计算最大上边界,比如最大数是234,坐标得到240,而不是234
        //确定横竖格宽度
        c.verBound = Math.ceil(c.MaxValue/10)*10;
        c.verFeq = c.verBound/c.itemNum;
        c.horFeq = c.horAxiWidth/c.itemNum;
    };
    Bcharts.prototype.draw = function(){
        var c = this;
        c.drawX();//x轴
        c.drawY();//y轴
        c.drawYLabel();//y坐标字儿
        c.drawXLabel();//y坐标字儿
        c.HorGuideLines();
        c.verGuideLines();
        c.drawBars();
    };
    Bcharts.prototype.drawX = function(){
      var c = this;
      var gd = c.context;
        gd.beginPath();
        gd.moveTo(c.horGap,c.ch -c.verGap);
        gd.lineTo(c.cw -c.horGap,c.ch -c.verGap);
        gd.lineWidth = 2;
        gd.stroke();
    };
    Bcharts.prototype.drawY = function(){
      var c = this;
      var gd = c.context;
        gd.beginPath();
        gd.moveTo(c.horGap,c.ch -c.verGap);
        gd.lineTo(c.horGap,c.verGap);
        gd.lineWidth = 2;
        gd.stroke();
    };
    Bcharts.prototype.drawYLabel = function(){
      var c = this;
      var gd = c.context;
      for(var i = 0;i<=c.itemNum;i++){
        var labelYText = c.verBound - i*c.verFeq;
        var labelPosX = c.horGap - c.horGap/c.axeRadio;
        var scaleReq = (c.verAxiWidth/c.verBound)*c.verFeq;
        var labelPosY = c.verGap+i*scaleReq;
        gd.textAlign = 'right';
        gd.fillText(labelYText,labelPosX,labelPosY);
      }
      Bcharts.prototype.drawXLabel = function(){
        var c = this;
        var gd = c.context;
        for(var i = 0;i<c.itemNum;i++){
          var labelXText = c.label[i];
          var labelPosX = c.horGap + i*c.horFeq +c.horFeq/2;
          var labelPosY = c.ch - c.verGap+c.verGap/c.axeRadio;
          gd.textAlign = 'center';
          gd.textBaseline = 'top';
          gd.fillText(labelXText,labelPosX,labelPosY);
        }
      };

};
    Bcharts.prototype.drawY = function(){
      var c = this;
      var gd = c.context;
        gd.moveTo(c.horGap,c.ch -c.verGap);
        gd.lineTo(c.horGap,c.verGap);
        gd.lineWidth = 2;
        gd.stroke();
    };
    Bcharts.prototype.HorGuideLines = function(){
      var c = this;
      var gd = c.context;

gd.strokeStyle = '#eeeeee';
      gd.lineWidth = 1;
      for(var i = 0;i<c.itemNum;i++){
        gd.beginPath();
        var scaleReq = (c.verAxiWidth/c.verBound)*c.verFeq;
        var horStartX = c.horGap;
        var horStartY = c.verGap+i*scaleReq;
        var horEndX = c.cw -c.horGap;
        var horEndY = c.verGap+i*scaleReq;
        gd.moveTo(horStartX,horStartY);
        gd.lineTo(horEndX,horEndY);
        gd.stroke();

}
    };
    Bcharts.prototype.verGuideLines = function(){
      var c = this;
      var gd = c.context;

gd.strokeStyle = '#eeeeee';
      gd.lineWidth = 1;
      for(var i = 0;i<=c.itemNum;i++){
        gd.beginPath();
        var verStartX = c.horGap+i*c.horFeq;
        var verStartY = c.ch - c.verGap;
        var verEndX = c.horGap+i*c.horFeq;
        var verEndY = c.verGap;
        gd.moveTo(verStartX,verStartY);
        gd.lineTo(verEndX,verEndY);
        gd.stroke();

}
    };
    Bcharts.prototype.drawBars = function () {
      // alert(1);
      var c = this;

for(var i = 0; i < c.itemNum; i++){
        // alert(1);
        var color = c.rndColor();
        var fillOpacity = '0.3';
        var fillColor = 'rgba('+ color.r + ', ' + color.g  + ', ' + color.b + ', ' + fillOpacity +')';
        var borderColor = 'rgba('+ color.r + ', ' + color.g  + ', ' + color.b + ')';

c.context.beginPath();

var barX = c.horGap + i * c.horFeq+c.horFeq/c.axeRadio;
        var barY = c.ch - c.verGap;
        var barWidth = c.horFeq - 2*c.horFeq/c.axeRadio;
        var barHeight = -c.verAxiWidth * c.values[i] / c.MaxValue;
        console.log(c.MaxValue);

c.context.fillStyle = fillColor;
        c.context.strokeStyle = borderColor;
        c.context.rect(barX, barY, barWidth, barHeight);
        // console.log(barX,barY,barWidth,barHeight);
        c.context.stroke();
        c.context.fill();
      }
    };

Bcharts.prototype.rndColor = function () {
      var r = getRandomInt(0, 257);
      var g = getRandomInt(0, 257);
      var b = getRandomInt(0, 257);
      return {r: r, g: g, b: b};
    };
    var charts = new Bcharts(targetId,cw,ch,data);
};
//https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/random
// 偷个懒,基础函数不写了
function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
}

```

PS:里面很多基础函数要会,其实画canvas考验的不是canvas技术,而是数学和基础知识,一定要打好基础。

整个代码git地址:

> https://github.com/leolau2012/bcharts

canvas系列教程06-柱状图项目4相关推荐

  1. canvas系列教程06 ——边界检测、碰撞检测

    边界检测 边界检测,即检测一个物体所处"运动环境的范围"(也就是边界). 边界限制(避免越界) if (ball.x < ball.radius) {//小球"碰到 ...

  2. 【微信小程序-原生开发】实用教程20 - 生成海报(实战范例为生成活动海报,内含生成指定页面的小程序二维码,保存图片到手机,canvas 系列教程)

    可在系列教程的基础上继续开发,也可以单独使用 [微信小程序-原生开发]系列教程 效果预览 代码实现 点击触发生成海报 在活动详情页,指定点击某图标/按钮,触发跳转到生成海报的页面 pages\comp ...

  3. [js高手之路] html5 canvas系列教程 - 线条样式(lineWidth,lineCap,lineJoin,setLineDash)

    上文,写完弧度与贝塞尔曲线[js高手之路] html5 canvas系列教程 - arcTo(弧度与二次,三次贝塞尔曲线以及在线工具),本文主要是关于线条的样式设置 lineWidth: 设置线条的宽 ...

  4. [js高手之路] html5 canvas系列教程 - 掌握画直线图形的常用API

    我们接着上文[js高手之路] html5 canvas系列教程 - 认识canvas以及基本使用方法继续. 一.直线的绘制 cxt.moveTo( x1, y1 ): 将画笔移动到x1, y1这个点 ...

  5. HTML弧度文本,[js高手之路] html5 canvas系列教程 - 文本样式(strokeText,fillText,measureText,textAlign,textBaseline)...

    canvas提供两种输出文本的方式: strokeText:描边文本 fillText:填充文本 fillStyle配合fillText使用,strokeStyle配合strokeText使用 str ...

  6. 前端画圆弧html弧线的像素,[js高手之路] html5 canvas系列教程 - arc绘制曲线图形(曲线,弧线,圆形)...

    arc:画弧度 cxt.arc( x, y, 半径, 开始角度,结束角度,是否逆时针 ); x, y: 为弧度的中心横坐标和纵坐标,如果这是画一个圆.那么x,y就是圆的圆心. 开始角度与结束角度都是以 ...

  7. 讲给后台程序员看的前端系列教程(06)——HTML5标签(5)

    C语言自学完备手册(33篇) Android多分辨率适配框架 HTML5前端开发实战系列教程 MySQL数据库实操教程(35篇图文版) 推翻自己和过往--自定义View系列教程(10篇) 走出思维困境 ...

  8. 【视频教程】帝国CMS制作网站系列教程06

    在很早之前跟大家分享过Bootstrap的视频教程,今天我跟大家分享一套帝国CMS制作网站的视频教程,本视频教程,主要是通过在本地搭建环境,制作网站的一个过程. 在这里,我给大家提供了一套帝国7.5版 ...

  9. canvas系列教程03-柱状图项目1

    弄了一堆线方块和函数,感觉挺玄乎,然并卵.我们直接写个项目看看. canvas一个比较拽的应用就是图表和游戏,我们从浅入深,先玩图表,图表我们今天说一个最简单柱状图. 柱状图很多人用百度的echars ...

最新文章

  1. vue全家桶项目搭建(vue-cli 2.9.6+vue-router+vuex+axios)
  2. Android加载大图片(压缩)
  3. springcloud 整合 gateway_从Spring Cloud到Kubernetes的微服务迁移实践
  4. 机器学习——深度学习之编程工具、流行网络结构、卷积神经网络结构的应用
  5. mac word 设置语言_如何更改Mac的语言和区域设置
  6. oracle 10g冷备份恢复处理详细步骤
  7. 让VS2013支持 C# 6.0 语法
  8. 0 FI配置-FI模块-财务会计-配置清单
  9. 【图像去噪】基于matlab GUI中值+小波+维纳+滤波器图像去噪【含Matlab源码 616期】
  10. 使用Liquid实现简单的数据交换
  11. Android基于Ymodem协议升级嵌入式MCU主控
  12. unity 裙子摆动_Unity中实现MMD效果
  13. 美团商品知识图谱的构建及应用
  14. 计算方法(数值分析)实验:勒让德多项式求展开的三次平方逼近多项式代码实现 java
  15. 人工智能真的具有创造力?
  16. 京东健康IPO:枪口对准阿里健康
  17. vue axios常用写法
  18. 影像去雾软件(雾气消除)免费版
  19. 花生日记,购物省钱还能赚钱,淘宝天猫优惠券一网打尽!2018,你还打算将错就错继续做微商吗?...
  20. 鼎阳数字示波器上位机软件EasyScopeX安装和使用教程

热门文章

  1. MPB:青岛大学苏晓泉组-全球微生物组整体结构和功能的搜索
  2. 【智能制造】机器学习在智能制造中的应用!
  3. [CATARC_2017S] Week 0
  4. ICPC 山东省省赛刷题 第十八届西南科技大学ACM程序设计竞赛(同步赛)牛客 BFH题解
  5. 计算机二级office题库音乐,计算机二级office题库
  6. 悦游网络加速器2013V0.11国际版 官方软件下载
  7. 广西职业技术学院计算机专业分数线,广西职业技术学院
  8. python开发音乐播放器教程_python开发简易版在线音乐播放器示例代码
  9. 东南亚有多少个国家?
  10. 未来五年国内将建逾300座微电网工程