js通过八个点 拖动改变div大小的实现方法

下面是“JS通过八个点拖动改变div大小的实现方法”的完整攻略。

1. 需求分析

我们需要实现一个可以通过拖动八个点来改变一个 div 元素的大小的功能。最好的做法是使用原生 JavaScript 实现,而不是使用第三方类库,这样我们可以更好地理解背后的实现原理。

2. HTML 结构

首先,我们需要准备一个 div 元素,用于展示效果。具体的实现方法是通过在 div 元素上创建八个 span 元素,用于拖动改变 div 元素的大小。

<div class="box">
  <span class="point top-left"></span>
  <span class="point top"></span>
  <span class="point top-right"></span>
  <span class="point right"></span>
  <span class="point bottom-right"></span>
  <span class="point bottom"></span>
  <span class="point bottom-left"></span>
  <span class="point left"></span>
</div>

3. CSS 样式

接下来,我们需要为这些元素添加 CSS 样式。具体实现方式是为 box 和 point 添加相关样式,使其具有接下来我们需要的拖动效果。

.box {
  width: 200px;
  height: 200px;
  background-color: #f0f0f0;
  position: relative;
}

.point {
  width: 10px;
  height: 10px;
  background-color: #333;
  position: absolute;
}

.top-left {
  top: -5px;
  left: -5px;
  cursor: nw-resize;
}

.top {
  top: -5px;
  left: 50%;
  margin-left: -5px;
  cursor: n-resize;
}

.top-right {
  top: -5px;
  right: -5px;
  cursor: ne-resize;
}

.right {
  top: 50%;
  right: -5px;
  margin-top: -5px;
  cursor: e-resize;
}

.bottom-right {
  bottom: -5px;
  right: -5px;
  cursor: se-resize;
}

.bottom {
  bottom: -5px;
  left: 50%;
  margin-left: -5px;
  cursor: s-resize;
}

.bottom-left {
  bottom: -5px;
  left: -5px;
  cursor: sw-resize;
}

.left {
  top: 50%;
  left: -5px;
  margin-top: -5px;
  cursor: w-resize;
}

其中,box 元素使用了 position: relative;,使得 point 元素可以根据 box 元素进行定位。point 元素使用了 position: absolute;,为了脱离文档流,并且可以根据 box 元素进行定位。

在 point 元素中,我们对运用了不同的鼠标样式和定位方式,以实现不同方向的拖动效果。

4. JavaScript 代码实现

最后,我们需要编写 JavaScript 代码,为拖动点添加对应的事件监听器,以实现拖动大小的功能。

4.1 获取元素

首先,我们需要获取 box 和 point 元素,以便在后续的操作中使用。

var box = document.querySelector('.box');
var points = document.querySelectorAll('.point');

4.2 实现拖动

接下来,我们需要为每个拖动点添加事件监听器,以实现拖动效果。具体实现方式是监听鼠标的 mousedown、mousemove、mouseup 事件。

points.forEach(function(point) {
  point.addEventListener('mousedown', handleMouseDown);
});

function handleMouseDown(e) {
  var point = e.target;
  var startX = e.pageX;
  var startY = e.pageY;
  var startWidth = parseInt(getComputedStyle(box).width);
  var startHeight = parseInt(getComputedStyle(box).height);
  var startTop = parseInt(getComputedStyle(box).top);
  var startLeft = parseInt(getComputedStyle(box).left);

  document.addEventListener('mousemove', handleMouseMove);
  document.addEventListener('mouseup', handleMouseUp);

  function handleMouseMove(e) {
    var deltaX = e.pageX - startX;
    var deltaY = e.pageY - startY;

    switch (point.className) {
      case 'point top-left':
        box.style.width = startWidth - deltaX + 'px';
        box.style.height = startHeight - deltaY + 'px';
        box.style.top = startTop + deltaY + 'px';
        box.style.left = startLeft + deltaX + 'px';
        break;
      case 'point top':
        box.style.height = startHeight - deltaY + 'px';
        box.style.top = startTop + deltaY + 'px';
        break;
      case 'point top-right':
        box.style.width = startWidth + deltaX + 'px';
        box.style.height = startHeight - deltaY + 'px';
        box.style.top = startTop + deltaY + 'px';
        break;
      case 'point right':
        box.style.width = startWidth + deltaX + 'px';
        break;
      case 'point bottom-right':
        box.style.width = startWidth + deltaX + 'px';
        box.style.height = startHeight + deltaY + 'px';
        break;
      case 'point bottom':
        box.style.height = startHeight + deltaY + 'px';
        break;
      case 'point bottom-left':
        box.style.width = startWidth - deltaX + 'px';
        box.style.height = startHeight + deltaY + 'px';
        box.style.left = startLeft + deltaX + 'px';
        break;
      case 'point left':
        box.style.width = startWidth - deltaX + 'px';
        box.style.left = startLeft + deltaX + 'px';
        break;
      default:
        break;
    }

    e.stopPropagation();
    e.preventDefault();
  }

  function handleMouseUp(e) {
    document.removeEventListener('mousemove', handleMouseMove);
    document.removeEventListener('mouseup', handleMouseUp);
  }

  e.stopPropagation();
  e.preventDefault();
}

在上述代码中,我们首先为每个 point 元素添加了 mousedown 事件监听器,当鼠标按下时会触发 handleMouseDown 函数。在 handleMouseDown 函数中,我们获取了相关信息,如起始坐标、元素宽高以及位置,以备后续使用。我们还添加了 mousemove 和 mouseup 事件监听器,以在鼠标移动时改变box元素的大小和位置,并在鼠标松开时移除监听器。

在 handleMouseMove 函数中,我们根据不同拖动点的位置,添加不同的改变逻辑,此处使用了一系列 switch 来判断分支。在 handleMouseUp 函数中,我们移除了所有的事件监听器。

4.3 完整代码

最终的代码实现如下:

<div class="box">
  <span class="point top-left"></span>
  <span class="point top"></span>
  <span class="point top-right"></span>
  <span class="point right"></span>
  <span class="point bottom-right"></span>
  <span class="point bottom"></span>
  <span class="point bottom-left"></span>
  <span class="point left"></span>
</div>

<style>
.box {
  width: 200px;
  height: 200px;
  background-color: #f0f0f0;
  position: relative;
}

.point {
  width: 10px;
  height: 10px;
  background-color: #333;
  position: absolute;
}

.top-left {
  top: -5px;
  left: -5px;
  cursor: nw-resize;
}

.top {
  top: -5px;
  left: 50%;
  margin-left: -5px;
  cursor: n-resize;
}

.top-right {
  top: -5px;
  right: -5px;
  cursor: ne-resize;
}

.right {
  top: 50%;
  right: -5px;
  margin-top: -5px;
  cursor: e-resize;
}

.bottom-right {
  bottom: -5px;
  right: -5px;
  cursor: se-resize;
}

.bottom {
  bottom: -5px;
  left: 50%;
  margin-left: -5px;
  cursor: s-resize;
}

.bottom-left {
  bottom: -5px;
  left: -5px;
  cursor: sw-resize;
}

.left {
  top: 50%;
  left: -5px;
  margin-top: -5px;
  cursor: w-resize;
}
</style>

<script>
var box = document.querySelector('.box');
var points = document.querySelectorAll('.point');

points.forEach(function(point) {
  point.addEventListener('mousedown', handleMouseDown);
});

function handleMouseDown(e) {
  var point = e.target;
  var startX = e.pageX;
  var startY = e.pageY;
  var startWidth = parseInt(getComputedStyle(box).width);
  var startHeight = parseInt(getComputedStyle(box).height);
  var startTop = parseInt(getComputedStyle(box).top);
  var startLeft = parseInt(getComputedStyle(box).left);

  document.addEventListener('mousemove', handleMouseMove);
  document.addEventListener('mouseup', handleMouseUp);

  function handleMouseMove(e) {
    var deltaX = e.pageX - startX;
    var deltaY = e.pageY - startY;

    switch (point.className) {
      case 'point top-left':
        box.style.width = startWidth - deltaX + 'px';
        box.style.height = startHeight - deltaY + 'px';
        box.style.top = startTop + deltaY + 'px';
        box.style.left = startLeft + deltaX + 'px';
        break;
      case 'point top':
        box.style.height = startHeight - deltaY + 'px';
        box.style.top = startTop + deltaY + 'px';
        break;
      case 'point top-right':
        box.style.width = startWidth + deltaX + 'px';
        box.style.height = startHeight - deltaY + 'px';
        box.style.top = startTop + deltaY + 'px';
        break;
      case 'point right':
        box.style.width = startWidth + deltaX + 'px';
        break;
      case 'point bottom-right':
        box.style.width = startWidth + deltaX + 'px';
        box.style.height = startHeight + deltaY + 'px';
        break;
      case 'point bottom':
        box.style.height = startHeight + deltaY + 'px';
        break;
      case 'point bottom-left':
        box.style.width = startWidth - deltaX + 'px';
        box.style.height = startHeight + deltaY + 'px';
        box.style.left = startLeft + deltaX + 'px';
        break;
      case 'point left':
        box.style.width = startWidth - deltaX + 'px';
        box.style.left = startLeft + deltaX + 'px';
        break;
      default:
        break;
    }

    e.stopPropagation();
    e.preventDefault();
  }

  function handleMouseUp(e) {
    document.removeEventListener('mousemove', handleMouseMove);
    document.removeEventListener('mouseup', handleMouseUp);
  }

  e.stopPropagation();
  e.preventDefault();
}
</script>

示例说明

下面给出两个示例说明:

示例1

在简单的 HTML 网页上添加上述 HTML 结构、CSS 样式和 JavaScript 代码,我们可以看到一个可以通过八个点拖动改变大小的方框。

你可以访问这个示例网页,以体验具体效果。

示例2

假设我们要在 React 网站上添加该功能,具体实现方式如下:

我们需在 React 组件中添加上述 HTML 结构,并加载上述 CSS 样式。然后添加以下 JavaScript 代码实现拖动功能:

import React, { useRef } from 'react';

function Box() {
  const boxRef = useRef(null);
  const pointsRef = useRef([]);

  const handleMouseDown = e => {
    const point = e.target;
    const startX = e.pageX;
    const startY = e.pageY;
    const startWidth = parseInt(getComputedStyle(boxRef.current).width);
    const startHeight = parseInt(getComputedStyle(boxRef.current).height);
    const startTop = parseInt(getComputedStyle(boxRef.current).top);
    const startLeft = parseInt(getComputedStyle(boxRef.current).left);

    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);

    function handleMouseMove(e) {
      const deltaX = e.pageX - startX;
      const deltaY = e.pageY - startY;

      switch (point.className) {
        case 'point top-left':
          boxRef.current.style.width = startWidth - deltaX + 'px';
          boxRef.current.style.height = startHeight - deltaY + 'px';
          boxRef.current.style.top = startTop + deltaY + 'px';
          boxRef.current.style.left = startLeft + deltaX + 'px';
          break;
        case 'point top':
          boxRef.current.style.height = startHeight - deltaY + 'px';
          boxRef.current.style.top = startTop + deltaY + 'px';
          break;
        case 'point top-right':
          boxRef.current.style.width = startWidth + deltaX + 'px';
          boxRef.current.style.height = startHeight - deltaY + 'px';
          boxRef.current.style.top = startTop + deltaY + 'px';
          break;
        case 'point right':
          boxRef.current.style.width = startWidth + deltaX + 'px';
          break;
        case 'point bottom-right':
          boxRef.current.style.width = startWidth + deltaX + 'px';
          boxRef.current.style.height = startHeight + deltaY + 'px';
          break;
        case 'point bottom':
          boxRef.current.style.height = startHeight + deltaY + 'px';
          break;
        case 'point bottom-left':
          boxRef.current.style.width = startWidth - deltaX + 'px';
          boxRef.current.style.height = startHeight + deltaY + 'px';
          boxRef.current.style.left = startLeft + deltaX + 'px';
          break;
        case 'point left':
          boxRef.current.style.width = startWidth - deltaX + 'px';
          boxRef.current.style.left = startLeft + deltaX + 'px';
          break;
        default:
          break;
      }

      e.stopPropagation();
      e.preventDefault();
    }

    function handleMouseUp(e) {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    }

    e.stopPropagation();
    e.preventDefault();
  };

  const handleBoxRef = reactElement => {
    boxRef.current = reactElement;
  };

  const handlePointsRef = (index, reactElement) => {
    pointsRef.current[index] = reactElement;
  };

  return (
    <div className="box" ref={handleBoxRef}>
      <span className="point top-left" ref={element => handlePointsRef(0, element)} onMouseDown={handleMouseDown} />
      <span className="point top" ref={element => handlePointsRef(1, element)} onMouseDown={handleMouseDown} />
      <span className="point top-right" ref={element => handlePointsRef(2, element)} onMouseDown={handleMouseDown} />
      <span className="point right" ref={element => handlePointsRef(3, element)} onMouseDown={handleMouseDown} />
      <span className="point bottom-right" ref={element => handlePointsRef(4, element)} onMouseDown={handleMouseDown} />
      <span className="point bottom" ref={element => handlePointsRef(5, element)} onMouseDown={handleMouseDown} />
      <span className="point bottom-left" ref={element => handlePointsRef(6, element)} onMouseDown={handleMouseDown} />
      <span className="point left" ref={element => handlePointsRef(7, element)} onMouseDown={handleMouseDown} />
    </div>
  );
}

此处我们使用了 React Hooks API 中的 useRef 来获取 box 和 point 元素,并为每个唯一的 point 元素分配了一个 ref。最终的效果和上面的普通 HTML 网页效果相同。

你可以访问这个示例网页,以查看完整的 React 实现例子。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:js通过八个点 拖动改变div大小的实现方法 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • 从axios源码角度解决bug的过程记录

    让我来详细讲解“从axios源码角度解决bug的过程记录”的完整攻略。 标题 1. 确认bug 首先,我们需要确认bug的存在,并确定bug所在的模块和源文件。可以通过debug、查看报错信息、分析代码逻辑等方式,尽可能找到bug的出现原因和位置。 2. 查看axios源码 确认bug后,需要查看axios源码,找到相关代码,进行深入分析,包括查看源代码、调…

    JavaScript 2023年5月27日
    00
  • Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结

    JQuery是一种JavaScript库,其中包括了许多有用的工具方法,其中包括四种数据请求方法:$.get(), $.post(), $.ajax(), $.getJSON()。以下是它们的详细讲解: $.get(url, data, success, dataType) url:请求的URL地址 data:发送给服务器的数据(可以省略) success:…

    JavaScript 2023年5月19日
    00
  • 原生js中运算符及流程控制示例详解

    原生JS中运算符及流程控制示例详解 运算符详解 赋值运算符 赋值运算符用于给变量或表达式赋值,常用的有“=”、“+=”、“-=”等运算符。 例如,下面代码将变量a赋值为1: var a = 1; 算术运算符 算术运算符用于数值的加减乘除,常用的有“+”、“-”、“*”、“/”、“%”等运算符。 例如,下面代码计算a和b的和,并将结果赋值给变量c: var a…

    JavaScript 2023年5月27日
    00
  • 浅谈在js传递参数中含加号(+)的处理方式

    下面我就来详细讲解在js传递参数中含加号(+)的处理方式: 1. 问题描述 在URL参数传递时有时会遇到含有加号(+)的情况,这时候我们需要进行特殊处理,否则这个加号会被解析成空格,导致参数传递错误。 例如,我们想要传递一个字符串 “hello+world”,但是如果直接将这个字符串”hello+world”作为URL参数进行传递,会被解析成 “hello …

    JavaScript 2023年5月19日
    00
  • javascript数组输出的两种方式

    当我们使用JavaScript编写程序时,数组是一个常用的数据类型,对于数组的输出操作,我们可以使用两种方式来实现。 方式一:使用for循环输出数组元素 使用for循环可以逐个遍历数组中的元素,并将其输出。下面是一个示例代码: var arr = [1, 2, 3, 4, 5]; for (var i = 0; i < arr.length; i++)…

    JavaScript 2023年5月27日
    00
  • Bootstrap源码解读表单(2)

    关于“Bootstrap源码解读表单(2)”这篇文章,主要是对Bootstrap框架中的表单组件的源码分析和实现方法进行了详细讲解。下面是我对这篇文章的完整攻略: 简介 此文章是 Bootstrap 源码解读系列的第 2 篇,主要介绍如何自定义表单组件,以及其中用到的几个重要的 CSS 类。 自定义表单组件 Bootstrap 的表单组件样式是十分灵活的,可…

    JavaScript 2023年6月10日
    00
  • vscode 一键规范代码格式的实现

    下面我将为大家讲解“vscode 一键规范代码格式的实现”的完整攻略。 1. 安装插件 要实现一键规范代码格式,需要安装 vscode 的插件 Prettier – Code formatter,可以通过在 vscode 中按下快捷键 Ctrl + Shift + X 打开插件商店,在搜索框中输入 Prettier,然后点击安装即可。 2. 配置插件 在 v…

    JavaScript 2023年6月10日
    00
  • js 数组克隆方法 小结

    以下是关于“js 数组克隆方法 小结”的完整攻略: 标准的数组克隆方式 在JavaScript中,有两种标准的数组克隆方式: 利用ES6的扩展运算符(…) const arr1 = [1, 2, 3]; const arr2 = […arr1]; console.log(arr1); // [1, 2, 3] console.log(arr2); /…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部