canvas的基本用法

ops/2025/2/1 19:46:43/

canvas

canvas元素简介

1.是个container元素<canvas width='100' height='100'></canvas>,有开闭标签

2.有且只有widthheight两个attribute,不需要写单位

canvas的基本使用

const canvasEl = document.getElementById('canvas01')
const ctx = canvasEl.getContext('2d')   //ctx包含了各种属性和画图的函数
ctx.fillStyle='#d55'
ctx.fillRect(200,20,200,50)   //填充矩形
ctx.strokeStyle='#55d'
ctx.lineWidth=10
ctx.strokeRect(100,60,-20,-50)   //描边矩形
ctx.lineWidth=2
ctx.strokeStyle='#5dd'
ctx.strokeRect(150,100,-20,-50)

canvas路径绘制

画多线段

ctx.beginPath()
ctx.moveTo(100,100)//用moveTo将画笔移动到下一个开始绘制的点,和之前绘制的尾部不连接
ctx.lineCap='round'
ctx.lineJoin='bevel'
ctx.lineWidth=5
ctx.lineTo(150,100)
ctx.lineTo(200,120)
ctx.moveTo(220,100)
ctx.lineTo(220,150)
ctx.stroke()
ctx.closePath()

线条的属性:

1.ctx.lineCap:线条端点样式,可以设置'round'|'butt'|'square' 圆角|截断|方角

2.ctx.lineJoin: 线条连接处样式 'round'|'bevel'|'miter' 圆角|倒角|默认

画三角形描边(stroke):需要用到ctx.closePath()

ctx.beginPath()
ctx.moveTo(200,200)
ctx.lineTo(200,250)
ctx.lineTo(300,100)
ctx.stroke()
ctx.closePath()

画三角填充(fill):可以没有ctx.closePath()

ctx.beginPath()
ctx.moveTo(200,200)
ctx.lineTo(200,250)
ctx.lineTo(300,100)
ctx.fill()
ctx.closePath()

画弧

CanvasPath.arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean)

ctx.beginPath()
ctx.arc(300,300,20,0,Math.PI*2,false)
ctx.moveTo(370,350)
ctx.arc(350,350,20,0,Math.PI,false)
ctx.stroke()
ctx.closePath()

画矩形

ctx.beginPath()
ctx.fillStyle='#e00'
ctx.rect(20,300,20,50)
ctx.fill()
ctx.closePath()ctx.beginPath()
ctx.lineStyle='#e00'
ctx.lineWidth=3
ctx.rect(20,400,50,80)
ctx.stroke()
ctx.closePath()

canvas绘制文字

ctx.font = "50px 仿宋"
ctx.textAlign = 'center'
ctx.textBaseline = 'bottom'
ctx.fillStyle = '#d00'
ctx.fillText("哈哈哈", 250, 90,200);
ctx.font = "20px 黑体"
ctx.strokeStyle = '#d000dd'
ctx.strokeText("嘿嘿嘿", 250, 200,200);

canvas绘制图片

1.ctx.drawImage(image, dx, dy)

2.ctx.drawImage(image, dx, dy, dWidth, dHeight)

3.ctx.drawImage(image,sx,sy,swidth,sheight,dx,dy,dwidth,dheight)

s开头的是裁剪坐标,d开头的是绘制坐标

示例:

const dogImage = new Image(200,200)
dogImage.src = './dog.jpg'
dogImage.onload = function(){ctx.drawImage(dogImage,10,10,300,300,0,0,100,100)
}

补充:

canvas绘制的图都是栅格图

canvas绘制状态

保存绘图状态,在进行复杂的绘图以后,可以随时返回当前的状态,主要是保存某个绘图时期的字体,颜色,线条宽度,坐标变换等状态,这样不用重复设置绘图样式,被保存的绘图状态会被推入一个栈中,每次调用restore()就会弹出到栈最顶层的状态,也就是让canvas的各类属性设置回到上一次保存的设置

ctx.save()

ctx.restore()

ctx.fillRect(0,0,100,100)
ctx.save()
ctx.translate(10,150)
ctx.fillRect(0,0,100,100)
ctx.restore()

canvas变形

1.ctx.translate(dx,dy) 平移画布

2.ctx.rotate(deg) 旋转画布

3.ctx.scale(sx,sy)缩放画布,只能在原坐标系统缩放

ctx.save()
ctx.beginPath()
ctx.translate(100,150)
ctx.scale(2, 2)
ctx.rotate(45)
ctx.fillRect(-50,-100,100,100)
ctx.restore()

canvas动画

1.通过setInterval,setTimeoutrequestAnimationFrame三种方法来控制时间

2.画一帧的步骤

1.ctx.clearRect()
2.ctx.save()
3.绘制动画图形
4.ctx.resotre()

示例:绘制表盘

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.container{position: relative;width: 500px;height: 500px;border-radius: 5px;margin: 50px auto;box-shadow: 1px 1px 10px 5px #d5d5d5;}canvas{position: absolute;top: 0;left: 0;}</style>
</head>
<body><div class="container"><canvas id="canvas01" width="500" height="500"></canvas></div><script>const canvasEl = document.getElementById('canvas01')const ctx = canvasEl.getContext('2d')function drawClock(pHours,pMinutes,pSeconds){let oldHours = pHours <= 12?(pHours/12)*60-15:((pHours-12)/12)*60-15let minutes = pMinutes - 15let seconds = pSeconds -15let hours = oldHours+Math.round((pMinutes/12))ctx.clearRect(0,0,500,500)ctx.save()//表盘ctx.beginPath()ctx.arc(250,250,105,0,Math.PI*2,false)ctx.fillStyle='#fff'ctx.fill()ctx.closePath()//表外框线条ctx.beginPath()ctx.strokeStyle= '#000'ctx.lineWidth = 5ctx.moveTo(356,250)ctx.arc(250,250,106,0,Math.PI*2,false)ctx.stroke()ctx.closePath()//表内框线ctx.beginPath()ctx.strokeStyle= '#000'ctx.lineWidth = 1ctx.moveTo(351,250)ctx.arc(250,250,101,0,Math.PI*2,false)ctx.stroke()ctx.closePath()//刻度线ctx.beginPath()ctx.lineWidth=1for(let j = 0;j<60;j++ ){ctx.save()ctx.translate(250,250)ctx.rotate(Math.PI*2/60*j)if(j%5===0){ctx.moveTo(95,0)ctx.lineTo(100,0)}else if(j%15===0){ctx.moveTo(90,0)ctx.lineTo(100,0)}else{ctx.moveTo(98,0)ctx.lineTo(100,0)}ctx.restore()}ctx.stroke()ctx.closePath()//刻度数字const numbers = [3,4,5,6,7,8,9,10,11,0,1,2]ctx.save()ctx.translate(247,254)for(let i = 0; i<numbers.length;i++){let x = Math.cos(Math.PI*2/12*i)*83let y = Math.sin(Math.PI*2/12*i)*83ctx.fillStyle='#000'ctx.textAlign = 'left'ctx.fillText(numbers[i],x,y)}ctx.restore()//秒针ctx.beginPath()ctx.strokeStyle= '#d33'ctx.lineCap = 'round'ctx.lineWidth = 1ctx.moveTo(250,250)ctx.arc(250,250,96,Math.PI*2/60*seconds,Math.PI*2/60*seconds,true)ctx.stroke()ctx.closePath()//分针ctx.beginPath()ctx.strokeStyle= '#111'ctx.lineCap = 'round'ctx.lineWidth = 2ctx.moveTo(250,250)ctx.arc(250,250,80,Math.PI*2/60*minutes,Math.PI*2/60*minutes,true)ctx.stroke()ctx.closePath()//时针ctx.beginPath()ctx.strokeStyle= '#222'ctx.lineCap = 'round'ctx.lineWidth = 4ctx.moveTo(250,250)ctx.arc(250,250,50,Math.PI*2/60*hours,Math.PI*2/60*hours,true)ctx.stroke()ctx.closePath()//表心ctx.beginPath()ctx.moveTo(250,250)ctx.fillStyle= '#fff'ctx.arc(250,250,1,0,Math.PI*2)ctx.fill()ctx.closePath()}let lastSecond = -1;function playAnimation(){const date = new Date()const seconds = date.getSeconds()const minutes = date.getMinutes()const hours = date.getHours()if(lastSecond !== seconds){drawClock(hours,minutes,seconds)lastSecond = seconds}requestAnimationFrame(()=>{playAnimation()})}playAnimation()</script>
</body>
</html>

http://www.ppmy.cn/ops/154838.html

相关文章

软件工程经济学-日常作业+大作业

目录 一、作业1 作业内容 解答 二、作业2 作业内容 解答 三、作业3 作业内容 解答 四、大作业 作业内容 解答 1.建立层次结构模型 (1)目标层 (2)准则层 (3)方案层 2.构造判断矩阵 (1)准则层判断矩阵 (2)方案层判断矩阵 3.层次单排序及其一致性检验 代码 …

HTTPS 协议原理

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; HTTPS 是什么&#x1f98b; 定义 二&#xff1a;&#x1f525; 概念准备&#x1f98b; 什么是"加密"&#x1f98b; 为什么要加密&#x1f98b; …

小程序-基础加强

前言 这一节把基础加强讲完 1. 导入需要用到的小程序项目 2. 初步安装和使用vant组件库 这里还可以扫描二维码 其中步骤四没什么用 右键选择最后一个 在开始之前&#xff0c;我们的项目根目录得有package.json 没有的话&#xff0c;我们就初始化一个 但是我们没有npm这个…

【8】思科IOS AP升级操作

1.概述 本文主要针对思科AP的升级操作进行记录,思科的AP目前主要分为IOS和COS AP,IOS AP是我们常见的AP3502/AP1602/AP2702等等型号的AP,而COS AP是AP2802/3802等型号的AP。当然这里所指的都是一些室内AP,如AP1572等室外AP也同样适用。本文先对IOS AP的升级操作进行总结,…

设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用

文章目录 概述1. 核心思想2. 结构3. 示例代码4. 优点5. 缺点6. 适用场景7. 案例&#xff1a;模板方法模式在数据处理中的应用案例背景UML搭建抽象基类 - 数据处理的 “总指挥”子类定制 - 适配不同供应商供应商 A 的数据处理器供应商 B 的数据处理器 在业务代码中整合运用 8. 总…

Redis实现,分布式Session共享

依赖 不指定版本防止冲突 直接用版本依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.4</version><relativePath/> <!-- lookup parent from …

Spring Boot 后端跨域解决方案:解锁前后端通信的障碍

随着前后端分离架构的普及&#xff0c;跨域资源共享&#xff08;Cross-Origin Resource Sharing, CORS&#xff09;问题成为了许多开发者必须面对的一个挑战。当Web浏览器尝试从一个源加载资源到另一个不同的源时&#xff0c;出于安全考虑&#xff0c;它会实施同源策略&#xf…

【Linux】日志设计模式与实现

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;Linux系统编程 这里将会不定期更新有关Linux的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 文章目…