Angular.js 实现带手柄自由调整页面大小的功能

因为目前是处于在angular项目中,所以下面分别一个记录简易的angular.js和在angular项目中使用的版本,仅供大家参考。

Angular.js

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Resizable Element with Angular Directive</title>
  <style>
    .resizable {
      width: 200px;
      height: 200px;
      background-color: lightgray;
      border: 1px solid #ccc;
      overflow: auto;
      position: relative;
    }
    .resize-handle {
      width: 10px;
      height: 10px;
      background-color: #000;
      position: absolute;
      bottom: 0;
      right: 0;
      cursor: nwse-resize;
    }
  </style>
</head>
<body>
  <div ng-app="resizableApp">
    <div ng-controller="ResizableController">
      <div resizable></div>
    </div>
  </div>

  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
  <script>
    angular.module('resizableApp', [])
      .controller('ResizableController', function($scope) {
        // 可以在这里添加控制器逻辑
      })
      .directive('resizable', function() {
        return {
          restrict: 'A',
          link: function(scope, element) {
            const resizableElement = element[0];
            const resizeHandle = document.createElement('div');
            resizeHandle.classList.add('resize-handle');
            resizableElement.appendChild(resizeHandle);

            let isResizing = false;
            let initialX;
            let initialY;
            let originalWidth;
            let originalHeight;

            resizeHandle.addEventListener('mousedown', function(event) {
              event.preventDefault();
              isResizing = true;
              initialX = event.clientX;
              initialY = event.clientY;
              originalWidth = parseFloat(getComputedStyle(resizableElement, null).getPropertyValue('width'));
              originalHeight = parseFloat(getComputedStyle(resizableElement, null).getPropertyValue('height'));

              document.addEventListener('mousemove', resize);
              document.addEventListener('mouseup', stopResize);
            });

            function resize(event) {
              if (isResizing) {
                const width = originalWidth + (event.clientX - initialX);
                const height = originalHeight + (event.clientY - initialY);
                resizableElement.style.width = width + 'px';
                resizableElement.style.height = height + 'px';
              }
            }

            function stopResize() {
              isResizing = false;
              document.removeEventListener('mousemove', resize);
              document.removeEventListener('mouseup', stopResize);
            }
          }
        };
      });
  </script>
</body>
</html>

在Angular项目中

在 Angular 项目中可以将上述功能作为 Angular 指令在组件中使用。

  1. 首先,创建一个名为 resizable 的自定义指令

    javascript 复制代码
    import { Directive, ElementRef, HostListener } from '@angular/core';
    
    @Directive({
      selector: '[resizable]'
    })
    
    export class ResizeDirective {
      private isResizing: boolean = false;
      private isRightResizing: boolean = false;
      private isBottomResizing: boolean = false;
      private startX: number = 0;
      private startY: number= 0;
      private startWidth: number= 0;
      private startHeight: number= 0;
      private handle: HTMLElement;
    
      constructor(private elementRef: ElementRef,private rendere:Renderer2) {
        this.handle = document.createElement('div');
        this.rendere.addClass(this.handle,'resize-handle');
        this.rendere.appendChild(this.elementRef.nativeElement,this.handle)
      }
    
      @HostListener('document:mousemove', ['$event'])
      onMouseMove(event: MouseEvent) {
        event.stopPropagation();
        if (this.isResizing) {
          this.rendere.setStyle(document.body,'cursor','ne-size');
          this.rendere.setStyle(this.elementRef.nativeElement,'cursor','ne-size');
          const dx = event.clientX - this.startX;
          const dy = event.clientY - this.startY;
          const newWidth = this.startWidth + dx;
          const newHeight = this.startHeight + dy;
          this.elementRef.nativeElement.style.width = newWidth + 'px';
          this.elementRef.nativeElement.style.height = newHeight + 'px';
        }
    
        if (this.isBottomResizing) {
          this.rendere.setStyle(document.body,'cursor','ns-size');
          const dy = event.clientY - this.startY;
          const newHeight = this.startHeight + dy;
          this.elementRef.nativeElement.style.height = newHeight + 'px';
        }
    
        if (this.isRightResizing) {
          this.rendere.setStyle(document.body,'cursor','ew-size');
          const dx = event.clientX - this.startX;
          const newWidth = this.startWidth + dx;
          this.elementRef.nativeElement.style.width = newWidth + 'px';
        }
      }
    
      @HostListener('mousedown', ['$event'])
      onMouseDown(event: MouseEvent) {
        event.stopPropagation();
        const rect = this.elementRef.nativeElement.getBoundingClientRect();
        const borderWidth = 10;
        const isOnRightBorder = event.clientX >= rect.right - borderWidth && event.clientX >= rect.right + borderWidth;
        const isOnBottomBorder = event.clientY >= rect.bottom - borderWidth && event.clientY >= rect.bottom + borderWidth;
        if (event.target === this.handle) {
          this.isResizing = true;
          this.isBottomResizing = false;
          this.isRightResizing = false;
          this.startX = event.clientX;
          this.startY = event.clientY;
          this.startWidth = this.elementRef.nativeElement.clientWidth;
          this.startHeight = this.elementRef.nativeElement.clientHeight;
          this.rendere.setStyle(document.body,'cursor','ne-size');
          this.rendere.setStyle(this.elementRef.nativeElement,'cursor','ne-size');
          event.preventDefault();
        }else if(isOnBottomBorder) {
          this.isResizing = false;
          this.isBottomResizing = true;
          this.isRightResizing = false;
          this.startY = event.clientY;
          this.startHeight = this.elementRef.nativeElement.clientHeight;
          this.rendere.setStyle(document.body,'cursor','ns-size');
          event.preventDefault();
        }else if(isOnRightBorder) {
          this.isResizing = true;
          this.isBottomResizing = false;
          this.isRightResizing = true;
          this.startX = event.clientX;
          this.startWidth = this.elementRef.nativeElement.clientWidth;
          this.rendere.setStyle(document.body,'cursor','ew-size');
          event.preventDefault();
        }
      }
    
      @HostListener('document:mouseup')
      onMouseUp() {
        this.isResizing = false;
        this.isBottomResizing = false;
        this.isRightResizing = false;
        this.rendere.setStyle(document.body,'cursor','auto');
        this.rendere.setStyle(this.elementRef.nativeElement,'cursor','auto');
      }
    }
  2. 在组件模板中使用该指令

    html 复制代码
    <div resizable class="resizable"></div>
  3. 最后,将 `ResizableDirective` 添加到您的 Angular 模块中

    javascript 复制代码
    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { ResizableDirective } from './resizable.directive';
    import { AppComponent } from './app.component';
    
    @NgModule({
      declarations: [
        AppComponent,
        ResizableDirective
      ],
      imports: [
        BrowserModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }

Angular项目中的注意事项:

  • 例子中是左基线为标准的代码(即仅横向宽度改变时,整个页面是向左缩进靠齐的),如果想改成右基线为标准进行缩进的代码,可参考下面的关键代码,其他代码不需改动(只写了需要改动的代码,其它代码完全不需改动):
javascript 复制代码
@HostListener('document:mousemove', ['$event'])
  onMouseMove(event: MouseEvent) {
    event.stopPropagation();
    if (this.isResizing) {
      const newWidth = this.startWidth - dx;
    }

    if (this.isRightResizing) {
      const newWidth = this.startWidth - dx;
    }
  }
  • event.preventDefault()这个方法的位置的使用,不可改动,不然页面的默认行为将会被阻止,比如默认选中等。
  • event.stopPropagation()不可删掉,不然在当有子组件的时候,会因为冒泡导致样式受到影响。
相关推荐
陈随易1 小时前
农村程序员-关于小孩教育的思考
前端·后端·程序员
云深时现月1 小时前
jenkins使用cli发行uni-app到h5
前端·uni-app·jenkins
昨天今天明天好多天1 小时前
【Node.js]
前端·node.js
亿牛云爬虫专家1 小时前
Puppeteer教程:使用CSS选择器点击和爬取动态数据
javascript·css·爬虫·爬虫代理·puppeteer·代理ip
2401_857610031 小时前
深入探索React合成事件(SyntheticEvent):跨浏览器的事件处理利器
前端·javascript·react.js
雾散声声慢2 小时前
前端开发中怎么把链接转为二维码并展示?
前端
熊的猫2 小时前
DOM 规范 — MutationObserver 接口
前端·javascript·chrome·webpack·前端框架·node.js·ecmascript
天农学子2 小时前
Easyui ComboBox 数据加载完成之后过滤数据
前端·javascript·easyui
mez_Blog2 小时前
Vue之插槽(slot)
前端·javascript·vue.js·前端框架·插槽
爱睡D小猪2 小时前
vue文本高亮处理
前端·javascript·vue.js