JavaScript全解析——canvas 入门(上)
●canvas 是 HTML5 新增的一个标签, 表示画布
●canvas 也是 h5 的画布技术, 我们通过代码的方式在画布上描绘一个图像
canvas 标签
●向进行 canvas 绘图, 首先我们先要了解到 canvas 标签
●是 html5 推出的一个标签
<html>
<head>...
</head>
<body><canvas></canvas>
</body>
</html>
复制代码
○canvas 默认是一个行内块元素
○canvas 默认画布大小是 300 * 150
○canvas 默认没有边框, 背景默认为无色透明
canvas 画布大小
●我们在绘图之前, 先要确定一个画布的大小
○因为画布默认是按照比例调整
○所以我们调整宽度或者高度的时候, 调整一个, 另一个自然会按照比例自己调整
○我们也可以宽高一起调整
●调整画布大小有两种方案
○第一种 : 通过 css 样式 ( 不推荐 )
<html>
<head><style>canvas {width: 1000px;height: 500px;}</style>
</head>
<body><canvas></canvas>
</body>
</html>
复制代码
○第二种 : 通过标签属性 ( 推荐 )
<html>
<head>...
</head>
<body><canvas width="1000" height="500"></canvas>
</body>
</html>
复制代码
●两种方案的区别
○通过 css 样式的调整方案, 不推荐
是因为这个方案其实并没有设置了画布的大小
而是把原先 300 * 150 的画布, 将他的可视窗口变成了 1000 * 500
所以真实画布并没有放大, 只是可视程度变大了
举个例子 : 就是你把一个 300 * 150 的图片, 放大到 1000 * 500 的大小来看
所以这个方式我们及其不推荐
○通过属性的调整方案, 推荐
这个才是真正的调整画布的的大小
也就是我们会在一个 1000 * 500 的画布上进行绘制
●画布的坐标
○canvas 画布是和我们 css 的坐标系一样的
○从 canvas 的左上角为 0 0 左边, 分别向右向下延伸为正方向
canvas 初体验
●准备工作已经完成了, 我们可以开始体验一下绘制了
●其实 canvas 画布很简单, 就和我们 windows 电脑的画板工具是一样的道理
●思考 :
我们在 windows 这个画板上绘制内容的时候
我们一定是先选定一个工具 ( 画笔, 矩形, 圆形, ... )
设定好样式 ( 粗细, 颜色 )
然后开始绘制
●其实在 canvas 绘制也是一个道理
拿到一个画布工具箱
从工具箱中选定工具
设定样式
开始绘制
●初体验步骤
●index.html
<html>
<head>...
</head>
<body><canvas id="canvas" width="600" height="300"></canvas><script src="./index.js"></script>
</body>
</html>
复制代码
●index.js
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')// 1. 获取当前这个画布的工具箱
// 语法: canvas 元素.getContext('2d')
const ctx = canvasEle.getContext('2d')// 2. 开始绘制
// 2-1. 讲画笔移动到一个指定位置开始下笔
// 语法: 工具箱.moveTo(x轴坐标, y轴坐标)
ctx.moveTo(100, 100)// 2-2. 将笔移动到一个指定位置, 画下一条轨迹
// 注意: 这里是没有显示的, 因为只是画了一个轨迹
// 语法: 工具箱.lineTo(x轴坐标, y轴坐标)
ctx.lineTo(300, 100)// 2-3. 设定本条线的样式
// 设定线的宽度
// 语法: 工具箱.lineWidth = 数字
ctx.lineWidth = 10
// 设定线的颜色
// 语法: 工具箱.strokeStyle = '颜色'
ctx.strokeStyle = '#000'// 2-4. 描边
// 把上边画下的痕迹按照设定好的样式描绘下来
// 语法: 工具箱.stroke()
ctx.stroke()
复制代码
●至此我们的第一个线段就绘制完毕, 画布上就会出现一条线段
○从坐标 ( 100, 100 ) 绘制到坐标 ( 300, 100 )
○线段长度为 200px
○线段宽度为 10px
○线段颜色为 '#000' ( 黑色 )
canvas 线宽颜色问题
●刚才我们经过了初体验, 画了一个线段
●看似没有问题, 也出现了线段, 但是其实内在是有一些问题的
●我们先来观察
●这次我们再来画一个线段
○从坐标 ( 100, 100 ) 绘制到坐标 ( 300, 100 )
○线段长度为 200px
○线段宽度为 1px
○线段颜色为 '#000' ( 黑色 )
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')// 1. 获取当前这个画布的工具箱
const ctx = canvasEle.getContext('2d')// 2. 开始绘制
ctx.moveTo(100, 100)// 2-2. 将笔移动到一个指定位置, 画下一条轨迹
ctx.lineTo(300, 100)// 2-3. 设定本条线的样式
// 设定线的宽度
ctx.lineWidth = 10
// 设定线的颜色
ctx.strokeStyle = '#000'// 2-4. 描边
ctx.stroke()
复制代码
●效果出现了, 没有什么问题
●只是看上去不太想 1px, 而且颜色有些浅
●不着急, 我们再来画一个线段
○从坐标 ( 100, 100 ) 绘制到坐标 ( 300, 100 )
○线段长度为 200px
○线段宽度为 2px
○线段颜色为 '#000' ( 黑色 )
●这个时候问题就出现了
○两次画出来的线段, 一次设置 1px 一次设置 2px
○感觉上 线宽度 一样
○两次画出来的线段, 两次都是设置为 '#000' 的颜色
○但是感觉上颜色不太一样
●这是因为浏览器在描述内容的时候, 最小的描述单位是 1px
●我们来模拟一下浏览器绘制的内容
○假设这是我们浏览器描述的画布中的像素点
○我们来做一个坐标的标记
○现在呢不关注线的长度和坐标, 我们就画一个宽度为 1px 的线段
○我们来剖析一下问题
因为在描绘这个线段的时候, 会把线段的最中心点放在这个像素点位上
也就是说, 在描述线宽的时候, 实际上会从 0.5px 的位置绘制到 1.5px 的位置
合计描述宽度为 1px
但是浏览器的最小描述为 1px
这里说的不是最小宽度为 1px, 是浏览器不能在非整数像素开始描述
也就是说浏览器没办法从 0.5 开始绘制, 也没有办法绘制到 1.5 停止
那么就只能是从 0 开始绘制到 2
所以线宽就会变成 2px 了
因为本身一个像素的黑色被强制拉伸到两个像素宽度, 所以颜色就会变浅
就像我们一杯墨水, 倒在一个杯子里面就是黑色
但是到在一个杯子里面的时候, 又倒进去一杯水, 颜色就会变浅
○实际描绘出来的样子
○这就变成了我们刚才看到的样子
●所以, 我们在进行 canvas 绘制内容的时候, 涉及到线段的时候
●我们一般不会把线段宽度设置成奇数, 一般都是偶数的
canvas 绘制平行线
●刚才我们绘制了线段, 接下来我们来绘制一个平行线, 也就是两个线段
●小伙伴: " 一个简单的效果, 想到就搞 "
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')// 1. 获取当前这个画布的工具箱
const ctx = canvasEle.getContext('2d')// 2. 开始绘制第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(300, 100)
ctx.lineWidth = 2
ctx.strokeStyle = '#000'
ctx.stroke()// 3. 开始绘制第二个线段
ctx.moveTo(100, 100)
ctx.lineTo(300, 100)
ctx.lineWidth = 2
ctx.strokeStyle = '#000'
ctx.stroke()
复制代码
●没有问题, 效果实现了
●接下来, 咱们稍微增加一下需求
○第一个线段线宽 2px, 黑色
○第二个线段线宽 10px, 红色
●这也简单啊, 稍微修改一下
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')// 1. 获取当前这个画布的工具箱
const ctx = canvasEle.getContext('2d')// 2. 开始绘制第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(300, 100)
ctx.lineWidth = 2
ctx.strokeStyle = '#000'
ctx.stroke()// 3. 开始绘制第二个线段
ctx.moveTo(100, 100)
ctx.lineTo(300, 100)
ctx.lineWidth = 10
ctx.strokeStyle = 'red'
ctx.stroke()
复制代码
●这是什么鬼, 为什么两个线段都变了, 不是应该只改变一个吗 ?
这是因为我们并没有告诉他这是两个不一样的线段
所以在设置线段样式的时候, 会默认按照最后一次设置的样式来绘制所有的线段
我们要想让第一个线段绘制完毕以后, 和第二个没有关系
我们需要告诉画布, 我的这个线段结束了, 后面的不要和我扯上关系
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')// 1. 获取当前这个画布的工具箱
const ctx = canvasEle.getContext('2d')// 2. 开始绘制第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(300, 100)
ctx.lineWidth = 2
ctx.strokeStyle = '#000'
ctx.stroke()// 3. 结束之前的绘制内容
// 语法: 工具箱.beginPath()
ctx.beginPath()// 4.. 开始绘制第二个线段
ctx.moveTo(100, 100)
ctx.lineTo(300, 100)
ctx.lineWidth = 10
ctx.strokeStyle = 'red'
ctx.stroke()
复制代码
●这样才是我们的需求
canvas 绘制三角形
●画完了线段, 咱们就来画一个简单的图形, 画一个三角形
●其实就是由三个线段组成, 用三个线段围成一个封闭图形即可
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')// 1. 获取当前这个画布的工具箱
const ctx = canvasEle.getContext('2d')// 2. 开始绘制第一个线段
// 三角形第一个点
ctx.moveTo(100, 100)
// 三角形第二个点
ctx.lineTo(200, 100)
// 三角形第三个点
ctx.lineTo(200, 200)
// 回到第一个点
ctx.lineTo(100, 100)
ctx.lineWidth = 2
ctx.strokeStyle = '#000'
// 描边
ctx.stroke()
复制代码
●看似没啥问题, 一个三角形就出来了
●但是我们仔细观察一下三角形的第一个角
●因为这是两个线段, 只是画到了一个点, 不可能重叠出一个 尖儿~~
●这个时候, 我们就不能这样绘制三角形了
当我们要绘制闭合图形的时候
我们不要手动绘制最后一个路径, 而是描述出形状
通过 canvas 让他自动闭合
●首先, 我们绘制出形状, 不要闭合最终路径
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')// 1. 获取当前这个画布的工具箱
const ctx = canvasEle.getContext('2d')// 2. 开始绘制第一个线段
// 三角形第一个点
ctx.moveTo(100, 100)
// 三角形第二个点
ctx.lineTo(200, 100)
// 三角形第三个点
ctx.lineTo(200, 200)ctx.lineWidth = 2
ctx.strokeStyle = '#000'
// 描边
ctx.stroke()
复制代码
●接下来, 让 canvas 来帮我们闭合这个封闭图形
// 0. 获取到页面上的 canvas 标签元素节点
const canvasEle = document.querySelector('#canvas')// 1. 获取当前这个画布的工具箱
const ctx = canvasEle.getContext('2d')// 2. 开始绘制第一个线段
ctx.moveTo(100, 100)
ctx.lineTo(200, 100)
ctx.lineTo(200, 200)// 自动闭合图形
// 语法: 工具箱.closePath()
ctx.closePath()ctx.lineWidth = 2
ctx.strokeStyle = '#000'
// 描边
ctx.stroke()
复制代码
●这个时候, 我们发现一个正常的三角形就出现了
●注意 : 闭合路径
closePath() 这个方法
是从当前坐标点, 直接用线段的方式连接到 modeTo() 的位置
也就是从当前坐标点直接连接到开始坐标点
相关文章:
JavaScript全解析——canvas 入门(上)
●canvas 是 HTML5 新增的一个标签, 表示画布 ●canvas 也是 h5 的画布技术, 我们通过代码的方式在画布上描绘一个图像 canvas 标签 ●向进行 canvas 绘图, 首先我们先要了解到 canvas 标签 ●是 html5 推出的一个标签 <html> <head>... </head> <body&…...
vue 插槽的用法
Vue的插槽(Slot)是一种可以让父组件向子组件传递内容的机制。插槽可以让开发者将组件的结构和内容分离开来,从而实现更好的可维护性和复用性。 在Vue中,插槽通过 标签实现。具体用法如下: 单个插槽 在子组件中使用一…...
【C++复习2】C++编译器的工作原理
如果你是一名newbird的话,建议观看如下视频加深你的理解,再看如下内容: https://www.bilibili.com/video/BV1N24y1B7nQ?p7 The cherno会额外告诉你如何将目标文件转换成汇编代码,CPU执行指令的过程以及编译器如何通过删除冗余变…...
回调函数_回顾
函数指针和回调函数 函数指针是指向函数的指针变量。 通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数。 函数指针可以像一般函数一样,用于调用函数、传递参数。 直接用指针表示函数,而不是*指针ÿ…...
今天面了个字节跳动拿35K出来的,真是砂纸擦屁股,给我露了一手啊
今年的金三银四已经结束,很多小伙伴收获不错,拿到了心仪的 offer。 各大论坛和社区里也看见不少小伙伴慷慨地分享了常见的面试题和八股文,为此咱这里也统一做一次大整理和大归类,这也算是划重点了。 俗话说得好,他山之…...
8. 数据结构与算法
8. 数据结构与算法 常见面试题 说说一个算法有哪些时间复杂度?归并算法时间复杂度是多少?⭐⭐⭐ O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) 归并算法时间复杂度是O(nlogn) 说说数组时间复杂度,什么场景下使用?⭐⭐⭐⭐⭐ 从渐进趋势…...
Springboot +Flowable,任务认领和回退(一)
一.简介 有的时候,一个任务节点会存在多个候选人,例如:张三提交一个任务,这个任务即可以由李四处理,又可以由王五处理,那么针对这种多个任务候选人的情况,该如何处理? 二.绘制流程…...
机器学习 | MATLAB实现CNN-LSTM卷积长短期记忆神经网络模型答疑
机器学习 | MATLAB实现CNN-LSTM卷积长短期记忆神经网络模型答疑 目录 机器学习 | MATLAB实现CNN-LSTM卷积长短期记忆神经网络模型答疑问题汇总问题一答疑问题二答疑问题三答疑问题四答疑问题五答疑参考资料问题汇总 有几个问题咨询一下: 1.数据集划分时出现了问题如何解决? 2…...
卷首语:我决定从零开始,用C++手写自己的键值数据库
2023年5月1日,周一下午。 我为什么要自己写一个? 今天中午,我在CSDN上提出了一个关于如何学习C的观点——通过用C造东西来学习C,于是为了实践这个观点,我决定用C手写一个简单的属于自己的键值数据库。 我会把这个键值…...
【Vue】收集表单数据 过滤器
收集表单数据 收集表单数据: 若:<input type"text"/>,则v-model收集的是value值,用户输入的就是value值若:<input type"radio"/>,则v-model收集的是value值,且要给标签配置value值若…...
Linux线程:死锁
1. 死锁 (1)概念 死锁(DeadLock)指两个或两个以上的进程或线程执行时,由于竞争临界资源而造成阻塞的现象;若不干涉,则无法推进下去。 (2)死锁的原因 ① 竞争临界资源…...
thinkphp+vue+html超市零食品美食推荐系统零食购物商城网站7v281
本系统的开发使获取食品推荐系统信息能够更加方便快捷,同时也使食品推荐系统管理信息变的更加系统化、有序化。系统界面较友好,易于操作 运行环境:phpstudy/wamp/xammp等 开发语言:php 后端框架:Thinkphp5 前端框架:vu…...
思考外语学习的底层逻辑(以英语、法语为例)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言一、英语1.学习历程2.英语学习的心得3.理论检验(持续更新) 二、法语1.学习历程2.读入数据 总结 前言 提示:这里谈谈自己为什么要…...
命名ACL配置
命名ACL配置 【实验目的】 掌握命名ACL的配置。验证配置。 【实验拓扑】 实验拓扑如图1所示。 图1 实验拓扑 设备参数如表所示。 表1 设备参数表 设备 接口 IP地址 子网掩码 默认网关 R1 S0/3/0 192.168.1.1 255.255.255.252 N/A Fa0/0 192.168.2.1 255.255.…...
2008-2019年主要城市PITI指数
2008-2019年主要城市PITI指数 1、来源:附在文件内 2、时间区间:2008-2019年 3、具体时间分布:、2008、2009-2010、2011、2012、2013-2014、2014-2015、2015-2016、2016-2017、2017-2018、2018-2019、 4、范围:包括110个城市&a…...
拷贝构造函数和赋值重载函数详解
1.拷贝构造函数 1.1拷贝构造函数的概念 拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。拷贝构造函数也是特殊的成员函数,其特征如下&#…...
5件关于JavaScript中this参数的事
this 关键字是 JavaScript 中最令人困惑的部分之一,本文试图通过介绍有关它的五个重要事项来阐明其目的和用法。 1、它允许访问同一对象上的其他属性 在 JavaScript 中,函数可以是独立的单元,但它们也可以用作对象的值。考虑下一个对象。 …...
面试题30天打卡-day17
1、什么是内部类? 内部类的分类有哪些 ?内部类的优点 ,内部类有哪些应用场景? 内部类:在一个类中创建一个新的类 内部类主要分为以下4种:成员内部类、局部内部类、静态内部类、匿名内部类。 成员内部类 …...
对标世界一流|弹性应对“供应链不确定性常态化” ——快消与重资产行业的经验互鉴
1963年,气象学家洛伦兹提出的“蝴蝶效应”表示:“一只蝴蝶在巴西扇动翅膀,有可能会在美国德克萨斯州引起一场龙卷风”。本文希望通过提供快消行业的先进实践,帮助重资产企业从“蝴蝶扇动翅膀”之前就开始行动,避免“龙…...
【MPC|云储能】基于模型预测控制(MPC)的微电网调度优化的研究(matlab代码)
目录 1 主要内容 2 程序难点及问题说明 3 部分程序 4 下载链接 1 主要内容 该程序分为两部分,日前优化部分——该程序首先根据《电力系统云储能研究框架与基础模型》上面方法,根据每个居民的实际需要得到响应储能充放电功率,优化得到整体…...
796. 子矩阵的和(C++和Python3)——2023.5.6打卡
文章目录 QuestionIdeasCode Question 输入一个 n 行 m 列的整数矩阵,再输入 q 个询问,每个询问包含四个整数 x1,y1,x2,y2 ,表示一个子矩阵的左上角坐标和右下角坐标。 对于每个询问输出子矩阵中所有数的和。 输入格式 第一行包含三个整数…...
docker打包部署spring boot应用(mysql+jar+Nginx)
文章目录 一、基本准备二、mysql部署二、jar部署三、Nginx部署 一、基本准备 小唐拿的就是之前放置在我们服务器上的应用进行部署,主要就是mysql和jar还有Vue的部署。 目前已经有的是jar、已经打包好的vue 项目参考:小破站数据大屏可视化(…...
Golang-常见数据结构Slice
Slice slice 翻译成中文就是切片,它和数组(array)很类似,可以用下标的方式进行访问,如果越界,就会产生 panic。但是它比数组更灵活,可以自动地进行扩容。 了解 slice 的本质, 最简单的方法就是…...
操作系统——设备管理
0.关注博主有更多知识 操作系统入门知识合集 目录 1.设备管理概念 2.SPOOLing技术 1.设备管理概念 在计算中,除CPU、内存以外的所有设备统称为外设,即外部设备,例如鼠标、键盘、打印机、摄像头、磁盘、硬盘......那么这些只需要连接到计…...
图片分类:精细化分类,(Fine-Grained Categorization) 基于人的行为的精细化分类
文字大纲 简介数据集常用数据集方法1 : 强监督方法2 : 弱监督传统 ResNet EfficientNet 等Two Level Attention Model双线性网络 Bilinear CNN model参考文献和学习路径简介 细粒度图像识别 (fine-grained image recognition),即 精细化分类。 细粒度图像分类(Fine-Graine…...
Matlab2012a的图像处理工具箱的imshow函数
在处理图片文件时,除了使用matlab自带的image函数,还可以考虑用matlab的图像处理工具箱。这个工具箱提供了imshow和imtool两个函数,可实现图片的显示。 这两个函数都支持Handle Graphics体系结构,它们可创建图像对象,…...
Linux_红帽8学习笔记分享_10(SELinux管理与防火墙)
Linux_红帽8学习笔记分享_10(SELinux管理与防火墙) 文章目录 Linux_红帽8学习笔记分享_10(**SELinux管理与防火墙**)1.Linux系统的安全机制1.1 Filesystem1.2 Service1.3 Firewall1.4 SELinux 2.SElinux理论概述3.SElinux的配置文件3.1 SELINUX参数3.2 SELINUXTYPE参数 4.查看和…...
【资料分享】
文章目录 前言《408统考,真题&解析(2009-2021)》《Android 移动应用基础教程(Android Studio)(第2版)》黑马程序员 源代码《Hackers & Painters》--Paul Graham《数字电路与逻辑设计(第3版…...
NewBing 还无法访问的几个问题
大部分的AI自媒体都在说,Bing new已经向全世界开放了,我也凑一下这个热闹,用Edge浏览器打开,访问https://www.bing.com/new?ccus 想体验一下Bing new的效果,结果如下: 相信很多人都碰到了这个问题 此体验…...
将 Segment Anything 扩展到医学图像领域
文章目录 前言技术交流SAM 拆解分析从医学角度理解 SAM 的效用MedSAM实验总结 前言 SAM 是一种在自然图像分割方面取得成功的模型,但在医学图像分割方面表现不佳。MedSAM 首次尝试将 SAM 的成功扩展到医学图像,并成为用于分割各种医学图像的通用工具。为…...
查域名解析/宁波正规优化seo公司
百度网盘AI大赛——表格检测 基于Resnet18回归表格的四个拐角坐标,本项目附带一个可以直接提交的样例,分数20。 比赛链接 1. 比赛介绍 生活中,扫描技术越来越常见,通过手机就能将图片转化为可编辑的文档等;但是现在…...
好看网站手机版/亚马逊关键词
1380. 矩阵中的幸运数 【简单题】【每日一题】 思路: 先找出每一行的最小值,存入集合list_r中,集合下标与行号对应;再找出每一列的最大值,存入集合list_c中,集合下标与列号对应。遍历矩阵每一个元素&#…...
网络营销方案500字/漯河seo推广
Hue版本:hue-3.9.0-cdh5.5.4 需要编译才能使用(联网) 说给大家的话:大家电脑的配置好的话,一定要安装cloudera manager。毕竟是一家人的。同时,我也亲身经历过,会有部分组件版本出现问题安装起…...
网站管理系统源码/关键词排名查询官网
把 Windows 下的应用部署到 Linux 下,使用到了 Quartz 集群的特性,所以建了 MySql 的中间表,一启动看到报错: Invocation of init method failed; nested exception is org.quartz.JobPersistenceException: Couldnt retrieve tri…...
枣庄市网站建设/艺考培训
2009他来了。2008的任务基本完成,2009还有很快多事要做。...
在线做qq空间的网站吗/福州网络推广运营
阅读目录JavaScript 遍历 from 表单所有控件 源码源码解析JavaScript 访问表单(四种方法)源码解析JavaScript 遍历 from 表单所有控件 源码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8">…...