旋转时使用拖动手柄调整 div 大小

2024-04-08

我可以找到类似的问题,涉及 jQuery UI lib,或者只有 css,没有可拖动的句柄,但没有任何纯数学问题。

我尝试执行的是拥有一个可调整大小和可旋转的 div。到目前为止很容易,我可以做到。

但旋转时会变得更加复杂,调整大小以相反的方式处理剂量计算:当拖离形状时,它会减小而不是增加。

除了计算之外,我希望能够根据旋转来更改调整大小手柄的光标,以始终有意义。 为此,我正在考虑检测哪个象限是调整大小句柄,并应用一个类来通过 css 更改光标。

  1. 我不想重新发明轮子,但我想要轻量级的代码和简单的 UI。所以我的要求是 jQuery,除此之外别无其他。没有 jQuery UI。
  2. 我可以开发直到实现这一点,但现在对我来说太数学化了。我很困惑,这就是为什么我需要你的帮助来检测旋转何时足以反转计算。

最终,如果有人有想法或更好的例子向我展示,我将寻求用户体验改进!

这是我的代码和一个可以尝试的 Codepen:http://codepen.io/anon/pen/rrAWJA http://codepen.io/anon/pen/rrAWJA

<html>
<head>
    <style>
    html, body {height: 100%;}

    #square {
        width: 100px;
        height: 100px;
        margin: 20% auto;
        background: orange;
        position: relative;
    }
    .handle * {
        position: absolute;
        width: 20px;
        height: 20px;
        background: turquoise;
        border-radius: 20px;
    }
    .resize {
        bottom: -10px;
        right: -10px;
        cursor: nwse-resize;
    }
    .rotate {
        top: -10px;
        right: -10px;
        cursor: alias;
    }
    </style>
    <script type="text/javascript" src="js/jquery.js"></script>
    <script>
        $(document).ready(function()
        {
            new resizeRotate('#square');
        });

        var resizeRotate = function(targetElement)
        {
            var self = this;
            self.target = $(targetElement);
            self.handles = $('<div class="handle"><div class="resize" data-position="bottom-right"></div><div class="rotate"></div></div>');
            self.currentRotation = 0;
            self.positions = ['bottom-right', 'bottom-left', 'top-left', 'top-right'];

            self.bindEvents = function()
            {
                self.handles
                    //=============================== Resize ==============================//
                    .on('mousedown', '.resize', function(e)
                    {
                        // Attach mouse move event only when first clicked.
                        $(document).on('mousemove', function(e)
                        {
                            var topLeft = self.target.offset(),
                                bottomRight = {x: topLeft.left + self.target.width(), y: topLeft.top + self.target.height()},
                                delta = {x: e.pageX - bottomRight.x, y: e.pageY - bottomRight.y};

                            self.target.css({width: '+=' + delta.x, height: '+=' + delta.y});
                        })
                        .one('mouseup', function(e)
                        {
                            // When releasing handle, round up width and height values :)
                            self.target.css({width: parseInt(self.target.width()), height: parseInt(self.target.height())});
                            $(document).off('mousemove');
                        });
                    })
                    //============================== Rotate ===============================//
                    .on('mousedown', '.rotate', function(e)
                    {
                        // Attach mouse move event only when first clicked.
                        $(document).on('mousemove', function(e)
                        {
                            var topLeft = self.target.offset(),
                                center = {x: topLeft.left + self.target.width() / 2, y: topLeft.top + self.target.height() / 2},
                                rad = Math.atan2(e.pageX - center.x, e.pageY - center.y),
                                deg = (rad * (180 / Math.PI) * -1) + 135;

                            self.currentRotation = deg;
                            // console.log(rad, deg);
                            self.target.css({transform: 'rotate(' + (deg)+ 'deg)'});
                        })
                        .one('mouseup', function(e)
                        {
                            $(document).off('mousemove');
                            // console.log(self.positions[parseInt(self.currentRotation/90-45)]);
                            $('.handle.resize').attr('data-position', self.positions[parseInt(self.currentRotation/90-45)]);
                        });
                    });
            };
            self.init = function()
            {
                self.bindEvents();
                self.target.append(self.handles.clone(true));
            }();
        }
    </script>
</head>
<body>
    <div id="all">
        <div id="square"></div>
    </div>
</body>
</html>

谢谢您的帮助!


这是对代码的修改,可以实现您想要的效果:

$(document).ready(function() {
  new resizeRotate('#square');
});

var resizeRotate = function(targetElement) {
  var self = this;
  self.target = $(targetElement);
  self.handles = $('<div class="handle"><div class="resize" data-position="bottom-right"></div><div class="rotate"></div></div>');
  self.currentRotation = 0;
  self.w = parseInt(self.target.width());
  self.h = parseInt(self.target.height());
  self.positions = ['bottom-right', 'bottom-left', 'top-left', 'top-right'];

  self.bindEvents = function() {
    self.handles
      //=============================== Resize ==============================//
      .on('mousedown', '.resize', function(e) {
        // Attach mouse move event only when first clicked.
        $(document).on('mousemove', function(e) {
            var topLeft = self.target.offset();           

            var centerX = topLeft.left + self.target.width() / 2;
            var centerY = topLeft.top + self.target.height() / 2;

            var mouseRelativeX = e.pageX - centerX;
            var mouseRelativeY = e.pageY - centerY;

            //reverse rotation
            var rad = self.currentRotation * Math.PI / 180;
            var s = Math.sin(rad);
            var c = Math.cos(rad);
            var mouseLocalX = c * mouseRelativeX + s * mouseRelativeY;
            var mouseLocalY = -s * mouseRelativeX + c * mouseRelativeY;

            self.w = 2 * mouseLocalX;
            self.h = 2 * mouseLocalY;
            self.target.css({
              width: self.w,
              height: self.h
            });
          })
          .one('mouseup', function(e) {
                $(document).off('mousemove');
          });
      })
      //============================== Rotate ===============================//
      .on('mousedown', '.rotate', function(e) {
        // Attach mouse move event only when first clicked.
        $(document).on('mousemove', function(e) {
            var topLeft = self.target.offset(),
              center = {
                x: topLeft.left + self.target.width() / 2,
                y: topLeft.top + self.target.height() / 2
              },
              rad = Math.atan2(e.pageX - center.x, center.y - e.pageY) - Math.atan(self.w / self.h),
              deg = rad * 180 / Math.PI;

            self.currentRotation = deg;
            self.target.css({
              transform: 'rotate(' + (deg) + 'deg)'
            });
          })
          .one('mouseup', function(e) {
            $(document).off('mousemove');
            $('.handle.resize').attr('data-position', self.positions[parseInt(self.currentRotation / 90 - 45)]);
          });
      });
  };
  self.init = function() {
    self.bindEvents();
    self.target.append(self.handles.clone(true));
  }();
}

主要变化如下:

在resize事件中,鼠标位置根据当前旋转变换到本地坐标系。然后,大小由鼠标在本地系统中的位置确定。

旋转事件考虑了盒子的纵横比(- Math.atan(self.w / self.h) part).

如果您想根据当前旋转更改光标,请检查手柄的角度(即self.currentRotation + Math.atan(self.w / self.h) * 180 / Math.PI)。例如。如果每个象限都有一个光标,只需检查该值是否在 0..90、90..180 等之间。您可能需要检查文档是否以及何时返回负数atan2.

注意:偶尔闪烁是由于盒子未垂直居中造成的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

旋转时使用拖动手柄调整 div 大小 的相关文章

  • 如何向 jquery-file-upload basic-plugin 添加取消上传按钮

    我正在使用 jquery file upload 和 Rails 4 我从https github com tors jquery fileupload rails paperclip example https github com to
  • 以一定时间间隔连续重复运行 JavaScript 函数

    这是我的第一个问题 希望您尽快回答 我想要代码连续重复一个函数 我尝试了一些代码 但没有成功 我尝试了这段代码 我想在一段时间后重复这个功能 我努力了setInterval and setTimeout 但是 我还没有收到结果 这将重复该任
  • 启用/禁用由用户输入确定的复选框

    我有一个简单的表单 用户可以在其中输入他的联系号码 如果联系号码以 07 开头 则该复选框已启用 其他我需要禁用它的复选框 我已经编写了一些代码 但我面临的问题是 当用户键入 01 时 它会被禁用 但如果他们继续在 01 之后添加任何其他数
  • 如何动态突出显示网页上的字符串?

    我想创建带有 url 的页面 例如 http xyzcorp schedules 2015Aug24 Aug28 Jim Hawkins http xyzcorp schedules 2015Aug24 Aug28 Billy Bones
  • 搜索深度嵌套数组以更新对象

    我有一个深层嵌套的数据结构 我有兴趣匹配数组 和数组数组 中的某个值 然后将一些数据推送到随附的数组中 例如以下是我的数组colors并伴随着的是更多颜色数组可能存在也可能不存在 var myData color green moreCol
  • 确定元素是在页面折叠上方还是下方

    我有一些页面有多个输入框 用户可以在其中输入文本 在单击 下一步 按钮之前 需要填写其中一些内容 我弹出验证错误供用户查看 但是如果问题不在页面上 我希望页面滚动到它 而不是他们必须搜索丢失 错误的字段 我有一个滚动到位 但我无法确定要滚动
  • 如何更改自动完成中的结果过滤器?

    我不想进行字面匹配 而是想通过正则表达式选择结果 我可以覆盖自动完成的默认行为来完成此任务还是需要替代结构 有一个内置的方法可以做到这一点 只需提供一个函数source http jqueryui com demos autocomplet
  • 为什么 Web Worker 性能在 30 秒后急剧下降?

    我正在尝试提高在网络工作人员中执行时脚本的性能 它旨在解析浏览器中的大型文本文件而不会崩溃 一切都运行得很好 但我注意到使用网络工作者时大文件的性能存在严重差异 于是我做了一个简单的实验 我在同一输入上运行脚本两次 第一次运行在页面的主线程
  • 为什么将 x 和 y 设置为 0 时 svg 文本会消失?

    我刚刚开始阅读有关svg我提出了以下问题 我正在创建一个简单的svg with a text里面如下图所示 从我的阅读中我了解到x and y of the text标签声明文本在标签内的位置svg space 为什么当我同时设置x and
  • 如何打开弹出窗口并用父窗口中的数据填充它?

    如何使用 JavaScript jQuery 使用父页面中 JS 变量的数据填充弹出窗口 在我的示例中 我有一个文件名数组 我在父窗口中最多列出五个 如果还有更多 我想提供一个链接来打开弹出窗口并列出数组中的每个帖子 因此 如果我打开一个包
  • 如何在 ASP.NET MVC 3 的 Razor 视图中编码嵌入的 javascript?

    如何在以下上下文中正确编码 JavaScript 我的 JSON 对象中的值是由应用程序管理员设置的 因此我假设它们需要正确编码 对于 HTML 和 JavaScript 都是如此 我在用着System Web Script Seriali
  • jQuery - 系列之外的 HighCharts 标签(条形图)

    function container highcharts chart type bar backgroundColor null width 360 title text null style display none subtitle
  • 如何处理requireJs超时错误?

    我正在使用 require js 作为加载框架编写一个移动混合应用程序 我遇到加载错误的问题 我想做的是在设备离线且无法下载在屏幕上显示地图所需的 google 地图 API 脚本时设置后备解决方案 我得到的只是 Uncaught Erro
  • JavaScript 数组扩展语法的时间复杂度是多少?

    我想知道在 JavaScript 中使用数组扩展的时间复杂度是多少 是线性 O n 还是常数 O 1 下面的语法示例 let lar Math max nums 传播称为 Symbol iterator 有关对象的属性 对于数组 这将迭代数
  • MongoDB中如何通过引用字段进行查询?

    我有两个 Mongo 模式 User id ObjectId name String country ObjectId Reference to schema Country Country id ObjectId name String
  • 在 HTML5 iOS 7 / iOS 8 中显示十进制键盘

    经过几个小时的搜索后 我只是有一个简单的问题 是否有可能在网络浏览器输入字段中显示小数键盘 input type number 只显示数字 但我需要在左下角使用逗号或点 我尝试过任何事情 pattern step等等 但没有显示十进制键盘
  • Node npm 包抛出使用严格:全局发布和安装后未找到命令

    我正在尝试发布 npm 包 当我全局安装该包并尝试运行 cli 命令时 我收到此错误 nvm versions node v0 12 2 bin myPack line 1 use strict command not found nvm
  • Flowtype 属性“msg”缺失为 null 或未定义

    我发现 Flow 很难用 我明白那个Array find可以返回或未定义 因此 通过阅读以下内容 github Array find on Array 引发 https github com facebook flow issues 351
  • 使用 JQuery 根据下拉列表选择的值显示/隐藏控件

    我正在尝试使用 JQuery 根据下拉菜单的选定索引显示 隐藏 div 标签 但它不起作用 任何帮助将不胜感激 Thanks
  • 在 PHP 中模拟 jQuery.ajax 请求

    我必须在 PHP 中模拟 AJAX 请求 就像在 jQuery 中一样 我当前的代码在这里 原始 AJAX 调用 不得修改 ajax type POST url someFile php data data success function

随机推荐

  • 如何不在uinavigationcontroller中调用viewdidload?

    我正在寻找针对我的情况的解决方案 我的应用程序如下 VC1 上有一个文本字段和按钮 用户键入名称 然后单击一个按钮 该按钮打开VC2 用户在 VC2 中提供附加信息 然后按 保存 我使用 segue 返回 VC1 并将这些附加信息作为字符串
  • 如何将 Istanbul Code Coverage 与转译的 Typescript 结合使用?

    我整个早上都在阅读有关此问题的文章 试图正确设置我的环境 但由于某种原因我不明白 我的设置 app source mixed js and ts scripts copied source js typescripts js transpi
  • 为什么我的 Azure Function 功能密钥不断重新生成?

    我有六种不同的 Azure 函数 每天会被调用数百次 不过 其中一个与其他任何一个实际上没有什么不同 开发了一项新的 功能 每隔几天 它就会更改功能键 该功能密钥用于对功能进行身份验证 因此每当它发生变化时就会中断我们的流程 原始密钥 以及
  • 如何使用 C# 从 FTP 服务器获取一系列文件

    我陷入了这样一个境地 我将通配符参数与 FtpWebRequest 对象一起使用 很糟糕 FtpWebRequest reqFTP FtpWebRequest FtpWebRequest Create new Uri ftp ftpServ
  • 方程解析库 C++ [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何进行 git rebase 并保留提交时间戳?

    我想进行变基以从我的历史记录中删除某个提交 我知道该怎么做 但是 如果我这样做 提交时间戳将设置为我完成变基的那一刻 我希望提交保留时间戳 我在这里看到了最后一个答案 https stackoverflow com a 19522951 3
  • 在 vega-lite 中实现自定义点击处理程序的正确方法是什么

    我似乎无法通过阅读文档来弄清楚这一点 有没有办法实现onClick我的任何标记的事件处理程序 由于 Vega Lite 尚不支持信号 您可以修补生成的 Vega 您可以将信号添加到已编译的 Vega 规范中 然后通过 Vega 视图 API
  • Logback:如何将日志目录从“tomcat/bin”更改为与应用程序相关的?

    我想用slf4j with logback用于记录 您可以在下面看到我的 logback xml
  • Android SmsRetrieverClient 的短信验证不解析消息

    尝试按照此处的步骤实现短信自动读取以进行验证 https developers google com identity sms retriever request https developers google com identity s
  • 如何在 Spring Data REST 项目中使用 DTO?

    Spring Data REST 自动仅公开域对象 但大多数情况下我们必须处理数据传输对象 那么如何以SDR方式做到这一点呢 一种如何合作的方法DTO https en wikipedia org wiki Data transfer ob
  • 如何在 Visual Studio Code 中获取 Unity 函数名称的智能感知?

    我正在关注有关 Unity 的教程 我发现讲师在编写方法名称时具有智能感知功能 然而 我只有类和变量的智能感知 我的意思是像 Rigidbody 这样的 Unity 类和我自己的变量 我还读过 自动补全在 Visual Studio 中不起
  • Android apk 构建的条件资源包含/排除

    我不断回到这个问题 因为似乎没有一个干净的解决方案 有没有人有一个好的策略来从 Android 子项目中排除资源 我有两种情况 1 基础库项目具有 en es 等本地化文件 子项目1使用所有本地化 一切都很好 子项目 2 仅本地化为英语 但
  • Bookdown:如何更改章节标题的大小?

    我正在使用 bookdown 为研讨会生成幻灯片 我使用菜单中的 大 字母选项来显示幻灯片 但是章节标题字体太大 我在哪里 如何修改那个 Thanks Paul 你可以用 css 来控制它yihui https stackoverflow
  • Keycloak Java 管理客户端在触发验证电子邮件时返回 400 错误

    我在 Spring Boot 2 2 上使用 keycloak 服务器版本 8 0 1 和 keycloak java admin 客户端版本 8 0 1 使用 webflux 和 netty 而不是 tomcat 如果此类信息有帮助的话
  • Python - “ascii”编解码器无法解码字节

    我正在使用 Python 2 6 和 Jinja2 创建 HTML 报告 我为模板提供了许多结果 模板循环遍历它们并创建 HTML 表 当调用 template render 时 我突然开始收到此错误 td result result st
  • sorl-缩略图不起作用

    我已经尝试了几个小时来让 sorl thumbnail 工作 但它就是行不通 困难的部分是它没有显示错误 所以我不知道出了什么问题 我按照说明安装了它 我的完整代码可以在这里找到 https github com samos123 Samo
  • 在同一个表上触发 INSERT 和 UPDATE

    众所周知 实体框架无法保存地理数据 所以我的想法是 在我的模型中将经度和纬度指定为十进制 执行用于创建表的 SQL 脚本后 我将启动另一个脚本来添加地理列 然后我想通过触发器在每次插入或更新 经度和纬度 时更新此列 下面的触发器是好的还是坏
  • 在新机器上部署.net应用程序并得到“系统无法执行指定的程序”

    我有一个启动 Excel 的 net 控制台应用程序 我让它在我的开发环境中运行 但我无法让它在我的生产环境中运行 当我尝试运行它时 收到以下错误 系统无法执行指定的程序 我已经在我的生产服务器上安装了 net 2 0 sp2 有任何想法吗
  • PyQT 列表视图不响应数据更改信号

    我一直在关注一些教程并尝试设置列表模型 我的主窗口有两个访问同一模型的列表视图 当我更新一个列表中的一项时 另一个列表不会自行更新 直到它获得焦点 我单击它 所以看起来 dataChanged 信号没有被发出 但我无法弄清楚我的代码与我所基
  • 旋转时使用拖动手柄调整 div 大小

    我可以找到类似的问题 涉及 jQuery UI lib 或者只有 css 没有可拖动的句柄 但没有任何纯数学问题 我尝试执行的是拥有一个可调整大小和可旋转的 div 到目前为止很容易 我可以做到 但旋转时会变得更加复杂 调整大小以相反的方式