如何使用x和y坐标更改角度4材质中mat-menu的绝对位置?

时间:2017-11-28 09:00:54

标签: angular-material

我在角4中有以下菜单

<button mat-button [matMenuTriggerFor]="menu" style="display:none;">Menu</button>
    <mat-menu #menu="matMenu">
        <button mat-menu-item *ngFor="let item of items" (click)="select(item)">
            {{ item }}
        </button>
    </mat-menu>

当用户使用屏幕选择文本时,我打开菜单 matMenuTrigger.openMenu();

但我想在用户选择文字的地方打开菜单。 我有用户选择的X和Y坐标,但如何更改菜单的位置?

我尝试过将Id添加到mat-menu并使用

更改它的位置
element.style.position = 'absolute'
element.style.left = screenX + 'px'
element.style.top = screenY + 'px'

但它没有改变菜单的位置。

修改 我已经改变了菜单的位置

this.matMenuTrigger.openMenu();
var element = document.getElementsByClassName('cdk-overlay-pane');
menu.style.position = "absolute";
menu.style.left = evt.pageX + 5 + 'px';
menu.style.top = evt.pageY + 5 + 'px';

其中evt是mouseup事件,它给出了用户文本选择的坐标(X,Y)。

但是,当我滚动页面时,再次打开菜单会回到原来的位置。 如何保持菜单改变滚动位置?

3 个答案:

答案 0 :(得分:10)

我已经实现了用户选择文本的开放式菜单。

我添加了隐藏按钮,点击打开菜单。 在用户文本选择上,我已将该按钮的style="display:none;"更改为style="display:'';",在显示该按钮后,我已将该按钮的位置更改为用户通过x和y坐标选择文本的位置然后按this.menuTrigger.openMenu();

以编程方式打开菜单

DEMO

菜单-example.ts

export class MenuIconsExample {
@ViewChild(MatMenuTrigger)
    private menuTrigger: MatMenuTrigger;

  addTextToOpns: Array<String> = ["option 1", "option 2", "option 3"];
  selectedOption: string = "no Option selected";
  onTextSelection(event: any):void{
    if(window.getSelection && window.getSelection().toString()){
      var menu = document.getElementById('menuBtn');
      menu.style.display = '';
      menu.style.position = 'absolute';
      menu.style.left = event.pageX + 5 + 'px';
      menu.style.top = event.pageY + 5 + 'px';

      this.menuTrigger.openMenu();  
    }

  }

  onMenuClosed():void {
    var menu = document.getElementById('menuBtn');
        if (menu) {
            menu.style.display = 'none';            
        }
  }

  addTextTo(selectedOpn): void {
    this.selectedOption = selectedOpn + ' selected';
  }

}

菜单-example.html的

<div (mouseup)="onTextSelection($event)">
  <button mat-button [matMenuTriggerFor]="menu" id="menuBtn" style="display:none;">Menu</button>
    <mat-menu #menu="matMenu" (close)="onMenuClosed()">
        <button class="menuOpnBtn" mat-menu-item *ngFor="let opn of addTextToOpns" (click)="addTextTo(opn)">
            {{ opn }}
        </button>
    </mat-menu>
  <p>
    text for selection
  </p>
</div>
<br/>
<br/>


<div><span>selected option : </span> <span>{{selectedOption}}</span></div>

答案 1 :(得分:0)

为了使该示例在更一般的情况下工作,我发现有必要使用“ menu.style.position ='fixed'(而不是” menu.style.position ='absolute')。

这是因为“ event.pageX”返回相对于视口的坐标。由于“ position = absolute”将按钮相对于其包含的父项定位,因此,仅当其包含的父项尚未嵌套在其他HTML元素中时,不可见按钮的位置才是正确的。

因此,总而言之,我将 menu-example.ts 的代码更改如下,现在看来在所有情况下都可以使用:

export class MenuIconsExample {
@ViewChild(MatMenuTrigger)
    private menuTrigger: MatMenuTrigger;

addTextToOpns: Array<String> = ["option 1", "option 2", "option 3"];
selectedOption: string = "no Option selected";
  onTextSelection(event: any):void{
    if(window.getSelection && window.getSelection().toString()){
      var menu = document.getElementById('menuBtn');
      menu.style.display = '';
      menu.style.position = 'fixed';
      menu.style.left = event.pageX + 5 + 'px';
      menu.style.top = event.pageY + 5 + 'px';

      this.menuTrigger.openMenu();  
    }

  }

  onMenuClosed():void {
    var menu = document.getElementById('menuBtn');
        if (menu) {
            menu.style.display = 'none';            
        }
  }

  addTextTo(selectedOpn): void {
    this.selectedOption = selectedOpn + ' selected';
  }

}

答案 2 :(得分:0)

您是否还在愚蠢地在这里徘徊,就像我浪费了3个小时来手动设置 mat-menu 的位置一样,只是因为 mat-menu 的触发元素从DOM在某些情况下并且您不希望同时关闭 mat-menu ,然后不要使用 ngIf ,而要使用 {{1 }} 属性,它将节省您大量的时间来创建一些隐藏元素,先显示该元素,再获取其坐标bla bla bla bla,也许可以节省某人的生命