记录--怎么写一个可以鼠标控制旋转的div?

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

说在前面

鼠标控制元素旋转在现在也是一个很常见的功能,让我们从实现div元素的旋转控制开始来了解元素旋转的具体原理和实现方法吧。

效果展示

体验地址

code.juejin.cn/pen/7290719…

实现步骤

画一个div

首先我们需要先画一个div,并在它上方加上旋转图标,我们可以通过这个图标来对div进行旋转,具体代码如下:

<!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><link rel="stylesheet" href="./index.css" /></head><body><div class="container"><div class="rotate-div"><div class="rotate-icon">↻</div></div></div></body><script src="./index.js"></script>
</html>

加点css

将div设置为红色背景的方块,调整旋转图标的位置,具体代码如下:

.container {display: flex;justify-content: center;align-items: center;height: 100vh;
}.rotate-div {position: relative;width: 200px;height: 200px;background-color: red;transform-origin: center center;
}.rotate-icon {position: absolute;top: -50px; /* 调整图标的位置 */left: 50%;transform: translateX(-50%);font-size: 20px;cursor: pointer;
}

效果如下:

完成鼠标拖拽旋转功能

鼠标在旋转图标按下的时候,我们需要监听鼠标移动事件,根据鼠标移动位置和初始点击位置的相对角度来计算方块旋转的角度。

1、获取方块和旋转图标元素对象

首先我们要先获取方块和旋转图标元素对象,便于后续事件监听和元素操作。

const rotateDiv = document.querySelector(".rotate-div");
const rotateIcon = document.querySelector(".rotate-icon");

返回值类型:TextRectangle对象,每个矩形具有四个整数性质( 上, 右 , 下,和左 )表示的坐标的矩形,以像素为单位。

 rectObject.top:元素上边到视窗上边的距离;

 rectObject.right:元素右边到视窗左边的距离;

 rectObject.bottom:元素下边到视窗上边的距离;

 rectObject.left:元素左边到视窗左边的距离;

我们记录下方块的初始中心点:

 const centerX = rect.left + rect.width / 2;const centerY = rect.top + rect.height / 2;
(2)计算旋转角度

Math.atan2()

  • 概述

Math.atan2()  返回从原点 (0,0) 到 (x,y) 点的线段与 x 轴正方向之间的平面角度 (弧度值),也就是 Math.atan2(y,x)

  • 语法
Math.atan2(y, x)
  • 参数

y, x

  • 描述

atan2 方法返回一个 -pi 到 pi 之间的数值,表示点 (x, y) 对应的偏移角度。这是一个逆时针角度,以弧度为单位,正 X 轴和点 (x, y) 与原点连线 之间。注意此函数接受的参数:先传递 y 坐标,然后是 x 坐标。

atan2 接受单独的 x 和 y 参数,而 atan 接受两个参数的比值。

由于 atan2 是 Math 的静态方法,所以应该像这样使用:Math.atan2(),而不是作为你创建的 Math 实例的方法。

function getAngle(centerX, centerY, mouseX, mouseY) {return Math.atan2(mouseY - centerY, mouseX - centerX) * (180 / Math.PI);
}

使用当前鼠标位置相对角度减去鼠标初始点击点的相对角度即可得到鼠标旋转的角度。

startingMouseAngle = getAngle(centerX, centerY, event.clientX, event.clientY);
const deltaMouseAngle = currentMouseAngle - startingMouseAngle;
(3)旋转角度简化

方块的最大旋转角度为360度,所以我们对角度进行取模,保持旋转角度在360度以内即可。

function normalizeRotation(rotation) {if (rotation >= 0) {return rotation % 360;} else {return (rotation % 360) + 360;}
}
(4)给方块设置旋转角度
rotateDiv.style.transform = `rotate(${newRotation}deg)`;
3、移除旋转逻辑

鼠标抬起的时候我们应该将旋转逻辑给移除,及将鼠标移动和抬起事件移除。

function stopSpin() {window.removeEventListener("mousemove", spin);window.removeEventListener("mouseup", stopSpin);
}
4、完整代码

完整的JavaScrip代码如下:

const rotateDiv = document.querySelector(".rotate-div");
const rotateIcon = document.querySelector(".rotate-icon");let startingMouseAngle = 0;
let startingRotation = 0;rotateIcon.addEventListener("selectstart", function (event) {event.preventDefault();
});
rotateIcon.addEventListener("mousedown", function (event) {const rect = rotateDiv.getBoundingClientRect();const centerX = rect.left + rect.width / 2;const centerY = rect.top + rect.height / 2;startingMouseAngle = getAngle(centerX, centerY, event.clientX, event.clientY);startingRotation = getCurrentRotation();window.addEventListener("mousemove", spin);window.addEventListener("mouseup", stopSpin);
});function stopSpin() {window.removeEventListener("mousemove", spin);window.removeEventListener("mouseup", stopSpin);
}function spin(event) {const rect = rotateDiv.getBoundingClientRect();const centerX = rect.left + rect.width / 2;const centerY = rect.top + rect.height / 2;const currentMouseAngle = getAngle(centerX,centerY,event.clientX,event.clientY);const deltaMouseAngle = currentMouseAngle - startingMouseAngle;let newRotation = startingRotation + deltaMouseAngle;newRotation = normalizeRotation(newRotation);rotateDiv.style.transform = `rotate(${newRotation}deg)`;
}function normalizeRotation(rotation) {if (rotation >= 0) {return rotation % 360;} else {return (rotation % 360) + 360;}
}function getAngle(centerX, centerY, mouseX, mouseY) {return Math.atan2(mouseY - centerY, mouseX - centerX) * (180 / Math.PI);
}function getCurrentRotation() {const transformStyle = window.getComputedStyle(rotateDiv).getPropertyValue("transform");const matrix = new DOMMatrixReadOnly(transformStyle);const angle = Math.acos(matrix.a) * (180 / Math.PI);return matrix.b < 0 ? -angle : angle;
}

本文转载于:

https://juejin.cn/post/7290410631655292969

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

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

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

相关文章

C++设计模式_08_Factory Method工厂方法模式

文章目录 1. “对象创建模式”模式1.1 典型模式 2. 动机&#xff08;Motivation&#xff09;3. 代码演示Factory Method工厂方法模式3.1 常规方法3.2 面向接口的编程3.2.1 FileSplitter1.cpp3.2.2 MainForm1.cpp 3.3 Factory Method工厂方法3.3.1 ISplitterFactory.cpp3.3.2 Ma…

只需五步,在Linux安装chrome及chromedriver(CentOS)

一、安装Chrome 1&#xff09;先执行命令下载chrome&#xff1a; wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm2&#xff09;安装chrome yum localinstall google-chrome-stable_current_x86_64.rpm看到下图中的Complete出现则代表安装…

分布式锁之mysql 锁

文章目录 使用数据锁&#xff1a;悲观锁 或者 乐观锁悲观锁乐观锁mysql锁总结 使用数据锁&#xff1a;悲观锁 或者 乐观锁 一个sql&#xff1a;直接更新时判断&#xff0c;在更新中判断库存是否大于0 update table set surplus (surplus - buyQuantity) where id 1 and (surp…

记录阿里云服务器(Centos7.9)部署Thingsboard(3.4.2)遇到的一些问题

记录编译Thingsboard遇到的一些问题 部署了一个thingsboard项目到阿里云服务器上&#xff0c;历时十一天&#xff0c;遇到了很多困难&#xff0c;国内关于Thingsboard的资料确实很少&#xff0c;所以想着写一篇博客记录一下&#xff0c;或许能够给以后编译遇到类似问题的人一些…

Python+playwright 实现Web UI自动化

实现Web UI自动化 技术&#xff1a;Pythonplaywright 目标&#xff1a;自动打开百度浏览器&#xff0c;并搜索“亚运会 金牌榜” 需安装&#xff1a;Playwright &#xff08;不用安装浏览器驱动&#xff09; # 使用浏览器&#xff0c;并可视化打开 browser playwright.ch…

tomcat、nginx实现四层转发+七层代理+动静分离实验

实验环境&#xff1a; nginx1——20.0.0.11——客户端 静态页面&#xff1a; nginx2——20.0.0.21——代理服务器1 nginx3——20.0.0.31——代理服务器2 动态页面&#xff1a; tomcat1——20.0.0.12——后端服务器1 tomcat2——20.0.0.22——后端服务器2 实验步骤&…

【CANoe】文件处理_hex文件读取解析

hex文件里面只有00&#xff0c;01&#xff0c;04三种码。那么我们在解析的时候只需要对这三种不同状态的进行不同的解析即可。 hex文件格式的解析&#xff0c;可阅读&#xff1a;HEX文件格式详解 首先创建一个Block的结构体&#xff0c;根据经验我们知道&#xff0c;一个数据…

EthernetIP 转MODBUS RTU协议网关连接FANUC机器人作为EthernetIP通信从站

远创智控YC-EIPM-RTU网关产品是一款高效的数据采集工具&#xff0c;它可以通过各种数据接口与工业领域的仪表、PLC、计量设备等产品连接&#xff0c;实时采集这些设备中的运行数据、状态数据等信息。采集到的数据经过整合和运算等操作后&#xff0c;可以被传输到其他设备或者云…

【C++】stackqueue

适配器是一种设计模式 &#xff0c; 该种模式是将一个类的接口转换成客户希望的另外一个接口 。 虽然 stack 和 queue 中也可以存放元素&#xff0c;但在 STL 中并没有将其划分在容器的行列&#xff0c;而是将其称为 容器适配 器 &#xff0c;这是因为 stack 和队列只是对其他容…

linux上在docker中使用anaconda创建虚拟环境

conda的一些命令以及创建环境的基本命令可参考&#xff1a;Conda环境搭建以及激活 以及 conda 本地环境常用操作 前言 这里是梳理linux上在docker中使用conda&#xff0c;以配置MLD-TResNet-L-AAM模型为例。论文笔记参考&#xff1a;多标签分类论文笔记 | Combining Metric Lea…

分类选择,最多五级

效果图&#xff0c;这种竖向的分类选择&#xff0c;每一列可以用不同的背景颜色 组件代码 <template><view class"toolTypeBox" :style"max-height:${maxHeight}"><block v-for"(item,index) in datalist"><block v-if&…

企业c#语言源代码防泄密解决方案

在当今数字化时代&#xff0c;企业的核心业务往往依赖于软件应用程序。为了保护企业的知识产权和敏感信息&#xff0c;源代码的保密至关重要。对于制造类企业尤其是智能制造业来讲&#xff0c;最近几年是高速发展的时期&#xff0c;很多公司在做工厂流水线设备时&#xff0c;就…

Python学习笔记——类、魔术方法

食用说明&#xff1a;本笔记适用于有一定编程基础的伙伴们。希望有助于各位&#xff01; 类 类的运用很常见&#xff1a;在大部分情况下&#xff0c;对一些特有的对象&#xff0c;可以使用特定的类来指向它&#xff1a; class Person:name unknownage -1sex 0partner No…

微信小程序三种授权登录以及授权登录流程讲解

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《微信小程序开发实战》。&#x1f3af;&#x1f3a…

小县城蔬菜配送小程序制作全攻略

随着互联网的普及和人们对生活品质要求的提高&#xff0c;越来越多的小县城开始开发蔬菜配送小程序&#xff0c;以满足当地居民对新鲜蔬菜的需求。制作一个小县城蔬菜配送小程序&#xff0c;需要经过以下步骤&#xff1a; 步骤一&#xff1a;登录乔拓云平台 首先&#xff0c;打…

揭开 Amazon Bedrock 的神秘面纱 | 基础篇

在 2023 年 4 月&#xff0c;亚马逊云科技曾宣布将 Amazon Bedrock 纳入使用生成式人工智能进行构建的新工具集。Amazon Bedrock 是一项完全托管的服务&#xff0c;提供各种来自领先 AI 公司&#xff08;包括 AI21 Labs、Anthropic、Cohere、Stability AI 和 Amazon 等&#xf…

Android音视频开发之基础知识

一、视频文件 1、视频格式 常见格式&#xff1a;mp4、mkv、flv 封装的数据&#xff1a;音频码流、视频码流 常用工具&#xff1a; [FFmpeg下载]:https://ffmpeg.org/download.html 下载、安装并配置环境变量 ffmpeg.exe 视频编解码 ffplay.exe 播放器库 ffprobe.exe 音视频分…

git(部分)

1、git三个区域&#xff1a;工作区&#xff0c;暂存区&#xff0c;版本库 2、git文件状态&#xff1a;未跟踪&#xff0c;已跟踪&#xff08;新添加&#xff0c;未修改&#xff0c;已修改&#xff09; 如何查看暂存区和工作区文件状态&#xff1a;git status -s 3、查看版本记…

mysql MVC jsp实现表分页

mysql是轻量级数据库 在三层架构中实现简单的分页 在数据库sql编程中需要编写sql语句 SELECT * FROM sys.student limit 5,5; limit x,y x是开始节点&#xff0c;y是开始节点后的需要显示的长度。 在jdbc编程中需要给出x和y 一般是页数*页码&#xff0c;显示的长度。 代…

【(数据结构)—— 基于单链表实现通讯录】

&#xff08;数据结构&#xff09;—— 基于单链表实现通讯录 一.通讯录的功能介绍1.基于单链表实现通讯录(1). 知识要求(2). 功能要求 二.通讯录的代码实现1.通讯录的底层结构(单链表)(1).思路展示(2).底层代码实现(单链表)1.单链表头文件 —— &#xff08;函数的定义&#x…