当前位置: 首页 > news >正文

canvas画带透明度的直线和涂鸦

提示:canvas画线

文章目录

  • 前言
  • 一、带透明度的直线和涂鸦
  • 总结


前言

一、带透明度的直线和涂鸦

test.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>canvas跟随鼠标移动画透明线</title><style>div,canvas,img{user-select: none;}.my_canvas,.bg_img{position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);}.cf{content: '';display: block;overflow: hidden;clear: both;}.fl{float: left;}.fr{float: right;}.bg_img{width: 674px;height: 495px;background: #ddd;}.img_tools{position: absolute;top: 20px;left: 50%;transform: translateX(-50px);border: 1px solid #eee;border-radius: 64px;height: 64px;line-height: 64px;box-sizing: border-box;padding: 15px 20px 0;}.img_tool{height: 32px;line-height: 32px;color: #000;font-size: 14px;text-align: center;width: 80px;border: 1px solid #ddd;border-radius: 32px;margin-right: 10px;cursor: pointer;}.img_tool_active{color: #409EFF;border: 1px solid #409EFF;}</style>
</head>
<body><div class="bg_img"></div><canvas id="myCanvasBot" class="my_canvas" width="674" height="495"></canvas><canvas id="myCanvasTop" class="my_canvas" width="674" height="495"></canvas><div class="img_tools cf"><div class="img_tool img_tool_active fl" onclick="changeType('curve',this)">涂鸦</div><div class="img_tool fl" onclick="changeType('line',this)">直线</div></div><script>const canvasWidth = 674;const canvasHeight = 495;//底层canvasconst botCan = document.getElementById('myCanvasBot');//顶层canvasconst topCan = document.getElementById('myCanvasTop');//底层画布const botCtx = botCan.getContext('2d');//顶层画布const topCtx = topCan.getContext('2d');topCtx.lineCap = 'round';topCtx.lineJoin = 'round';//鼠标是否按下  是否移动let isDown = false,isMove = false;//鼠标是否在canvas上抬起let isCanUp = false;//需要画图的轨迹let drawPoints = [];//起始点x,ylet startPoint = {x:0,y:0};//图片历史let imgHistory = [];//icon历史// let partHistory = [];//操作类型let drawType = 'curve';//鼠标按下const mousedown = (e)=>{isDown = true;let x = (e||window.event).offsetX;let y = (e||window.event).offsetY;startPoint = {x,y};drawPoints.push([{x,y}]);topCtx.strokeStyle = 'rgba(255,0,0,0.2)';topCtx.lineWidth = 10;topCtx.beginPath();topCtx.moveTo(x,y);}//鼠标移动const mousemove = (e)=>{let x = (e||window.event).offsetX;let y = (e||window.event).offsetY;if(isDown){isMove = true;switch(drawType){case 'curve':drawCurve(x,y);break;case 'line':drawLine(x,y);break;}}}//鼠标抬起const mouseup = (e)=>{isCanUp = true;if(isDown){// topCan内容画到botCan上topToBot();}}//topCan内容画到botCan上const topToBot = ()=>{//把topCan画布生成图片let img = new Image();img.src = topCan.toDataURL('image/png');img.onload = ()=>{// partHistory.push(img);//添加到botCtx画布botCtx.drawImage(img,0,0);let historyImg = new Image();historyImg = botCan.toDataURL('image/png');historyImg.onload = ()=>{//添加到历史记录imgHistory.push(historyImg);}//清除topCtx画布topCtx.clearRect(0,0,canvasWidth,canvasHeight);//botCan画完之后,重置canvas的mouseup isCanUpif(isCanUp)isCanUp=false;}drawPoints = [];isDown = false;isMove = false;}//画透明度直线const drawLine = (x,y)=>{if(!isDown)return;//清空当前画布内容topCtx.clearRect(0,0,canvasWidth,canvasHeight);//必须每次都beginPath  不然会卡topCtx.beginPath();topCtx.moveTo(startPoint.x,startPoint.y);topCtx.lineTo(x,y);topCtx.stroke();}//画带透明度涂鸦const drawCurve = (x,y)=>{drawPoints.push({x,y});//清空当前画布内容topCtx.clearRect(0,0,canvasWidth,canvasHeight);//必须每次都beginPath  不然会卡topCtx.beginPath();topCtx.moveTo(drawPoints[0].x,drawPoints[0].y);for(let i=1;i<drawPoints.length;i++){topCtx.lineTo(drawPoints[i].x,drawPoints[i].y);}topCtx.stroke();}//切换操作const changeType = (type,that)=>{if(drawType == type) return;let tools = document.getElementsByClassName('img_tool');for(let i=0;i<tools.length;i++){let ele = tools[i];if(ele.classList.contains('img_tool_active'))ele.classList.remove('img_tool_active'); //ele.removeClassName('img_tool_active');}that.classList.add('img_tool_active');drawType = type;}//canvas添加鼠标事件topCan.addEventListener('mousedown',mousedown);topCan.addEventListener('mousemove',mousemove);topCan.addEventListener('mouseup',mouseup);//全局添加鼠标抬起事件document.addEventListener('mouseup',(e)=>{let x = (e||window.event).offsetX;let y = (e||window.event).offsetY;if(!isCanUp){if(drawType == 'line'){let clientX = topCan.getBoundingClientRect().x;let clientY = topCan.getBoundingClientRect().y;drawLine(x-clientX,y-clientY);}// topCan内容画到botCan上topToBot();}});//全局添加鼠标移动事件document.addEventListener('mousemove',(e)=>{if(isMove)return isMove = false;let x = (e||window.event).offsetX;let y = (e||window.event).offsetY;if(drawType == 'line'){let clientX = topCan.getBoundingClientRect().x;let clientY = topCan.getBoundingClientRect().y;drawLine(x-clientX,y-clientY);}});</script>
</body>
</html>

在这里插入图片描述
在这里插入图片描述

总结

踩坑路漫漫长@~@

相关文章:

canvas画带透明度的直线和涂鸦

提示&#xff1a;canvas画线 文章目录 前言一、带透明度的直线和涂鸦总结 前言 一、带透明度的直线和涂鸦 test.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content…...

linux命令 curl忽略https证书

curl https://www.baidu.com 会提示需要htttps证书&#xff0c;加 -k 即可&#xff0c;如下&#xff1a; curl -k https://www.baidu.com 如果要带头部&#xff0c;认证数据&#xff0c;加-H curl -s -k -H "Authorization: Bearer 651fasgassssgjage2" https:/…...

游戏引擎中网络游戏的基础

一、前言 网络游戏所面临的挑战&#xff1a; 一致性&#xff1a;如何在所有的主机内都保持一样的表现可靠性&#xff1a;网络传输有可能出现丢包安全性&#xff1a;反作弊&#xff0c;反信息泄漏。多样性&#xff1a;不同设备之间链接&#xff0c;比如手机&#xff0c;ipad&a…...

ES6(ECMAScript 6)中常用的知识点总结(包含示例代码)

ES6(ECMAScript 6)是JavaScript语言的最新版本,它在ES5的基础上做了很多增强和扩展&#xff0c;使JavaScript的编程模式更加现代化和优雅,不仅拓展了语言表达能力,也为编程带来了全新的编程范式和思维方式。在项目中使用ES6,让代码更加简洁、方便模块化和面向对象实现等&#x…...

老师人手必备的教学神器有哪些?这5款教学软件一定要知道!

教师职业生活中有哪些“神器”&#xff1f;对老师来说堪称神器的东西有很多&#xff0c;笔者虽不是老师&#xff0c;工作内容有所不同&#xff0c;但工作给人带来的心力消耗&#xff08;心累/压力/焦虑&#xff09;、身体上的疲惫&#xff08;困&#xff09;等等&#xff0c;这…...

华为机试题-核酸检测人数

题目 为了达到新冠疫情精准防控的需要&#xff0c;为了避免全员核酸检测带来的浪费&#xff0c;需要精准圈定可能被感染的人群。现在根据传染病流调以及大数据分析&#xff0c;得到了每个人之间在时间、空间上是否存在轨迹的交叉。现在给定一组确诊人员编号 (X1, X2, X3, …, n…...

SQLAlchemy模型映射提示declarative_base() takes 0 positional arguments but 1 was given

原码&#xff1a; #SQLAlchemy模型映射表结构. from sqlalchemy import create_engine,Column,Integer,String from sqlalchemy.ext.declarative import declarative_base# 数据库的变量 HOST 127.0.0.1 PORT 3306 DATA_BASE itbz USER root PWD 123456 DB_URL fmysqlpy…...

linux系统Kubernetes工具ingress暴露服务

Ingress Ingressingress详解创建 Ingress 资源部署 Ingress 控制器&#xff08;Nginx&#xff09;下载ingress controller创建ingress-controller测试ingress创建两个应用和service配置ingress转发文件 修改ingress转发类型 Ingress 暴露服务基于域名的虚拟主机 Ingress 》ing…...

centos2anolis

我的centos7原地升级到anolis7记录 注意&#xff1a;如果是桌面版请先卸载firefox&#xff0c;否则so文件冲突。 参考&#xff1a; CentOS 7和8Linux系统迁移到国产Linux龙蜥Anolis OS 8手册_disable pam_pkcs11 module in pam configuration-CSDN博客 关于 CentOS 迁移龙蜥…...

Cesium安装部署运行

目录 1.简介 2.Cesium项目下载 3.Cesium项目运行 4.cesium运行 1.简介 Cesium是国外一个基于JavaScript编写的使用WebGL的地图引擎。Cesium支持3D,2D,2.5D形式的地图展示&#xff0c;可以自行绘制图形&#xff0c;高亮区域&#xff0c;并提供良好的触摸支持&#xff0c;且支…...

【Android 内存优化】KOOM线程泄漏监控的实现源码分析

文章目录 线程monitor的流程怎么判断线程是否泄漏AddThreadJoinThreadExitThreadDetachThread 总结 前面我们通过研究KOOM的开源代码&#xff0c;研究了关于Java层和native层内存泄漏监控的实现原理。还剩下线程泄漏这部分没有进行分析&#xff0c;今天来补全它。整体下来&…...

【爬虫基础】第1讲 网络爬虫基本知识

什么是网络爬虫 网络爬虫&#xff08;Web crawler&#xff09;是一种自动化程序&#xff0c;用于在互联网上收集信息。它可以通过扫描和解析网页的超链接&#xff0c;自动访问网页并抓取所需的数据。网络爬虫常用于搜索引擎和数据采集工具中。 作用 通过有效的爬虫手段批量采…...

scrapy爬虫框架

scrapy爬虫框架 一、scrapy的概念作用和工作流程1、scrapy的概念2、scrapy框架的作用3、scrapy的工作流程&#xff08;重点&#xff09;3.1 回顾之前的爬虫流程3.2 改写上述流程3.3 scrapy的流程3.4 scrapy的三个内置对象3.5 scrapy中每个模块的具体作用 二、scrapy的入门使用1…...

【深度学习】基础知识

吴恩达DeepLearning Python # 1.numpy c c.ravel() 将多维数组拉平 # 2.time tic time.time() toc time.time() print(str(1000*(toc- tic))"ms")...

Electron应用自动更新实现及打包部署全攻略

Electron应用自动更新实现及打包部署全攻略 Electron自动更新原理配置更新服务器打包与发布更新全攻略实战步骤部署与测试部署更新测试更新流程错误处理与调试 高级特性与优化用户体验与反馈安全与隐私保护维护与持续集成性能优化结语 在现代跨平台桌面应用开发领域中&#xff…...

【爬虫基础】第6讲 opener的使用

在爬虫中&#xff0c;opener是一个用来发送HTTP请求的对象。它可以用来模拟浏览器发送请求&#xff0c;包括设置请求头、处理Cookie等操作。使用opener可以实现一些高级功能&#xff0c;如模拟登录、处理验证码等。 方法1&#xff1a; from urllib.request import Request,bu…...

Milvus 向量数据库:如何基于docker-compose在本地快速搭建测试环境

文章目录 1. 安装 milvus1.1. milvus v2.3.12版本信息1.2. 安装milvus步骤1.3. 安装管理工具Attu1.4. 将Attu由docker-compose启动参考Milvus 向量数据库专为向量查询与检索设计,能够为万亿级向量数据建立索引,详见介绍请参见: milvus: 专为向量查询与检索设计的向量数据库 …...

python --dejavu音频指纹识别

Dejavu是一个用于音频指纹识别的Python库&#xff0c;它能够将音频文件转换成独特的指纹&#xff0c;然后通过比对数据库中已知音频的指纹&#xff0c;识别出输入音频的来源或相似音频。Dejavu库支持多种类型的音频文件&#xff0c;包括MP3、WAV等&#xff0c;同时也支持在不同…...

完全二叉树的层序遍历[天梯赛]

文章目录 题目描述思路 题目描述 输入样例 8 91 71 2 34 10 15 55 18 输出样例 18 34 55 71 2 10 15 91思路 完全二叉树最后一层可以不满&#xff0c;但上面的每一层的节点数都是满的 后序遍历的顺序为"左右根"&#xff0c;我们可以用数组模拟完全二叉树&#xff0c;…...

C语言看完我这篇编译与链接就够啦!!!

1. 前言 Hello&#xff01;大家好我是小陈&#xff0c;今天来给大家介绍最详细的C语言编译与链接。 2. 编译和链接 我们通常用的编译器&#xff0c;比如Visual Sudio,这样的IDE(集成开发环境&#xff09;一般将编译和链接的过程一步完成&#xff0c;通常将这这种编译和链接合…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...

Vue 实例的数据对象详解

Vue 实例的数据对象详解 在 Vue 中,数据对象是响应式系统的核心,也是组件状态的载体。理解数据对象的原理和使用方式是成为 Vue 专家的关键一步。我将从多个维度深入剖析 Vue 实例的数据对象。 一、数据对象的定义方式 1. Options API 中的定义 在 Options API 中,使用 …...