canvas的学习
在base64和blob笔记里,使用了canvas进行图片压缩,但是画布的基础就是画画
文章来自三期画布基础教程
// 生成画布
var c = document.getElementById("myCanvas");
c.width = 500;
c.height = 500;
// 生成画笔
var ctx = c.getContext("2d");
// 线,闭合线,填充线
ctx.beginPath(); // 开始画
ctx.moveTo(100, 100); // 画笔移动到
ctx.lineWidth = 2; // 画笔粗细
ctx.lineCap = 'round'; // 线条首尾
ctx.lineJoin = 'round'; // 线条连接处
ctx.lineTo(300,100); // 画一条线,开始的x是100,结束的x是300,开始的y是100,结束是0
ctx.lineTo(200,200); // 画笔初始位置是上一个方法执行后的点
ctx.closePath(); // 闭合线,把开始的位置和上一句代码的位置连接起来
ctx.fill(); //写这句就不需要写closePath了,这句是closePath+填充
ctx.stroke();
// 闭合方形
ctx.beginPath(); // 开始画
ctx.strokeStyle = "red";
ctx.globalAlpha = 0.3;//设置全局透明度
ctx.strokeRect(50,50, 200, 200); //绘制边框
ctx.stroke();
// 填充方形
ctx.beginPath(); // 开始画
ctx.fillStyle = "blue"; //设置颜色
ctx.fillRect(50,50, 200, 200); //绘制方块
ctx.stroke();
// 圆
ctx.beginPath(); // 重新开始一笔
ctx.arc(400, 400, 50, 0, Math.PI*2, false); // 绘制圆圈轨迹,最后一个参数是从上半圆还是下半圆
ctx.stroke();
// 气泡聊天窗
ctx.beginPath();
ctx.moveTo(100,130);
ctx.quadraticCurveTo(100,100,130,100);
ctx.lineTo(270,100);
ctx.quadraticCurveTo(300,100,300,130);
ctx.lineTo(300,200);
ctx.quadraticCurveTo(300,230,270,230);
ctx.lineTo(175,230);
ctx.quadraticCurveTo(140,280,100,280);
ctx.quadraticCurveTo(130,280,150,230);
ctx.lineTo(130,230);
ctx.quadraticCurveTo(100,230,100,200);
ctx.closePath();
ctx.stroke(); // 这一笔结束
// 心形
ctx.beginPath();
ctx.moveTo(100,100);
ctx.bezierCurveTo(100,50,170,50,200,100);
ctx.bezierCurveTo(230,50,300,50,300,130);
ctx.bezierCurveTo(300,140,300,210,200,250);
ctx.bezierCurveTo(100,200,100,140,100,130);
ctx.stroke();
// 点
ctx.beginPath();
ctx.fillRect(51+2*16,35,4,4);
ctx.stroke();
//线性渐变
ctx.beginPath();
var lineargradient = ctx.createLinearGradient(0,0,0,140);// 准备调料
lineargradient.addColorStop(0,'#00ABEB');
lineargradient.addColorStop(0.5, "#fff");
lineargradient.addColorStop(0.5, "green");
lineargradient.addColorStop(1,'#fff');
ctx.fillStyle = lineargradient;
ctx.fillRect(10,10,130,130);
ctx.stroke();
/*径向渐变*/
ctx.beginPath();
var radgrad = ctx.createRadialGradient(45,45,10,52,50,30); // 准备调料
radgrad.addColorStop(0, "#fff");
radgrad.addColorStop(0.9, "green");
radgrad.addColorStop(1, "rgba(255,255,255,0)"); //最后一个颜色最好写成透明的,这样圆圈以外部分会以这个颜色填充
ctx.fillStyle = radgrad;
ctx.fillRect(0,0,150,150);
ctx.stroke();
// 虚线
ctx.beginPath();
ctx.setLineDash([10, 10]); //设置设置虚线的间隔 x1表示虚线自身长度 x2表示间隔长度 默认单位:px
ctx.lineDashOffset = 5; //设置偏移量
ctx.strokeRect(100,100,100,100); //绘制虚线边框
ctx.stroke();
// 文字
ctx.shadowOffsetX = 2; //阴影x方向偏移量
ctx.shadowOffsetY = 2; //阴影y方向偏移量
ctx.shadowBlur = 5; //阴影模糊度
ctx.shadowColor = "rgba(0,0,0,0.5)"; //阴影颜色
ctx.font = "20px Times New Roman";
ctx.fillStyle = "black";
ctx.fillText("Sample String", 5, 30);
// save和restore,保存画布的状态
ctx.fillStyle = "darkblue";
ctx.lineWidth = 1;
ctx.fillRect(0,0,150,150);
ctx.save(); //第一次保存 保存了 fillStyle "darkblue"
ctx.fillStyle = "#09f";
ctx.fillRect(15,15,120,120);
ctx.save(); //第二次保存 保存了 fillStyle "#09f"
ctx.fillStyle = "#fff";
ctx.fillRect(30,30,90,90);
ctx.restore(); //恢复到第二次保存的状态
ctx.fillRect(45,45,60,60);
ctx.restore(); //恢复到第一次保存的状态
ctx.fillRect(60,60,30,30);
//先画一个路径然后裁剪
ctx.clip();
// 偏移
ctx.transform(水平方向的移动,竖直方向的移动);
ctx.transform(水平方向的缩放,水平方向的偏移,竖直方向的偏移,竖直方向的缩放,水平方向的移动,竖直方向的移动);
ctx.scale(0.4,0.4); // 缩放
ctx.rotate(-Math.PI/2); // 角度,参数是pi
// 橡皮擦
ctx.clearRect(50,50, 200, 200); //清除范围,这里清除的是方块,如果要清除方块描边的话,需要把范围扩大
// 画图,参数有三种填发,2个,4个,8个
sx,开始剪切的 x 坐标位置。
sy,开始剪切的 y 坐标位置。
swidth,被剪切图像的宽度。
sheight,被剪切图像的高度。
x,在画布上放置图像的 x 坐标位置。
y,在画布上放置图像的 y 坐标位置。
width,要使用的图像的宽度。(伸展或缩小图像)
height,要使用的图像的高度。(伸展或缩小图像)
ctx.drawImage(img,x,y);
ctx.drawImage(img,x,y,width,height);
ctx.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
封装一个划线的方法
function drawLine(sx, sy, ex, ey){
ctx.beginPath();
ctx.moveTo(sx,sy);
ctx.lineTo(ex,ey);
ctx.stroke();
ctx.closePath();
}
一像素画笔
function draw(){
// 当只绘制1像素的线的时候,坐标点需要偏移,这样才能画出1像素实线
ctx.translate(0.5,0.5);
ctx.lineWidth = 1;
drawLine(50, 50, 100, 50); // 上面的划线方法
ctx.translate(-0.5,-0.5); // 还原位置
}
动画效果
// 计时器和清除计时器就不说了
// 动画专用的计时器
var nextAnimation = ""
function draw(){
nextAnimation = window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw); // 执行
window.cancelAnimationFrame(nextAnimation); // 把下一帧清除就等于停止递归
画布事件
var mousePosition = {};
var mouseTimer = null;
canvas.addEventListener("mousemove",function(e){
e = e || window.event;
if( e.layerX || e.layerX==0 ){
mousePosition.x = e.layerX;
mousePosition.y = e.layerY;
}else if( e.offsetX || e.offsetX==0 ){
mousePosition.x = e.offsetX;
mousePosition.y = e.offsetY;
}
clearTimeout(mouseTimer);
mouseTimer = setTimeout(function(){
// 清空画布
ctx.clearRect(0,0,canvas.width, canvas.height);
drawBarAnimate(true);
},10);
});
function drawBarAnimate(mouseMove){
// for循环去生成方块
drawRect(x, y, X, Y,mouseMove)
}
// 绘制方块
function drawRect( x, y, X, Y, mouseMove ){
ctx.beginPath();
ctx.rect( x, y, X, Y );
// 判断参数的两个值是否在当前的 beginPath 和 closePath 的绘制区域内
if(mouseMove && ctx.isPointInPath(mousePosition.x, mousePosition.y)){
ctx.fillStyle = "green";
}else{
ctx.fillStyle = "red";
}
ctx.fill();
ctx.closePath();
}