Canvas 基础二

一、绘制矩形

  1、rect (x, y, width, height)   : 绘制矩形的路径

    ---用轨迹画的,不是独立路径( 没有beginPath() )

    ---需要stroke()描边才会显示

 

  2、strokeRect (x, y, width, height)   : 描边矩形

    ---自动描边,有独立路径

 

  3、fillRect (x, y, width, height)   : 填充矩形

    ---自动填充(默认黑色),有独立路径

  

  4、clearRect (x, y, width, height)  : 清除矩形

    ---相当于橡皮擦

    

      var myCanvas = document.querySelector("canvas");
      var ctx = myCanvas.getContext("2d");
      ctx.fillRect(100, 100, 300, 200);
      ctx.clearRect(100,100,50,50);  

如下图:

 

  5、绘制渐变矩形

  ---与css3差不多,渐变三要素 : 方向(有起始坐标, 结束坐标)  初始颜色   结束颜色

  

      var myCanvas = document.querySelector("canvas");
      var ctx = myCanvas.getContext("2d");
      var linearGradient = ctx.createLinearGradient(100, 100, 400, 300);
      linearGradient.addColorStop(0, 'yellow');
      linearGradient.addColorStop(.5, 'pink');
      linearGradient.addColorStop(1, 'red');
      ctx.fillStyle = linearGradient;
      ctx.fillRect(100, 100, 300, 200);

  如下图:

  

 

二、绘制扇形

  1、圆弧

    (1)什么是弧度???

      ---  一种长度的描述单位

      ---  一弧度的长等于圆的半径的长

      ---  一个圆有 2π个弧度

      ---  一个角度等于 π / 180 个弧度

      ---  90度等于 π / 2个弧度

   2、绘制圆弧

    (1)确定圆心(坐标)

    (2)确定半径

    (3)确定 起始绘制 和 结束绘制 的位置 ,弧的位置 --- startAngle , endAngle

    (4)确定绘制的方向,默认是顺时针(false),逆时针(true)

    (5)绘制圆弧的函数  ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise)

    例:在中心位置画一个半径为150px的圆弧 ,0度到90度位置的圆弧

    var w = ctx.canvas.width;
    var h = ctx.canvas.height;
    ctx.arc(x / 2, h / 2, 150, 0 , Math.PI / 2);
    ctx.stroke();

  3、绘制扇形

        //第一种
        //先移动原点到中心点
        ctx.moveTo(w / 2, h / 2);
        //绘制圆弧时其实绘制了两条轨迹
        ctx.arc(w / 2, h / 2, 150, Math.PI / 2, Math.PI);
        //闭合路径
        ctx.closrPath();
        ctx.stroke();


        //第二种
        //先绘制圆弧
        ctx.arc(w / 2, h / 2, 150, Math.PI / 2, Math.PI);
        //绘制一条到中心点的轨迹
        ctx.lineTo(w / 2,  h / 2);
        //闭合路径
        ctx.closePath();
        ctx.stroke();

  

 三、绘制n等分的随机颜色的圆

         var myCanvas = document.querySelector("canvas");
          var ctx = myCanvas.getContext("2d");
       //确认中心点X
          var x0 = ctx.canvas.width / 2;
       //确认中心点Y
          var h0 = ctx.canvas.height / 2;
       //绘制多少个扇形
          var num = 6;
       //获取扇形的角度
          var angle = 2 * Math.PI / num;
       //随机颜色函数
          var randomColor = function(){
            var r = Math.floor(Math.random() * 256);
            var g = Math.floor(Math.random() * 256);
            var b = Math.floor(Math.random() * 256);
            return "rgb("+r+","+g+","+b+")";
          }

          for(var i = 0; i < num; i++){
        //获取每一次的起始位置
            var stratAngle = i * angle;
        //获取每一次的结束位置
            var endAngle = (i + 1) * angle;
            ctx.beginPath();
            ctx.moveTo(x0, h0);
            ctx.arc(x0, h0, 150, stratAngle, endAngle);
            ctx.fillStyle = randomColor();
            ctx.fill();
          }

  

 四、绘制带数据的饼图

        var myCanvas = document.querySelector("canvas");
        var ctx = myCanvas.getContext("2d");
        var x0 = ctx.canvas.width / 2;
        var y0 = ctx.canvas.height / 2;
        // 自定义了四个数组
        var data = [8,30,19,12];
        var angleList = [];
        var total = 0;
        data.forEach(function(item,i){
          total += item;
          if(i == data.length -1){
            angleList.push(2 * Math.PI * (data[0] / total));
          }
        });
        // 计算4个数据分别占弧度的比例,加入angleList中
        data.forEach(function(item,i){
          if(i >= 1){
            angleList.push(2 * Math.PI * (item / total));
          }
        })

        var randomColor = function(){
            var r = Math.floor(Math.random() * 256);
            var g = Math.floor(Math.random() * 256);
            var b = Math.floor(Math.random() * 256);
            return "rgb("+r+","+g+","+b+")";
          }
        // 开始弧度
        var startAngle = 0;
        angleList.forEach(function(item,i){
          // 结束弧度是开始弧度加上新的弧度
          var endAngle = startAngle + item;
          ctx.beginPath();
          ctx.moveTo(x0, y0);
          ctx.arc(x0, y0, 150, startAngle, endAngle);
          ctx.fillStyle = randomColor();
          ctx.fill();
          // 开始弧度是上一次的结束弧度
          startAngle = endAngle;
        })

  

五、画布中绘制文字

  1、 strokeText (str, x, y)      : 绘制描边文本

  2、fillText(str, x, y)  : 绘制填充文本  

    注:起始坐标位于左下角

  3、font = ‘ size, family‘ : 设置文本的大小和字体(第一个参数是大小,第二个参数是字体)

    例:ctx.font = ' 40px, Microsoft YaHei ' ;

  4、textAlign = left, center, right, start(默认), end  : 设置文本水平方向的对齐方式

  5、textBaseline = top , middle, bottom  : 设置文本垂直方向的对齐方式

  6、measureText(str)  :获取文本的宽度

 

六、绘制饼图加标题和说明

  ---绘制完饼图,别人根本看不懂那一块是那一块,所以需要加上标题和说明

    ---从扇形的弧中间伸出一条线,在画一条横线,在横线上写上文字标题

    ---在画布的左上角,绘制一个和扇形一样颜色的矩形说明,旁边附上文字说明

  如:

  

  1、绘制扇形中间伸出来的线

    1.1---如何确定这条线的位置 :两点确定一条 ——  中心点和线末端的点

    1.2---如何确定末端的点 : 

    

     如上图:可以把它看成一个直角三角形,则 X1 = X0 + a ;   Y1 = Y0 + b ;

    1.3---那么又如何确定 a 和 b 的长度呢?

    这时需要用到三角函数的勾股定理,看下图:

    

       已知 c = 1, 则 a = cos ( 30° ) * c 

             b = sin ( 30° ) * c

    1.4---现在知道了 a 和 b 怎么求了,那么弧度又如何求呢?

      由前面知道了弧度等于  比例 * 2π

      而这里的弧度等于 : 开始弧度 + 当前弧度 / 2;

                startAnglr + angle / 2;

      所以 X1 = X0 + cos( startAngle + angle / 2 ) * radius 

         Y1 = X0 + sin(  startAngle + angle / 2 ) * radius

    1.5---代码

    

// 创建饼图对象
        var PieChart = function(cavs){
        this.ctx = document.querySelector("canvas").getContext("2d");
        this.x0 = this.ctx.canvas.width / 2 + 60;
        this.y0 = this.ctx.canvas.height / 2;
        // 半径
        this.radius = 150;
        // 标题伸出去的线的长度
        this.outLine = 20 + this.radius;
        // 说明矩形的宽
        this.rectW = 30;
        // 说明矩形的高
        this.rectH = 16;
        // 说明矩形的左间距
        this.space = 20;
      }
      // 初始化
      PieChart.prototype.init = function(data){
        this.drawPie(data);
      }
      // 绘制饼图函数
      PieChart.prototype.drawPie = function(data){
        var that = this;
        // 获取带有数据的数组,其中包含num,title,angle,ratio
        var angleList = this.transfromAngle(data);
        var startAngle = 0;
        angleList.forEach(function(item,i){
          // 结束弧度等于开始弧度加上当前弧度
          var endAngle = startAngle + item.angle;
          //绘制标题
          that.drawTitle(startAngle,item.angle,item.title,item.ratio);
          
          that.ctx.beginPath();
          that.ctx.moveTo(that.x0, that.y0);
          that.ctx.arc(that.x0, that.y0, that.radius, startAngle, endAngle);
          that.ctx.fillStyle = that.getRandomColor();
          that.ctx.fill();
          // 绘制说明
          that.drawDescription(i,item.title);
          // 开始弧度等于上一次的结束弧度
          startAngle = endAngle;
        })
      }
      // 绘制标题函数
      PieChart.prototype.drawTitle = function(startAngle,angle,title,ratio){
          // 获取X方向线的长度,可以理解为a的长度
          var outXLine = Math.cos(startAngle + angle / 2) * this.outLine;
          // 获取Y方向线的长度,可以理解为b的长度
          var outYLine = Math.sin(startAngle + angle / 2) * this.outLine;
          // 获取末端点X坐标
          var outX = this.x0 + outXLine;
          // 获取末端点Y坐标
          var outY = this.y0 + outYLine;
          // 设置标题为 title加上ratio
          var str = title+" : "+ratio;
          this.ctx.beginPath();
          this.ctx.moveTo(this.x0, this.y0);
          this.ctx.lineTo(outX, outY);
          // 设置标题垂直方向底线对齐
          this.ctx.textBaseline = "bottom";
          // 设置标题字体大小和字体
          this.ctx.font = "14px Microsoft YaHei";
          // 设置标题颜色
          this.ctx.fillStyle = "#000";
          // 如果末端点在中心点的右边,则横线向右,否则向左
          if(outX >= this.x0){
            this.ctx.lineTo(outX + this.ctx.measureText(str).width, outY);
            this.ctx.textAlign = 'left';
          }else{
            this.ctx.lineTo(outX - this.ctx.measureText(str).width, outY);
            // 设置文字水平对齐基于起始点的右边
            this.ctx.textAlign = 'right';
          }
          // 设置字体
          this.ctx.fillText(str, outX, outY);
          this.ctx.stroke();
      }
      PieChart.prototype.drawDescription = function(index,title){
        // 1、矩形的大小
        // 2、上边和左边的间距
        // 3、矩形之间的间距
        this.ctx.fillRect(this.space, this.space + index * (10 + this.rectH), this.rectW, this.rectH);
        this.ctx.beginPath();
        this.ctx.textAlign = "left";
        this.ctx.textBaseline = "top";
        this.ctx.font = "12px Microsoft YaHei";
        this.ctx.fillText(title, this.space + this.rectW + 10, this.space + index * (10 + this.rectH) + this.rectH / 4);
      }
      PieChart.prototype.transfromAngle = function(data){
          var total = 0;
          // 获取数据总数
          data.forEach(function(item,i){
            total += item.num;
          })
          data.forEach(function(item,i){
            // 获取弧度并存如data中
            item.angle = item.num / total * Math.PI * 2;
            // 获取百分比并精确到小数点后两位,存入data中
            item.ratio = Math.round(item.num / total * 10000) / 100 + "%";
          })
          return data;
      }
      PieChart.prototype.getRandomColor = function(){
        var r = Math.floor(Math.random() * 256);
        var g = Math.floor(Math.random() * 256);
        var b = Math.floor(Math.random() * 256);
        return "rgb("+r+","+g+","+b+")";
      }
      var data = [
        {
          num : 8,
          title : "15-20岁"
        },
        {
          num : 30,
          title : "20-25岁"
        },
        {
          num : 12,
          title : "25-30岁"
        },
        {
          num : 16,
          title : "30-35岁"
        },
        {
          num : 5,
          title : "35-40岁"
        },
      ];

      var pie = new PieChart();
      pie.init(data);

  

    

   

原文地址:https://www.cnblogs.com/hxblogs/p/13262153.html