JS操作canvas

<canvas>元素本身并不可见,它只是创建了一个绘图表面并向客户端js暴露了强大的绘图API。

1  <canvas> 与图形

为优化图片质量,不要在HTML中使用width和height属性设置画布的屏幕大小。而要使用CSS的样式属性width和height来设置画布在屏幕上的预期大小。然后在JS开始绘制前,再将画布对象的width和heigh属性设置为CSS像素乘以window.devicePixelRatio。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<canvas width="100" height="100" id="canvas1"></canvas>
<canvas id="canvas2" style="width: 100px; height: 100px"></canvas>
</body>
</html>
<script>
    let canvas2 = document.querySelector("#canvas2");

    canvas2.width = 100 * window.devicePixelRatio;
    canvas2.height = 100 * window.devicePixelRatio;
</script>

图 代码实现效果

1.1 save()、restore()与beginPath()

beginPath() 开始一条路径或重置当前路径,表示重新开始一个新的路径内容。

<script>
    let context = document.querySelector("#canvasId").getContext("2d");

    context.rect(0,0,30,30);
    context.fillStyle = "green";
    context.fill();
    // 缺失 content.beginPath() 那么上面的矩形fillStyle颜色
    // 始终是在beginPath出现之前设置的fillStyle,即"red";
    context.rect(40,40,30,30);
    context.fillStyle = "red";
    context.fill();

    context.beginPath(); // 重新开始路径内容
    context.rect(80,80,30,30);
    context.fillStyle = "blue";
    context.fill();
</script>

图 beginPath演示效果图

save()方法把当前的图形状态(不包括当前定义的路径和当前的点)推到一个保存到状态栈中,而restore()方法则从该栈中弹出状态。

<script>
  let context = document.querySelector("#canvasId").getContext("2d");
  context.fillStyle = "green";
  context.fillRect(0,0,50,50);
  context.save(); //保存fillStyle等状态信息
  context.fillStyle = "red";
  context.fillRect(60,0,50,50);
  context.save();
  context.restore(); // red
  context.fillRect(120,0,50,50);
  context.restore(); // green
  context.fillRect(180,0,50,50);
</script>

图 store() 演示效果图

1.2 渐变色

需要将fillStyle(或strokeStyle)设置为CanvasGradient对象。上下文有两个方法用于创建这个对象:

1)createLinearGradient(),参数是定义一条直线的两个点的坐标,颜色将在这条直线的方向上渐变。

2)createRadialGradient(),需要指定两个圆心和半径(着两个圆不一定是同心圆),小圆内部区域或大圆外部区域将被实色填充,这两个区域之间的部分则会以渐变色填充。

在创建这个对象后,必须调用该对象的addColorStop()方法定义渐变色。第一个参数是一个介于0.0和1.0之间的数值,第二个参数是一个CSS颜色说明。至少必须调用这个方法两次。

<script>
    let canvas = document.querySelector("#canvasId");
    canvas.width = 300 * window.devicePixelRatio;
    canvas.height = 200 * window.devicePixelRatio;
    let context = canvas.getContext("2d");
    context.rect(0,0,130,150);
    let canvasGradient = context.createLinearGradient(30,20, 130,150);
    context.fillStyle = canvasGradient;
    canvasGradient.addColorStop(0,"red");
    canvasGradient.addColorStop(1,"blue");
    context.fill();

    context.beginPath(); // 开始新路径
    context.rect(140,0,200,200);
    let radial = context.createRadialGradient(240,100,50,240,100,100);
    context.fillStyle = radial;
    radial.addColorStop(0, "yellow");
    radial.addColorStop(1,"green");
    context.fill();
</script>

图 渐变色实现效果

1.3 坐标系转换

translate()方法简单地向左、右、上、下移动坐标系原点。rotate()方法按照指定角度旋转坐标轴。scale()方法沿x轴或y轴拉伸或压缩距离(给scale()方法传入一个负缩放因子会围绕原点反转坐标轴,就好像镜子里的倒影一样)。

<script>
    let context = document.querySelector("#canvasId").getContext("2d");

    (function scaleTest() {
        context.translate(100,0);
        drawTrapezoid("green")
        context.scale(-1,1);
        drawTrapezoid("red")
    }());

    function drawTrapezoid(color) {
        context.beginPath();
        context.moveTo(0,20);
        context.lineTo(0,170);
        context.lineTo(-70,150);
        context.lineTo(-70,70);
        context.closePath();
        context.fillStyle = color;
        context.fill();
        context.save();
    }
</script>

图 scale 实现效果图

《JavaScript权威指南》中的科赫雪花代码:

<script>
    let canvas = document.querySelector("#canvasId");
    canvas.width = 500 * window.devicePixelRatio;
    canvas.height = 500 * window.devicePixelRatio;
    let c = canvas.getContext("2d");
    let deg = Math.PI / 180;

    function snowflake(n,x,y,len) {
        c.save();
        c.translate(x,y);
        c.moveTo(0,0);
        leg(n);
        c.rotate(-120 * deg);
        leg(n);
        c.rotate(-120 * deg);
        leg(n);
        c.closePath();
        c.restore();

        function leg(n) {
            c.save();
            if (n === 0) {
                c.lineTo(len,0);
            } else {
                c.scale(1/3,1/3);
                leg(n-1);
                c.rotate(60 * deg);
                leg(n-1);
                c.rotate(-120 * deg);
                leg(n-1);
                c.rotate(60 * deg);
                leg(n-1);
            }
            c.restore();
            c.translate(len,0);
        }
    }

    snowflake(0,25,125,125);
    snowflake(1,175,125,125);
    snowflake(2,325,125,125);
    snowflake(3,475,125,125);
    snowflake(4,625,125,125);
    c.stroke();
</script>

图 科赫雪花实现效果

1.4 剪切

clip()方法定义一个剪切区域,定义后,这个区域外部将不会被绘制。它的作用是遮罩,用来隐藏没有遮罩的部分。

<script>
    const context = document.querySelector("#canvasId").getContext("2d");
    context.fillStyle = "red";
    context.arc(100,100,100,0,Math.PI * 2,true);
    context.fill();
    context.clip();
    context.beginPath();
    context.fillStyle = "blue";
    context.arc(200,100,100,0,Math.PI * 2, true);
    context.fill();
    context.beginPath();
    context.fillStyle = "green";
    context.arc(100,200,100,0,Math.PI * 2, true);
    context.fill();;
</script>

图 clip()演示效果图

1.5 像素操作

context的getImageDate()方法返回一个ImageData对象,表示画布中某矩形区域中包含的原始像素(包括R、G、B和A组件)。createImageData()创建空的ImageData对象,ImageData对象中的像素是可写的。putImageData()方法则是把像素复制到画布中。

<script>
    let canvas = document.querySelector("#canvasId");
    canvas.width = 300 * window.devicePixelRatio;
    canvas.height = 300 * window.devicePixelRatio;
    let context = canvas.getContext("2d");
    context.fillStyle = "#008000";
    context.arc(100,100,100,0,Math.PI,true);
    context.fill();
    let imageData = context.getImageData(0,0,200,200);
    let width = imageData.width,height = imageData.height;
    let data = imageData.data; // 每个像素占用4个连续字节,分别是R、G、B和A
    for (let pos = 0; pos < data.length; pos+=4) {
        if (data[pos + 1] === 128) {
            data[pos] = 255;
            data[pos + 1] = 0; //G
            data[pos + 2] = 0; // B
            data[pos + 3] = 255; // A
        }
    }
    context.putImageData(imageData,210,0);
</script>

图 像素操作演示效果图

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

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

相关文章

父组件用ref获取子组件数据

子组件 Son/index.vue 子组件的数据和方法一定要记得用defineExpose暴露&#xff0c;不然父组件用ref是获取不到的&#xff01;&#xff01;&#xff01; <script setup> import { ref } from "vue"; const sonNum ref(1); const changeSon () > {sonNum.…

DAY54 392.判断子序列 + 115.不同的子序列

392.判断子序列 题目要求&#xff1a;给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是…

探秘Vue组件间通信:详解各种方式助你实现目标轻松搞定!

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! ​ 目录 ⭐ 专栏简介 &#x1f4d8; 文章引言 一…

threejs(13)-着色器设置点材质

着色器材质内置变量 three.js着色器的内置变量&#xff0c;分别是 gl_PointSize&#xff1a;在点渲染模式中&#xff0c;控制方形点区域渲染像素大小&#xff08;注意这里是像素大小&#xff0c;而不是three.js单位&#xff0c;因此在移动相机是&#xff0c;所看到该点在屏幕…

基于单片机的电源切换控制器设计(论文+源码)

1.系统设计 在基于单片机的电源切换控制器设计中&#xff0c;系统功能设计如下&#xff1a; &#xff08;1&#xff09;实现电源的电压检测&#xff1b; &#xff08;2&#xff09;如果电压太高&#xff0c;通过蜂鸣器进行报警提示&#xff0c;继电器进行切换&#xff0c;使…

Idea 编译SpringBoot项目Kotlin报错/Idea重新编译

原因应该是一次性修改了大量的文件, SpringBoot项目启动Kotlin报错, Build Project也是同样的结果, 报错如下 Error:Kotlin: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.9.0, expected version is 1.1.13. Build-&…

python语言的由来与发展历程

Python语言的由来可以追溯到1989年&#xff0c;由Guido van Rossum&#xff08;吉多范罗苏姆&#xff09;创造。在他的业余时间里&#xff0c;Guido van Rossum为了打发时间&#xff0c;决定创造一种新的编程语言。他受到了ABC语言的启发&#xff0c;ABC语言是一种过程式编程语…

Hadoop-HDFS架构与设计

HDFS架构与设计 一、背景和起源二、HDFS概述1.设计原则1.1 硬件错误1.2 流水访问1.3 海量数据1.4 简单一致性模型1.5 移动计算而不是移动数据1.6 平台兼容性 2.HDFS适用场景3.HDFS不适用场景 三、HDFS架构图1.架构图2.Namenode3.Datanode 四、HDFS数据存储1.数据块存储2.副本机…

亚马逊云AI大语言模型应用下的创新Amazon Transcribe的使用

Transcribe简介 语音识别技术&#xff0c;也被称为自动语音识别&#xff08;Automatic Speech Recognition&#xff0c;简称ASR&#xff09;&#xff0c;其目标是将人类的语音中的词汇内容转换为计算机可读的输入&#xff0c;例如按键、二进制编码或者字符序列。语音识别技术已…

2023-11-14 LeetCode每日一题(阈值距离内邻居最少的城市)

2023-11-14每日一题 一、题目编号 1334. 阈值距离内邻居最少的城市二、题目链接 点击跳转到题目位置 三、题目描述 有 n 个城市&#xff0c;按从 0 到 n-1 编号。给你一个边数组 edges&#xff0c;其中 edges[i] [fromi, toi, weighti] 代表 fromi 和 toi 两个城市之间的…

阿里达摩院开源DAMO-YOLO

1.简介 DAMO-YOLO是一个兼顾速度与精度的目标检测框架&#xff0c;其效果超越了目前的一众YOLO系列方法&#xff0c;在实现SOTA的同时&#xff0c;保持了很高的推理速度。DAMO-YOLO是在YOLO框架基础上引入了一系列新技术&#xff0c;对整个检测框架进行了大幅的修改。具体包括…

c语言从入门到实战——基于指针的数组与指针数组

基于指针的数组与指针数组 前言1. 数组名的理解2. 使用指针访问数组3. 一维数组传参的本质4. 冒泡排序5. 二级指针6. 指针数组7. 指针数组模拟二维数组 前言 指针的数组是指数组中的元素都是指针类型&#xff0c;它们指向某种数据类型的变量。 1. 数组名的理解 我们在使用指针…

Excel-快速将公式运用到一整列

先在该列的第一个单元格里写好公式&#xff0c;然后单击该单元格 在图中标示的地方输入我们需要填充的单元格区域 同时按住Ctrl和Enter键&#xff0c;这时需要填充的单元格区域就都被选中了 然后单击一下图中公式的后面&#xff0c;再次按下Ctrl和Enter键&#xff0c;这样就完…

第3章:搜索与图论【AcWing】

文章目录 图的概念图的概念图的分类有向图和无向图 连通性连通块重边和自环稠密图和稀疏图参考资料 图的存储方式邻接表代码 邻接矩阵 DFS全排列问题题目描述思路回溯标记剪枝代码时间复杂度 [N 皇后问题](https://www.luogu.com.cn/problem/P1219)题目描述全排列思路 O ( n ! …

Unity--互动组件(Toggle)

1.组件的可交互 2.组件的过渡状态 3.组件的导航 4.Toggle的属性和参数设置 Toggle 切换控制是一个复选框&#xff0c;允许用户打开或关闭的一个选项&#xff1b; ”Toggle的属性和参数&#xff1a;“” Is on&#xff1a;&#xff08;开启&#xff09; 拨动开关是否从一开…

二叉树基础

前言 我们好久没有更新数据结构的博文了&#xff0c;今天来更新一期树&#xff01;前几期我们已经介绍了顺序表、链表&#xff0c;栈和队列等基本的线性数据结构并对其分别做了实现&#xff0c;本期我们再来介绍一个灰常重要的非线性基本结构 ---- 树型结构。 本期内容介绍 树…

计算机 - - - 浏览器网页打开本地exe程序,网页打开微信,网页打开迅雷

效果 在电脑中安装了微信和迅雷&#xff0c;可以通过在地址栏中输入weixin:打开微信&#xff0c;输入magnet:打开迅雷。 同理&#xff1a;在网页中使用a标签&#xff0c;点击后跳转链接打开weixin:&#xff0c;也会同样打开微信。 运用同样的原理&#xff0c;在网页中点击超…

第3关:集合操作100

任务描述相关知识编程要求测试说明 任务描述 本关任务&#xff1a;使用 集合操作解决实际问题 相关知识 1.集合并操作符 可转换为SQL 若R,S的属性名不同&#xff0c;可使用重命名使相应列名一致后进行并操作 例如&#xff1a;R(A,B,C) S(D,E,F) select A,B from R union sel…

【STM32】串口和printf

1.数据通信的基本知识 1.串行/并行通信 2.单工/半双工/全双工通信 类似于【广播 对讲 电话】 不是有两根线就是全双工&#xff0c;而是输入和输出都有对应的数据线。 3.同步/异步通信 区分同步/异步通信的根本&#xff1a;判断是否有时钟信号&#xff08;时钟线&#xff09;。…

开源维修上门服务小程序SAAS系统源码 带完整搭建教程

在现代生活中&#xff0c;家电设备维修往往是一个耗时且繁琐的过程。消费者需要花费大量时间寻找合适的维修人员&#xff0c;并面临服务质量不稳定的风险。同时&#xff0c;对于维修人员来说&#xff0c;寻找客户和接收订单的过程也十分繁琐。因此&#xff0c;开发一款基于小程…