angular - ngBootstrap Angular 8 - 可调整大小和可拖动的模态
问题描述
我正在尝试将引导程序https://ng-bootstrap.github.io/#/components/modal/examples
版本 4 与 Angular 8 一起使用。我想让模态可重新调整大小和可拖动。我看到了一些其他版本的例子,比如 3.xx,但不是 angular - http://jsfiddle.net/GDVdN/
带有 AAngular 8 的 Bootstrap4 的任何参考 - 模态可调整大小 + 可拖动?
解决方案
我得到的最接近的是创建一个组件,使内部的任何元素“可调整大小”。
更新:使用“modal-dialog”样式的“play”
想象一个像这样的组件
<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>
.css 使 div 位于左、右、上、下和四个角的位置
我们监听 mouseDown,并“获取”类名,我们可以将拖动类型存储在变量中
export enum TypeDrag {
Move,
Top,
Bottom,
Left,
Right,
TopRight,
BottomRight,
TopLeft,
BottomLeft
}
当鼠标按下时,我们订阅 mouseUp 和 mouseMove,一个 mouseUp 简单地删除对 mouseMove 的订阅
mouseMove 改变 div 的样式来改变位置和尺寸
我们需要将 ElementRef 指示为 Input 以拖动“模态”
还有一个额外的考虑是 ngb-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):
null
}
我尝试用代码中的注释来解释
通常这是堆栈闪电战
@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'
}
});
}
}
使用很简单,例如(查看如何指示“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>
注意:要更改 dragHolder 中的光标,我们需要添加类
.cell-top {
cursor: move;
}
推荐阅读
- android - react-native 如何使用链接打开本地文件 url?
- jquery - 如何从动态填充的表格中获取可点击单元格的数据
- amazon-web-services - 当消息被添加到 SQS 时,仅向 lambda 发送事件主体而不是整个事件
- ios - 我如何知道 NFC 护照芯片读取了哪个数据组?
- node.js - npm package.json 别名,例如 webpack
- python - 理解将月份名称映射到其数值的字典
- c# - 如何从自定义基础项目创建 ASP.NET Core MVC 样板
- django - django,在过滤器中遍历多个表(模型)
- react-native - 在 React Native Navigation 中的选项卡之间切换时如何保持堆叠的屏幕
- flutter - FLUTTER:如何制作模糊的文字?