canvas学习

Canvas API 提供了一个通过 JavaScript 和 HTML 的 元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。

Canvas 的基本用法

<canvas> 元素

<canvas id="tutorial" width="150" height="150"></canvas>
 function draw() {var canvas = document.getElementById("canvas");if (canvas.getContext) {var ctx = canvas.getContext("2d");ctx.fillStyle = "rgb(200,0,0)";ctx.fillRect(10, 10, 55, 50);ctx.fillStyle = "rgba(0, 0, 200, 0.5)";ctx.fillRect(30, 30, 55, 50);}}

注意:这里不要使用css设置canvas的宽高,不然会导致图像是扭曲的。

canvas绘制图形

canvas的坐标系:

canvas的坐标系不同于数学中的坐标系,是以左上角为原点的坐标系。
在这里插入图片描述

绘制直线线
<canvasid="c"width="300"height="200"style="border: 1px solid #ccc;"
></canvas><script>// 2、获取 canvas 对象const cnv = document.getElementById('c')// 3、获取 canvas 上下文环境对象const cxt = cnv.getContext('2d')// 4、绘制图形cxt.moveTo(100, 100) // 起点坐标 (x, y)cxt.lineTo(200, 100) // 终点坐标 (x, y)cxt.stroke() // 将起点和终点连接起来
</script>
  • 绘制直线需要的三个方法:
    1. moveTo(x1, y1):起点坐标 (x, y)
    2. lineTo(x2, y2):下一个点的坐标 (x, y)
    3. stroke():将所有坐标用一条线连起来
  • 直线样式
    • lineWidth:线的粗细
    • strokeStyle:线的颜色
    • lineCap:线帽:默认: butt; 圆形: round; 方形: square
      新开路径
  • beginPath()
    如果不想相互污染,需要做2件事:
    • 使用 beginPath() 方法,重新开一个路径
    • 设置新线段的样式(必须项)
  • closePath() 闭合路径
矩形

fillRect(x, y, width, height)
绘制一个填充的矩形

strokeRect(x, y, width, height)
绘制一个矩形的边框

clearRect(x, y, width, height)
清除指定矩形区域,让清除部分完全透明。

或者 rect(x, y, width, height) 配合fill()和stroke() 使用

圆形弧

arc(x, y, radius, startAngle, endAngle, anticlockwise)

这里是引用arc() 函数中表示角的单位是弧度,不是角度。角度与弧度的 js 表达式:
弧度=(Math.PI/180)*角度

弧线

arcTo(cx, cy, x2, y2, radius) 根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。
在这里插入图片描述

贝塞尔曲线

在这里插入图片描述

// 绘制一个聊天框
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d');ctx.moveTo(200,300)
ctx.quadraticCurveTo(150,300,150,200);
ctx.quadraticCurveTo(150,100,300,100);
ctx.quadraticCurveTo(450,100,450,200);
ctx.quadraticCurveTo(450,300,250,300);
ctx.quadraticCurveTo(250,350,150,350);
ctx.quadraticCurveTo(250,350,200,300);ctx.stroke()
三次贝塞尔曲线

在这里插入图片描述

// 绘制爱心
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d');ctx.moveTo(300,200)
ctx.bezierCurveTo(350,150,400,200,300,250)
ctx.bezierCurveTo(200,200,250,150,300,200)ctx.closePath()
ctx.stroke()
Path2D

保存一个路径对象,可以重复使用

const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d');var heartPath = new Path2D();
heartPath.moveTo(300,200)
heartPath.bezierCurveTo(350,150,400,200,300,250)
heartPath.bezierCurveTo(200,200,250,150,300,200)ctx.stroke(heartPath)
ctx.fill(heartPath)

样式和色彩

颜色设置

strokeStyle = ‘red’
全局透明度: ctx.globalAlpha = 0.5

渐变
  • 线性渐变
    createLinearGradient(x0: number, y0: number, x1: number, y1: number)

QQ录屏20240614093835

const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')let index = 0
function render() {ctx.clearRect(0, 0, 600, 400)index += 0.01if (index >= 1) {index = 0}let linearGradient = ctx.createLinearGradient(100, 200, 400, 500)linearGradient.addColorStop(0, 'red')linearGradient.addColorStop(index, '#ffcccc')linearGradient.addColorStop(1, 'blue')ctx.fillStyle = linearGradientctx.fillRect(100, 200, 300, 300)requestAnimationFrame(render)
}
requestAnimationFrame(render)

扩充:如何使用requestAnimationFrame

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
requestAnimationFrame的出现解决了这个问题。它使用浏览器的刷新率作为参考,确保动画帧的更新在每一帧之间的间隔是最佳的,从而实现更加流畅和自然的动画效果。

function animate() {// 执行动画逻辑timer=requestAnimationFrame(animate);
}// 启动动画
let timer=requestAnimationFrame(animate);//取消动画
  • 径向渐变
    createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number)
    在这里插入图片描述
// 案例实现一个看似3d的球体(有高光)const cnv = document.getElementById('c')const ctx = cnv.getContext('2d')let radialGradient = ctx.createRadialGradient(250, 150, 10, 300, 200, 100)radialGradient.addColorStop(0, '#e3e5ff')radialGradient.addColorStop(1, 'blue') ctx.fillStyle = radialGradientctx.arc(300, 200, 100, 0, (Math.PI / 180) * 360)ctx.fill()
  • 锥形渐变
    createConicGradient(startAngle: number, x: number, y: number)
    在这里插入图片描述
let conicGradient = ctx.createConicGradient(0,300,200);
conicGradient.addColorStop(0,'red');
conicGradient.addColorStop(0.5,'yellow');
conicGradient.addColorStop(1,'blue');
印章样式填充
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
var img = new Image();
img.src= '../image/fs.png';
img.onload = function () {var pattern = ctx.createPattern(img,'repeat-y');ctx.fillStyle = pattern;ctx.fillRect(0,0,600,400)
}
阴影
  • shadowOffsetX = float
  • shadowOffsetY = float
    shadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0。
  • shadowBlur = float
    shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0。
  • shadowColor = color
    shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。
function draw() {var ctx = document.getElementById("canvas").getContext("2d");ctx.shadowOffsetX = 2;ctx.shadowOffsetY = 2;ctx.shadowBlur = 2;ctx.shadowColor = "rgba(0, 0, 0, 0.5)";ctx.font = "20px Times New Roman";ctx.fillStyle = "Black";ctx.fillText("Sample String", 5, 30);
}
线条类型 LineStyle
属性和方法说明可设置的类型
lineWidth = value设置线条宽度。
lineCap = type设置线条末端样式。butt,round 和 square。默认是 butt。
lineJoin = type设定线条与线条间接合处的样式。round、bevel 和 miter。默认是 miter。
miterLimit = value限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。
getLineDash()返回一个包含当前虚线样式,长度为非负偶数的数组。
setLineDash(segments)设置当前虚线样式,方法接受一个数组,来指定线段与间隙的交替。ctx.setLineDash([4, 2]);
lineDashOffset = value设置虚线样式的起始偏移量。

绘制文本

fillText(text, x, y [, maxWidth])
strokeText(text, x, y [, maxWidth])

function draw() {var ctx = document.getElementById("canvas").getContext("2d");ctx.font = "48px serif";ctx.fillText("Hello world", 10, 50);
}

文本样式

  • font = value
    当前我们用来绘制文本的样式。这个字符串使用和 CSS font 属性相同的语法。默认的字体是 10px sans-serif。

  • textAlign = value
    文本对齐选项。可选的值包括: start,end, left, right or center. 默认值是 start。

  • textBaseline = value
    基线对齐选项。可选的值包括:top, hanging,middle, alphabetic, ideographic , bottom 。默认值是 alphabetic。

  • direction = value
    文本方向。可能的值包括:ltr, rtl, inherit。默认值是 inherit。

预测量文本宽度

measureText()

使用图像

  • drawImage(image, x, y)
    其中 image 是 image 或者 canvas 对象,x 和 y 是其在目标 canvas 里的起始坐标。
  • 缩放 drawImage(image, x, y, width, height)
    width 和 height,这两个参数用来控制 当向 canvas 画入时应该缩放的大小
  • 切片 drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
    其他 8 个参数,前 4 个是定义图像源的切片位置和大小,后 4 个则是定义切片的目标显示位置和大小。
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
const image = new Image()
image.src = './image/flower.png'
image.width = 20
image.height = 10
image.onload = () => {// drawImage(image, dx, dy, dw, dh)ctx.drawImage(image, 30, 30,300,200)// drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)// ctx.drawImage(image, 0, 0, 200, 200, 100, 100, 100, 100)
}

处理像素

  • ctx.getImageData(sx, sy, sw, sh);
    返回值
    一个ImageData 对象,包含 canvas 给定的矩形图像数据。
    每4个值表示一个像素点的rgba值,所以处理像素时每次+=4
    在这里插入图片描述
    右下角变成黑白的了
const context = document.getElementById('c')
const ctx = context.getContext('2d')
const img = new Image() // 创建图片对象
img.src = './image/flower.png' // 加载本地图片// 图片加载完成后在执行其他操作
img.onload = () => {// 渲染图片ctx.drawImage(img, 0, 0)// 获取图片信息const imageData = ctx.getImageData(0, 0, img.width, img.height)console.log('imageData: ', imageData)for (let i = 0; i < imageData.data.length; i += 4) {// 添加上透明度// imageData.data[i + 3] = imageData.data[i + 3] * 0.5// 变成黑白的图片let avg = (imageData.data[i]+imageData.data[i+1]+imageData.data[i+2])/3imageData.data[i] = avg;imageData.data[i+1] = avg;imageData.data[i+2] = avg;}ctx.putImageData(imageData, 0, 0,200,200,200,200)
}

变形 Transformations

状态的保存和恢复

  • save()
    保存画布 (canvas) 的所有状态

  • restore()
    save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。
    在这里插入图片描述

const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')ctx.fillStyle = 'red'
ctx.fillRect(0, 0, 100, 100)
ctx.save()
ctx.fillStyle = 'blue'
ctx.fillRect(100, 100, 100, 100)
ctx.save()
ctx.fillStyle = 'yellow'
ctx.fillRect(200, 200, 100, 100)
ctx.save()
ctx.fillStyle = 'green'
ctx.fillRect(300, 300, 100, 100)ctx.restore()
ctx.fillRect(400, 400, 100, 100)

最后保存了 黄色,restore之后再绘制,就能画出黄色的矩形。

变形

  • 平移 translate(x, y)

  • 旋转 rotate(angle)
    旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate方法。

  • 缩放 scale(x, y)

  • 变形 transform(a, b, c, d, e, f)

    • 这个方法是将当前的变形矩阵乘上一个基于自身参数的矩阵,如下面的矩阵所示:
      
    • 在这里插入图片描述
      • a (m11)
        水平方向的缩放
      • b(m12)
        竖直方向的倾斜偏移
      • c(m21)
        水平方向的倾斜偏移
      • d(m22)
        竖直方向的缩放
      • e(dx)
        水平方向的移动
      • f(dy)
        竖直方向的移动
  • setTransform()

transform VS 而setTransform
transform() 每次执行都会参考上一次变换后的结果,而setTransform() 每次调用都会基于最原始是状态进行变换。

组合 Compositing

globalCompositeOperation = type
这个属性设定了在画新图形时采用的遮盖策略,其值是一个标识 12 种遮盖方式的字符串。

裁切

clip()
将当前正在构建的路径转换为当前的裁剪路径。

案例

在这里插入图片描述

绘图板
参考代码 :https://gitee.com/zpp2000131/canvas-study/blob/master/canvas%E8%A7%86%E9%A2%91%E8%AF%BE/1-14%20%E7%94%BB%E5%9B%BE%E6%9D%BF.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Python]Anaconda相关命令

环境操作相关命令 查看所有环境 conda env list创建环境 conda create --name cahttts python3.10激活环境 conda activate cahttts安装依赖文件 pip install -r requirements.txt查看GPU型号 nvidia-smi -LGPU 0: NVIDIA A10 (UUID: GPU-9f1fc9cf-582a-25ac-849c-2f77343…

ESD与EOS区别

最近小白在做项目时&#xff0c;被一个实习生问道了&#xff0c;关于EOS与ESD区别。说实话&#xff0c;以前专注于测试debug的我&#xff0c;在回答对方时&#xff0c;并没法做到太全面的解答。于是乎&#xff0c;借助周内的空闲时间&#xff0c;小白还是简单学习总结了一番。 …

Harbor镜像中心搭建

文章目录 Harbor镜像中心搭建前置条件下载Harbor创建CA证书配置Harbor开始启动地址映射访问配置本地登录配置外部虚拟机访问 Harbor镜像中心搭建 Harbor是一个镜像中心&#xff0c;我们所熟知的DockerHub就是一个镜像中心&#xff0c;我们可以把我们打包的镜像放在镜像中心中供…

关于Java

关于Java Java语言关于并发JVM调优工具写在最后 Java语言 Java语言作为当下主流开发语言&#xff0c;其面向对象的开发模式以及一次编译多次运行&#xff0c;跨平台运行以及自动的垃圾回收机制可以说是给开发者节省了很大的时间用于逻辑功能的开发&#xff0c;那么在开发过程中…

【Linux】pycharmgit相关操作

目录 1. git安装配置2. 相关内容3. pycharm连接远程仓库3.1 配置3.2 clone远程仓库3.3 本地仓库上传远程 4. 分支管理4.1 更新代码4.2 新建分支4.3 分支合并4.4 代码比对 5. 版本管理6. 命令行操作6.1 配置git6.2 基础操作6.3 分支操作 1. git安装配置 下载链接&#xff1a;官…

07--Zabbix监控告警

前言&#xff1a;和普米一样运维必会的技能&#xff0c;这里总结一下&#xff0c;适用范围非常广泛&#xff0c;有图形化界面&#xff0c;能帮助运维极快确定问题所在&#xff0c;这里记录下概念和基础操作。 1、zabbix简介 Zabbix是一个基于 Web 界面的企业级开源解决方案&a…

【C++】C++入门的杂碎知识点

思维导图大纲&#xff1a; namespac命名空间 什么是namespace命名空间namespace命名空间有什么用 什么是命名空间 namespace命名空间是一种域&#xff0c;它可以将内部的成员隔绝起来。举个例子&#xff0c;我们都知道有全局变量和局部变量&#xff0c;全局变量存在于全局域…

SQLAlchemy:filter()和filter_by()的微妙差异

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 在Python编程中&#xff0c;SQLAlchemy是一个强大的ORM&#xff08;对象关系映射&#xff09;工具&#xff0c;它允许使用Python代码来操作数据库。然而&#xff0c;对于新手来说&#xff0c;SQLAlchemy中的一些函数…

mybatis-plus使用拦截器实现sql完整打印

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 在使用mybatis-plus&#xff08;mybatis&#xff09;的时候&#xff0c;往往需要…

英伟达开源最强通用模型Nemotron-4 340B:开启AI合成数据新纪元

【震撼发布】 英伟达最新力作——Nemotron-4 340B,一个拥有3400亿参数的超级通用模型,震撼登场!这不仅是技术的一大飞跃,更是AI领域的一次革命性突破! 【性能卓越】 Nemotron-4 340B以其卓越的性能超越了Llama-3,专为合成数据而生。它将为医疗健康、金融、制造、零售等行…

Studio One 6.6.2 for Mac怎么激活,有Studio One 6激活码吗?

如果您是一名音乐制作人&#xff0c;您是否曾经为了寻找一个合适的音频工作站而苦恼过&#xff1f;Studio One 6 for Mac是一款非常适合您的MacBook的音频工作站。它可以帮助您轻松地录制、编辑、混音和发布您的音乐作品。 Studio One 6.6.2 for Mac具有直观的界面和强大的功能…

C++初学者指南第一步---1. C++开发环境设置

C初学者指南第一步—1. C开发环境设置 目录 C初学者指南第一步---1. C开发环境设置1.1 工具1.1.1 代码编辑器和IDE1.1.2 Windows1.1.3 命令行界面 1.2 编译器1.2.1 gcc/g (支持Linux/Windows/MacOSX)1.2.2 clang/clang (支持Linux/Windows/MacOS)1.2.3 Microsoft Visual Studio…

《面向对象程序设计》第3章 类与对象(判断、选择、填空)-练习

1-1 常量对象可以使用常量成员函数。 T F | 参考答案 答案 T 2分 1-2 在定义常量成员函数和声明常量成员函数时都应该使用const关键字。 T F | 参考答案 答案 T 2分 1-3 对象间赋值将调用拷贝构造函数。 T F | 参考答案 答案 F 2分 1-4 对象数组生命期…

奇思妙想-可以通过图片闻见味道的设计

奇思妙想-可以通过图片闻见味道的设计 偷闲半日享清闲&#xff0c;炭火烧烤乐无边。肉串飘香引客至&#xff0c;笑语欢声绕云间。人生难得几回醉&#xff0c;且把烦恼抛九天。今宵共饮开怀酒&#xff0c;改日再战新篇章。周四的傍晚&#xff0c;难得的闲暇时光让我与几位挚友相…

PAT B1026. 程序运行时间

题目描述 要获得一个C语言程序的运行时间,常用的方法是调用头文件time.h,其中提供了clock(&#xff09;函数,可以捕捉从程序开始运行到clock()被调用时所耗费的时间。这个时间单位是clock tick,即“时钟打点”。同时还有一个常数CLK_TCK——给出了机器时钟每秒所走的时钟打点数…

继电器的保护二极管如何选择

继电器在实际应用中&#xff0c;通常都会使用三极管或MOS管控制&#xff0c;其最基本的应用电路如图&#xff1a; 那为什么要在继电器线圈上并联一个二极管呢&#xff1f;我们可以看看没有并联二极管时电路会出现什么情况&#xff0c;我们使用下图所示的电路参数仿真一下&#…

食家巷助力“甘肃乡村振兴,百强主播·打call 甘味”活动

2024年&#xff0c;甘肃省“商务乡村振兴”促消费暨“百强主播打call 甘味”活动在天水市龙城广场盛大启动。 活动现场&#xff0c;来自甘肃省 14 个市州的农特产品展台琳琅满目&#xff0c;让人目不暇接。此次活动中&#xff0c;各企业带来了多款深受消费者喜爱的产品&a…

【AI实践】Dify调用本地和在线模型服务

背景 Ollama可以本地部署模型&#xff0c;如何集成私有数据、如何外部应用程序对接&#xff0c;因此需要有一个应用开发框架 Dify功能介绍 欢迎使用 Dify | 中文 | Dify 下文将把dify部署在PC上&#xff0c;windows环境&#xff1b; 安装部署 安装dify及docker jacobJacobs…

【图解IO与Netty系列】Netty源码解析——服务端启动

Netty源码解析——服务端启动 Netty案例复习Netty原理复习Netty服务端启动源码解析bind(int)initAndRegister()channelFactory.newChannel()init(channel)config().group().register(channel)startThread()run()register0(ChannelPromise promise)doBind0(...) 今天我们一起来学…

ssm162基于SSM的药房药品采购集中管理系统的设计与实现+vue

药房药品采购集中管理系统的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对药房药品采购信息管理混乱&…