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

2023-11-20 14:04

本文主要是介绍【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到8ctx.beginPath();ctx.arc(200, 200, 170, convertNum(7), convertNum(8));ctx.stroke();// 14-16ctx.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到8ctx.beginPath();ctx.arc(200, 200, 170, convertNum(7), convertNum(8));ctx.stroke();// 14-16ctx.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>

这篇关于【canvas】了解canvas,并实现会议预定记录钟表盘、页面水印的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/395141

相关文章

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、