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

提示:canvas画线

文章目录


前言

一、带透明度的线

test.html

c 复制代码
<!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

c 复制代码
<!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>

三、试错,只存上一次的点,线会出现断裂的情况

c 复制代码
<!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>

总结

踩坑路漫漫长@~@

相关推荐
鬼手点金1 小时前
nanoGPT/nanochat 能做出 DeepSeek/Qwen 这样的大模型吗?
服务器·前端·javascript·bug·openclaw
软件技术NINI2 小时前
美妆商城html+Css+js 4页
javascript·css·html
蛋蛋的就会顺顺的2 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
码艺-Alimjan3 小时前
Tauri 源码备份 · 打包 & 解压 总结,源码收集之路
前端·javascript·vue.js
死磕音视频3 小时前
让小模型做选择题:限定候选项并读取 logits 概率的入门实践(附 Python 代码)
开发语言·python·大模型·文本分类·transformers
顽疲5 小时前
Java vue 养老系统源码详解:月账单 care_month_bill 与 Quartz 扣费 Job 实践
java·开发语言·vue.js·vue养老·springboot养老·java养老
DevUp5 小时前
标着 JavaScript 的 Wiki 与知识库:既不是 CMS 也不是 SSG(番外三)
javascript·node.js·cms
Wang's Blog5 小时前
Java 项目实战: 交友项目 - 安装开发工具与环境准备
java·开发语言·交友
kyriewen6 小时前
我上手了 Vite+ 1.0:Node 不用自己装,lint 却翻车了
前端·javascript·程序员
鹏多多7 小时前
前端是如何死去的?| 完整时间线
前端·javascript·程序员