ngBootstrap Angular 8 - 模态可调整大小和可拖动 [英] ngBootstrap Angular 8 - Modal Resizable and Draggable
问题描述
我正在尝试在 Angular 8 中使用引导程序 https://ng-bootstrap.github.io/#/components/modal/examples
版本 4.我想让模态重新调整大小并且可拖动.我看到了一些其他版本的例子,比如 3.xx 但没有 angular - http://jsfiddle.net/GDVdN/
是否有关于带有 Angular 8 的 Bootstrap4 的参考 - 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屋!