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的坐标系不同于数学中的坐标系,是以左上角为原点的坐标系。
在这里插入图片描述

绘制直线线
<canvas
  id="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.01
    if (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 = linearGradient
    ctx.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 = radialGradient
 ctx.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])/3
        imageData.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

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

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

相关文章

基数和基数转换

目录 一、定义&#xff1a; 二、各个进制&#xff1a; 1、二进制&#xff1a; 2、八进制&#xff1a; 3、十进制&#xff1a; 4、十六进制&#xff1a; 三、基数转换&#xff1a; 1、各类基数转十进制&#xff1a; 二转十&#xff1a; 八转十&#xff1a; 十六转八&a…

1. 人工智能中的相关术语的概述

1.1 机器学习的概念&#xff1a;机器学习是指从有限的观测数据中学习出具有一般性的规律&#xff0c;并利用这些规律对未知数据进行预测的方法。机器学习可以分为监督学习&#xff0c;无监督学习和强化学习。 传统的机器学习主要关注于如何学习一个预测模型。一般需要首先将数据…

【教程】学会用PS做海报(教你如何套模板+模板资源),以研电赛展架为例

网上的视频都是好几十个小时&#xff0c;看起来很耗费时间&#xff0c;其实做海报&#xff0c;展架只用到其中的一部分功能&#xff0c;本文会进行讲解 这里写目录标题 去年研电赛做的展架1.首先打开比赛给的展板照片&#xff0c;按照研电赛要求设置大小2.调出ps的几个窗口&am…

苹果发布云AI系统;谷歌警告0day漏洞被利用;微软紧急推迟 AI 召回功能;劫持活动瞄准 K8s 集群 | 网安周报0614

苹果发布私有云计算&#xff0c;开创 AI 处理新时代&#xff0c;隐私保护再升级&#xff01; 苹果宣布推出一个名为“私有云计算”&#xff08;PCC&#xff09;的“开创性云智能系统”&#xff0c;该系统专为在云中以保护隐私的方式处理人工智能&#xff08;AI&#xff09;任务…

【数学竞赛】阿里巴巴全球数学竞赛(附2019-2024年试题+答案)

阿里巴巴全球数学竞赛对所有年龄、背景和职业的个人开放。迄今为止&#xff0c;最年长的参赛者超过80岁&#xff0c;最年轻的仅8岁。 2024年共计801名选手参加比赛&#xff0c;涟水这中专的姜萍获得了全球12名的出众成绩&#xff0c;港中大也抛出了橄榄枝。 初赛注重享受数学之…

【Linux内核】伙伴系统算法和slab分配器(1)

【Linux内核】伙伴系统算法和slab分配器&#xff08;1&#xff09; 目录 【Linux内核】伙伴系统算法和slab分配器&#xff08;1&#xff09;伙伴系统&#xff08;buddy&#xff09;算法伙伴系统算法基本原理内存申请内存回收 接口函数源码分析内存分配接口物理内存释放接口规范…

【TypeScript】类型兼容(协变、逆变和双向协变)

跟着小满zs 学习 ts&#xff0c;原文&#xff1a;学习TypeScript进阶类型兼容_typescript进阶阶段类型兼容 小满-CSDN博客 类型兼容&#xff0c;就是用于确定一个类型是否能赋值给其他的类型。如果A要兼容B 那么A至少具有B相同的属性。 // 主类型 interface A {name: string,a…

【游戏】一款纯web集前后端为一体的沙盒游戏框架介绍

1.biomes-game是什么&#xff1f; 一款基于MIT协议开源沙盒 MMORPG。游戏中可建造、采集、玩迷你游戏等等&#xff0c;所有操作均可通过浏览器完成。它主要使用React框架&#xff0c;前后端用 Typescript 和 WebAssembly 编写。 2.如何本地体验&#xff1f; 配置&#xff1a;…

计算机网络 —— 一文搞懂TCP/UDP

传输层&#xff1a;TCP/UDP 1. TCP1.1 TCP连接管理1.2 TCP首部格式 2. UDPUDP首部格式 3. 其他传输层协议3.1 SCTP3.2 DCCP 传输层实现源端主机和目标端主机上对等实体间会话&#xff0c;TCP/IP中两个代表性的传输层协议分别是TCP和UDP&#xff0c;两者均使用端口来标识传输数据…

数据防泄漏的六个步骤|数据防泄漏软件有哪些

在当前复杂多变的网络安全环境下&#xff0c;数据防泄漏软件成为了企业信息安全架构中不可或缺的一环。下面以安企神软件为例&#xff0c;告诉你怎么防止数据泄露&#xff0c;以及好用的防泄露软件。 1. 安企神软件 安企神软件是当前市场上备受推崇的企业级数据防泄漏解决方案…

为什么微信输入法是比搜狗输入法更好的选择?

微信输入法官网&#xff1a;https://z.weixin.qq.com/ 最近使用搜狗输入法时&#xff0c;频繁弹出广告&#xff0c;实在令人烦恼&#xff0c;于是我干脆卸载了它。然而&#xff0c;电脑上没有输入法是不行的。经过在网上对比了许多输入法软件后&#xff0c;我发现了微信输入法。…

算法:分治(快排)题目练习

目录 题目一&#xff1a;颜色分类 题目二&#xff1a;排序数组 题目三&#xff1a;数组中的第k个最大元素 题目四&#xff1a;库存管理III 题目一&#xff1a;颜色分类 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地对它们进行排序&#xff0c;…

红队攻防渗透技术实战流程:中间件安全:JettyJenkinsWeblogicWPS

红队攻防渗透实战 1. 中间件安全1.1 中间件-Jetty-CVE&信息泄漏1.2 中间件-Jenkins-CVE&RCE执行1.2.1 cve_2017_1000353 JDK-1.8.0_291 其他版本失效1.2.2 CVE-2018-10008611.2.3 cve_2019_100300 需要用户帐号密码1.3 中间件-Weblogic-CVE&反序列化&RCE1.4 应…

驱动开发(四):Linux内核中断

驱动开发系列文章&#xff1a; 驱动开发&#xff08;一&#xff09;&#xff1a;驱动代码的基本框架 驱动开发&#xff08;二&#xff09;&#xff1a;创建字符设备驱动 驱动开发&#xff08;三&#xff09;&#xff1a;内核层控制硬件层 驱动开发&#xff08;四&#xf…

2024FIC决赛

容器密码&#xff1a;2024Fic~Competition~Finals杭州&Powered~By~HL! 案件背景: 2023年3月15日凌晨,受害人短视频平台上看到一段近期火爆的交通事故视频&#xff0c;留言后有人通过私信联系&#xff0c;称有一个赚大钱的机会&#xff0c;该人自称李某&#xff0c;提议让…

如何通过抖音自动评论精准获客实现业务增长?这些方法值得一试!

在当今竞争激烈的商业环境中&#xff0c;企业若想脱颖而出&#xff0c;就必须掌握精准获客的艺术。精准获客&#xff0c;即通过精确的市场定位和营销策略&#xff0c;吸引并保留最有可能成为客户的目标群体。它不仅能提高转化率&#xff0c;还能有效降低营销成本&#xff0c;是…

实况:老菜鸟自力更生从零开始重学spring目标是画出一张唬人大图(二、源码下载编译)

前情提要&#xff1a;调试前的基础知识梳理 速览 “Spring”包含哪些东西源码下载源码编译1、编译工具选择&#xff1a;gradle2、使用gradle编译spring并导入idea预编译spring-oxm导入IDEA确认合适的jdk版本排除spring-aspects模块 开始调试 “Spring”包含哪些东西 可以明确的…

LVS负载均衡:理解IPVS和IPVSADM的内部工作原理

LVS 负载均衡工作模式 LVS&#xff08;Linux Virtual Server&#xff09; 共有三种工作模式&#xff1a;DR、Tunnel、NAT。 DR&#xff08;Direct Routing&#xff09;&#xff1a; 技术原理&#xff1a;DR模式下&#xff0c;LVS调度器接收到请求后&#xff0c;直接通过MAC地址…

Kali中安装和使用docker的学习笔记

一、常见命令 ctrl 、shift、 &#xff1a; 窗口变大&#xff1b; ctrl 、- &#xff1a;窗口变小&#xff1b; ctrl L&#xff1a; 清屏 &#xff1b; sudo su : 切换root 用户&#xff1b; ip addr / ifconfig: 获取IP地址&#xff1b; systemctl start ssh…

探索Python的多媒体解决方案:ffmpy库

文章目录 探索Python的多媒体解决方案&#xff1a;ffmpy库一、背景&#xff1a;数字化时代的多媒体处理二、ffmpy&#xff1a;Python与ffmpeg的桥梁三、安装ffmpy&#xff1a;轻松几步四、ffmpy的五项基本功能1. 转换视频格式2. 调整视频质量3. 音频转换4. 视频截图5. 视频合并…