canvas学习

news2025/7/15 3:45:26

canvas 是一块画布,可以设置宽高 ,默认 300 * 150

使用方式

1. 声明书写 canvas标签

2. 拿到canvas的dom

3. 调用方法 getContext (注意 此方法在prototype上)

 方法集合:

填充:

1. fillStyle, 设置填充颜色  ,不设置默认为黑色

2. fillRect , 4个参数  x y  宽 高

画笔:

3. strokeStyle 设置画笔的颜色

4. strokeRect 4个参数  x y  宽 高的颜色 // 绘制被填充的矩形

5. rect  4个参数  x y  宽 高 // 创建矩形,没有画上

6. ctx.stroke()  // 画上去

7. fill  把图形画到画布上

8. closePath() // 闭合

9. arc(300, 100, 50, 0, Math.PI * 2, false ) // 6个参数  x y 圆心坐标,半径  起始角度           3.14*2  ,false为顺时针, true 逆时针

10  arcTo(150,20,150,70,50) // 起始坐标 终止坐标  半径

11 translate (300,300)设置基准点

 <canvas id="canvas" width="600" height="300"></canvas>
  <script>
// 获取元素
let canvas = document.querySelector('#canvas')
// 创建绘画环境

const ctx = canvas.getContext('2d')
// console.log(ctx);
// ctx.fillStyle = "#0000ff" // 设置填充颜色
// ctx.fillRect(0, 20, 150, 100) // 绘制被填充的矩形

// ctx.strokeStyle = '#00ff11' // 设置画笔的颜色
// ctx.strokeRect(0, 20, 150, 100) // 绘制被填充的矩形

// ctx.rect(50,50,100,100) // 创建矩形,没有画上
// ctx.strokeStyle = '#00ff11' 
// ctx.stroke() // 画上去s

// ctx.rect(50, 50, 100, 100) // 创建一个矩形
// ctx.fillStyle = "#0000ff"
// ctx.fill() // 把矩形画到画布上

// 抬笔画路径
// ctx.beginPath()
// ctx.moveTo(0, 0) // 从10 移动到20 可以理解为从x y 偏移
// ctx.lineTo(100, 100) // 画直线从100 - 100 
// ctx.strokeStyle = 'blue'
// ctx.lineWidth = 5 // 设置宽度   
// ctx.stroke()

// ctx.beginPath()
// ctx.moveTo(200, 50) 
// ctx.lineTo(150, 150)
// ctx.closePath() // 闭合
// ctx.lineWidth = 10 // 设置宽度   
// ctx.strokeStyle = 'red'
// ctx.stroke()

// 画圆
// ctx.beginPath()
// ctx.strokeStyle = 'blue'
// ctx.arc(300, 100, 50, 0, Math.PI * 2, false ) // 6个参数  x y 圆心坐标,半径  起始角度 3.14*2  ,false为顺时针, true 逆时针
// ctx.stroke()

// 弧度
// ctx.beginPath()
// ctx.moveTo(100,100)
// // ctx.lineTo(100,100)
// ctx.strokeStyle = 'blue'
// ctx.arcTo(150,20,150,70,50) // 起始坐标 终止坐标  半径
// ctx.stroke()
//  </script>

小时钟案例

---------------------------

老陈讲解

 

 二次贝塞尔曲线和三次贝塞尔曲线

 

 

 

 

Path2D

样式和颜色控制

 

线性渐变 

 

径向渐变

 

 圆锥渐变

图案样式 Patterns 

 线段和虚线样式设置

 

 

 

 

 

 阴影 

绘制图像和视频 

 

 

 文字绘制与对齐

移动TRanslating

 

 

 

 

变形 Transforms 

 

位移

 

 旋转

 合成

具体查文档

HTML 5 Canvas 参考手册

 

刮刮卡

 

 裁剪

 

 

状态的保存和恢复 

 

像素操作 

 

 

所有参数 

 

 高级封装绘制元素和实现元素交互

通过class类进行封装 

 

 

 canvas实现在线画板

 

 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
.active {
  color: #fff;
  background-color: orangered;
  border: 1px solid transparent;
}
  </style>
</head>

<body>
  <canvas id="c1" width="800" height="600"></canvas>
  <hr>
  <button id="boldBtn">粗线条</button>
  <button id="thinBtn">细线条</button>
  <button id="saveBtn">保存签名</button>
  <input type="color" id="color" />
  <button class="clearBtn">橡皮擦</button>
  <button id="nullBtn">清空画布</button>

  <script>
// 获取画布
const canvas = document.querySelector('#c1')
const ctx = canvas.getContext('2d')
// 连接处圆润
ctx.lineJoin = 'round'
// 开端和结束端也是圆的
ctx.lineCap = 'round'

// 获取按钮
const boldBtn = document.querySelector('#boldBtn')
const thinBtn = document.querySelector('#thinBtn')
const saveBtn = document.querySelector('#saveBtn')
const inputColor = document.querySelector('#color')
const clearBtn = document.querySelector('.clearBtn')
const nullBtn = document.querySelector('#nullBtn')

// 设置变量确认是否开始绘画
let isDraw = false

// 鼠标按下
canvas.onmousedown = () => {
  isDraw = true
  ctx.beginPath()
  let x = event.pageX - canvas.offsetLeft
  let y = event.pageY - canvas.offsetTop
  ctx.moveTo(x, y)
}

// 鼠标移动
canvas.onmousemove = () => {
  if (isDraw) {
    let x = event.pageX - canvas.offsetLeft
    let y = event.pageY - canvas.offsetTop
    ctx.lineTo(x, y)
    ctx.stroke()
  }
}

// 鼠标离开 
canvas.onmouseleave = () => {
  isDraw = false
  ctx.closePath()
}

// 鼠标弹起 
canvas.onmouseup = () => {
  isDraw = false
  ctx.closePath()
}

// 设置按钮方法
boldBtn.onclick = () => {
  ctx.globalCompositeOperation = 'source-over'
  ctx.lineWidth = 20
  boldBtn.classList.add('active')
  thinBtn.classList.remove('active')
  clearBtn.classList.remove('active')
}

thinBtn.onclick = () => {
  ctx.globalCompositeOperation = 'source-over'
  ctx.lineWidth = 2
  thinBtn.classList.add('active')
  boldBtn.classList.remove('active')
  clearBtn.classList.remove('active')
}

clearBtn.onclick = () => {
  ctx.globalCompositeOperation = 'destination-out'
  ctx.lineWidth = 30
  clearBtn.classList.add('active')
  boldBtn.classList.remove('active')
  thinBtn.classList.remove('active')
}

nullBtn.onclick = () => {
  ctx.clearRect(0, 0, 800, 600)
}

saveBtn.onclick = () => {
  let urlData = canvas.toDataURL()
  let img = new Image()
  img.src = urlData
  document.body.appendChild(img)

  let downLoadA = document.createElement('a')
  downLoadA.setAttribute('download', '酷炫签名')
  downLoadA.href = urlData
  downLoadA.click()
  document.remove(downLoadA)
}

inputColor.onchange = () => {
  ctx.strokeStyle = inputColor.value
}
  </script>
</body>

</html>

绘制时钟

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
* {
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  justify-content: center;
}

canvas {
  margin-top: 30px;
  border: 1px solid black;
}

.active {
  color: #fff;
  background-color: orangered;
  border: 1px solid transparent;
}
  </style>
</head>

<body>
  <canvas id="c1" width="800" height="600"></canvas>


  <script>
// 获取画布
const canvas = document.querySelector('#c1')
const ctx = canvas.getContext('2d')

function render() {
  ctx.clearRect(0, 0, 800, 600)
  // 存档,保存当前坐标位置和上下文对象的状况
  ctx.save()
  ctx.translate(400, 300)
  ctx.rotate(-Math.PI / 2)

  ctx.save()
  for (let i = 0; i < 12; i++) {
    // 绘制小时的刻度
    ctx.beginPath()
    ctx.moveTo(170, 0)
    ctx.lineTo(190, 0)
    ctx.lineWidth = 8
    ctx.strokeStyle = 'gray'
    ctx.stroke()
    ctx.closePath()
    ctx.rotate(Math.PI * 2 / 12)
  }

  ctx.restore()
  ctx.save()
  for (let i = 0; i < 60; i++) {
    // 绘制分钟的刻度 
    ctx.beginPath()
    ctx.moveTo(180, 0)
    ctx.lineTo(190, 0)
    ctx.lineWidth = 2
    ctx.strokeStyle = 'gray'
    ctx.stroke()
    ctx.closePath()
    ctx.rotate(Math.PI * 2 / 60)
  }
  ctx.restore()
  ctx.save()

  // 获取当前时间
  let time = new Date()
  let hour = time.getHours()
  let min = time.getMinutes()
  let sec = time.getSeconds()
  hour = hour >= 12 ? hour - 12 : hour

  // 绘制秒针 
  ctx.rotate(Math.PI * 2 / 60 * sec)
  ctx.beginPath()
  ctx.moveTo(-30, 0)
  ctx.lineTo(190, 0)
  ctx.lineWidth = 2
  ctx.strokeStyle = 'red'
  ctx.stroke()
  ctx.closePath()
  ctx.restore()
  ctx.save()

  // 绘制分针 
  ctx.rotate(Math.PI * 2 / 60 * min + Math.PI * 2 / 60 / 60 * sec)
  ctx.beginPath()
  ctx.moveTo(-20, 0)
  ctx.lineTo(130, 0)
  ctx.lineWidth = 4
  ctx.strokeStyle = '#888'
  ctx.stroke()
  ctx.closePath()
  ctx.restore()
  ctx.save()

  // 绘制时针
  ctx.rotate(Math.PI * 2 / 12 * hour + Math.PI * 2 / 12 / 60 * min + Math.PI * 2 / 12 / 60 / 60 *
    sec)
  ctx.beginPath()
  ctx.moveTo(-15, 0)
  ctx.lineTo(110, 0)
  ctx.lineWidth = 8
  ctx.strokeStyle = '#333'
  ctx.stroke()
  ctx.closePath()
  ctx.restore()

  ctx.restore()
  requestAnimationFrame(render)
}
render()
  </script>
</body>

</html>

 

 

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

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

相关文章

详解非负矩阵分解(NMF)及其在脑科学中的应用

非负矩阵分解及其在脑科学中的应用 基本原理确定最优因子数量代码实现非负矩阵分解与主成分分析的区别非负矩阵分解在脑科学中的应用应用一:神经发育模式:T2w/T1w比值映射的非负矩阵分解(NMF)应用二:微观结构的协方差模式基本原理 NMF的基本思想可以简单描述为:对于任意给…

Python用PyMC3实现贝叶斯线性回归模型

在本文中&#xff0c;我们将在贝叶斯框架中引入回归建模&#xff0c;并使用PyMC3 MCMC库进行推理。 最近我们被客户要求撰写关于叶斯线性回归模型的研究报告&#xff0c;包括一些图形和统计输出。我们将首先回顾经典频率论的多重线性回归方法。然后讨论贝叶斯如何考虑线性回归。…

8、MyBatis核心配置文件之typeAliases(mybatis-config.xml)

MyBatis核心配置文件之typeAliases&#xff08;mybatis-config.xml&#xff09; 1、&#xff01;&#xff01;&#xff01;&#xff01;注意 2、 设置类型别名&#xff08;比如有的全类名&#xff08;resultType&#xff09;太长了不好使用&#xff09; typeAlias :设置某个类…

Python版本的温湿度+Nokia5110 display(SPI)

前提需要把micropython的固件安装到系统中 安装micropython到esp8266中 本实验需要&#xff1a; 1. ESP8266&#xff08;我的是Wemos D1) 2. DHT11 3. Nokia5110 LCD 连线&#xff1a; DHT11 out --> D2(GPIO-016) (-接入GND&#xff0c;接入3.3vcc) Nokia 5110 LCD We…

GO语言最常用的语法

一 ,变量&#xff1a;变量赋值只能在函数内使用&#xff0c;故第三种方式只能在函数内使用&#xff0c;可使用var()同时定义多个变量变量定义 使用var关键字 var a bool var a bool true 不指定类型直接初始化让编译器选择 var a "abc" 使用 “ : "…

Python入门、环境搭建、变量、数据类型

目录 前景 官方下载 基本数据类型 动态语言的体现 静态语言的体现 弱语言的体现 强语言的体现 注释 整数 浮点型 浮点型计算方案 字符串 布尔 引用数据类型 列表 [ ] 列表方法 集合Set{} 基本方法 特殊需求方法 应用场景 字典{} 常见操作 元组 操作符 练习…

基于ANSYS 2019R1全解一款双吸泵的双向流固耦合方法

作者&#xff1a;李雷 一、导读 对于旋转机械来说&#xff0c;传统设计从理论计算到手工木模图&#xff0c;再到模型泵的加工制造&#xff0c;最后进行相关性能试验。当性能试验与预期效果差距较大的时候还需要修改水力模型。这种传统的设计不仅设计周期长&#xff0c;而且成…

Vue3+nodejs全栈项目(资金管理系统)——后端篇(二)用户模块

文章目录用户模块的增删改查新增创建user_info表初始化路由模块路由模块处理函数(添加&#xff09;测试查询路由模块处理函数(查询)测试编辑&#xff08;根据id&#xff09;路由模块处理函数&#xff08;编辑/更新&#xff09;测试删除(根据id&#xff09;路由模块处理函数测试…

黑马JVM学习笔记-内存结构

什么是JVM? 定义&#xff1a; Java Virtual Machine - java 程序的运行环境(Java二进制字节码的运行环境) 好处&#xff1a;3 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收功能数组下标越界检查(下标越界抛出异常比数组新元素覆盖其他部分造成的危害小)…

1. SAP Business Application Studio 里创建一个基于 CAP 模型的最简单的 OData 服务

本教程已经花费了 24 个文章的篇幅,介绍了使用 SAP ABAP SEGW 这个开发工具,开发基于 SAP ABAP 技术栈的 OData 服务的详细步骤。 正如本教程目录 中提到的那样,SAP OData 开发技术包含传统的 ABAP,RAP(Restful ABAP Programming) 和 CAP(Cloud Application Programming) …

前端程序员接私活,直呼赚麻了

总有一些前端程序员会想找私活&#xff0c;但是又不清楚具体的办法&#xff0c;或者是做了但没完全做&#xff0c;吃力又不讨好还赚不到钱。今天就给大家介绍一些可行性高的方法&#xff0c;让你快速找到合适的前端兼职。 干货满满&#xff0c;希望大家点赞收藏下&#xff0c;别…

Java 异常中 e.getMessage() 和 e.toString() e.printStackTrace()的区别常见的几种异常

Java 异常中 e.getMessage() 和 e.toString() e.printStackTrace()的区别 一、概述 在java异常体系中&#xff0c;要打印异常信息&#xff0c;可以通过&#xff1a;e.getMessage() 、 e.toString() e.printStackTrace() 等方法打印出 一些 异常信息。已知的是这些方法都可以打…

WinBUGS对多元随机波动率模型:贝叶斯估计与模型比较

在本文中&#xff0c;我们通过一个名为WinBUGS的免费贝叶斯软件&#xff0c;可以很容易地完成基于似然的多变量随机波动率&#xff08;SV&#xff09;模型的估计和比较。 最近我们被客户要求撰写关于随机波动率的研究报告&#xff0c;包括一些图形和统计输出。通过拟合每周汇率…

机器学习笔记之贝叶斯线性回归(一)线性回归背景介绍

机器学习笔记之贝叶斯线性回归——线性回归背景介绍引言回顾&#xff1a;线性回归场景构建从概率密度函数认识最小二乘法回顾&#xff1a;最小二乘估计回顾&#xff1a;线性回归与正则化关于线性回归的简单小结贝叶斯线性回归贝叶斯方法贝叶斯方法在线性回归中的任务贝叶斯线性…

kubernetes深入理解Pod对象之调度篇

目录 一、Pod调度流程 二、 容器资源限制 2.1 内存和CPU限制 三、 NodeSelector 四、NodeAffinity 4.1 基本概念 4.2 Pod 示例 4.2.1使用首选的节点亲和性调度 Pod 4.2.2依据强制的节点亲和性调度 Pod 五、Taints与Tolerations 5.1 基本概念 5.2Taints与Toleratio…

Ceph块存储

目录 一、环境准备 二、什么是块存储 三、创建块共享 1、查看存储池 2、创建镜像、查看镜像 3、镜像扩容、缩容 四、客户端通过KRBD访问共享镜像 1、客户端安装 2、客户端配置 3、客户端获取镜像 4、客户端写入数据 五、快照 1、查看、创建快照 2、还原快照 六、…

shell实战案例:系统性能监控脚本

一 简介 下面我们来编写一个检测系统环境、监控系统性能的脚本&#xff0c;并判断各项数据指标是否符合预设的阈值。如果数据有异常&#xff0c;就报警&#xff0c;如何报警&#xff0c;视情况而定。注意脚本中的很多预设值只是假设值&#xff0c;在实际生产环境中还需要根据业…

cubeIDE开发, 物联网应用之stm32的蓝牙通信设计

一、蓝牙通信技术 蓝牙技术是一种点对点点对面的网络构架&#xff0c;他可以在限制的范围内以很快的速度传输网络数据&#xff0c;在物联网应用中&#xff0c;支持网状网络的物联网短距离无线通信。目前它还被广泛用于智能可穿戴设备、智能门锁、智能医疗设备、智能照明设备、智…

十二、CANdelaStudio入门-Security

本专栏将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希望能对大家有所帮助,与大家共同成长,早日成为一名车载诊断、通信全栈工程师。 本文介绍CANdelaStudio的Security概念,欢迎各位朋友订阅、评论,…

【GamePlay】Unity手机屏幕UI适配问题

前言 关于UI不同分辨率适配问题和摄像机视口的注意事项 画布大小与锚点 首先要了解这两个东西 对于画布大小&#xff0c;主要理解match的含义&#xff0c;滑到Width时&#xff0c;表示以宽度为基准&#xff0c;Width不变&#xff0c;Height根据真机分辨率改变。 比如自己设…