【canvas】了解canvas,并实现会议预定记录钟表盘、页面水印

  初识canvas

Canvas 有什么用

Canvas 允许使用直线、曲线、矩形、圆形等基本图形绘制出复杂的图形

Canvas 可以加载图像,并进行各种处理,如裁剪、缩放、旋转等操作

Canvas 可以通过 JavaScript 控制,所以你可以利用帧动画原理,在画布上连续绘制图形,从而实现流畅的动画效果。

Canvas 提供了强大的绘图能力,使得将复杂的数据以图表或图形的方式展示变得更加容易。你可以绘制柱状图、折线图、饼状图等,以直观的方式展示数据

canvas 绘图基本步骤:

  • 建立canvas 画布
 <canvas id="canvas"></canvas>
  • 通过canvas 画布获取上下文对象

上下文对象可以理解为画笔,画布建好了,然后再准备好画笔 是不是就可以开画拉

const canvas = document.querySelector('#canvas')
canvas.height = window.innerHeight
canvas.width = window.innerWidth
const ctx = canvas.getContext(‘2d’)
  • 设置画笔颜色与图形形状
ctx.fillStyle = 'red'
ctx.fillRect(0, 0, 500, 500)

就完成一个最简单的绘制:

使用用canvas绘制一个机器人头像:

    <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>

再识canvas

 W3C 坐标系

canvas中的路径

beginPath(): 这个方法用于开始一个新的路径,相当于重置了路径的起点和样式。

closePath(): 这个方法将路径的最后一个点与路径起点连接,形成封闭的图形。

moveTo(50, 100):起点坐标 (x, y)

lineTo(200, 50):下一个点的坐标 (x, y)

stroke(): 这个方法用于描边路径,将上面的坐标用一条线连接起来

fill(): 这个方法用于填充路径所包围的区域,采用当前路径样式的设置(例如填充的颜色)

样式 

lineWidth:线的粗细

strokeStyle:线的颜色

lineCap:线帽:默认: butt; 圆形: round; 方形: square

详细可看:Canvas 从入门到劝朋友放弃(图解版)✨ - 知乎

 效果图:

创建一个动态的时间

        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')

这段代码的作用是将分钟数和秒数转换为字符串,并在字符串长度不足2位时,在字符串前面填充0 

 有会议的时间段 绘制选中状态

    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();

绘制时间刻度,固定刻度显示时间,其他显示原点

    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();

完整代码: 

<!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>

动态添加水印 

<!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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/167188.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Latex学习

二 实例 1. \Delta_{w}\frac{\partial l}{\partial w_{i1}}weight:\frac{\partial l}{\partial x_{i1}} 效果如下 其中对于希腊字母的大小写来说&#xff0c;可以参考&#xff1a; 【LaTeX 语法】字母表示 ( 大写、小写、异体 希腊字母 | 粗体字母 | 花体字母 )_latex字母_韩…

大白话解释什么类加载机制

大家好&#xff0c;我是伍六七。 今天我们来聊聊一个 Java 面试必考基础题目&#xff1a;类加载机制和双亲委派机制。 Java 类的加载机制是 Java 虚拟机&#xff08;JVM&#xff09;中类加载&#xff08;Class Loading&#xff09;和链接&#xff08;Linking&#xff09;的过…

RT-DETR优化改进:SEAM、MultiSEAM分割物与物相互遮挡、分割小目标性能

🚀🚀🚀本文改进:SEAM、MultiSEAM分割物体与物体相互遮挡性能 🚀🚀🚀SEAM、MultiSEAM分割物与物相互遮挡、分割小目标性能 🚀🚀🚀RT-DETR改进创新专栏:http://t.csdnimg.cn/vuQTz 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; RT-DETR模型创新…

【cpolar】搭建我的世界Java版服务器,公网远程联机

&#x1f3a5; 个人主页&#xff1a;深鱼~&#x1f525;收录专栏&#xff1a;cpolar&#x1f304;欢迎 &#x1f44d;点赞✍评论⭐收藏 目录 前言&#xff1a; 1. 搭建我的世界服务器 1.1 服务器安装java环境 1.2 配置服务端 2. 测试局域网联机 3. 公网远程联机 3.1 安…

数字IC前端学习笔记:时钟切换电路

相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 有些时候我们需要在系统运行时切换系统时钟&#xff0c;最简单的方法就是使用一个MUX&#xff08;数据选择器&#xff09;选择输出的时钟&#xff0c;如下代码片所…

【C++】​——多态性与模板(其一)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

Kotlin学习——hello kotlin 函数function 变量 类 + 泛型 + 继承

Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复用代码&#xff0c;以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…

MySQL数据库入门到大牛_基础_09_子查询(子查询分类方法;单行子查询,多行子查询;相关子查询)

前面的第三章到第八章中&#xff0c;我们讲的是查询&#xff0c;查询的基本结构已经进行了介绍&#xff0c;聚合函数学习完后已经介绍了查询语句的完整的执行流程。 子查询指一个查询语句嵌套在另一个查询语句内部的查询&#xff0c;这个特性从MySQL 4.1开始引入。本章也是查询…

【开源】基于JAVA的校园二手交易系统

项目编号&#xff1a; S 009 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S009&#xff0c;文末获取源码。} 项目编号&#xff1a;S009&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 二手商品档案管理模…

卫生纸标准及鉴别

一、标准分类及含义 &#xff08;1&#xff09;标准分类 ①GB——国家强制标准&#xff08;即最低标准&#xff09; ②GB/T——国家推荐标准 ③QB——轻工行业标准 ④QB/T——轻工行业推荐标准 &#xff08;2&#xff09;含义 ①国家标准是指国家标准化主管机构批准发布的。…

element中el-upload上传文件去掉文件列表

<template><el-uploadref"upload"action"/api/upload":limit"1"accept.xlsx:on-success"uploadSuccess":on-error"uploadError"><el-button size"small" type"primary">点击上传<…

传输层协议 - UDP(User Datagrm Protocol)

文章目录&#xff1a; 传输层再谈端口号端口号划分知名端口号&#xff08;Well-Know Port Number&#xff09;netstat 命令iostat 命令pidof UDP 协议UDP 协议格式UDP 协议的特点面向数据报UDP 的缓冲区UDP 使用注意事项UDP 协议的应用基于 UDP 的应用层协议 在 DDoS 攻击中如何…

【数字图像处理】Gamma 变换

在数字图像处理中&#xff0c;Gamma 变换是一种重要的灰度变换方法&#xff0c;可以用于图像增强与 Gamma 校正。本文主要介绍数字图像 Gamma 变换的基本原理&#xff0c;并记录在紫光同创 PGL22G FPGA 平台的布署与实现过程。 目录 1. Gamma 变换原理 2. FPGA 布署与实现 2…

◢Django 分页+搜索

1、搜索数据 从数据库中获取数据&#xff0c;并进行筛选&#xff0c;xx__contains q作为条件&#xff0c;查找的是xx列中有q的所有数据条 当有多个筛选条件时&#xff0c;将条件变成一个字典&#xff0c;传入 **字典 &#xff0c;ORM会自行翻译并查找。 筛选电话号码这一列…

2021年3月青少年软件编程(Python)等级考试试卷(一级)

2021年3月青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;一级&#xff09; 分数&#xff1a;100.00 题数&#xff1a;37一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09;二、判断题&#xff08;共10题&#xff0c;每题…

.NET 8 Video教程介绍(开篇)

教程简介 本文将简单描述视频网站教程&#xff0c;视频网站是一个类似于腾讯视频一样的网站&#xff0c;视频资源用户自己上传&#xff0c;然后提供友好的界面查看视频和搜索视频&#xff0c;并且提供管理页面对于视频进行管理&#xff0c;我们将使用Blazor作为前端&#xff0…

uniapp中实现圆形进度条的方式有哪些?

前言 在uniapp开发小程序或者apk时&#xff0c;页面需要用到一个圆形进度条&#xff08;带文字和百分比的&#xff09;&#xff0c;自己也自定义过一个,但是有一点小问题&#xff0c;咱先展示如何引入插件市场的在介绍自定义的&#xff01;一共四种&#xff0c;但是你需要考虑自…

PPT基础:表格

目录 表格基本功能底纹框线单元格表格美化 表格基本功能 底纹 所在位置&#xff1a;插入图表>>>表设计>>>底纹 底纹&#xff1a;相当于每个单元格的“颜色填充”如何用表格拆分图片 &#xff08;1&#xff09;生成一个表格>>>插入一张图片>>…

高效开发与设计:提效Spring应用的运行效率和生产力 | 京东云技术团队

引言 现状和背景 Spring框架是广泛使用的Java开发框架之一&#xff0c;它提供了强大的功能和灵活性&#xff0c;但在大型应用中&#xff0c;由于Spring框架的复杂性和依赖关系&#xff0c;应用的启动时间和性能可能会受到影响。这可能导致开发过程中的迟缓和开发效率低下。优…

Transformer笔记

Transformer encoder-decoder架构 Encoder&#xff1a;将输入序列转换为一个连续向量空间中的表示。Encoder通常是一个循环神经网络&#xff08;RNN&#xff09;或者卷积神经网络&#xff08;CNN&#xff09;&#xff0c;通过对输入序列中的每个元素进行编码&#xff0c;得到…