JS操作canvas

news2024/11/22 17:36:07

<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>

图 像素操作演示效果图

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

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

相关文章

STM32中独立看门狗和窗口看门狗的使用方法

独立看门狗&#xff08;Independent Watchdog&#xff0c;IWDG&#xff09;和窗口看门狗&#xff08;Window Watchdog&#xff0c;WWDG&#xff09;是STM32微控制器中提供的两种看门狗定时器。看门狗定时器是一种硬件计时器&#xff0c;用于监视系统的运行状态&#xff0c;并在…

HTTP/2.0协议详解

前言 HTTP/2.0&#xff1a;互联网通信的革新标准 随着互联网技术的飞速发展&#xff0c;HTTP协议作为互联网应用最广泛的通信协议&#xff0c;也在不断演进和优化。HTTP/2.0是HTTP协议的最新版本&#xff0c;它旨在提供更高效、更安全、更快速的互联网连接。 一、HTTP/2.0的…

​软考-高级-系统架构设计师教程(清华第2版)【第6章 数据库设计基础知识(234~262)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第6章 数据库设计基础知识&#xff08;234~262&#xff09;-思维导图】 课本里章节里所有蓝色字体的思维导图

多维时序 | MATLAB实现PSO-LSTM-Attention粒子群优化长短期记忆神经网络融合注意力机制的多变量时间序列预测

多维时序 | MATLAB实现PSO-LSTM-Attention粒子群优化长短期记忆神经网络融合注意力机制的多变量时间序列预测 目录 多维时序 | MATLAB实现PSO-LSTM-Attention粒子群优化长短期记忆神经网络融合注意力机制的多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果…

XUbuntu22.04之安装pkg-config(一百九十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

机器学习—基本术语

目录 1.样本&#xff08;示例&#xff09; 2.属性 3.属性值 4.属性空间 5.样本空间 6.学习&#xff08;训练&#xff09; 7.数据集 8.测试 9.假设 10.学习器 11.标记 12.样例 13.标记空间&#xff08;样例空间&#xff09; 14.分类与回归 15.有监督学习、无监督…

【HUST】网安纳米|2023年研究生纳米技术考试参考

目录 1 纳米材料是什么 2 纳米材料的结构特性 3 纳米结构的其他特性 4 纳米结构的检测技术 5 纳米材料的应用 打印建议&#xff1a;PPT彩印&#xff08;这样重点比较突出&#xff09;&#xff0c;每面12张PPT&#xff0c;简单做一下关键词目录&#xff0c;亲测可以看清。如…

AWTK实现汽车仪表Cluster/DashBoard嵌入式GUI开发(七):FREERTOS移植

前言: 一般的GUI工程都需要一个操作系统,可能是linux,重量级的,也可能是FreeRTOS,轻量级的。 一句话理解那就是工程就是FreeRTOS task任务的集合。 一个main函数可以看到大框架: 很显然,除了第一个是硬件配置的初始化,中间最重要的部分就是要创建任务,把AWTK的应用…

DDR SDRAM 学习笔记

一、基本知识 1.SDRAM SDRAM : 即同步动态随机存储器&#xff08;Synchronous Dynamic Random Access Memory&#xff09;, 同步是指其时钟频率与对应控制器&#xff08;CPU/FPGA&#xff09;的系统时钟频率相同&#xff0c;并且内部命令 的发送与数据传输都是以该时钟为基准…

竞赛选题 深度学习的水果识别 opencv python

文章目录 0 前言2 开发简介3 识别原理3.1 传统图像识别原理3.2 深度学习水果识别 4 数据集5 部分关键代码5.1 处理训练集的数据结构5.2 模型网络结构5.3 训练模型 6 识别效果7 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习…

EasyExcel入门使用教程

文章目录 简介一、工程创建&#x1f391;二、读操作&#x1f38a;二、写操作&#x1f384;总结 简介 数据导入导出意义 后台管理系统是管理、处理企业业务数据的重要工具&#xff0c;在这样的系统中&#xff0c;数据的导入和导出功能是非常重要的&#xff0c;其主要意义包括以下…

了解STM32看门狗定时器的工作原理和原则

STM32 系列微控制器的看门狗定时器 (Watchdog Timer&#xff0c;WWDG) 是一种重要的硬件资源&#xff0c;用于检测系统的异常状态&#xff0c;并在发生异常时执行特定的操作&#xff0c;以确保系统能够正常运行。在本文中&#xff0c;我将详细介绍 STM32 看门狗定时器的工作原理…

Java Elasticsearch 按一定时间间隔(timeInterval)循环查询数据

最近有个需求&#xff0c;前端传入时间间隔&#xff0c;去elasticsearch按照时间间隔统计每个时间间隔内数据量。 public List<HashMap<String,Object>> getCount(RequestParam Integer time, RequestParam String selectedDatedTime) {SimpleDateFormat format n…

Oracle(2-3) Basic Oracle Net Server Side Configuration

文章目录 一、基础知识1、The Listener Process监听器进程2、Connection Methods 连接方法3、Spawn and Bequeath Conn4、Direct Hand-Off Connections 直接切换连接5、Redirection Session 重定向会话6、Simple to Complex:N-Tier 简单到复杂&#xff1a;N层7、Service Config…

双写绕过 [极客大挑战 2019]BabySQL 1

打开题目 随便输入账号密码 根据报错信息可知这是单引号的字符型注入 那我们试试万能密码 1 or 11 页面报错 1 or 11 页面报错 而且根据报错内容显示是没有我们注入上去的or的 那我们就试试 1 order by 3 # 页面报错&#xff0c;根据报错显示页面过滤掉了or和by 那我们…

Java 并发-Lock

目录 Lock 源码 lock() tryLock() tryLock(long time, TimeUnit unit) Lock与synchronized Lock Lock 是 java.util.concurrent.locks包 下的接口。 上图是 java.util.concurrent.locks包下主要常用的类与接口的关系。 源码 public interface Lock {void lock();void l…

Flowable串行流程移动活动

在Activiti6和Activiti7中跳转节点都要自己实现&#xff0c;Flowable增加了这个功能。 一&#xff1a;简介 串行流程是指简单的一条线的流程&#xff0c;流程中如果包含会签、排它网关也算串行流程。 节点移动有三种方式&#xff1a; 向前移动foreward。向后移动back。直接跳…

并发编程产生的根本原因和C#怎么处理并发问题?

并发编程产生的根本原因和C#怎么处理并发问题&#xff1f; 前言 对于现在很多编程语言来说&#xff0c;多线程已经得到了很好的支持&#xff0c; 以至于我们写多线程程序简单&#xff0c;但是一旦遇到并发产生的问题就会各种尝试。 因为不是明白为什么会产生并发问题&#…

Android 布局优化,看过来 ~

屏幕刷新机制 基本概念 刷新率&#xff1a;屏幕每秒刷新的次数&#xff0c;单位是 Hz&#xff0c;例如 60Hz&#xff0c;刷新率取决于硬件的固定参数。帧率&#xff1a;GPU 在一秒内绘制操作的帧数&#xff0c;单位是 fps。Android 采用的是 60fps&#xff0c;即每秒 GPU 最多…

11-13 /11-14代理模式 AOP

调用者 代理对象 目标对象 代理对象除了可以完成核心任务&#xff0c;还可以增强其他任务,无感的增强 代理模式目的: 不改变目标对象的目标方法的前提,去增强目标方法 分为:静态代理,动态代理 静态代理 有对象->前提需要有一个类&#xff0c;那么我们可以事先写好一个类&a…