[canvas] Understand canvas and implement meeting reservation record clock face and page watermark

  First introduction to canvas

What is Canvas used for?

Canvas allows you to draw complex graphics using basic graphics such as lines, curves, rectangles, circles, etc.

Canvas can load images and perform various processing, such as cropping, scaling, rotation, etc.

Canvas can be controlled through JavaScript, so you can use the frame animation principle to continuously draw graphics on the canvas to achieve smooth animation effects.

Canvas provides powerful drawing capabilities, making it easier to display complex data in charts or graphs. You can draw bar charts, line charts, pie charts, etc. to display data in an intuitive way

Basic steps for canvas drawing:

  • Create canvas canvas
 <canvas id="canvas"></canvas>
  • Get the context object through canvas canvas

The context object can be understood as a brush . Once the canvas is created, and then the brush is ready, can you start painting?

const canvas = document.querySelector('#canvas')
canvas.height = window.innerHeight
canvas.width = window.innerWidth
const ctx = canvas.getContext(‘2d’)
  • Set brush color and graphic shape
ctx.fillStyle = 'red'
ctx.fillRect(0, 0, 500, 500)

Just complete the simplest drawing:

Use canvas to draw a robot avatar:

    <canvas id="robot" width="200" height="200"></canvas>

    <script>
        const canvas = document.getElementById('robot');
        const ctx = canvas.getContext('2d');

        //fillStyle=>设置填充区域的颜色
        ctx.fillStyle = 'gray';
        //strokeStyle=>设置描边的颜色
        ctx.strokeStyle = 'black';
        //lineWidth=>设置描边的宽度
        ctx.lineWidth = 2;

        // 在Canvas绘图中,每个新的路径(line、rect、arc等)都会自动连接到之前绘制的路径上。如果希望绘制一个新的路径,就需要使用beginPath()方法来开启一个新路径
        ctx.beginPath();
        // 以 (x, y) 为圆心,半径为 r,从 startAngle 开始,到 endAngle 结束,画一个弧形
        ctx.arc(100, 100, 50, 0, Math.PI * 2);
        console.log(Math.PI) //3.1415926
        //对路径进行填充。
        ctx.fill();
        //对路径进行描边。
        ctx.stroke();

        // 画眼睛
        ctx.fillStyle = 'white';
        ctx.beginPath();
        ctx.arc(75, 70, 10, 0, Math.PI * 2);
        ctx.arc(125, 70, 10, 0, Math.PI * 2);
        ctx.fill();

        // 画瞳孔
        ctx.fillStyle = 'black';
        ctx.beginPath();
        ctx.arc(75, 70, 3, 0, Math.PI * 2);
        ctx.arc(125, 70, 3, 0, Math.PI * 2);
        ctx.fill();

        // 画嘴巴
        ctx.beginPath();
        ctx.moveTo(70, 130);
        ctx.bezierCurveTo(70, 140, 130, 140, 130, 130);
        ctx.stroke();

        // 画腮红
        ctx.fillStyle = 'pink';
        ctx.beginPath();
        ctx.arc(60, 110, 10, 0, Math.PI * 2);
        ctx.arc(140, 110, 10, 0, Math.PI * 2);
        ctx.fill();
    </script>

Re-recognizing canvas

 W3C coordinate system

path in canvas

beginPath(): This method is used to start a new path, which is equivalent to resetting the starting point and style of the path.

closePath(): This method connects the last point of the path to the starting point of the path to form a closed shape.

moveTo(50, 100): Starting point coordinates (x, y)

lineTo(200, 50): Coordinates of the next point (x, y)

stroke(): This method is used to stroke the path and connect the above coordinates with a line.

fill(): This method is used to fill the area enclosed by the path, using the settings of the current path style (such as the fill color)

style 

lineWidth: line thickness

strokeStyle: line color

lineCap: Wire Cap: Default:  butt; Round:  round; Square: square

详细可看:Canvas from getting started to convincing friends to give up (illustrated version) ✨ - Zhihu

 Rendering:

Create a dynamic time

        function updateTime() {
            var now = new Date();
            var today = now.toDateString();
            var time = now.toLocaleTimeString();
            var hours = now.getHours();
            var minutes = now.getMinutes();
            var seconds = now.getSeconds();

            var minutesString = minutes.toString().padStart(2, '0')
            var secondsString = seconds.toString().padStart(2, '0');
            var timeString = hours + ":" + minutesString + ":" + secondsString;
            $("h1").text(timeString);
        }
        updateTime()
        setInterval(updateTime, 1000);

var minutesString = minutes.toString().padStart(2, '0')

What this code does is convert minutes and seconds into strings, and pad 0s in front of the strings if the string length is less than 2 digits. 

 Draw the selected state during the time period when there is a meeting

    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    // 线条宽度、线条末端样式、阴影模糊度
    ctx.lineWidth = 15;
    ctx.lineCap = "round";
    ctx.shadowBlur = 15;
    // 将角度值转换为弧度值
    function degToRad(degree) {
        var factor = Math.PI / 180;
        return degree * factor;
    }

    // 转换数值 360度转换成24份,并修正从0点开始
    function convertNum(num) {
        return degToRad(num * 15 - 90);
    }
    function draw() {
        ctx.strokeStyle = "#42dfbf";
        ctx.shadowColor = '#95e0d1';

        // 创建了一个径向渐变对象
        gradient = ctx.createRadialGradient(100, 100, 50, 100, 100, 150);
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, 400, 400);

        // 0点到3点
        // beginPath 开始一个新的绘图路径
        ctx.beginPath();
        // arc 方法绘制了一个弧线
        ctx.arc(200, 200, 170, convertNum(0), convertNum(4));
        // stroke 方法绘制出刻度线
        ctx.stroke();

        // 7到8
        ctx.beginPath();
        ctx.arc(200, 200, 170, convertNum(7), convertNum(8));
        ctx.stroke();

        // 14-16
        ctx.beginPath();
        ctx.arc(200, 200, 170, convertNum(14), convertNum(16));
        ctx.stroke();
    }
    draw();

Draw a time scale, a fixed scale displays the time, and others display the origin

    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    // 线条宽度、线条末端样式、阴影模糊度
    ctx.lineWidth = 15;
    ctx.lineCap = "round";
    ctx.shadowBlur = 15;
    // 将角度值转换为弧度值
    function degToRad(degree) {
        var factor = Math.PI / 180;
        return degree * factor;
    }
    // 绘制表盘刻度线
    function drawClockFace() {
        ctx.shadowColor = '#40b7c6';
        ctx.strokeStyle = "#90bdc3";
        for (var i = 0; i < 24; i++) {
            var angle = degToRad(i * 15 - 90);
            ctx.beginPath();
            ctx.arc(200, 200, 170, angle, angle + degToRad(0.5));

            if (i % 3 === 0) {
                // 绘制文本
                ctx.save();
                ctx.translate(200, 200); // 将坐标原点移动到表盘中心
                ctx.rotate(angle + Math.PI / 2); // 旋转文本使其与刻度对齐
                ctx.textAlign = "center";
                ctx.font = "bold 20px Arial";
                ctx.fillStyle = "#fff";
                ctx.fillText(i.toString(), 0, -163); // 在指定位置绘制文本
                ctx.restore();
            } else {
                // 绘制圆点
                ctx.stroke();
            }
        }
    }
    drawClockFace();

Complete code: 

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>
<style>
    body {
        background-color: gray;
    }

    .content {
        position: relative;
        display: flex;
        justify-content: center;
    }

    h1 {
        font-family: helvetica;
        font-size: 2.5rem;
        color: black;
        position: absolute;
        top: 38%;
        z-index: -1;
    }

    #canvas {
        display: block;
        margin: 5vh auto;
        border-radius: 50%;
        box-shadow: 0 5px 14px black;
    }
</style>

<body>
    <div class="content">
        <h1></h1>
        <canvas id="canvas" width="400" height="400"></canvas>
    </div>
</body>
<script src="https://cdn.staticfile.org/jquery/3.7.1/jquery.js"></script>
<script>
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    // 线条宽度、线条末端样式、阴影模糊度
    ctx.lineWidth = 15;
    ctx.lineCap = "round";
    ctx.shadowBlur = 15;
    // 将角度值转换为弧度值
    function degToRad(degree) {
        var factor = Math.PI / 180;
        return degree * factor;
    }
    // 绘制表盘刻度线
    function drawClockFace() {
        ctx.shadowColor = '#40b7c6';
        ctx.strokeStyle = "#90bdc3";
        for (var i = 0; i < 24; i++) {
            var angle = degToRad(i * 15 - 90);
            ctx.beginPath();
            ctx.arc(200, 200, 170, angle, angle + degToRad(0.5));

            if (i % 3 === 0) {
                // 绘制文本
                ctx.save();
                ctx.translate(200, 200); // 将坐标原点移动到表盘中心
                ctx.rotate(angle + Math.PI / 2); // 旋转文本使其与刻度对齐
                ctx.textAlign = "center";
                ctx.font = "bold 20px Arial";
                ctx.fillStyle = "#fff";
                ctx.fillText(i.toString(), 0, -163); // 在指定位置绘制文本
                ctx.restore();
            } else {
                // 绘制圆点
                ctx.stroke();
            }
        }
    }

    draw();
    drawClockFace();


    // 转换数值 360度转换成24份,并修正从0点开始
    function convertNum(num) {
        return degToRad(num * 15 - 90);
    }
    function draw() {
        ctx.strokeStyle = "#42dfbf";
        ctx.shadowColor = '#95e0d1';
        function updateTime() {
            var now = new Date();
            var today = now.toDateString();
            var time = now.toLocaleTimeString();
            var hours = now.getHours();
            var minutes = now.getMinutes();
            var seconds = now.getSeconds();

            var minutesString = minutes.toString().padStart(2, '0')
            var secondsString = seconds.toString().padStart(2, '0');
            var timeString = hours + ":" + minutesString + ":" + secondsString;
            $("h1").text(timeString);
        }
        updateTime()
        setInterval(updateTime, 1000);

        // 创建了一个径向渐变对象
        gradient = ctx.createRadialGradient(100, 100, 50, 100, 100, 150);
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, 400, 400);

        // 0点到3点
        // beginPath 开始一个新的绘图路径
        ctx.beginPath();
        // arc 方法绘制了一个弧线
        ctx.arc(200, 200, 170, convertNum(0), convertNum(4));
        // stroke 方法绘制出刻度线
        ctx.stroke();

        // 7到8
        ctx.beginPath();
        ctx.arc(200, 200, 170, convertNum(7), convertNum(8));
        ctx.stroke();

        // 14-16
        ctx.beginPath();
        ctx.arc(200, 200, 170, convertNum(14), convertNum(16));
        ctx.stroke();
    }
</script>

</html>

Add watermark dynamically 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="content" style="width: 400px;height: 400px;background-color: antiquewhite;">
        你好
    </div>
    <script>
        /**
     * 动态添加水印
     * @param {String} str 水印内容
     */
        function addWaterMark(str) {
            const body = document.getElementById('content');
            const canvas = document.createElement('canvas');

            body.appendChild(canvas);

            canvas.width = 200;
            canvas.height = 200;
            canvas.style.display = 'none';
            var cans = canvas.getContext('2d');
            cans.rotate((-20 * Math.PI) / 180);
            cans.font = '12px Microsoft JhengHei';
            cans.fillStyle = 'rgba(17, 17, 17, 1)';
            cans.textAlign = 'left';
            cans.textBaseline = 'Middle';
            // 表示在 <canvas> 上绘制一段文本,起始位置为左上角的 (30, 105),并且文本的最大宽度限制为 200。水印的文本内容将会从 (30, 105) 开始,并在指定的最大宽度内绘制
            cans.fillText(str, 0, 130, 200);
            body.style.backgroundImage = 'url(' + canvas.toDataURL('image/png') + ')';
        }
        addWaterMark("阿晨出品 必然精品")
    </script>
</body>

</html>

Additional effects:

Dynamic ring effect

Rendering:

 

Complete code:

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>
<style>
    body {
        background-color: gray;
    }

    .content {
        position: relative;
        display: flex;
        justify-content: center;
    }

    h1 {
        font-family: helvetica;
        font-size: 2.5rem;
        color: black;
        position: absolute;
        top: 38%;
        z-index: -1;
    }

    #canvas {
        display: block;
        margin: 5vh auto;
        border-radius: 50%;
        box-shadow: 0 5px 14px black;
    }
</style>

<body>
    <div class="content">
        <h1></h1>
        <canvas id="canvas" width="200" height="200"></canvas>
    </div>
</body>
<script src="https://cdn.staticfile.org/jquery/3.7.1/jquery.js"></script>
<script>
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    // 线条宽度、线条末端样式、阴影模糊度
    ctx.lineWidth = 10;
    ctx.lineCap = "round";
    // ctx.shadowBlur = 10;
    // 将百分比转换为弧度值
    function percentToRad(percent) {
        var factor = Math.PI / 50;
        return percent * factor;
    }
    let endAngle1 = -25
    let endAngle2 = -25
    let endAngle3 = -25
    function draw(num1, num2, num3) {
        // 清除画布
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        if (endAngle1 < num1) {
            endAngle1 += speed
        }
        if (endAngle2 < num2) {
            endAngle2 += speed
        }
        if (endAngle3 < num3) {
            endAngle3 += speed
        }
        ctx.strokeStyle = "#ededef";
        ctx.shadowColor = '#ededef';
        ctx.beginPath();
        ctx.arc(100, 100, 80, 0, Math.PI * 2);
        ctx.stroke();

        ctx.strokeStyle = "#42dfbf";
        ctx.shadowColor = '#42dfbf';
        ctx.beginPath();
        // 圆心坐标为(200, 200),半径为170,起始角度为0度,结束角度为23度
        ctx.arc(100, 100, 80, percentToRad(-25), percentToRad(endAngle1));
        ctx.stroke();

        ctx.strokeStyle = "#40b5c6";
        ctx.shadowColor = '#40b5c6';
        ctx.beginPath();
        // 圆心坐标为(200, 200),半径为170,起始角度为0度,结束角度为23度
        ctx.arc(100, 100, 65, percentToRad(-25), percentToRad(endAngle2));
        ctx.stroke();

        ctx.strokeStyle = "#f3c239";
        ctx.shadowColor = '#f3c239';
        ctx.beginPath();
        // 圆心坐标为(200, 200),半径为170,起始角度为0度,结束角度为23度
        ctx.arc(100, 100, 50, percentToRad(-25), percentToRad(endAngle3));
        ctx.stroke();
    }
    // draw()
    // 设置绘制速度,单位为弧度/帧
    var speed = percentToRad(10);

    // 启动动画
    var animation = setInterval(function () {
        draw(10, 20, 30);
    }, 30);

</script>

</html>

 

Guess you like

Origin blog.csdn.net/weixin_52479803/article/details/134504888