【问题标题】:Adding resize functionality to an element in angular以角度向元素添加调整大小功能
【发布时间】:2019-08-26 13:04:06
【问题描述】:

我正在按照 codepen 示例添加调整大小功能 在使用 MARGIN=4 的 cmets 中提到(这里我无法添加 codepen 链接) codepen 是我能找到的最好的工作示例。

在盒子的所有 4 个边上添加了 4 个元素。

我已经为 pointerdown 、 pointermove 和 pointerup 添加了主机侦听器,但我坚持执行 Resizable 指令中存在的 animate() 函数。

在指令中,代码主要有 3 个函数来完成所有的计算 onDown()calc(e)animate()

import { Directive,
         ElementRef,
         HostListener } from '@angular/core';
import { DraggableDirective } from './draggable.directive';

@Directive({
 selector: '[appResizable]' // Attribute selector
})

export class ResizableDirective extends DraggableDirective{

constructor(public element:ElementRef){
super(element);
}

minWidth = 60;
minHeight = 40;
// Thresholds
MARGINS = 4;

//End Of whats configurable
clicked = null;
public onRightEdge; onBottomEdge; onLeftEdge; onTopEdge;
public b; x; y;

redraw = false;
e;
clickedDragging = false;

ngOnInit(){
 this.animate() 
}

@HostListener('dragStart', ['$event'])
 onDragStart(e:PointerEvent): void{
 this.clickedDragging = true;
 this.onDown(e);
 e.preventDefault();
 }

@HostListener('dragMove', ['$event'])
  onDragMove(ee): void{
   if (!this.dragging || ee.pointerId !== this.pointerId) {
    return;
   }
   if((<HTMLElement>event.srcElement).id === ('side-top')){
   this.onMove(ee);
   ee.preventDefault();
   }
 }

 @HostListener('dragEnd', ['$event'])
     ondragend(ev): void{
     this.onUp(ev);
  }

onMove(ee){
    if (!this.dragging || ee.pointerId !== this.pointerId) {
     return;
   }
   if(this.clickedDragging){
     this.calc(ee);
     this.e = ee;
     this.redraw = true;
    }
   }

onDown(e){
    this.calc(e);

    let isResizing = this.onRightEdge || this.onBottomEdge || 
                     this.onLeftEdge || this.onTopEdge;

    this.clicked = {
      x: this.x,
      y: this.y,
      cx: e.clientX,
      cy: e.clientY,
      w: this.b.width,
      h: this.b.height,
      isResizing: isResizing,
      onRightEdge: this.onRightEdge,
      onBottomEdge: this.onBottomEdge,
      onLeftEdge: this.onLeftEdge,
      onTopEdge: this.onTopEdge,
   }

 }

calc(e){
   this.b = this.element.nativeElement.getBoundingClientRect();
   this.x = e.clientX - this.b.left;
   this.y = e.clientY - this.b.top;

   this.onRightEdge = this.x >= this.b.width - this.MARGINS;
   this.onBottomEdge = this.y >= this.b.height - this.MARGINS;
   this.onLeftEdge = this.x < this.MARGINS;
   this.onTopEdge = this.y < this.MARGINS;
  }

animate(){
  requestAnimationFrame(this.animate);
  if(!this.redraw)return;
  this.redraw = false;

  if(this.clicked && this.clicked.isResizing){

    if(this.clicked.onRightEdge){ 
      this.element.nativeElement.style.width = Math.max(this.x, 
      this.minWidth) + 'px';
    }

   if(this.clicked.onBottomEdge){
       this.element.nativeElement.style.height = Math.max(this.y, 
       this.minHeight) + 'px';
    }

   if(this.clicked.onLeftEdge){
     let currentWidth = Math.max(this.clicked.cx - 
         this.e.clientX + this.clicked.w, this.minWidth);

     if(currentWidth > this.minWidth){
      this.element.nativeElement.style.width = currentWidth + 'px';
      this.element.nativeElement.style.left = this.e.clientX + 'px';
     }
    }

    if (this.clicked.onTopEdge) {
     var currentHeight = Math.max(this.clicked.cy - 
                                  this.e.clientY  +
                                   this.clicked.h, this.minHeight);
     if (currentHeight > this.minHeight) {
      this.element.nativeElement.style.height = currentHeight + 'px';
      this.element.nativeElement.style.top = this.e.clientY + 'px'; 
     }
    }

  return;
 }
}

onUp(ev) {
   this.calc(ev);
   this.clicked = null;
   }  
}

应用了指令的 HTML sn-p

<div class="box" *ngFor="let box of dropzone1" appDroppable (dragStart)="currentBox = box" appMovable>
    {{ box.dis }}

    <div class="side side-h" id="side-top" (dragStart)=(e) (dragMove)=(e) (dragEnd)=(e) appResizable></div>
    <div class="side side-v" id="side-right" (click)="clcikme(e)" ></div>
    <div class="side side-h" id="side-bottom" (click)="clcikme(e)"></div>
    <div class="side side-v" id="side-left" (click)="clcikme(e)"></div>
</div>

在 b 的 codepen 示例中

this.b = this.element.nativeElement.getBoundingClientRect();

整个元素已被占用,我也必须这样做,在我的情况下,我有指令所在的边框

我正在附加一个工作 stackblitz 可调整大小的指令存在于可拖动文件夹中并在 hello 组件中使用 在pointerdown的stackblitz控制台日志中,也可以看到pointermove。

https://stackblitz.com/edit/angular-pcpev1?file=src/app/hello.component.html

未定义的控制台动画错误

请参考 cmets 中的 codepen 示例。

更新

https://stackblitz.com/edit/angular-pcpev1?file=src%2Fapp%2Fhello.component.html

【问题讨论】:

标签: javascript html css angular


【解决方案1】:

抱歉,我无法修复您的代码,因为它一团糟,您这样做完全错误,您只是在一个代码中执行了我建议的两种方法。此外,您在指令之外泄漏了调整大小内部,需要隐藏 div,在外部您只应该使用 resize 属性,并且所有内容都应该在指令内创建。

这里,这是从顶部开始的:

@Directive({
    selector: '[resize]'
})
class Resizable implements OnInit, OnDestroy {
    private nodes: HtmlElement[] = [];
    private data: {x: number, y: number, rect: ClientRect, direction: string};
    constructor(@Inject(ElementRef) private element: ElementRef) {
        this.mousemove = this.mousemove.bind(this);
        this.mouseup = this.mouseup.bind(this);
    }
    mousemove(e) {
        if (this.data) {
            switch(this.data.direction) {
                case 'top':
                    var offset = this.data.y - e.clientY;
                    var height = this.data.rect.height;
                    var top = this.data.rect.top;
                    var style = this.element.nativeElement.style;
                    style.height = height + offset + 'px';
                    style.top = top - offset + 'px';
                    break;
            }
        }
    }
    ngOnInit() {
        var node = document.createElement('div');
        node.classList.add('border-top', 'border');
        this.element.nativeElement.appendChild(node);
        this.nodes.push(node);
        window.addEventListener('mousemove', this.mousemove);
        window.addEventListener('mouseup', this.mouseup);
    }
    @HostListener('mousedown', ['$event'])
    mousedown(e) {
        if (e.target.classList.contains('border')) {
            var rect = this.element.nativeElement.getBoundingClientRect();
            this.data = {
                x: e.clientX,
                y: e.clientY,
                rect,
                direction: e.target.className.match(/border-([^ ]+)/)[1]
            };
            e.preventDefault();
        } else {
            delete this.data;
        }
    }
    mouseup(e) {
         delete this.data;
    }
    ngOnDestroy() {
        this.nodes.forEach(n => n.remove());
        window.removeEventListener('mousemove', this.mousemove);
        window.removeEventListener('mouseup', this.mouseup);
    }
}

这里是CodePen demo

【讨论】:

  • 非常感谢,我如何将它应用到其余 3 面
  • @Enthu 您需要为每一边创建 div(使用类border-xxx)创建将元素移动到一边并在switch(this.data.direction) { 中进行类似计算的CSS,使用bottom,@987654327 @ 和 left
  • 非常感谢,我会实施,如果有任何问题我会问,非常感谢
  • @Enthu 如果您只想更改一侧,则必须拖动它。当您通过拖动顶部和左侧调整大小时,需要更改左侧和顶部。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 1970-01-01
  • 2013-04-15
  • 2018-11-26
  • 2018-06-14
  • 2013-12-02
  • 2022-01-24
相关资源
最近更新 更多