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

canvas基础学习(鼠标点位拖拽)

一. 效果

二. 代码

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

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

        body {
            overflow: hidden;
            margin: 0;
            padding: 0;
        }

        #div {
            width: 100%;
            height: 100vh;
        }

        #canvas {
            width: 100%;
            height: 100%;
            background-color: #000;
        }
    </style>
</head>

<body>
    <div id="div">
        <canvas id="canvas"></canvas>
    </div>
    <script>
        // 获取元素
        const canvas = document.getElementById("canvas");
        const div = document.getElementById("div");
        // 获取canvas画布
        const ctx = canvas.getContext("2d");
        // 获取宽高
        const w = div.offsetWidth;
        const h = div.offsetHeight;
        // 设置宽高
        canvas.width = w;
        canvas.height = h;

        // 是否可以拖拽
        let isMove = false
        // 点位对象数组
        let pointList = [];

        // 构造点位函数  批量生产点位
        function Point(x, y, color) {
            // 点位坐标
            this.x = x;
            this.y = y;
            // 点位颜色
            this.color = color;
            // 点位半径
            this.r = 20;
        }

        // 绘制点位函数
        Point.prototype.draw = function () {
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
            ctx.fillStyle = this.color;
            ctx.fill();
        }

        // 鼠标点击事件
        div.addEventListener("mousedown", (e) => {
            // 鼠标的坐标
            let x = e.clientX;
            let y = e.clientY;

            // 点位坐标和鼠标坐标的距离
            for (let i = 0; i < pointList.length; i++) {
                let point = pointList[i];
                // 勾股定理判断  鼠标在点位的半径内
                let distance = Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2));
                if (distance < point.r) {
                    // 将点位放到数组的第一位
                    let obj = pointList[i];
                    pointList[i] = pointList[0]
                    pointList[0] = obj
                    // 开启拖拽
                    isMove = true
                }
            }
        })

        // 鼠标移动事件
        div.addEventListener("mousemove", (e) => {
            // 鼠标的坐标
            let x = e.clientX;
            let y = e.clientY;
            // 判断鼠标是否变为手指
            let boolean = false;
            // 鼠标是否在点位的半径内
            for (let i = 0; i < pointList.length; i++) {
                let point = pointList[i];
                let distance = Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2));
                if (distance < point.r) {
                    // 鼠标变为手指
                    boolean = true
                }
            }

            // 拖拽点位(鼠标点击时已经将拖拽点位提到了点位数组的第一个所以只需要将第一个点位的坐标改为鼠标的坐标即可)
            if (isMove) {
                pointList[0].x = x;
                pointList[0].y = y;
                // 清除画布  
                ctx.clearRect(0, 0, w, h);
                // 重新绘制点位
                for (let i = 0; i < pointList.length; i++) {
                    if (i !== 0) {
                        let point = pointList[i];
                        point.draw();
                    }
                }
                // 最后绘制的点位层级最高
                pointList[0].draw();

            }
            // 鼠标是否变为手指
            if (boolean) {
                div.style.cursor = 'pointer'
            } else {
                div.style.cursor = 'default'
            }

        })

        // 鼠标抬起事件
        div.addEventListener("mouseup", (e) => {
            // 关闭拖拽
            isMove = false
        })

        // 随机生成点位  随机颜色  随机坐标
        for (let i = 0; i < 10; i++) {
            let point = new Point(Math.random() * w, Math.random() * h, "hsl(" + Math.random() * 360 + ", 100%, 50%)");
            pointList.push(point);
            point.draw();
        }


    </script>
</body>

</html>

http://www.kler.cn/a/370235.html

相关文章:

  • 如何使用CRM数据分析优化销售和客户关系?
  • Level2逐笔成交逐笔委托毫秒记录:今日分享优质股票数据20250121
  • Python----Python高级(文件操作open,os模块对于文件操作,shutil模块 )
  • wireshark工具简介
  • C语言之装甲车库车辆动态监控辅助记录系统
  • Jenkins-pipeline Jenkinsfile说明
  • 为什么有的说法是STM32有60个外部中断,有的说法是有23个中断
  • vscode中提升效率的插件扩展——待更新
  • 基于Distil-Whisper的实时ASR【自动语音识别】
  • python实战项目47:Selenium采集百度股市通数据
  • 电商 API 接口:提升用户体验的关键路径深度解析
  • AtCoder ABC376A-D题解
  • 雷池社区版compose文件配置讲解--fvm
  • 分布式并发场景的核心问题与解决方案
  • Java | Leetcode Java题解之第516题最长回文子序列
  • Camp4-L0:Linux 前置基础
  • 招商银行实时汇率查询接口-外汇实时汇率API-外汇实时汇率
  • 云联网对等连接--实现内网互通
  • 解决cuda环境使用dgl
  • ImportError: cannot import name ‘Sequential‘ from ‘keras.models‘
  • 如何将 HashiCorp Vault 与 Node.js 集成:安全管理敏感数据
  • UE5之5.4 第一人称示例代码阅读2 子弹发射逻辑
  • Oracle 第9章:存储过程与函数
  • Android Handler消息机制完全解析-IdleHandler和epoll机制(四)
  • Spring Boot的核心优势及其应用详解
  • 基于SSM(spring+springmvc+mybatis)+MySQL开发的新闻推荐系统