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.xdnf.cn/news/1451909.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【计算机网络仿真实验-实验2.4、2.5】静态路由、动态路由(RIP)

实验2.4 静态路由 1. 实验拓扑图 注意&#xff1a;有些同学不知道两个路由器之间如何用串行DCE(红线)相接&#xff0c;只需要为路由器分别增加新的HWIC-2T接口卡就好了 不知道如何添加物理接口的&#xff0c;可以查看本人计算机网络专栏中【计算机网络仿真实验——实验准备】…

Java面向对象-抽象类和抽象方法

Java面向对象-抽象类和抽象方法 1、代码案例展示2、抽象类和抽象方法的关系&#xff1a; 1、代码案例展示 1、在一个类中会有一类方法&#xff0c;无需重写&#xff0c;直接使用 2、在一个类中会有一类方法&#xff0c;会对这个方法进行重写 3、一个方法的方法体去掉&#xff…

QT打包(windows linux)封包 完整图文版

目录 简介: 一. for windows 1.首先下载组件 2.开始构建Release版本. 3.然后点击构建 4.在文件夹内直接点击exe文件,会报下面的错误,因为缺少dll连接; 5.需要把这个exe单独复制到一个文件夹内, 6.先cd到单独exe所在的文件夹; cd 文件路径 7.然后运行 windeployqt 文…

Linux安装Tomcat和Nginx

目录 前言一、系统环境二、Tomcat安装步骤Step1 安装JDK环境Step2 安装Tomcat 三、Nginx安装步骤四、测试4.1 测试Tomcat4.2 测试Nginx 总结 前言 本篇文章介绍如何在Linux上安装Tomcat web服务器。 一、系统环境 虚拟机版本&#xff1a;VMware Workstation 15 ProLinux镜像…

【AI基础】第六步:纯天然保姆喂饭级-安装并运行qwen2-7b

整体步骤类似于 【AI基础】第五步&#xff1a;纯天然保姆喂饭级-安装并运行chatglm3-6b-CSDN博客。 此系列文章列表&#xff1a; 【AI基础】概览 【AI基础】第一步&#xff1a;安装python开发环境-windows篇_下载安装ai环境python 【AI基础】第一步&#xff1a;安装python开发环…

观成科技:基于深度学习技术的APT加密流量检测与分类检测方案

一、前言 近年来APT攻击的案例屡见不鲜&#xff0c;给国家、企业以及个人的利益造成极大威胁。随着流量加密技术的不断成熟&#xff0c;许多APT组织倾向于将流量加密后进行传输&#xff0c;从而保护传输内容。由于加密流量的实际载荷已被加密&#xff0c;故采用原始的流量检测…

GO RACE 测试在低版本GCC上报错误 exit status 0xc0000139

windows机器环境&#xff0c;go程序使用race定位时一运行就报错&#xff0c;写了个example如&#xff1a; 能看到加了race之后就不行了&#xff0c; 搜了一下&#xff0c;git上有个issue&#xff1a; runtime: Race detector causes exit status 0xc0000139 on Windows 11 wi…

除了ps我们还可以使用什么方法来处理图片?

照片模糊了怎么办?当照片拍的不好时&#xff0c;容易出现模糊的状况&#xff0c;其实照片模糊了可以通过后期软件加工处理&#xff0c;但是ps操作很复杂&#xff0c;对我们有一定的技术基础要求&#xff0c;那么有没有别的图片处理工具呢&#xff1f; ps它的图片处理功能较为全…

俄罗斯Yandex推广投放如何开户?Yandex广告开户和代运营推广流程详解_俄罗斯_受众_搜索引擎

在俄罗斯进行Yandex广告推广是一种有效的在线营销方式&#xff0c;特别是针对俄罗斯市场。Yandex是俄罗斯最受欢迎的搜索引擎&#xff0c;类似于Google在全球范围内的地位。以下是通过Yandex广告推广的一般步骤&#xff0c;以及如何通过上海上弦进行广告开户和代运营。 1. Yan…

【计算机视觉】人脸算法之图像处理基础知识(一)

图像处理基础知识&#xff08;一&#xff09; 1.图像的构成 图像的构成可以包括以下几方面知识&#xff1a; 1.像素&#xff1a;图像的基本单位&#xff0c;是图像中的一个点。每个像素都有特定的位置和色彩值。在数字图像中&#xff0c;像素的颜色通常由红、绿、蓝&#xf…

基于QT5.12.7的VTK8.2下的VS2015 X64源码编译以及测试

有一段时间没更新博客了&#xff0c;最近在考虑使用VTK作为软件的后处理显示&#xff0c;相比于OSG&#xff0c;VTK在后处理上集成了很多优秀的算法&#xff0c;使用起来比较方便&#xff0c;而且后处理一般不需要太多的交互&#xff0c;所以VTK是一个不错的选择。 之前对VTK了…

彩色打印一般多少钱一张

彩色打印的价格因多种因素而异&#xff0c;包括打印设备的品牌、纸张质量、打印数量以及打印服务提供商的定价策略等。以下是根据参考文章提供的信息&#xff0c;对彩色打印价格的一般性归纳和描述&#xff1a; 设备品牌与型号&#xff1a; 不同品牌和型号的彩色激光打印机价…

Uni-App中的u-datetime-picker时间选择器Demo

目录 前言Demo 前言 对于网页端的推荐阅读&#xff1a;【ElementUI】详细分析DatePicker 日期选择器 事情起因是两个时间选择器同步了&#xff0c;本身是从后端慢慢步入全栈&#xff0c;对此将这个知识点从实战进行提炼 通过Demo进行总结 Demo 用于选择日期和时间的组件&a…

TFT屏幕波形显示

REVIEW 关于TFT显示屏&#xff0c;之前已经做过彩条显示&#xff1a; TFT显示屏驱动_tft驱动-CSDN博客 关于ROM IP核&#xff0c;以及coe文件生成&#xff1a; FPGA寄存器 Vivado IP核_fpga寄存器资源-CSDN博客 1. TFT屏幕ROM显示正弦波 ①生成coe文件 %% sin-cos wave dat…

【C语言】14. qsort 的底层与模拟实现

一、回调函数 回调函数就是⼀个通过函数指针调用的函数。 把函数的指针&#xff08;地址&#xff09;作为参数传递给另⼀个函数&#xff0c;当这个指针被用来调用其所指向的函数时&#xff0c;被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用&#xff0c;而是…

手把手教你入门vue+springboot开发(三)--登录功能后端

文章目录 前言一、redis安装二、后端代码1.修改application.yml文件2.增加utils文件3.增加Result类4.修改UserController类5.修改UserMapper类6.修改UserService和UserServiceImpl类7.增加LoginInterceptor类8.增加WebConfig类9.修改pom.xml文件 前言 前两篇我们用vuespringbo…

《站在2024年的十字路口:计算机专业是否仍是高考生的明智之选?》

文章目录 每日一句正能量前言行业竞争现状行业饱和度和竞争激烈程度[^3^]新兴技术的影响[^3^]人才需求的变化[^3^]行业创新动态如何保持竞争力 专业与个人的匹配度判断专业所需的技术能力专业核心课程对学生的要求个人兴趣和性格特点专业对口的职业发展要求实践和经验个人价值观…

从大型语言模型到大脑语言理解:探索话语理解的神经机制

随着科技的飞速发展&#xff0c;人工智能领域取得了令人瞩目的成就。在这其中&#xff0c;大型语言模型&#xff08;LLMs&#xff09;以其卓越的性能和广泛的应用前景&#xff0c;成为了当前研究的热点。然而&#xff0c;尽管LLMs在文本生成、语言翻译等领域展现出了惊人的能力…

怎么图片转excel表格?推荐三个方法

怎么图片转excel表格&#xff1f;在信息化高速发展的今天&#xff0c;图片转Excel表格的需求日益凸显&#xff0c;尤其是在职场办公中&#xff0c;这一需求更是显得尤为迫切。为了满足广大用户的需求&#xff0c;市面上涌现出了众多图片转Excel的软件。今天&#xff0c;就为大家…

依赖自动装配

黑马程序员SSM框架 文章目录 1、依赖自动装配2、依赖自动装配的特征 1、依赖自动装配 IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配自动装配方式 按类型&#xff08;常用&#xff09;按名称按构造方法不启用自动装配 配置中使用bean标签auto…