CSS CANVAS

187 阅读4分钟

Canvas

什么是canvas

canvas 是一个可以使用脚本(通常为Javascript) 在其中绘制图形的HTML元素,canvas标签只有两个 非通用属性widthheight,canvas的默认大小是300*150,注意:如果你绘制出来的图像是扭曲的,尝试在<canvas>的属性中明确规定宽度和高度,而不是使用csscanvas 元素和普通元素一样,有margin.border,bakcground等样式属性

基本用法

元素引入

<canvas id='cav width='800' height='500'>
   浏览器不支持canvas
</canvas>

渲染上下文

canvas本身不具备画图形的功能,一切由canvas内部的CanvasRenderingContext2D对象来做

var canvas=document.getElementById('cav');
var ctx=canvas.getContext('2d');

绘制图形

绘制矩形

HTML中的元素canvas只支持一种原生的图形绘制,矩形,所有其他的图形的绘制,都至少需要生成一条路径,canvas提供了三种绘制矩形的方法

/*
fillRect(x,y,width,height) 绘制一个填充的矩形
clearRect(x,y,width,height) 清除指定矩形区域,让清除部分完全透明
strokeRect(x,y,width,height) 绘制一个矩形的边框

绘制线段

/*
1. 开始路径 ctx.beginPath()
2. 设置起点 ctx.moveTo(x,y)
3. 设置重点(经过点) ctx.lineTo(x,y)
4. 绘制 ctx.stroke()
5. 结束路径 ctx.closePath()

绘制三角形

利用绘制线段的原理绘制三角形

绘制弧形

绘制弧形的参数分别是:弧形圆心x坐标,y坐标,半径,起始角(以三点钟的位置开始),结束角,方向(true表示逆时针,false表示顺时针)ctx.arc(600,200,100,0,Math.PI*2,false)

绘制赛贝尔曲线

二次赛贝尔曲线,三次赛贝尔曲线
/*
1. 开始路径 ctx.begingPath()
2. 设置起点 ctx.moveTo(x,y)
3. 设置贝塞尔曲线
    1. 二次赛贝尔曲线
        1. ctx.quadraticCurveTo(cpx,cpy,x,y) 参数是控制点x坐标,控制点y坐标,结束点x坐标,结束点y坐标
    2. 三次贝塞尔曲线
        1. ctx.bezieCurveTo(cpx,cpy,cpx2,cpy2,x,y) 参数是控制点1的x坐标,控制点1的y坐标,控制点2的x坐标,控制点2的y坐标,结束点x坐标,结束点y坐标
4. 绘制 ctx.stroke()
5. 结束路径 ctx.closePath()

canvas 第三方库

ecomfe.github.io/zrender/ind…

实际举例

实例 - 矩形

//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
//设置填充颜色
ctx.fillStyle='blue';
//绘制一个矩形
ctx.fillRect(100,100,200,200);
//清空矩形范围
ctx.clearRect(150,150,100,100);
//线宽
ctx.lineWidth=20;
//绘制边框矩形
ctx.strokeRect(75,75,250,250);

实例 - 绘制三角形

//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
ctx.beginPath();    //开始绘画
ctx.moveTo(20,20);  //第一个起始点
ctx.lineTo(20,100); //第二个点
ctx.lineTo(70,100); //第三个点
ctx.closePath();    //方法创建从当前点到开始点的路径
ctx.stroke();       //方法在画布上绘制确切的路径

实例 - 填充三角形

//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
ctx.beginPath();    //开始绘画
ctx.moveTo(20,20);  //第一个起始点
ctx.lineTo(20,100); //第二个点
ctx.lineTo(70,100); //第三个点
ctx.closePath();    //方法创建从当前点到开始点的路径
ctx.stroke();       //方法在画布上绘制确切的路径
ctx.fillStyle="green"; // 设置填充颜色
ctx.fill();        // 填充绘制的这部分图形

实例 - 圆

//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
ctx.beginPath();  //开始绘画
ctx.arc(100,75,50,0,2*Math.PI); //画圆
ctx.stroke();     //结束绘画

实例 - 二次贝塞尔曲线

//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
ctx.beginPath();   //开始绘画
ctx.moveTo(20,20); //设置起始点
ctx.quadraticCurveTo(20,100,200,20); //绘制二次贝塞尔曲线  参数分别是控制点xy,结束点xy
ctx.stroke();     //结束绘画

实例 - 三次贝塞尔曲线

//获取canvas
var cvs=document.querySelector('canvas');
//获取上下文对象
var ctx=cvs.getContext('2d');
ctx.beginPath();   //开始绘画
ctx.moveTo(20,20); //设置起始点
ctx.bezierCurveTo(800,250,900,300,950,100); //绘制三次贝塞尔曲线  参数分别是控制点1,xy, 控制点2,xy,结束点xy
ctx.stroke();     //结束绘画

canvas裁剪

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    *{ margin: 0; padding: 0;}
    table{ width: 1000px; height: 500px;box-shadow: 10px 10px 10px black}
    table td{ border:1px  dotted gray;}
    canvas{ top: 0; left: 0; position: absolute;}
  </style>
</head>
<body>
<table border="1" cellpadding="0" cellspacing="0">
  <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</table>
<canvas id="canvas" width="1000" height="500"></canvas>
<script>
  //获取canvas
  var cvs=document.querySelector('canvas');
  //获取上下文对象
  var ctx=cvs.getContext('2d');
  //设置填充颜色
  ctx.fillStyle='blue';

  //使用save方法可以把当前的场景保存下来
  ctx.save();

  //指定一个裁剪区域
  ctx.rect(0,0,200,200);
  //根据指定的裁剪区域进行裁剪,使用ctx的clip方法进行裁剪,裁剪的原理:根据指定的裁剪区域进行裁剪后,在canvas上无论画什么图形最终能在裁剪的区域内部才显示;
  ctx.clip();

  //第一个圆弧
  ctx.beginPath();
  ctx.arc(200,200,100,0,Math.PI*2,false);
  ctx.strokeStyle='deepskyblue';
  ctx.lineWidth=10;
  ctx.stroke();
  ctx.closePath();

  //因为使用了clip方法,所以在clip方法之后画的图形如果不在裁剪区域,就都不会显示出来,我们想要正常像是以后画的图形,我们可以利用restore方法来还原裁剪前通过save保存下来的场景即可
  ctx.restore();
  //第二个圆弧
  ctx.beginPath();
  ctx.arc(220,220,100,0,Math.PI*2,false);
  ctx.strokeStyle='orangered';
  ctx.stroke();
  ctx.closePath();
</script>
</body>
</html>

你画我猜

<!DOCTYPE html>
<html> 
<head> 
<meta charset="UTF-8"> 
<title></title> 
<style type="text/css"> 
*{margin: 0; padding: 0; } 
#box{width: 600px; height: 500px; margin: 100px auto; border: 1px solid black; } 
#box .control{height: 100px; } 
#box .control div{height: 50px; line-height: 50px; } 
#box .control .changeColor{padding-left: 15px; } 
#box .control .changeColor input{width: 30px; height: 30px; margin: 0 15px; font-size: 0; /*background-color: orange;*/ vertical-align: middle; } 
#box .control .changeColor input:nth-of-type(1){background-color: black; } 
#box .control .changeColor input:nth-of-type(2){background-color: pink; } 
#box .control .changeColor input:nth-of-type(3){background-color: red; } 
#box .control .changeColor input:nth-of-type(4){background-color: orange; } 
#box .control .changeColor input:nth-of-type(5){background-color: brown; } 
#box .control .changeColor input:nth-of-type(6){background-color: purple; } 
#box .control .clear{height: 50px; } 
#box .control .clear input{width: 100px; height: 50px; margin: 0 15px; font-size: 20px; background-color: #FDF5E5; } 
#canvas{background-color: #FFEBCB; } 
b{font-size: 20px; } 
</style> </head> <body> <div id="box"> <div class="control"> <div class="changeColor"> 选择画笔颜色: <input type="button" value="黑色" /> <input type="button" value="粉色" /> <input type="button" value="红色"/> <input type="button" value="橘色"/> <input type="button" value="棕色" /> <input type="button" value="紫色" /> </div> <div class="clear"> <input type="button" value="清空画布" id="clearAllBtn" /> 当前选中的颜色:<b>黑色</b> <input type="button" value="橡皮擦" id="rubberBtn" /> </div> </div> <canvas id="canvas" width="600" height="400"></canvas> </div> 

<script type="text/javascript">
  var canvas = document.querySelector("#canvas");
  var ctx = canvas.getContext("2d");

  //记录坐标的对象用来给move使用
  var pointerObj={}
  //切换橡皮檫的状态
  var isRubber=false;

  //按下事件
  canvas.addEventListener('mousedown',function (ev) {
    var x=ev.offsetX;
    var y=ev.offsetY;
    console.log(x+" "+y);

    pointerObj.x=x;
    pointerObj.y=y;

    if(isRubber){
      //橡皮擦
      rubberFn(x,y);
    }else{
      //画画
      draw(x,y);
    }

    this.addEventListener('mousemove',move);
    this.addEventListener('mouseup',up);
  })
  function move(e){
    var x=e.offsetX;
    var y=e.offsetY;

    if(isRubber){
      rubberFn(x,y);
    }
    else{
      draw(x,y);
    }

    //移动的时候把之前的点存储起来
    pointerObj.x=x;
    pointerObj.y=y;

  }
  function up(){
    canvas.removeEventListener('mousemove',move);
    // removeEventListener('mouse',up);
  }

  //画画
  function draw(x,y) {
    ctx.beginPath();
    // ctx.lineWidth=5;
    ctx.lineCap='round';
    ctx.moveTo(x,y);
    ctx.lineTo(pointerObj.x,pointerObj.y);
    ctx.stroke();
    ctx.closePath();
  }

  var colorBtns=document.querySelectorAll('.changeColor input');
  for(var i=0;i<colorBtns.length;i++){
    colorBtns[i].onclick=changeColor;
  }

  function  changeColor() {
    ctx.strokeStyle=getComputedStyle(this,null).backgroundColor;
    var b=document.querySelector('b');
    b.style.color=ctx.strokeStyle;
    b.innerHTML=this.value;

    //改变橡皮擦的状态
    isRubber=false;
  }

  var clearAllBtn=document.querySelector('#clearAllBtn');
  var rubberBtn=document.querySelector('#rubberBtn');
  //清空画布
  clearAllBtn.onclick=function () {
    ctx.clearRect(0,0,canvas.width,canvas.height);
  }
  //橡皮擦
  rubberBtn.onclick=function(){
    //开启橡皮擦功能
    isRubber=true;
  }

  function rubberFn(x,y){
    ctx.beginPath();
    //保存之前先把当前场景保存下来
    ctx.save();
    //创建裁剪区域
    ctx.arc(x,y,20,0,Math.PI*2,false);
    //进行裁剪
    ctx.clip();
    //裁剪之后创建一个清空矩形,但根据裁剪的原理,只有在裁剪区域内部有效
    ctx.clearRect(0,0,canvas.width,canvas.height);
    //还原之前的场景
    ctx.restore();
    // ctx.stroke();
    ctx.closePath();

  }
</script>
</body>
</html>