缩放

HTML
JavaScript
<canvas id="canvas"></canvas>
window.onload = function () {
    var flag = 0;
    var scale = 0;
    var flagScale = 0;
    var canvas = document.querySelector("#canvas");

    if (canvas.getContext) {
        const ctx = canvas.getContext('2d');

        const getPixelRatio = (context) => {
            return window.devicePixelRatio || 1;
        }

        // 高清绘制
        const ratio = getPixelRatio();
        canvas.style.width = document.documentElement.clientWidth + 'px';
        canvas.style.height = document.documentElement.clientHeight + 'px';
        canvas.width = document.documentElement.clientWidth * ratio;
        canvas.height = document.documentElement.clientHeight * ratio;

        // 此处保存默认状态到样式栈中
        ctx.save();

        // -----------此处修改 样式容器 start-----------
        // 原点位置:(150,150)
        ctx.translate(150, 150);
        ctx.beginPath();
        // 偏移量为自身的一半
        ctx.fillRect(-50, -50, 100, 100);
        // -----------此处修改 样式容器 end-----------

        // 此处弹出样式栈中的默认状态,替换当前样式容器的样式
        ctx.restore();

        setInterval(function () {
            flag++;
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.save();
            ctx.translate(150, 150);
            // 每次旋转 1 度
            ctx.rotate(flag * Math.PI / 180);

            if (scale == 100) {
                flagScale = -1;
            } else if (scale == 0) {
                flagScale = 1;
            }
            scale += flagScale;
            // 缩放
            ctx.scale(scale / 50, scale / 50);

            ctx.beginPath();
            ctx.fillRect(-50, -50, 100, 100);
            ctx.restore();
        }, 10)
    }
}

表盘

HTML
JavaScript
<canvas id="clock" width="400" height="400"></canvas>
window.onload = function () {
    var clock = document.querySelector("#clock");
    if (clock.getContext) {
        var ctx = clock.getContext("2d");

        setInterval(function () {
            ctx.clearRect(0, 0, clock.width, clock.height);
            move();
        }, 1000);
        move();

        function move() {
            ctx.save();
            ctx.lineWidth = 8;
            ctx.strokeStyle = "black";
            ctx.lineCap = "round";
            ctx.translate(200, 200);
            ctx.rotate((-90 * Math.PI) / 180);
            ctx.beginPath();

            //外层空心圆盘
            ctx.save();
            ctx.strokeStyle = "#325FA2";
            ctx.lineWidth = 14;
            ctx.beginPath();
            ctx.arc(0, 0, 140, 0, (360 * Math.PI) / 180);
            ctx.stroke();
            ctx.restore();

            //时针刻度
            ctx.save();
            for (var i = 0; i < 12; i++) {
                ctx.rotate((30 * Math.PI) / 180);
                ctx.beginPath();
                ctx.moveTo(100, 0);
                ctx.lineTo(120, 0);
                ctx.stroke();
            }
            ctx.restore();

            //分针刻度
            ctx.save();
            ctx.lineWidth = 4;
            for (var i = 0; i < 60; i++) {
                ctx.rotate((6 * Math.PI) / 180);
                if ((i + 1) % 5 != 0) {
                    ctx.beginPath();
                    ctx.moveTo(117, 0);
                    ctx.lineTo(120, 0);
                    ctx.stroke();
                }
            }
            ctx.restore();

            //时针 分针 秒针 表座
            var date = new Date();
            var s = date.getSeconds();
            var m = date.getMinutes() + s / 60;
            var h = date.getHours() + m / 60;
            h = h > 12 ? h - 12 : h;

            //时针
            ctx.save();
            ctx.lineWidth = 14;
            ctx.rotate((h * 30 * Math.PI) / 180);
            ctx.beginPath();
            ctx.moveTo(-20, 0);
            ctx.lineTo(80, 0);
            ctx.stroke();
            ctx.restore();

            //分针
            ctx.save();
            ctx.lineWidth = 10;
            ctx.rotate((m * 6 * Math.PI) / 180);
            ctx.beginPath();
            ctx.moveTo(-28, 0);
            ctx.lineTo(112, 0);
            ctx.stroke();
            ctx.restore();

            //秒针
            ctx.save();
            ctx.lineWidth = 6;
            ctx.strokeStyle = "#D40000";
            ctx.fillStyle = "#D40000";
            ctx.rotate((s * 6 * Math.PI) / 180);
            ctx.beginPath();
            ctx.moveTo(-30, 0);
            ctx.lineTo(83, 0);
            ctx.stroke();

            //表座
            ctx.beginPath();
            ctx.arc(0, 0, 10, 0, (360 * Math.PI) / 180);
            ctx.fill();

            //秒头
            ctx.beginPath();
            ctx.arc(96, 0, 10, 0, (360 * Math.PI) / 180);
            ctx.stroke();
            ctx.restore();
            ctx.restore();
        }
    }
};

马赛克

HTML
JavaScript
<canvas id="canvas" height="400">您的浏览器不支持 canvas</canvas>
var canvas = document.querySelector("#canvas");
if (canvas.getContext) {
    var ctx = canvas.getContext("2d");

    const getPixelRatio = (context) => {
        return window.devicePixelRatio || 1;
    }
    const ratio = getPixelRatio();
    canvas.style.width = document.documentElement.clientWidth - 10 + 'px';
    canvas.style.height = document.documentElement.clientHeight - 10 + 'px';
    canvas.width = document.documentElement.clientWidth * ratio;
    canvas.height = document.documentElement.clientHeight * ratio;

    var img = new Image();
    img.src = "./meimei.jpg";

    img.onload = function () {
        draw(img.width / 2, img.height / 2);
    }

    function draw(width, height) {
        ctx.drawImage(img, 0, 0, width, height);

        var oldImgdata = ctx.getImageData(0, 0, width, height); // 获取原图
        var newImgdata = ctx.createImageData(width, height);

        /*  马赛克:
        		1.选取一个 x*x 的马赛克矩形
        		2.从马赛克矩形中随机抽出一个像素点的信息(rgba)
        		3.将整个马赛克矩形中的像素点信息统一调成随机抽出的那个
        */
        var size = 5; // 选取一个 5*5马赛克矩形
        for (var i = 0; i < oldImgdata.width / size; i++) {
            for (var j = 0; j < oldImgdata.height / size; j++) {
                // (i,j)  每一个马赛克矩形的坐标
                // 从马赛克矩形中随机抽出一个像素点的信息(rgba)
                // Math.random()  [0,1)
                // Math.random()*size  [0,5)
                // Math.floor(Math.random()*size) [0,4]
                var color = getPxInfo(oldImgdata,
                    i * size + Math.floor(Math.random() * size),
                    j * size + Math.floor(Math.random() * size));
                // 将整个马赛克矩形中的像素点信息统一调成随机抽出的那个
                for (var a = 0; a < size; a++) {
                    for (var b = 0; b < size; b++) {
                        setPxInfo(newImgdata, i * size + a, j * size + b, color)
                    }
                }
            }
        }
        // ctx.clearRect(0, 0, canvas .width, canvas .height);
        ctx.putImageData(newImgdata, img.width, 0);
    }

    function getPxInfo(imgdata, x, y) {
        var color = [];
        var data = imgdata.data;
        var w = imgdata.width;
        var h = imgdata.height;
        color[0] = data[(y * w + x) * 4];
        color[1] = data[(y * w + x) * 4 + 1];
        color[2] = data[(y * w + x) * 4 + 2];
        color[3] = data[(y * w + x) * 4 + 3];
        return color;
    }

    function setPxInfo(imgdata, x, y, color) {
        var data = imgdata.data;
        var w = imgdata.width;
        var h = imgdata.height;
        data[(y * w + x) * 4] = color[0];
        data[(y * w + x) * 4 + 1] = color[1];
        data[(y * w + x) * 4 + 2] = color[2];
        data[(y * w + x) * 4 + 3] = color[3];
    }
}

绘制直角坐标系

HTML
JavaScript
<canvas id="canvas" width="600" height="400">您的浏览器不支持 canvas</canvas>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const getPixelRatio = (context) => {
    return window.devicePixelRatio || 1;
}

// 高清绘制
const ratio = getPixelRatio();
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
canvas.width = canvas.width * ratio;
canvas.height = canvas.height * ratio;

// 提前设置相关属性
const ht = canvas.clientHeight;
const wd = canvas.clientWidth;
const pad = 20;
const bottomPad = 20;
const step = 100;

const drawAxis = (options) => {
    const {
        ht,
        wd,
        pad,
        bottomPad,
        step,
        ctx
    } = options;

    // 绘制坐标轴
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = 'lightblue';
    ctx.moveTo(pad, pad);
    ctx.lineTo(pad, ht * ratio - bottomPad);
    ctx.lineTo(wd * ratio - pad, ht * ratio - bottomPad);
    ctx.stroke();
    ctx.closePath();

    // 绘制 X 轴方向刻度
    ctx.beginPath();
    ctx.lineWidth = 1;
    ctx.strokeStyle = '#666';
    for (let i = 1; i < Math.floor(wd * ratio / step); i++) {
        ctx.moveTo(pad + i * step, ht * ratio - bottomPad);
        ctx.lineTo(pad + i * step, ht * ratio - bottomPad - 10);
    }
    ctx.stroke();
    ctx.closePath();

    // 绘制 Y 轴方向刻度
    ctx.beginPath();
    ctx.lineWidth = 1;
    ctx.strokeStyle = '#666';
    for (let i = 1; i < Math.floor(ht * ratio / step); i++) {
        ctx.moveTo(pad, (ht * ratio - bottomPad) - (i * step));
        ctx.lineTo(pad + 10, (ht * ratio - bottomPad) - (i * step));
    }
    ctx.stroke();
    ctx.closePath();
}

drawAxis({
    ht: ht,
    wd: wd,
    pad: pad,
    bottomPad: bottomPad,
    step: step,
    ctx: ctx
});

绘制直方图

HTML
JavaScript
<canvas id="canvas" width="600" height="400">您的浏览器不支持 canvas</canvas>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const getPixelRatio = (context) => {
    return window.devicePixelRatio || 1;
};

// 高清绘制
const ratio = getPixelRatio();
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
canvas.width = canvas.width * ratio;
canvas.height = canvas.height * ratio;

// 提前设置相关属性
const ht = canvas.clientHeight;
const wd = canvas.clientWidth;
const pad = 20;
const bottomPad = 20;
const step = 100;

const drawAxis = (options) => {
    const {
        ht,
        wd,
        pad,
        bottomPad,
        step,
        ctx
    } = options;
    // 绘制坐标轴
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = "lightblue";
    ctx.moveTo(pad, pad);
    ctx.lineTo(pad, ht * ratio - bottomPad);
    ctx.lineTo(wd * ratio - pad, ht * ratio - bottomPad);
    ctx.stroke();
    ctx.closePath();
    // 绘制 X 轴方向刻度
    ctx.beginPath();
    ctx.lineWidth = 1;
    ctx.strokeStyle = "#666";
    for (let i = 1; i < Math.floor((wd * ratio) / step); i++) {
        ctx.moveTo(pad + i * step, ht * ratio - bottomPad);
        ctx.lineTo(pad + i * step, ht * ratio - bottomPad + 10);
    }
    ctx.stroke();
    ctx.closePath();

    // 绘制 Y 轴方向刻度
    ctx.beginPath();
    ctx.lineWidth = 1;
    ctx.strokeStyle = "#666";
    for (let i = 1; i < Math.floor((ht * ratio) / step); i++) {
        ctx.moveTo(pad, ht * ratio - bottomPad - i * step);
        ctx.lineTo(pad + 10, ht * ratio - bottomPad - i * step);
    }
    ctx.stroke();
    ctx.closePath();
};

drawAxis({
    ht: ht,
    wd: wd,
    pad: pad,
    bottomPad: bottomPad,
    step: step,
    ctx: ctx,
});

// 绘制矩形:描边+填充
// ctx.beginPath()
// ctx.lineWidth = 5
// ctx.strokeStyle = 'orange'
// ctx.fillStyle = 'hotpink'
// ctx.rect(100, 100, 300, 200)
// ctx.fill()
// ctx.stroke()
// ctx.closePath()

// 绘制矩形:描边
// ctx.beginPath()
// ctx.lineWidth = 4
// ctx.strokeStyle = 'seagreen'
// ctx.strokeRect(100, 310, 300, 200)
// ctx.closePath()

// 绘制矩形:填充
// ctx.beginPath()
// ctx.fillStyle = 'skyblue'
// ctx.fillRect(410, 310, 300, 200)
// ctx.closePath()
// 绘制直方图
ctx.beginPath();
for (var i = 1; i < Math.floor((wd * ratio) / step); i++) {
    // 随机高度 [300,350)
    const height = Math.random() * 300 + 50;
    // 随机颜色 [0,255)的16进制
    ctx.fillStyle = "#" + parseInt(Math.random() * 0xffffff).toString(16);
    // x,y,宽度,高度
    ctx.fillRect(i * step, ht * ratio - bottomPad - height, 40, height);
}
ctx.closePath();

绘制圆弧

HTML
JavaScript
<canvas id="canvas" width="600" height="400">您的浏览器不支持 canvas</canvas>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const getPixelRatio = (context) => {
  return window.devicePixelRatio || 1;
};

// 高清绘制
const ratio = getPixelRatio();
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
canvas.width = canvas.width * ratio;
canvas.height = canvas.height * ratio;

// 提前设置相关属性
const ht = canvas.clientHeight;
const wd = canvas.clientWidth;
const pad = 20;
const bottomPad = 20;
const step = 100;

const drawAxis = (options) => {
  const { ht, wd, pad, bottomPad, step, ctx } = options;
  // 绘制坐标轴
  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.strokeStyle = "lightblue";
  ctx.moveTo(pad, pad);
  ctx.lineTo(pad, ht * ratio - bottomPad);
  ctx.lineTo(wd * ratio - pad, ht * ratio - bottomPad);
  ctx.stroke();
  ctx.closePath();
  // 绘制 X 轴方向刻度
  ctx.beginPath();
  ctx.lineWidth = 1;
  ctx.strokeStyle = "#666";
  for (let i = 1; i < Math.floor((wd * ratio) / step); i++) {
    ctx.moveTo(pad + i * step, ht * ratio - bottomPad);
    ctx.lineTo(pad + i * step, ht * ratio - bottomPad + 10);
  }
  ctx.stroke();
  ctx.closePath();

  // 绘制 Y 轴方向刻度
  ctx.beginPath();
  ctx.lineWidth = 1;
  ctx.strokeStyle = "#666";
  for (let i = 1; i < Math.floor((ht * ratio) / step); i++) {
    ctx.moveTo(pad, ht * ratio - bottomPad - i * step);
    ctx.lineTo(pad + 10, ht * ratio - bottomPad - i * step);
  }
  ctx.stroke();
  ctx.closePath();
};

drawAxis({
  ht: ht,
  wd: wd,
  pad: pad,
  bottomPad: bottomPad,
  step: step,
  ctx: ctx,
});

// 绘制圆环
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = "orange";
// x,y,r,开始角度,结束角度,true为逆时针绘制
ctx.arc(400, 300, 200, 0, Math.PI / 4, true);
ctx.stroke();
ctx.closePath();

// 绘制圆形
ctx.beginPath();
ctx.fillStyle = "skyblue";
ctx.moveTo(400, 300);
// x,y,r,开始角度,结束角度,true为逆时针绘制
ctx.arc(400, 300, 100, 0, -Math.PI / 2, true);
ctx.fill();
ctx.closePath();

绘制饼图

HTML
JavaScript
<canvas id="canvas" width="600" height="400">您的浏览器不支持 canvas</canvas>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const getPixelRatio = (context) => {
  return window.devicePixelRatio || 1;
};

// 高清绘制
const ratio = getPixelRatio();
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
canvas.width = canvas.width * ratio;
canvas.height = canvas.height * ratio;

// 提前设置相关属性
const ht = canvas.clientHeight;
const wd = canvas.clientWidth;
const pad = 20;
const bottomPad = 20;
const step = 100;

const drawAxis = (options) => {
  const { ht, wd, pad, bottomPad, step, ctx } = options;
  // 绘制坐标轴
  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.strokeStyle = "lightblue";
  ctx.moveTo(pad, pad);
  ctx.lineTo(pad, ht * ratio - bottomPad);
  ctx.lineTo(wd * ratio - pad, ht * ratio - bottomPad);
  ctx.stroke();
  ctx.closePath();
  // 绘制 X 轴方向刻度
  ctx.beginPath();
  ctx.lineWidth = 1;
  ctx.strokeStyle = "#666";
  for (let i = 1; i < Math.floor((wd * ratio) / step); i++) {
    ctx.moveTo(pad + i * step, ht * ratio - bottomPad);
    ctx.lineTo(pad + i * step, ht * ratio - bottomPad + 10);
  }
  ctx.stroke();
  ctx.closePath();

  // 绘制 Y 轴方向刻度
  ctx.beginPath();
  ctx.lineWidth = 1;
  ctx.strokeStyle = "#666";
  for (let i = 1; i < Math.floor((ht * ratio) / step); i++) {
    ctx.moveTo(pad, ht * ratio - bottomPad - i * step);
    ctx.lineTo(pad + 10, ht * ratio - bottomPad - i * step);
  }
  ctx.stroke();
  ctx.closePath();
};

drawAxis({
  ht: ht,
  wd: wd,
  pad: pad,
  bottomPad: bottomPad,
  step: step,
  ctx: ctx,
});

ctx.beginPath();
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = 4;
ctx.shadowColor = "#333";
ctx.fillStyle = "#5C1918";
ctx.moveTo(400, 300);
ctx.arc(400, 300, 100, -Math.PI / 2, -Math.PI / 4);
ctx.fill();
ctx.closePath();

ctx.beginPath();
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = 4;
ctx.shadowColor = "#5C1918";
ctx.fillStyle = "#A32D29";
ctx.moveTo(400, 300);
ctx.arc(400, 300, 110, -Math.PI / 4, Math.PI / 4);
ctx.fill();
ctx.closePath();

ctx.beginPath();
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = 4;
ctx.shadowColor = "#A32D29";
ctx.fillStyle = "#B9332E";
ctx.moveTo(400, 300);
ctx.arc(400, 300, 120, Math.PI / 4, (Math.PI * 5) / 8);
ctx.fill();
ctx.closePath();

ctx.beginPath();
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = 4;
ctx.shadowColor = "#B9332E";
ctx.fillStyle = "#842320";
ctx.moveTo(400, 300);
ctx.arc(400, 300, 130, (Math.PI * 5) / 8, Math.PI);
ctx.fill();
ctx.closePath();

ctx.beginPath();
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = 4;
ctx.shadowColor = "#842320";
ctx.fillStyle = "#D76662";
ctx.moveTo(400, 300);
ctx.arc(400, 300, 140, Math.PI, (Math.PI * 3) / 2);
ctx.fill();
ctx.closePath();

碰撞检测

HTML
JavaScript
<canvas id="canvas">您的浏览器不支持 canvas</canvas>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const getPixelRatio = (context) => {
    return window.devicePixelRatio || 1;
}

// 高清绘制
const ratio = getPixelRatio();
canvas.style.width = document.documentElement.clientWidth + 'px';
canvas.style.height = document.documentElement.clientHeight + 'px';
canvas.width = document.documentElement.clientWidth * ratio;
canvas.height = document.documentElement.clientHeight * ratio;

// 绘制小球
const drawCircle = (x, y, r) => {
    ctx.beginPath();
    ctx.fillStyle = 'orange';
    ctx.arc(x, y, r, 0, Math.PI * 2);
    ctx.fill();
    ctx.closePath();
}

// 配置属性
const wd = canvas.clientWidth * ratio;
const ht = canvas.clientHeight * ratio;
let x = y = 100; // 初始坐标
const r = 40;
let xSpeed = 6;
let ySpeed = 4;

drawCircle(x, y, r);

setInterval(() => {
    ctx.clearRect(0, 0, wd, ht); // 清空画布
    // 小球超出左右的边界,xSpeed偏移量为取反,向相反方向移动
    if (x - r <= 0 || x + r >= wd) {
        xSpeed = -xSpeed;
    }
    // 小球超出上下的边界,ySpeed偏移量取反,向相反方向移动
    if (y - r <= 0 || y + r >= ht) {
        ySpeed = -ySpeed;
    }
    // 小球向右下运动
    x += xSpeed;
    y += ySpeed;
    drawCircle(x, y, r);
}, 20);

弹性球

HTML
JavaScript
<canvas id="canvas">您的浏览器不支持 canvas</canvas>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const getPixelRatio = (context) => {
    return window.devicePixelRatio || 1;
}

// 高清绘制
const ratio = getPixelRatio()
canvas.style.width = document.documentElement.clientWidth + 'px';
canvas.style.height = document.documentElement.clientHeight + 'px';
canvas.width = document.documentElement.clientWidth * ratio;
canvas.height = document.documentElement.clientHeight * ratio;

class Ball {
    constructor(canvas) {
        this.canvas = canvas;
        this.ctx = this.canvas.getContext('2d');
        this.wd = this.canvas.clientWidth * ratio;
        this.ht = this.canvas.clientHeight * ratio;
        // 随机数 半径:【40,50)
        this.r = Math.random() * 40 + 10;
        // 随机数 x轴:【this.wd - (this.r * 2),this.wd - (this.r * 2)+ this.r)
        this.x = Math.random() * (this.wd - (this.r * 2)) + this.r;
        // 随机数 y轴:【this.ht - (this.r * 2),this.ht - (this.r * 2)+ this.r)
        this.y = Math.random() * (this.ht - (this.r * 2)) + this.r;
        // 随机数 颜色:【0,235)16进制
        this.color = '#' + parseInt(Math.random() * 0xFFFFFF).toString(16);
        // 随机数 x偏移:【4,10)
        this.xSpeed = Math.random() * 4 + 6;
        // 随机数 y偏移:【6,10)
        this.ySpeed = Math.random() * 6 + 4;
        this.init();
    }
    init() {
        this.run();
        this.draw();
    }
    draw() {
        this.ctx.beginPath();
        this.ctx.fillStyle = this.color;
        this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
        this.ctx.fill();
        this.ctx.closePath();
    }
    run() {
        if (this.x - this.r <= 0 || this.x + this.r >= this.wd) {
            this.xSpeed = -this.xSpeed;
        }
        if (this.y - this.r <= 0 || this.y + this.r >= this.ht) {
            this.ySpeed = -this.ySpeed;
        }
        this.x += this.xSpeed;
        this.y += this.ySpeed;
    }
}

let ballArr = [];
for (let i = 0; i < 100; i++) {
    let ball = new Ball(canvas);
    ballArr.push(ball);
}

// 动画
setInterval(() => {
    ctx.clearRect(0, 0, canvas.clientWidth * ratio, canvas.clientHeight * ratio);
    for (let i = 0; i < ballArr.length; i++) {
        let ball = ballArr[i];
        ball.init();
    }
}, 15);

绘制关系图

HTML
JavaScript
<canvas id="canvas">您的浏览器不支持 canvas</canvas>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const getPixelRatio = (context) => {
    return window.devicePixelRatio || 1;
}

// 高清绘制
const ratio = getPixelRatio();
canvas.style.width = document.documentElement.clientWidth + 'px';
canvas.style.height = document.documentElement.clientHeight + 'px';
canvas.width = document.documentElement.clientWidth * ratio;
canvas.height = document.documentElement.clientHeight * ratio;

class Ball {
    constructor(options) {
        this.canvas = options.canvas;
        this.text = options.title;
        this.ctx = this.canvas.getContext('2d');
        this.wd = this.canvas.clientWidth * ratio;
        this.ht = this.canvas.clientHeight * ratio;
        this.r = Math.random() * 40 + 10;
        this.x = Math.random() * (this.wd - (this.r * 2)) + this.r;
        this.y = Math.random() * (this.ht - (this.r * 2)) + this.r;
        this.color = '#' + parseInt(Math.random() * 0xFFFFFF).toString(16);
        this.xSpeed = Math.random() * 4 + 6;
        this.ySpeed = Math.random() * 6 + 4;
        this.init();
    }
    init() {
        this.run();
        this.draw();
    }
    draw() {
        this.drawCircle();
        this.drawText(this.text, this.x, this.y + this.r + 10);
    }
    // 绘制圆形
    drawCircle() {
        this.ctx.beginPath();
        this.ctx.fillStyle = this.color;
        this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
        this.ctx.fill();
        this.ctx.closePath();
    }
    // 绘制文字
    drawText(text, x, y) {
        this.ctx.font = 'normal 20px 微软雅黑';
        this.ctx.textAlign = 'center';
        this.ctx.textBaseline = 'middle';
        this.ctx.fillText(text, x, y);
    }
    // 绘制线条
    drawLine(startX, startY, endX, endY, color) {
        this.ctx.beginPath();
        this.ctx.lineWidth = 1;
        this.ctx.strokeStyle = color || '#666';
        this.ctx.moveTo(startX, startY);
        this.ctx.lineTo(endX, endY);
        this.ctx.stroke();
        this.ctx.closePath();
    }
    run() {
        if (this.x - this.r <= 0 || this.x + this.r >= this.wd) {
            this.xSpeed = -this.xSpeed;
        }
        if (this.y - this.r <= 0 || this.y + this.r >= this.ht) {
            this.ySpeed = -this.ySpeed;
        }
        this.x += this.xSpeed;
        this.y += this.ySpeed;
    }
}

let ballArr = [];
let titleArr = ['Vue', 'Webpack', 'React', 'Angular', 'Python', 'Nodejs', 'eCharts', 'Next'];

for (let i = 0; i < 8; i++) {
    let ball = new Ball({
        canvas: canvas,
        title: titleArr[i]
    })
    ballArr.push(ball);

    // 连线
    for (let j = 0; j < i; j++) {
        let preBall = ballArr[j];
        ball.drawLine(ball.x, ball.y, preBall.x, preBall.y);
    }
}

// 做动画
setInterval(() => {
    ctx.clearRect(0, 0, canvas.clientWidth * ratio + 10, canvas.clientHeight * ratio + 10);
    // 1.先绘制连线
    for (let i = 0; i < ballArr.length; i++) {
        let ball = ballArr[i];
        // 连线
        for (let j = 0; j < i; j++) {
            let preBall = ballArr[j];
            ball.drawLine(ball.x, ball.y, preBall.x, preBall.y, ball.color);
        }
    }
    // 2.再绘制小球(小球会在线的上面绘制)
    for (let i = 0; i < ballArr.length; i++) {
        let ball = ballArr[i];
        ball.init();
    }
}, 15);
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 缩放
  2. 2. 表盘
  3. 3. 马赛克
  4. 4. 绘制直角坐标系
  5. 5. 绘制直方图
  6. 6. 绘制圆弧
  7. 7. 绘制饼图
  8. 8. 碰撞检测
  9. 9. 弹性球
  10. 10. 绘制关系图