ngBootstrap Angular 8 - 模态可调整大小和可拖动 [英] ngBootstrap Angular 8 - Modal Resizable and Draggable

查看:36
本文介绍了ngBootstrap Angular 8 - 模态可调整大小和可拖动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 Angular 8 中使用引导程序 https://ng-bootstrap.github.io/#/components/modal/examples 版本 4.我想让模态重新调整大小并且可拖动.我看到了一些其他版本的例子,比如 3.xx 但没有 angular - http://jsfiddle.net/GDVdN/

任何关于 Bootstrap4 与 Angular 8 的参考 - Modal 可调整大小 + 可拖动?.

解决方案

我得到的最接近的是创建一个可以调整大小"的组件里面的任何元素.

更新:播放"具有模态对话框"样式

想象一个像这样的组件

<ng-content></ng-content><div class="cell-border-top"></div><div class="cell-border-bottom"></div><div class="cell-border-left"></div><div class="cell-border-right"></div><div class="cell-top-right"></div><div class="cell-bottom-right"></div><div class="cell-top-left"></div><div class="cell-bottom-left"></div>

.css 使 div 位于左、右、上、下和四个角的位置

我们听 mouseDown,然后getting"我们可以在变量中存储拖动类型的 className

export enum TypeDrag {移动,最佳,底部,剩下,对,右上,右下角,左上方,左下方}

当鼠标按下时,我们订阅 mouseUp 和 mouseMove,mouseUp 简单地删除订阅 mouseMove

mouseMove 改变div的样式改变位置和尺寸

我们需要指定一个 ElementRef 作为 Input 来拖动modal"

还有一个额外的考虑是 ngb-modal 将 modal 改变了margin-left"和margin-top",所以我需要将边距设置为 0 到带有 calssName==modal-dialog"的 div.为此,我们创建了一个递归函数

获取模态对话框"我们使用递归函数

findModalContent(element:HTMLElement){return element.className=="modal-dialog"?element:element.parentElement?this.findModalContent(element.parentElement):空值}

我试着用代码中的注释来解释

通常这是 stackblitz

@Component({选择器:'角度窗口',templateUrl: './angular-window.component.html',styleUrls: ['./angular-window.component.css']})导出类 AngularWindowComponent 实现 OnInit {正确:任何;incr: number[] = [0, 0, 0, 0];本机元素:任何;类型拖动:类型拖动;产地:任何;onDrag: boolean = false;移动订阅:任何;//div: 任何;<--在更新中删除类名 = ['细胞顶部','单元格边框顶部','单元格边框底部','cell-border-left','单元格边界右','右上单元格','右下角单元格','左上角单元格','左下角单元格'];风格:任何=空;构造函数(私有元素引用:元素引用){}@Input() set dragHolder(value) {//拖动保持器将是一个//模板引用变量//我们添加类cell-top";value.classList.add("cell-top");}/*现在不需要了//我需要指明背景颜色@Input('background-color') backgroundColor = 'white';*/ngOnInit(): 无效 {//获取modalContent"this.modalContent=this.findModalContent(this.elementRef.nativeElement)//我们订阅mouseDownfromEvent(this.elementRef.nativeElement, 'mousedown').管道(//我们过滤,只获取元素的className//是由变量classNames"指示的一种;//或者如果className包含cell-top"过滤器((事件:鼠标事件)=> {const classes = (event.target as any).className;if (classs && typeof classes === 'string') {const className = classes.split(' ');return className.indexOf("cell-top")>=0?true:this.classNames.indexOf(classs) >= 0;}返回假;})).subscribe((event: MouseEvent) => {this.div = this.elementRef.nativeElement.childNodes[0];this.rect = this.div.getBoundingClientRect();this.origin = { x: event.screenX, y: event.screenY };this.onDrag = true;const className = (event.target as any).className.split(' ');this.typeDrag =className.indexOf('cell-top')>=0?TypeDrag.Move:(this.classNames.indexOf(className[0])) 作为 TypeDrag;//根据typeDrag,我存储在this.incr"中;移动这个.incr =this.typeDrag == TypeDrag.Move?[1, 0, 1, 0]: this.typeDrag == TypeDrag.Top?[1, -1, 0, 0]: this.typeDrag == TypeDrag.Bottom?[0, 1, 0, 0]: this.typeDrag == TypeDrag.Right?[0, 0, 0, 1]: this.typeDrag == TypeDrag.Left?[0, 0, 1, -1]: this.typeDrag == TypeDrag.TopRight?[1, -1, 0, 1]: this.typeDrag == TypeDrag.TopLeft?[1, -1, 1, -1]: this.typeDrag == TypeDrag.BottomRight?[0, 1, 0, 1]: [0, 1, 1, -1];this.onDrag = true;/*没必要//去除边距";在模态对话框中const modalContent=this.findModalContent(this.div.parentElement)如果(模态内容)modalContent.style.margin=0;*///我们订阅mouseUpfromEvent(文档,'mouseup').pipe(take(1)).subscribe(() => {如果(this.moveSubscription){this.moveSubscription.unsubscribe();this.moveSubscription = 未定义;this.onDrag = false;}});//我们订阅mouseMove如果(!this.moveSubscription){this.moveSubscription = fromEvent(document, 'mousemove').pipe(startWith({screenY:this.origin.y,screenX:this.origin.x})).订阅((moveEvent: MouseEvent) =>{const incrTop = moveEvent.screenY - this.origin.y;const incrLeft = moveEvent.screenX - this.origin.x;const width = this.rect.width + this.incr[3] * incrLeft;const heigth = this.rect.height + this.incr[1] * incrTop;/*前this.style = {位置:'绝对','z-索引':1051,'背景颜色':this.backgroundColor,顶部:this.rect.top + this.incr[0] * incrTop + 'px',高度:(高度 <75 ? 75 : 高度)+ 'px',左:this.rect.left + this.incr[2] * incrLeft + 'px',宽度:(宽度 <50 ? 50 : 宽度)+ 'px'};*///现在:this.modalContent.style['max-width']=(宽度 <50 ? 50 : 宽度) + 'px'this.modalContent.style['margin-top']=this.rect.top + this.incr[0] * incrTop + 'px'this.modalContent.style['margin-left']=this.rect.left + this.incr[2] * incrLeft + 'px'this.style={width:(width <50 ? 50 : width-1) + 'px',高度:(高度 <75 ? 75 : heigth-1) + 'px'}});}}

使用很简单,例如(查看如何指示dragHolder")

<angular-window [dragHolder]=header"><div class="modal-header"><h4 #header class="modal-title w-100";id="modal-basic-title">配置文件更新</h4>

<div class="modal-body">

<div class="modal-footer">

</angular-window></ng-模板>

注意:要更改 dragHolder 中的光标,我们需要添加类

.cell-top {光标:移动;}

I am trying to use the bootstrap https://ng-bootstrap.github.io/#/components/modal/examples version 4 with Angular 8. I want to make modal re-sizable and draggable. I see a few examples for other versions like 3.xx but not with angular - http://jsfiddle.net/GDVdN/

Any references for Bootstrap4 with ANgular 8 - Modal resizable + draggable?.

解决方案

The most closer I get is create a component that makes "resizable" any element inside.

Update: "play" with styles of "modal-dialog"

Imagine a component like

<div class="resizable" [ngStyle]="style">
  <ng-content></ng-content>
  <div class="cell-border-top"></div>
  <div class="cell-border-bottom"></div>
  <div class="cell-border-left"></div>
  <div class="cell-border-right"></div>
  <div class="cell-top-right"></div>
  <div class="cell-bottom-right"></div>
  <div class="cell-top-left"></div>
  <div class="cell-bottom-left"></div>
</div>

the .css make that the divs was a position in left, right, top, bottom and in the four corners

we listen mouseDown, and "getting" the className we can store in a variable the type of drag

export enum TypeDrag {
  Move,
  Top,
  Bottom,
  Left,
  Right,
  TopRight,
  BottomRight,
  TopLeft,
  BottomLeft
}

When mouse down we subscribe to mouseUp and to mouseMove, a mouseUp simple remove the subscription to mouseMove

The mouseMove change the style of the div to change the position and dimensions

We need indicate as Input an ElementRef to drag the "modal"

There're and addicional consideration that is that the ngb-modal place the modal changing the "margin-left" and "margin-top", so I need style the margin to 0 to a div with calssName=="modal-dialog". For this, we create a recursive function

To get the "modal-dialog" we use a recursive function

findModalContent(element:HTMLElement)
{
  return element.className=="modal-dialog"?element:
            element.parentElement?this.findModalContent(element.parentElement):
            null
}

I try to explain with comments in the code

And as usually this is the stackblitz

@Component({
  selector: 'angular-window',
  templateUrl: './angular-window.component.html',
  styleUrls: ['./angular-window.component.css']
})
export class AngularWindowComponent implements OnInit {
  rect: any;
  incr: number[] = [0, 0, 0, 0];
  nativeElement: any;
  typeDrag: TypeDrag;
  origin: any;
  onDrag: boolean = false;
  moveSubscription: any;
  //div: any;  <--remove in the updated

  classNames = [
    'cell-top',
    'cell-border-top',
    'cell-border-bottom',
    'cell-border-left',
    'cell-border-right',
    'cell-top-right',
    'cell-bottom-right',
    'cell-top-left',
    'cell-bottom-left'
  ];

  style: any = null;
  constructor(private elementRef: ElementRef) {}

  @Input() set dragHolder(value) { //the drag holder will be a 
                                   //template reference variable
                                   //we add the class "cell-top"

    value.classList.add("cell-top");
  }

  /*It's not necesary now
  //I need indicate the background-color
  @Input('background-color') backgroundColor = 'white';
  */

  ngOnInit(): void {

    //get the "modalContent"
        this.modalContent=this.findModalContent(this.elementRef.nativeElement)

    //we subscribe to mouseDown
    fromEvent(this.elementRef.nativeElement, 'mousedown')
      .pipe(
        //we filter, only get if the className of element 
        //is one of the indicate by the variable "classNames"
        //or if the className include the "cell-top"

        filter((event: MouseEvent) => {
          const classs = (event.target as any).className;
          if (classs && typeof classs === 'string') {
            const className = classs.split(' ');
            return className.indexOf("cell-top")>=0?true:
              this.classNames.indexOf(classs) >= 0;
          }
          return false;
        })
      )
      .subscribe((event: MouseEvent) => {

        this.div = this.elementRef.nativeElement.childNodes[0];
        this.rect = this.div.getBoundingClientRect();
        this.origin = { x: event.screenX, y: event.screenY };

        this.onDrag = true;

        const className = (event.target as any).className.split(' ');
        this.typeDrag =className.indexOf('cell-top')>=0?TypeDrag.Move:
         (this.classNames.indexOf(className[0])) as TypeDrag;

        //acording the typeDrag, I store in "this.incr" the move
          
        this.incr =
          this.typeDrag == TypeDrag.Move
            ? [1, 0, 1, 0]
            : this.typeDrag == TypeDrag.Top
            ? [1, -1, 0, 0]
            : this.typeDrag == TypeDrag.Bottom
            ? [0, 1, 0, 0]
            : this.typeDrag == TypeDrag.Right
            ? [0, 0, 0, 1]
            : this.typeDrag == TypeDrag.Left
            ? [0, 0, 1, -1]
            : this.typeDrag == TypeDrag.TopRight
            ? [1, -1, 0, 1]
            : this.typeDrag == TypeDrag.TopLeft
            ? [1, -1, 1, -1]
            : this.typeDrag == TypeDrag.BottomRight
            ? [0, 1, 0, 1]
            : [0, 1, 1, -1];

        this.onDrag = true;

        /*Not necesary
        //remove the "margin" in modal-dialog
        const modalContent=this.findModalContent(this.div.parentElement)
        if (modalContent)
          modalContent.style.margin=0;
        */

        //we subscribe to mouseUp    
        fromEvent(document, 'mouseup')
          .pipe(take(1))
          .subscribe(() => {
            if (this.moveSubscription) {
              this.moveSubscription.unsubscribe();
              this.moveSubscription = undefined;
              this.onDrag = false;
            }
          });

        //we subscribe to mouseMove

        if (!this.moveSubscription) {
          this.moveSubscription = fromEvent(document, 'mousemove').pipe(
            startWith({screenY:this.origin.y,screenX:this.origin.x})
          ).subscribe(
            (moveEvent: MouseEvent) => {
              const incrTop = moveEvent.screenY - this.origin.y;
              const incrLeft = moveEvent.screenX - this.origin.x;
              const width = this.rect.width + this.incr[3] * incrLeft;
              const heigth = this.rect.height + this.incr[1] * incrTop;
              /*before
              this.style = {
                position: 'absolute',
                'z-index': 1051,
                'background-color': this.backgroundColor,
                top: this.rect.top + this.incr[0] * incrTop + 'px',
                height: (heigth < 75 ? 75 : heigth) + 'px',
                left: this.rect.left + this.incr[2] * incrLeft + 'px',
                width: (width < 50 ? 50 : width) + 'px'
              };
              */
              //now:
              this.modalContent.style['max-width']=
                        (width < 50 ? 50 : width) + 'px'
              this.modalContent.style['margin-top']=
                        this.rect.top + this.incr[0] * incrTop + 'px'
              this.modalContent.style['margin-left']=
                        this.rect.left + this.incr[2] * incrLeft + 'px'
              this.style={
                 width:(width < 50 ? 50 : width-1) + 'px',
                 height:(heigth < 75 ? 75 : heigth-1) + 'px'
              }
      });
  }
}

the use is simple,e.g. (see how indicate the "dragHolder")

<ng-template #content let-modal>
  <angular-window [dragHolder]="header">
    <div class="modal-header">
      <h4 #header class="modal-title w-100" 
           id="modal-basic-title">Profile update</h4>
    </div>
    <div class="modal-body">
    </div>
    <div class="modal-footer">
    </div>
  </angular-window>
</ng-template>

NOTE: To change the cursor in dragHolder we need add the class

.cell-top {
  cursor: move;
}

这篇关于ngBootstrap Angular 8 - 模态可调整大小和可拖动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆