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日

相关文章

  • javascript高级程序设计(第三版)学习笔记(一) 正则表达式整理

    首先,需要解释一下该学习笔记的主题——正则表达式。 正则表达式 正则表达式,又称为“正则式”、“规则表达式”、“正规表达式”,是一种针对某种模式(字符串)进行匹配的工具。它通常被应用于字符串搜索、替换和拆分等场景。 正则表达式语法 正则表达式有自己独特的语法和规则,以下是一些常见的语法以及它们的意义: /pattern/:表示一个正则表达式模式,将被用于字符…

    JavaScript 2023年5月28日
    00
  • 使用Python解析JSON的实现示例

    下面我将为您详细讲解“使用Python解析JSON的实现示例”的完整攻略。 一、JSON简介 JSON全称为JavaScript Object Notation,它是一种轻量级的数据交换格式。在现代的Web应用开发中,JSON作为一种简单、易于理解的数据格式而备受推崇,常常使用在前后端数据交互、API接口等场景中。 一个JSON对象由一些键值对组成,键值对之…

    JavaScript 2023年6月11日
    00
  • event.X和event.clientX的区别分析

    那么让我们来详细分析一下“event.X和event.clientX的区别”。 1. 事件对象(event)简介 在JavaScript中,与事件相关的数据都被封装在一个事件对象中,该对象用来携带事件发生时的一些信息,比如事件类型、目标元素、鼠标坐标、键盘按键等。 2. event.X和event.clientX的区别 event.X表示鼠标相对于当前元素的…

    JavaScript 2023年6月11日
    00
  • JS验证逗号隔开可以是中文字母数字

    JS验证逗号隔开可以是中文字母数字,一般用于输入框中输入多个值,用逗号隔开这种需求。下面是一个使用 JavaScript 进行验证的完整攻略: 1. 正则表达式验证 为验证输入的内容是否符合要求,可以使用正则表达式进行验证。下面的正则表达式可以验证输入的内容是否为逗号隔开的中文字母数字组合: /^[a-zA-Z0-9\u4e00-\u9fa5]+(,[a-z…

    JavaScript 2023年6月10日
    00
  • javascript检查浏览器是否已经启用XX功能

    要检查浏览器是否支持某项功能,可以使用JavaScript内置的对象——Navigator对象。Navigator对象提供了许多信息,包括浏览器的名称、版本、操作系统和是否支持某些特定的功能。以下是检查浏览器是否支持某些功能的几种方法: 方法一:使用navigator对象的属性检查 Navigator对象的属性包含许多信息,其中一些属性可用于检查浏览器是否支…

    JavaScript 2023年6月11日
    00
  • JavaScript图片的Base64编码以及转换详解

    JavaScript图片的Base64编码以及转换详解 在进行前端开发时,我们会遇到需要将图片转换为Base64编码的情况,本篇攻略将会详细讲解JavaScript如何进行图片的Base64编码以及如何进行Base64编码的还原。 图片的Base64编码 在JavaScript中,可以使用FileReader的方法将图片读取为base64格式的字符串,具体步…

    JavaScript 2023年5月19日
    00
  • 在HTML代码中使用JavaScript代码的例子

    在HTML代码中使用JavaScript代码是一种常见的前端编程技巧,可以为网页添加各种交互和动态效果。下面是两个使用JavaScript代码的例子,分别展示在HTML中如何使用内联JavaScript代码和外部JavaScript文件。 内联JavaScript代码 内联JavaScript代码直接在HTML元素的代码里嵌入JavaScript代码,可以实…

    JavaScript 2023年5月18日
    00
  • 详解javascript的变量与标识符

    我们来详细讲解JavaScript的变量与标识符。 变量 在JavaScript中,变量是用于存储数据的容器,它们可以被任何地方引用或更改。在使用变量之前,需要先声明它们,以告诉JavaScript编译器它们的类型。 声明变量有三种方式: 使用var关键字 var name = ‘张三’; 使用let关键字(ES6新增) let age = 20; 使用co…

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