Skip to main content

开发者的画布

<canvas id="tutorial" width="300" height="150">
    你的浏览器不支持canvas,请升级你的浏览器
</canvas>

function draw(){
    const canvas = document.getElementById('tutorial')
    if(!canvas.getContext) return
    const ctx = canvas.getContext("2d")
    //开始代码
}

基本篇

IE8以下支持canvas

https://github.com/arv/explorercanvas

引入js包

<!--[if lte IE 8]><script type="text/javascript" src="excanvas.js"></script><![endif]-->

绘图环境宽高,效果相同

  • canvas.width
  • canvas.height
  • ctx.canvas.width/ctx.canvas.height

绘图环境状态保存和恢复

  • ctx.save();
  • ctx.restore();

绘图拷贝和粘贴

let imgData=ctx.getImageData(10,10,50,50);
ctx.putImageData(imgData,10,70);

清空全部canvas的像素内容

ctx.clearRect(0, 0, canvas.width, canvas.height);

返回canvas真实坐标x,y

function windowToCanvas(canvas,x=e.clientX,y=e.clientY) {
    //通过API获取DOMRect对象
    let bbox = canvas.getBoundingClientRect();
    return {
        //扣除当前对象的left,top
        x:x-bbox.left*(canvas.width/bbox.width),
        y:y-bbox.top*(canvas.height/bbox.height)
    }
}

图片篇

返回包含图片的data URL

  • 适合小图片/同步加载/任意浏览器中使用
  • 图片的类型默认为 image/png
  • return "data:" + mimeType + ";base64," + base64Encode(encodedImage);
let fullQuality = canvas.toDataURL('image/jpeg',1);
let lowQuality = canvas.toDataURL('image/webp',0.1);

返回包含图片的Blob

  • 适合大图片/异步加载/仅应用内部使用
  • 全称: Binary Large Object(File 继承自 Blob)
  • 图片的类型默认为 image/png,分辨率为96 dpi
resultBlob = File.create(encodedImage.data(), encodedImage.size(), encodingMimeType);
function blobCallback(blob){
    //创建一个img标签
    var newImg = document.createElement("img"),
        //以blob对象为基础创建一个url
        url = URL.createObjectURL(blob);
    console.log(url);
    console.log(blob);
    //加载后销毁
    newImg.onload = function () {
        // no longer need to read the blob so it's revoked
        URL.revokeObjectURL(url);
    };
    //img标签属性赋值
    newImg.src = url;
    //添加为子元素
    document.body.appendChild(newImg);
}
canvas.toBlob((blob)=>{blobCallback(blob)}, "image/jpeg", 0.95);

绘制图片

ctx.drawImage(image, x, y,width,height)

图像重复

ctx.createPattern(image, repeat)
    repeat 全部重复
    repeat-x 沿x轴重复
    repeat-y 沿y轴重复
    no-repeat 不重复

通用篇

全局透明度

ctx.globalAlpha = 0.5;

设置或返回填充canvas的颜色、渐变、模式

ctx.fillStyle = 'cornflowerblue';

用于设置或返回笔触的颜色、渐变、模式

ctx.strokeStyle = 'blue';

设置填充渐变

gradient = ctx.createLinearGradient(start-x,start-y,end-x,end-y);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.25, 'white');
gradient.addColorStop(0.5, 'purple');
gradient.addColorStop(0.75, 'red');
gradient.addColorStop(1, 'yellow');
ctx.fillStyle=gradient;

旋转/缩放/平移/水平镜像/垂直镜像

ctx.rotate(-Math.PI/8);
ctx.scale(2,2);
ctx.translate(30,30);
ctx.scale(1,-1);
ctx.scale(-1,1);

存为Path2D对象

let rectangle = new Path2D();
rectangle.rect(10, 10, 50, 50);
ctx.stroke(rectangle);

字体篇

设置字体格式

ctx.font = '38pt Arial';

设置文字的内容和位置

ctx.fillText('Hello World', canvas.width / 2 - 150, canvas.height / 2 + 15);
ctx.strokeText("Hello World", canvas.width / 2 - 150, canvas.height / 2 + 15);

检查字体的宽度

ctx.measureText('Hello World').width

线条篇

设置线条宽度

ctx.lineWidth = 0.5;

绘制线条

ctx.beginPath();
// 通过给x+0.5,y+0.5实现抗锯齿,使线条更加平滑
ctx.moveTo(x+0.5,y+0.5);
ctx.lineTo(x+0.5,y+0.5);
ctx.stroke();

闭合路径

ctx.closePath();

设置虚线模式

ctx.setLineDash([5,4,3]);

设置虚线偏移量(动态)

offset+=3.0;
ctx.lineDashOffset=offset;

设置线段端点

ctx.lineCap='butt';
ctx.lineCap='round';
ctx.lineCap='square';

设置线段连接点

ctx.lineJoin='round';
ctx.lineJoin='bevel';
ctx.lineJoin='miter';

判断路径中是否包含监测点

ctx.isPointInPath(x,y)

图形篇

描边->空心

ctx.stroke();

填充->实心

ctx.fill();

绘制圆形

ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise)
    /**
    * x,y指定圆心
    * radius为半径
    * startAngle,endAngle为起始点和终点,整圆值为0,Math.PI * 2
    * anticlockwise是否顺时针
    */
    /**绘制圆弧**/
        //方法1
        ctx.beginPath();
        ctx.arc(100, 100, 50, Math.PI / 4, Math.PI, false);
        ctx.stroke();

        //方法2
        ctx.beginPath();
        ctx.moveTo(100, 20);
        //起始点(100,20),A点(130,20),B点(130,50)
        ctx.arcTo(100+30,20,100+30,20+30,30);
        ctx.stroke();

    /**二次贝塞尔曲线**/
        //控制点120.5,180 
        //结束点200.5,180
        ctx.beginPath();
        ctx.moveTo(120.5,130);
        ctx.quadraticCurveTo(120.5,180,200.5,180);
        ctx.stroke();

    /**三次贝塞尔曲线**/
        ctx.beginPath();
        ctx.moveTo(20,20)
        ctx.bezierCurveTo(20,100,200,100,200,20)
        ctx.stroke();

    /**绘制圆形剪纸**/
        ctx.beginPath();
        //利用非零环绕规则:两个图形绘画方向相反,则计算差值
        ctx.arc(300, 190, 150, 0, Math.PI * 2, false);
        ctx.arc(300, 190, 120, 0, Math.PI * 2, true);
        ctx.fill();

设置外角类型

ctx.lineJoin='round'

绘制矩形

ctx.strokeRect(x, y, width, height)
ctx.fillRect(x, y, width, height)
    /**绘制阴影矩形**/
        //禁用阴影:shadowColor:undefine;
        ctx.shadowColor="rgba(0,0,0,0.75)";
        //阴影水平偏移
        ctx.shadowOffsetX=5;
        //阴影垂直偏移
        ctx.shadowOffsetY=5;
        //越大越模糊
        ctx.shadowBlur=5;
        ctx.strokeRect(x, y, width, height)
        ctx.fillRect(x, y, width, height)
    /**逆时针绘制矩形**/
    function rect(x,y,w,h,direction) {
        if(direction){
            ctx.moveTo(x,y);
            ctx.lineTo(x,y+h);
            ctx.lineTo(x+w,y+h);
            ctx.lineTo(x+w,y);
            ctx.closePath();
        }else{
            ctx.moveTo(x,y);
            ctx.lineTo(x + w, y);
            ctx.lineTo(x + w, y + h);
            ctx.lineTo(x, y + h);
            ctx.closePath();
        }
    }

事件篇

鼠标事件

canvas.addEventListener('mousedown',function (event){})
canvas.addEventListener('mousemove',function (event){})
canvas.addEventListener('mouseup',function (event){})
canvas.addEventListener('mouseout',function (event){})
window.addEventListener('keydown',function (event){},true);
window.addEventListener('keypress',function (event){},true);
window.addEventListener('keyup',function (event){},true);

总结篇

canvas 跟 img 标签相比,唯一的不同就是它并没有 src 和 alt 属性。

canvas 只有两个属性 width 和 height,默认值为300*150。

canvas基础:

  • 对于canvas来说,左上角的坐标是(0,0)

  • 单线条:

    1. moveTo => 画笔定位(必须,否则 lineTo 无效)

    2. lineTo =>路径运动

      lineWidth =>线条宽度
      lineCap =>线条端点形状 => 获值 round|square|butt
      lineJoin =>线条交界处外角类型 => miter|round|bevel
    3. stroke =>描边方法

      strokeStyle =>设置颜色 => 获值形式 color|gradient|pattern
  • 多线条:

    1. beginPath =>告诉 canvas 我们要绘制一条全新路径,防止之前效果被污染
      • 矩形基础:
        1. fillRect =>绘制填充矩形
        2. strokeRect =>绘制边框矩形
        3. clearRect =>清除矩形区域