使用Canvas绘图

Canvas绘图

使用Canvas绘图

  • 自己的一些理解和注意点:
  • 1、目的:能“替代”flash等其他用于做动画或者游戏的插件的一个标签,可以减小页面结构,让页面加载速度更快
  • 2、canvas可以理解为一个div,只不过div是用来存放元素的,canvas则提供了一个绘制图形的区域
  • 3、canvas标签习惯上在标签内部对其大小进行设置(其他样式还是该怎样写怎样写还是用css),而不是css js
  • 4、canvas标签本身可以认为是一张普通画板,除此之外没有其他功能,内部的所有内容或者图形要用js脚本来完成
  • 5、画板和画家:var huaban=document.querySelector(".canvas")
    var bicaso=huaban.getContext(“2d”);(getContext() 方法返回一个用于在画布上绘图的环境
  • 6、画家有一个官方称呼:【convas上下文对象,习惯上命名为ctx(context)】
  • 7、要用canvas则先要准备一个脚本并且获取到canvas上下文(首先要检测 getContext() 方法是否存在)
  • 8、特征:
    上屏即像素化(内部绘制的图形一旦完成就不能变更,相当于已经是像素了只能擦掉重新画)
  • 9、fps:frame per second(每秒钟多少帧)(就像ps时间轴中的帧动画)
  • 10、如果canvas要加载一个图片,必须先等到图片load完再上屏,这与画家画油画感觉很像,先要看到整个物体,而不是像3D打印机过到哪画到哪

细致的基本用法

2D上下文(与python的使用turtle库画图类比)

  • 填充和描边
    • fillStyle :填充
    • strokeStyle:描边
  • 绘制矩形(三个方法都是4个参数)
    • fillRect(矩形的 x 坐标、矩形的 y 坐标、矩形
      宽度和矩形高度)
    • strokeRect()
    • clearRect()
// 绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
// 绘制半透明的蓝色矩形
context.fillStyle = "rgba(0,0,255,0.5)";
context.fillRect(30, 30, 50, 50);
// 绘制红色描边矩形
context.strokeStyle = "#ff0000";
context.strokeRect(10, 10, 50, 50);
  • 绘制路径(首先调出beginPath()方法)

    • 一些方法如下图:在这里插入图片描述
  • 一个例子:(绘制一个不带数字的时钟表盘)

var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d");
// 开始路径
context.beginPath();
// 绘制外圆
context.arc(100, 100, 99, 0, 2 * Math.PI, false);
// 绘制内圆
context.moveTo(194, 100);
context.arc(100, 100, 94, 0, 2 * Math.PI, false);
// 绘制分针
context.moveTo(100, 100);
context.lineTo(100, 15);
// 绘制时针
context.moveTo(100, 100);
context.lineTo(35, 100);
// 描边路径
context.stroke();
}
  • 绘制文本(两个方法都接受4个参数)
    • fillText(要绘制的文本字符串、x 坐标、y 坐标和可选的最大像素宽度)
    • strokeText()
    • 2个方法都以下面三个属性为基础:
      在这里插入图片描述

这几个属性都有默认值,因此没有必要每次使用它们都重新设置一遍值

  • 变换(5个方法)
    在这里插入图片描述

  • 绘制图像(使用 ==drawImage(传入一个 HTML 元素,以及绘制该图像的起点的 x 和 y 坐标)==方法)

1、除了给 drawImage() 方法传入 HTML <img> 元素外还可以传入另一个 <canvas> 元素作为其第一个参数
2、操作的结果可以通过
toDataURL() 方法获得(不过,有一个例外,即图像不能来自其他域。如果图像来自其他域,调用
toDataURL()抛出一个错误

  • 阴影(4个属性)
    在这里插入图片描述

像ps混合模式中添加阴影,可以改变阴影深度大小和偏移量

  • 渐变(两步走)
    • 1、创建一个新的线性渐
      变,可以调用 createLinearGradient(起点的 x 坐标、起点的 y 坐
      标、终点的 x 坐标、终点的 y 坐标)
      方法
      +2、使用 addColorStop(色标位置和 CSS 颜色值) 方法来指定色标
      例子:
var gradient = createRectLinearGradient(context, 30, 30, 50, 50);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
//绘制渐变矩形
context.fi llStyle = gradient;
context.fillRect(30, 30, 50, 50);
  • 模式(实质是重复的图像,用来填充或描边图形)
    • createPattern(一个 HTML 元素,一个表示如何重复图像的字符串) 方法

第二个参数的值与 CSS 的 background-repeat 属性值相同,包括 “repeat” 、 “repeat-x” 、“repeat-y” 和 “no-repeat”

  • 使用图像数据
    • 取得原始图像数据:getImageData(要取得其数据的画面区域的 x , y 坐标以及该区域的像素宽度,高度)
var imageData = context.getImageData(10, 5, 50, 50);//取得左上角坐标为(10,5)、大小为 50×50 像素的区域的图像数据

理解:上个例子返回ImageData 的实例,每个 ImageData 对象都有三个属性: width 、 height 、data,data是一个数组,保存着图像中每一个像素的数据,而每个像素用4个元素来保存,分别表示红、绿、蓝(就像ps中的alpha通道)和透明度值

  • 合成(两个属性)
    • ==globalAlpha:==是一个介于 0 和 1 之间的值(包括 0和 1),用于指定所有绘制的透明度,默认值为 0
    • 例子:
//绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//修改全局透明度
context.globalAlpha = 0.5;
//绘制蓝色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
//重置全局透明度
context.globalAlpha = 0;

理解:蓝色矩形会呈现半透明效果,透过它可以看到下面的红色矩形

  • globalComposition-
    Operation
    :表示后绘制的图形怎样与先绘制的图形结合,这个属性的的值是固定的:如图:
    在这里插入图片描述

  • 给出看视频学的两个例子:

这是一个控制一个矩形左右来回移动的代码段

<style>
    .canvas {
        border: 1px solid pink
    }
</style>

<body>
    <canvas width="300" height="200" class="canvas"></canvas>
    <script>
        var huaban = document.querySelector(".canvas");
        var bicaso = huaban.getContext("2d");
        var timer = null;
        var distance = 10;
        var fangxiang = 1;//本变量表示累加的变量,用来控制图形前进的方向,+1表示右,-1表示向左
        timer = setInterval(function () {
            if (distance == 0) {
                fangxiang = 1;//通过变更横坐标来变更方向
            }
            if (distance == 250) {
                fangxiang = -1;
            }
            switch (fangxiang) {
                case 1: {

                    //擦除原有图形
                    bicaso.clearRect(0, 0, 300, 200);
                    //绘制新图形
                    bicaso.fillRect(++distance, 50, 50, 50);
                }
                    break;
                case -1: {

                    //擦除原有图形
                    bicaso.clearRect(0, 0, 300, 200);
                    //绘制新图形
                    bicaso.fillRect(--distance, 50, 50, 50);

                }
                    break;
            }


        }, 25);

    </script>
</body>

第二个例子:实现鼠标粒子跟随效果,要用到underscore库,相关可参考https://blog.csdn.net/napolunyishi/article/details/23695477?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.nonecase

  <style>
    canvas { background: #333; }
  </style>
</head>
<body>
  <canvas width="800" height="500">您的浏览器不支持此标签!</canvas>
  <script src="js/underscore.min.js"></script>
  <script>
    // 获取canvas元素
    var cvs = document.querySelector("canvas");
    // 获取上下文对象
    var ctx = cvs.getContext("2d");
    // 声明一个空数组,用来放后面生成的小球
    var ballsArr = [];
 
    // 创建一个小球类
    function Balls (x, y){
      // 坐标x为传进来的x
      this.x = x;
      // 坐标y为传进来的y
      this.y = y;
      // 生成的小球半径为5到10中的任一整数(参数随便)
      this.r = _.random(5, 10);
      // 生成的小球的颜色为这七种颜色中的随机一种(参数随便)
      this.c = _.sample(["red", "orange", "yellow", "green", "cyan", "blue", "white"]);
      // 小球坐标x的增量为-4到4之间的整数(参数随便)
      this.dx = _.random(-4, 4);
      // 小球坐标y的增量为-4到4之间的整数(参数随便)
      this.dy = _.random(-4, 4);
      // 把生成的小球存入数组ballsArr
      ballsArr.push(this);
    }
 
    // 给所有Balls绑定一个方法update,目的是为了每次都能按照随机方向移动
    Balls.prototype.update = function (){
      // 每次x坐标加上增量dx
      this.x += this.dx;
      // 每次y坐标加上增量dy
      this.y += this.dy;
      // 每次半径缩小0.5(参数随便)
      this.r -= 0.5;
      // 半径小于等于0的话,就从小球数组中移出
      if(this.r <= 0){
        _.without(ballsArr, this);
      }
    }
 
    // 给所有Balls绑定一个方法render,目的是画圆。
    Balls.prototype.render = function (){
      // 半径小于等于0就没必要画了
      if(this.r <= 0){
        return;
      }
      // 开始绘制
      ctx.beginPath();
      // 绘制圆形,(圆心坐标x,圆心坐标y, 起始弧度,终止弧度,[顺逆时针])
      ctx.arc(this.x, this.y, this.r, 0, 2*Math.PI);
      // 颜色为数组中随机的一个
      ctx.fillStyle = this.c;
      // 画上画布
      ctx.fill();
      // 终止绘制
      ctx.closePath();  
    }
 
    // onmousemove事件监听
    cvs.onmousemove = function (){
      new Balls(event.offsetX, event.offsetY);
      new Balls(event.offsetX, event.offsetY);
    }
 
    // setInterval 模拟25FPS的帧率
    setInterval(function (){
      // 因为canvas上屏即像素化,所以先清屏
      ctx.clearRect(0, 0, cvs.width, cvs.height);
      // _.each方法是针对每一个前面的元素,都运行后面的方法
      _.each(ballsArr, function (value){
        value.update();
        value.render();
      });
    }, 40);
 
  </script>
</body>

WebGl(绘制3d图形)可以参考https://www.cnblogs.com/mirror-pc/p/4181398.html

猜你喜欢

转载自blog.csdn.net/Phoebe4/article/details/107524780