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

yizhihongxing

下面是“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日

相关文章

  • JavaScript中使用Math.PI圆周率属性的方法

    当我们需要计算几何图形的面积或周长时,经常需要用到圆周率常数 π (pi)。在 JavaScript 中,我们可以使用 Math.PI 属性来访问这个数值,下面是详细步骤: 步骤1:访问Math.PI常数 Math.PI 属性中存储着圆周率的数值。可以通过直接使用 Math.PI 的方式来访问这个属性。代码如下: console.log(Math.PI); …

    JavaScript 2023年5月28日
    00
  • 探究JavaScript中的五种事件处理程序方式

    让我们来探究JavaScript中的五种事件处理程序方式: 事件处理程序方式 在JavaScript中,有五种主要的事件处理程序方式: HTML事件处理程序 DOM0级事件处理程序 DOM2级事件处理程序 DOM3级事件处理程序 EventUtil事件处理程序 下面我们将会详细讲解这五种事件处理程序方式的用法和区别。 1. HTML事件处理程序 HTML事件…

    JavaScript 2023年5月18日
    00
  • Web程序员必备的7个JavaScript函数

    当今Web开发的世界中,JavaScript是不可或缺的一个重要工具。因此,作为Web程序员,熟练掌握JavaScript,并掌握一些实用的JavaScript函数是非常重要的。 下面是Web程序员必备的7个JavaScript函数的详细攻略: 1. String.prototype.trim() JavaScript字符串对象的trim()函数用于删除字符…

    JavaScript 2023年5月27日
    00
  • JS定时器使用,定时定点,固定时刻,循环执行详解

    关于JS定时器的使用,通常有两种方式:setTimeout和setInterval。其中,setTimeout可以在指定的时间后执行一次代码,而setInterval则可以每隔指定的时间重复执行代码,直到手动停止它。 setTimeout 语法 setTimeout(function, milliseconds, param1, param2, …) 参…

    JavaScript 2023年5月27日
    00
  • JavaScript 几种循环方式以及模块化的总结

    当我们编写JavaScript程序时,经常需要使用循环语句来遍历数组,对象,或执行一些代码块。其中常用的循环有for、while、do-while和for of等,下面进行详细讲解: for循环 for循环是最常见的循环语句,通常用于遍历数组,语法如下: for (初始化; 条件; 计数器) { //要执行的代码块 } 其中,初始化部分只在循环开始执行一次,…

    JavaScript 2023年5月27日
    00
  • 使用JavaScript进行表单校验功能

    下面是“使用JavaScript进行表单校验功能”的完整攻略,包含以下几个步骤: 1. 界面设计 首先需要针对需要进行表单校验的页面进行合理的界面设计,包括表单中需要填写的各种项以及提示信息等等。需要根据实际情况来进行定制,保证界面简洁、明了,并且易于理解和操作。 2. 校验规则制定 制定合理的校验规则可以有效地保证表单填写的正确性。针对不同项的填写内容,可…

    JavaScript 2023年6月10日
    00
  • JavaScript从数组的indexOf()深入之Object的Property机制

    JavaScript从数组的indexOf()深入之Object的Property机制攻略 什么是Property机制 在JavaScript中,Object是一种特殊的数据类型,它使用了一种被称为Property的机制来存储和访问数据。每个Object都有一组Property,每个Property包括一个名称和一个值。值可以是任何类型的JavaScript…

    JavaScript 2023年5月28日
    00
  • 浅析script标签中的defer与async属性

    当我们在HTML文档中使用<script>标签引入JavaScript文件时,我们可以为这个标签添加两个重要的属性:defer和async。这两个属性都是为了优化JavaScript的加载和执行,但它们有一些不同之处。下面我们来分别对这两个属性进行详细的解析。 Defer属性 defer属性告诉浏览器,这个脚本将被延迟到页面加载完成后再执行。这意…

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