美文网首页
canvas基础

canvas基础

作者: 你怀中的猫 | 来源:发表于2022-05-28 15:24 被阅读0次

1、注意

  • canvas只兼容 IE9 以上的浏览器
  • canvas 有默认宽高 300x150
  • canvas 如果用style设置宽高 会导致画布变形
  • 所以通常使用行间样式 width height 来设置宽高

2、canvas绘制步骤

  • 1、获取canvas标签
    var canvas = document.getElementById
  • 2、获取canvas工作环境(功能端口)
    var ctx = canvas.getContext('2d');
  • 3、开始绘制
    ctx.beginPath();
  • 4、设置画线的粗细(有默认值,可以不设置)
    ctx.lineWidth = 5;
  • 5、设置线的颜色(有默认值,默认为黑色)
    ctx.strokeStyle = 'red';
  • 6、确定起始点坐标
    ctx.moveTo();
  • 7、确定结束点坐标
    ctx.lineTo();
  • 8、结束绘制
    ctx.closePath();
  • 9、绘制图形
    ctx.stroke();

3、绘制一个矩形

function Rect(width,x,y,bgcolor,line) { 
        this.width = width;
        this.x = x;
        this.y = y;
        this.bgColor = bgColor;
        this.line = line;
    }
Rect.prototype.draw = function () {
        ctx.beginPath();
        //4、设置画线的粗细
        ctx.lineWidth = this.line;
        //5、线的颜色
        ctx.strokeStyle = this.bgColor;
        //6、确定起始点坐标
        ctx.moveTo(this.x, this.y);
        //7、结束点坐标
        ctx.lineTo(this.x, this.y + this.width);
        ctx.lineTo(this.x + this.width, this.y + this.width);
        ctx.lineTo(this.x + this.width, this.y);
        ctx.lineTo(this.x, this.y);
        ctx.closePath();
        //8、绘制图形
        ctx.stroke();
}

//实例化
var r1 = new Rect();
r1.draw();

4、绘制一个三角形

 //封装一个 三角形类
    function Triangle(options) {
        this.x1 = options.x1;
        this.y1 = options.y1;
        this.x2 = options.x2;
        this.y2 = options.y2;
        this.x3 = options.x3;
        this.y3 = options.y3;
        //线宽、颜色
        this.color = options.color || '#007aff';
        this.line = options.line || 2;
        // this.draw();
    }

    Triangle.prototype.draw = function () {
        ctx.beginPath();
        ctx.lineWidth = this.line;
        ctx.strokeStyle = this.color;
        ctx.moveTo(this.x1, this.y1);
        ctx.lineTo(this.x2, this.y2);
        ctx.lineTo(this.x3, this.y3);
        ctx.fillStyle = '#fff';
        ctx.fill();
        ctx.closePath();
        ctx.stroke();
    }

5、绘制圆弧

  • ctx.arc(x,y,r,begin,end,bool)
参数 参数表示的意义
x 圆心 x 坐标
y 圆心 y 坐标
r 半径
begin 起始点与0度夹角
end 结束点与0度夹角
bool(布尔值) false 默认值 顺时针绘制、true 逆时针绘制
  • 角度计算 : 1度 = Math.PI / 180

6、绘制扇形

//定义一个扇形类
    function Circle(options) {
        this.x = options.x;
        this.y = options.y;
        this.r = options.r;
        //起始角度
        this.begin = options.begin;
        //结束
        this.end = options.end;
        this.color = options.color || '#007aff';
    }

    var deg = Math.PI / 180;
    //给扇形类添加一个方法
    Circle.prototype.draw = function () {
        ctx.beginPath();
        ctx.moveTo(this.x, this.y)
        ctx.arc(this.x, this.y, this.r, this.begin * deg, this.end * deg - Math.PI / 2);
        ctx.fillStyle = this.color;
        ctx.fill();
        ctx.lineWidth = 3;
        ctx.closePath();
        ctx.stroke();
    }

//实例化
var y1 = new Circle({
            x: 300,
            y: 300,
            r: 100,
            begin: 0,
            end: 360 * deg,
});
y1.draw();


//按照百分比绘制圆弧 
function bai(n) {
        n = 360 * n / 100;
        var y2 = new Circle({
            x: 450,
            y: 450,
            r: 100,
            begin: -90,
            end: n,
            color: 'red',
        });
        y2.draw();
    }
    bai(50)

7、绘制饼状图方法

 //封装饼状图
    function createPie(options) {
        var x = options.x;
        var y = options.y;
        var r = options.r;
        var data = options.data;
        var deg = Math.PI / 180;
        //封装随机数
        function randNum(min, max) {
            return Math.floor(Math.random() * (max - min + 1) + min);
        }

        //随机颜色
        function randColor() {
            var r = randNum(0, 255);
            var g = randNum(0, 255);
            var b = randNum(0, 255);
            return `rgb(${r},${g},${b})`;
        }

        function Set(x, y, r, begin, end, color) {
            this.x = x;
            this.y = y;
            this.r = r;
            this.begin = begin;
            this.end = end;
            this.color = color || randColor();

        }
        Set.prototype.draw = function () {
            ctx.beginPath();
            ctx.moveTo(this.x, this.y)
            ctx.arc(this.x, this.y, this.r, this.begin * deg, this.end * deg);
            ctx.fillStyle = this.color;
            ctx.fill();
            ctx.lineWidth = 3;
            ctx.closePath();
            ctx.stroke();
        }
        var arr = data;
        for (var i = 0; i < arr.length - 1; i++) {
            var min_index = i;
            for (var j = i + 1; j < arr.length; j++) {
                if (arr[j].num < arr[min_index].num) {
                    min_index = j;
                }
            }
            var min = arr[i];
            arr[i] = arr[min_index];
            arr[min_index] = min;
        }
        console.log(arr);
        //计算总数
        var sum = 0
        for (var i = 0; i < arr.length; i++) {
            sum += arr[i].num;
        }
        console.log(sum);

        //计算比例
        var begin = 0;
        var end = 0;
        for (var i = 0; i < arr.length; i++) {
            end += arr[i].num / sum * 360;
            console.log(end);
            var s1 = new Set(400, 400, 200, begin, end);
            s1.draw()
            begin = end;

        }
    }
    createPie({
        x: 300,
        y: 300,
        r: 200,
        data: [
            {
                type: '0-40',
                num: 5,
                color: "red",
            },
            {
                type: '40-60',
                num: 8,
                color: "#ccc",
            },
            {
                type: '60-80',
                num: 12,
                color: "blue",
            },
            {
                type: '80-90',
                num: 9,
                color: "#ccc",
            },
            {
                type: '90-100',
                num: 6,
                color: "blue",
            },
        ]
    })
    // 计算文字 起点坐标公式
    // textX= Math.cos(角度)*(半径+文字里饼状图的距离)+圆心坐标X
    // textY= Math.sin(角度)*(半径+文字里饼状图的距离)+圆心坐标Y


8、绘制文字

  • 1、文字字体必须设置,否则不会正常展示
    ctx.font = "oblique 50px '微软雅黑'";
  • 2、设置文字水平位置
    ctx.textAline = 'right'
常用值 代表的意思
left 起始点在文字的左边
right 起始点在文字的右边
center 起始点在文字的中间
  • 设置文字纵向对齐方式
    ctx.textBaseline = 'bottom';
常用值 代表的意思
alphabetic 默认,根据字母基线对齐
top 文字顶部对齐
middle 文字中间对齐
bottom 文字底部对齐
Hanging 悬挂基线
  • 3、实心文字
    ctx.fillText('Hello Wold', 300, 200);
  • 4、空心文字
    ctx.strokeText('Hello Wold', 300, 300);

9、绘制贝塞尔曲线

  • ctx.quadraticCurveTo(控制点X,控制点Y,结束点X,结束点Y)
  • 绘制贝塞尔曲线需要三个点
  • 第一个起始点 moveTo(起始点X,起始点Y)
  • 第二个点 控制点 贝塞尔曲线的前两个参数 就是控制点的x、y
  • 第三个点 结束点 贝塞尔曲线的后两个参数
//鼠标移动的方法
    canvas.onmousemove = function (e) {
        //获取鼠标坐标  ,将鼠标坐标点,当作贝塞尔曲线的控制点
        var mx = e.offsetX;
        var my = e.offsetY;

        canvas.width = canvas.width;
        box()

        //绘制曲线
        ctx.beginPath();
        ctx.lineWidth = 5;
        ctx.strokeStyle = '#007aff';
        ctx.moveTo(400, 400);
        ctx.quadraticCurveTo(mx, my, 700, 400)
        ctx.stroke();
        

        ctx.beginPath();
        ctx.lineWidth = 3;
        ctx.strokeStyle = '#000';
        ctx.moveTo(400, 400);
        ctx.lineTo(700, 400)
        ctx.closePath();
        ctx.stroke();

        ctx.beginPath();
        ctx.lineWidth = 3;
        ctx.strokeStyle = 'red';
        ctx.moveTo(400, 400);
        ctx.lineTo(mx, my)
        ctx.closePath();
        ctx.stroke();


        ctx.beginPath();
        ctx.lineWidth = 3;
        ctx.strokeStyle = 'orange';
        ctx.moveTo(700, 400);
        ctx.lineTo(mx, my)
        ctx.closePath();
        ctx.stroke();

    }


    function box() {
        //先计算需要多少格子
        var num = 20;
        var n = canvas.width / num;
        console.log(canvas.width);
        var m = canvas.height / num;
        ctx.beginPath();
        ctx.strokeStyle = '#ccc';
        var x = 0;
        var y = 0;
        for (var i = 0; i < m; i++) {
            for (var j = 0; j < n; j++) {
                ctx.strokeRect(x, y, num, num);
                x += num;
            }
            y += num;
            x = 0;
        }
        ctx.stroke();
    }

10、帧频率(浏览器每次渲染的频率)

  • requestAnimationFrame
  • 帧频率实现的原理是 递归
  • 只有在展示的时候,才会执行,页面切换到后台,自动停止,降低了浏览器压力
//时间轴
var timer = 0;
function move(){
    timer++
    //计时器效果
    requestAnimationFrame(move);

    //定时器效果
     if (timer == 500) {
            alert('帧频率已停止')
            //清除帧频率
            cancelAnimationFrame(z)
        }
}
move();

11、平移

  • ctx.translate(x,y)
  • 移动的不是画出来的图形
  • 而是坐标原点 (0,0)点
  • 所以每次必须 先平移后绘制

12、保存和恢复坐标原点

  • 保存当前坐标系设置 存档
    ctx.save();
  • 移动结束之后,将移动了的坐标系 恢复
    restore 永远恢复最新一次的 存档
    ctx.restore();

13、旋转

function deg(n){ return n * (Math.PI / 180); }

  • ctx.rotate(deg(90))

14、绘制钟表

 var ctx = canvas.getContext('2d');
    canvas.width = window.innerWidth - 50;
    canvas.height = window.innerHeight - 50;

    //封装随机数
    function randNum(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    }

    //随机颜色
    function randColor() {
        var r = randNum(0, 255);
        var g = randNum(0, 255);
        var b = randNum(0, 255);
        return `rgb(${r},${g},${b})`;
    }

    //封装一个钟表类
    function Clock() {
        this.r = 200;
        //时分秒针的颜色
        this.hc = randColor();
        this.mc = randColor();
        this.sc = randColor();

    }
    //度数的方法
    function deg(n) {
        return n * (Math.PI / 180);
    }

    Clock.prototype.draw = function () {
        ctx.save()
        ctx.beginPath();
        //绘制表盘
        ctx.arc(400, 300, this.r, 0, deg(360))
        // ctx.arc(400, 300, 10, 0, deg(360))
        ctx.lineWidth = 4;
        ctx.closePath()
        ctx.stroke();

        //圆点
        ctx.beginPath();
        //绘制表盘
        ctx.fillStyle = 'red';
        ctx.fill();
        ctx.arc(400, 300, 5, 0, deg(360))
        ctx.closePath()
        ctx.stroke();

        //绘制刻度
        var long = this.r / 6;
        var middle = this.r / 9;
        var short = this.r / 12;
        // console.log(long,short);

        //先平移坐标系 到圆点
        ctx.translate(400, 300);

        //绘制表盘
        for (var i = 0; i < 60; i++) {
            ctx.save();
            ctx.rotate(deg(6 * i))
            ctx.beginPath();
            var l = 0;
            if (i % 5 == 0 && i % 15 != 0) {
                l = this.r - middle;
                ctx.lineWidth = 3;
            } else if (i % 15 == 0) {
                l = this.r - long;
                ctx.lineWidth = 4;
            } else {
                l = this.r - short;
                ctx.lineWidth = 2;
            }
            ctx.moveTo(l, 0);
            ctx.lineTo(this.r, 0);
            ctx.closePath();
            ctx.stroke()
            ctx.restore()
        }

        //计算时分秒旋转角度
        var date = new Date();
        //当前系统时间 时分秒
        var h = date.getHours();
        var m = date.getMinutes();
        var s = date.getSeconds();
        var ms = date.getUTCMilliseconds();
        var timer = date.getTime();

        /*
            1min  60000ms
            1h    3600000ms
            1d    86400000ms
            12h   43200000ms

            注意 :中国时区差八小时,所以要加上 八小时的毫秒数
        */

        //加 中国时区
        var h = (timer % 86400000 + 1000 * 60 * 60 * 8) * 720 / 86400000;
        var m = timer % 3600000 * 360 / 3600000;
        var s = timer % 60000 * 360 / 60000;
        // console.log(ms);
        ctx.rotate(deg(270))

        //绘制时针
        ctx.save();
        ctx.rotate(deg(h))
        ctx.beginPath();
        ctx.lineWidth = 5;
        ctx.strokeStyle = this.hc;
        ctx.moveTo(0, 0);
        ctx.lineTo(this.r / 2.5, 0);
        ctx.stroke();
        ctx.restore();

        //绘制分针
        ctx.save();
        ctx.rotate(deg(m))
        ctx.beginPath();
        ctx.lineWidth = 4;
        ctx.strokeStyle = this.mc;
        ctx.moveTo(0, 0);
        ctx.lineTo(this.r / 1.6, 0)
        ctx.stroke()
        ctx.restore();

        //绘制秒针
        ctx.save();
        ctx.rotate(deg(s))
        ctx.beginPath();
        ctx.lineWidth = 2
        ctx.strokeStyle = this.sc;
        ctx.moveTo(0, 0);
        ctx.lineTo(this.r / 1.25, 0)
        ctx.stroke()
        ctx.restore();

        ctx.restore();


    }

    var c1 = new Clock(); 
    function run(){
        canvas.width = canvas.width
        c1.draw();
        // console.log(c1);
        requestAnimationFrame(run)
    }
    run()

15、绘制图片

  • ctx.drawImage(img,x,y,w,h);
参数 参数代表的意思
img DOM图片对象
x 图片左上角 x 坐标
y 图片左上角 y 坐标
w 图片的宽
h 图片的高
  • 创建img对象
var img = new Image();
img.src = './shark1.png';
  • 最好是在 图片加载完毕的时候,在对图片进行加载
        ctx.drawImage(this, x,y,w,h)
    }
  • 图片的裁剪
    ctx.drawImage(img,cx,cy,cw,ch,x,y,w,h);
参数 参数代表的意思
img DOM图片对象
cx 裁剪起点x
cy 裁剪起点y
cw 裁剪宽度 以原图大小为参照物
ch 裁剪高度 以原图大小为参照物
x 图片左上角 x 坐标
y 图片左上角 y 坐标
w 图片的宽
h 图片的高

相关文章

网友评论

      本文标题:canvas基础

      本文链接:https://www.haomeiwen.com/subject/xamiprtx.html