canvas跟随鼠标移动画带透明度的线

提示:canvas画线

文章目录

  • 前言
  • 一、带透明度的线
  • 二、试错,只有lineTo的时候画,只有最后地方是透明度的
  • 三、试错,只存上一次的点,线会出现断裂的情况
  • 总结


前言

一、带透明度的线

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%);
        }
        .bg_img{
            width: 674px;
            height: 495px;
            background: #ddd;
        }
    </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>
    <script>
        const canvasWidth = 674;
        const canvasHeight = 495;
        //底层canvas
        const botCan = document.getElementById('myCanvasBot');
        //顶层canvas
        const topCan = document.getElementById('myCanvasTop');
        //底层画布
        const botCtx = botCan.getContext('2d');
        //顶层画布
        const topCtx = topCan.getContext('2d');
        //鼠标是否按下  是否移动  是否画图了
        let isDown = false,isMove = false,isDrawed = false;
        //需要画图的轨迹
        let drawPoints = [];
        //起始点x,y
        let startPoint = {
            x:0,
            y:0
        };
        //图片历史
        let imgHistory = [];
        //icon历史
        let partHistory = [];
        //鼠标按下
        const mousedown = (e)=>{
            isDown = true;
            let x = (e||window.event).offsetX;
            let y = (e||window.event).offsetY;
            startPoint = {x,y}
            // drawPoints.push({x,y});
            drawPoints.push([{x,y}]);
            topCtx.beginPath();
            topCtx.moveTo(x,y);
        }
        //鼠标移动
        const mousemove = (e)=>{
            if(isDown){
                isMove = true;
                drawCurve(e);
            }
        }
        //鼠标抬起
        const mouseup = (e)=>{
            if(isDown&&isMove){
                isDown = false;
                isMove = false;
                drawPoints = [];
                //把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);
                }
            }
        }
        //画带透明度涂鸦
        const drawCurve = (e)=>{
            let x = (e||window.event).offsetX;
            let y = (e||window.event).offsetY;
            drawPoints.push({x,y});
            topCtx.strokeStyle = 'rgba(255,0,0,0.2)';
            topCtx.lineWidth = 10;
            //清空当前画布内容
            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();
        }


        //canvas添加鼠标事件
        topCan.addEventListener('mousedown',mousedown);
        topCan.addEventListener('mousemove',mousemove);
        topCan.addEventListener('mouseup',mouseup);
        //全局添加鼠标抬起事件
        document.addEventListener('mouseup',()=>{
            isDown = false;
            isMove = false;
            isDrawed = false;
        });
    </script>
</body>
</html>

在这里插入图片描述

二、试错,只有lineTo的时候画,只有最后地方是透明度的

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%);
        }
        .bg_img{
            width: 674px;
            height: 495px;
            background: #ddd;
        }
    </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>
    <script>
        const canvasWidth = 674;
        const canvasHeight = 495;
        //底层canvas
        const botCan = document.getElementById('myCanvasBot');
        //顶层canvas
        const topCan = document.getElementById('myCanvasTop');
        //底层画布
        const botCtx = botCan.getContext('2d');
        //顶层画布
        const topCtx = topCan.getContext('2d');
        //鼠标是否按下  是否移动  是否画图了
        let isDown = false,isMove = false,isDrawed = false;
        //需要画图的轨迹
        let drawPoints = [];
        //起始点x,y
        let startPoint = {
            x:0,
            y:0
        };
        //图片历史
        let imgHistory = [];
        //icon历史
        let partHistory = [];
        //鼠标按下
        const mousedown = (e)=>{
            isDown = true;
            let x = (e||window.event).offsetX;
            let y = (e||window.event).offsetY;
            startPoint = {x,y}
            // drawPoints.push({x,y});
            drawPoints.push([{x,y}]);
            topCtx.beginPath();
            topCtx.moveTo(x,y);
        }
        //鼠标移动
        const mousemove = (e)=>{
            if(isDown){
                isMove = true;
                drawCurve(e);
            }
        }
        //鼠标抬起
        const mouseup = (e)=>{
            if(isDown&&isMove){
                isDown = false;
                isMove = false;
                drawPoints = [];
                //把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);
                }
            }
        }
        //画带透明度涂鸦
        const drawCurve = (e)=>{
            let x = (e||window.event).offsetX;
            let y = (e||window.event).offsetY;
            drawPoints.push({x,y});
            topCtx.strokeStyle = 'rgba(255,0,0,0.2)';
            topCtx.lineWidth = 10;
            //清空当前画布内容
            // 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.lineTo(x,y);
            topCtx.stroke();
        }


        //canvas添加鼠标事件
        topCan.addEventListener('mousedown',mousedown);
        topCan.addEventListener('mousemove',mousemove);
        topCan.addEventListener('mouseup',mouseup);
        //全局添加鼠标抬起事件
        document.addEventListener('mouseup',()=>{
            isDown = false;
            isMove = false;
            isDrawed = false;
        });
    </script>
</body>
</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%);
        }
        .bg_img{
            width: 674px;
            height: 495px;
            background: #ddd;
        }
    </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>
    <script>
        const canvasWidth = 674;
        const canvasHeight = 495;
        //底层canvas
        const botCan = document.getElementById('myCanvasBot');
        //顶层canvas
        const topCan = document.getElementById('myCanvasTop');
        //底层画布
        const botCtx = botCan.getContext('2d');
        //顶层画布
        const topCtx = topCan.getContext('2d');
        //鼠标是否按下  是否移动  是否画图了
        let isDown = false,isMove = false,isDrawed = false;
        //需要画图的轨迹
        let drawPoints = [];
        //起始点x,y
        let startPoint = {
            x:0,
            y:0
        };
        //上一次的点
        let lastPoint = {
            x:0,
            y:0
        };
        //图片历史
        let imgHistory = [];
        //icon历史
        let partHistory = [];
        //鼠标按下
        const mousedown = (e)=>{
            isDown = true;
            let x = (e||window.event).offsetX;
            let y = (e||window.event).offsetY;
            startPoint = {x,y}
            // drawPoints.push({x,y});
            drawPoints.push([{x,y}]);
            lastPoint = {x,y}
            topCtx.beginPath();
            topCtx.moveTo(x,y);
        }
        //鼠标移动
        const mousemove = (e)=>{
            if(isDown){
                isMove = true;
                drawCurve(e);
            }
        }
        //鼠标抬起
        const mouseup = (e)=>{
            if(isDown&&isMove){
                isDown = false;
                isMove = false;
                drawPoints = [];
                //把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);
                }
            }
        }
        //画带透明度涂鸦
        const drawCurve = (e)=>{
            let x = (e||window.event).offsetX;
            let y = (e||window.event).offsetY;
            drawPoints.push({x,y});
            topCtx.strokeStyle = 'rgba(255,0,0,0.2)';
            topCtx.lineWidth = 10;
            topCtx.beginPath();
            topCtx.moveTo(lastPoint.x,lastPoint.y);
            topCtx.lineTo(x,y);
            topCtx.stroke();
            lastPoint = {x,y};
        }


        //canvas添加鼠标事件
        topCan.addEventListener('mousedown',mousedown);
        topCan.addEventListener('mousemove',mousemove);
        topCan.addEventListener('mouseup',mouseup);
        //全局添加鼠标抬起事件
        document.addEventListener('mouseup',()=>{
            isDown = false;
            isMove = false;
            isDrawed = false;
        });
    </script>
</body>
</html>

在这里插入图片描述

总结

踩坑路漫漫长@~@

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

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

相关文章

Apipost智能Mock功能详解

在接口开发过程中&#xff0c;Mock功能可以帮助开发者快速测试和验证接口的正确性和稳定性&#xff0c;以便快速迭代和修复问题。Apipost推出智能Mock功能&#xff0c;可以在智能期望中填写一些触发条件&#xff0c;开启后&#xff0c;Apipost会根据已设置的触发条件&#xff0…

CMake简单使用02

有如下的目录结构 main.cpp func.h: func.cpp 外层的CMakeLists.txt #需求的最低cmake程序版本 cmake_minimum_required(VERSION 3.2)#本工程的名字&#xff0c;- OpenGL.sln project(OpenGL)#本工程支持的c版本 set(CMAKE_CXX_STANDARD 17)#搜索所有的.cpp&#xff0c;加…

【LeetCode】回溯

labuladong回溯 回溯算法秒杀所有排列-组合-子集问题 回溯 一个回溯问题&#xff0c;实际上就是遍历一棵决策树的过程&#xff0c;树的每个叶子节点存放着一个合法答案。你把整棵树遍历一遍&#xff0c;把叶子节点上的答案都收集起来&#xff0c;就能得到所有的合法答案。 站…

Unity---Lua语言

Lua Binaries Download 13.2 逻辑热更新——Lua1-3_哔哩哔哩_bilibili nil表示空 只有false和nil为false&#xff0c;其他值都为true ..连接两个字符串

docker基础(八)之docker commit,docker tag,docker cp,docker diff

文章目录 概述docker commit语法OPTIONS说明&#xff1a;docker commit --help实例使用场景 docker tag语法示例使用场景为什么要这样做呢&#xff1f; docker cp语法OPTIONS说明&#xff1a;docker cp --help示例 docker diff语法示例使用场景&#xff1a; 概述 用于学习和记…

Java学习day1

打开命令提示符&#xff08;cmd&#xff09;窗口&#xff1a; 按下winR键&#xff0c;输入cmd 按回车或点击确定&#xff0c;打开cmd窗口 常用cmd命令 盘符名称冒号&#xff08;D:)&#xff1a;盘符切换&#xff0c;示例表示由C盘切换到D盘 dir&#xff1a;查看当前路径下的内…

第十节HarmonyOS 常用容器组件2-Counter

1、描述 计数器组件&#xff0c;提供相应的增加或者减少的计数操作。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 2、子组件 可以包含子组件。 3、接口 Counter() 从API version 9开始…

9.串口通信

串口基本认识 串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方 式的扩展接口。串行接口&#xff08;Serial Interface&#xff09;是指数据一位一位地顺序传送。其特点是通信线路简 单&#x…

Redis五种数据结构,以及所对应在大厂中的实战应用

Redis五种数据结构&#xff0c;以及所对应在大厂中的实战 String应用场景&#xff08;单值缓存、对象缓存、分布式锁、计数器、存储session集群共享、分布式全局序列号&#xff09; Hash应用场景对象缓存、电商购物车、购物车操作优点&#xff1a;1. 同类别归类存储 2. 消耗更小…

day11【网络编程】-综合案例

day11【网络编程】 第三章 综合案例 3.1 文件上传案例 文件上传分析图解 【客户端】输入流&#xff0c;从硬盘读取文件数据到程序中。【客户端】输出流&#xff0c;写出文件数据到服务端。【服务端】输入流&#xff0c;读取文件数据到服务端程序。【服务端】输出流&#xf…

java 泛型(中)

本篇文章主要说明的是泛型类、泛型接口、泛型方法等。 在学习之前&#xff0c;希望能对泛型有个大概了解&#xff0c;可参考链接 java 泛型&#xff08;上&#xff09;-CSDN博客 1、泛型类 &#xff08;1&#xff09;格式&#xff1a;修饰符 class 类名<类型>{} &…

CI/CD环境搭建

服务简介 Gitlab 官网&#xff1a;https://about.gitlab.com/ GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务。安装方法是参考GitLab在GitHub上的Wiki页面。Gitlab是被广泛使用的基于git的开源代码管…

2024阿里云服务器99计划优惠活动_开年采购季优惠价格表

2024阿里云开年采购活动3月优惠&#xff0c;99计划云服务器99元一年、免费领取上云扶持优惠券&#xff0c;不只是云服务器、云数据库、存储、云电脑、域名等均有活动&#xff0c;阿里云服务器网aliyunfuwuqi.com整理阿里云开年采购上云无忧活动入口、优惠价格表和优惠券领取详细…

unbantu Apache的基本配置与配置静态资源访问

目录 前言: 1.Apache介绍 2.安装Apache 3. 测试Apache服务是否启动成功 3.1配置Servername 3.2重启服务 4.配置Apache主页面 5. 配置静态的资源 6.为静态资源设置访问权限(基于源地址) 致谢: 前言: 此博客是基于unbantu的Apache服务的详细解析&#xff0c;在这片博…

QPainter绘图和QChart图表和QCustomplot绘曲线图

一&#xff0c;QPainter绘图 Qt里的所有绘图&#xff0c;比如一个按钮和一个Label的显示&#xff0c;都有绘图系统来执行。绘图系统基于 QPainter、QPaintDevice和QPainEngine类。QPainter是可以直接用来操作绘图的类&#xff0c;而 QPaintDevice和QPainEngine都比QPainter更底…

TCP | TCP协议格式 | 三次握手

1.TCP协议 为什么需要 TCP 协议 &#xff1f;TCP 工作在哪一层&#xff1f; IP网络层是不可靠的&#xff0c;TCP工作在传输层&#xff0c;保证数据传输的可靠性。 TCP全称为 “传输控制协议&#xff08;Transmission Control Protocol”&#xff09;。 TCP 是面向连接的、可靠…

DBO优化高斯回归预测(matlab代码)

DBO-高斯回归预测matlab代码 蜣螂优化算法(Dung Beetle Optimizer, DBO)是一种新型的群智能优化算法&#xff0c;在2022年底提出&#xff0c;主要是受蜣螂的的滚球、跳舞、觅食、偷窃和繁殖行为的启发。 数据为Excel股票预测数据。 数据集划分为训练集、验证集、测试集,比例…

GESP图形化编程四级认证真题 2024年3月

GESP 图形化四级试卷 &#xff08;满分&#xff1a;100 分 考试时间&#xff1a;120 分钟&#xff09; 一、单选题&#xff08;共 10 题&#xff0c;每题 2 分&#xff0c;共 30 分&#xff09; 1、小杨的父母最近刚刚给他买了一块华为手表&#xff0c;他说手表…

PyTorch深度学习:遥感影像地物分类的高效工具

我国高分辨率对地观测系统重大专项已全面启动&#xff0c;高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成&#xff0c;将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB&#xff0c;遥感大数据时…

JMeter 环境安装及配置

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…