typescript 如何在一个html表格中创建一个n行的悬停?Angular

qrjkbowd  于 2023-02-10  发布在  TypeScript
关注(0)|答案(2)|浏览(112)

我试图创建一个预览表,显示事件,我以前在这里寻求帮助,它解决了在表中定位元素的问题。用同样的逻辑,我试图创建一个预览根据持续时间(小时)和根据列采取的位置,并保存在事件列表中。
当我试图使预览它不带我很好的元素有时会出现,并在其他人消失我已经几个小时,但我仍然无法解决它,除了显示预览后,单击事件应保存。
为什么预览 Flink ?
这是我的代码:
堆栈 lightning 战:https://stackblitz.com/edit/angular-ivy-k22v8c?file=src/app/app.component.ts
超文本:

<div class="calendar-container">
  <table
    (mouseenter)="activatePreview()"
    (mouseleave)="deactivatePreview()"
    (mousemove)="calculatePreview($event)"
  >
    <tr>
      <th></th>
      <th class="cell-place" *ngFor="let place of places">{{ place }}</th>
    </tr>
    <tr *ngFor="let hour of hours">
      <td class="cell-hour">{{ hour }}</td>
      <td class="cell" *ngFor="let place of places"></td>
    </tr>
  </table>
  <div *ngIf="previewActive">
    <div class="preview" [ngStyle]="preview.position">
      <p>{{ preview.location }}</p>
    </div>
  </div>
  <div *ngFor="let event of events">
    <div class="event" [ngStyle]="event.position">
      <p>{{ event.location }}</p>
    </div>
  </div>
</div>

TS:

export class AppComponent implements AfterViewInit {
  hours = [
    '8:00 AM',
    '9:00 AM',
    '10:00 AM',
    '11:00 AM',
    '12:00 PM',
    '1:00 PM',
    '2:00 PM',
    '3:00 PM',
    '4:00 PM',
    '5:00 PM',
  ];
  places = ['P1', 'P2', 'P3', 'P4', 'P5'];
  events: any = [];

  cellWidth = 0;
  cellWidthHour = 0;
  cellHeight = 0;

  previewActive = false;
  previewDuration = 2;
  preview: any = {};
  currentCell = null;

  activatePreview() {
    this.previewActive = true;
  }

  deactivatePreview() {
    this.previewActive = false;
    this.currentCell = null;
    this.preview = {};
  }

  calculatePreview(event: any) {
    if (!this.previewActive) {
      return;
    }

    // Get the position of the cursor
    const x = event.clientX;
    const y = event.clientY;

    // Calculate the column (location) of the preview
    const columns = document.getElementsByClassName('cell-place');
    let column;
    for (const col of Array.from(columns)) {
      if (
        col.getBoundingClientRect().left <= x &&
        x <= col.getBoundingClientRect().right
      ) {
        column = col;
        break;
      }
    }

    if (!column) {
      return;
    }
    console.log(column);

    // Calculate the start and end times of the preview
    const rows = document.getElementsByClassName('cell-hour');
    let startIndex = -1;
    let endIndex = -1;
    for (let i = 0; i < rows.length; i++) {
      const row = rows.item(i);
      if (
        row.getBoundingClientRect().top <= y &&
        y <= row.getBoundingClientRect().bottom
      ) {
        startIndex = i;
        endIndex = i + this.previewDuration - 1;
        break;
      }
    }
    console.log(startIndex, endIndex);

    // Check if the preview goes beyond the limit of the table
    if (startIndex === -1 || endIndex === -1 || endIndex >= rows.length) {
      return;
    }

    // Check if the cursor is in a new cell
    const newCell = startIndex + '-' + endIndex;
    console.log(newCell);
    if (newCell === this.currentCell) {
      return;
    }
    this.currentCell = newCell;

    // Update the preview based on the calculations
    const startTime = this.hours[startIndex];
    const endTime = this.hours[endIndex];
    const location = column.innerHTML;

    this.preview = { startTime, endTime, location };
    this.preview.position = this.calculateEventPosition(
      startTime,
      endTime,
      location
    );
    console.log(this.preview);
  }

  constructor() {}

  ngAfterViewInit() {
    // this.getCellSize();
    this.createEvent('11:00 AM', '12:00 PM', 'P3');
  }

  createEvent(startTime: string, endTime: string, location: string) {
    const event: any = { startTime, endTime, location };
    event.position = this.calculateEventPosition(startTime, endTime, location);
    this.events.push(event);
  }

  calculateEventPosition(startTime: string, endTime: string, location: string) {
    const rect = document
      .getElementsByTagName('table')[0]
      .getBoundingClientRect();
    const columns = document.getElementsByClassName('cell-place');
    const rows = document.getElementsByClassName('cell-hour');
    const column = Array.from(columns).find((x) => x.innerHTML == location);
    const start = rows.item(this.hours.indexOf(startTime));
    const end = rows.item(this.hours.indexOf(endTime));

    const left = column.getBoundingClientRect().left - rect.left;
    const top = start.getBoundingClientRect().top - rect.top;
    const width = column.getBoundingClientRect().width;
    const height =
      end.getBoundingClientRect().top - start.getBoundingClientRect().top;

    return {
      height: height + 'px',
      top: top + 'px',
      left: left + 'px',
      width: width + 'px',
    };
  }
}

CSS:

.calendar-container {
  position: relative;
}

table {
  border-collapse: collapse;
  width: 100%;
}

td,
th {
  border: 1px solid #dddddd;
  text-align: center;
}

table td {
  height: 25px;
}

.event {
  box-sizing: border-box;
  position: absolute;
  background-color: #f2f2f2;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.preview {
  box-sizing: border-box;
  position: absolute;
  background-color: yellow;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9;
}

我已经创建了预览逻辑的一部分,但它不工作,因为它应该,它给我一个 Flink 错误,有时与延迟,也预览应该只有约小时,另一件事,让我怀疑是我如何才能保存与点击,事件有n持续时间,现在是在硬代码,必须根据位置列。

fwzugrvs

fwzugrvs1#

窃听器在这里

<table
    (mouseenter)="activatePreview()"
    (mouseleave)="deactivatePreview()"
    (mousemove)="calculatePreview($event)"
>...</table>

当鼠标从一个单元格移动到另一个单元格时,同时触发mouseenter和mouseleave事件绑定,这将调用mouseleave事件,该事件处理程序将变量currentCell复位。
解决方案:
删除这两个事件侦听器(mouseenter)和(mouseleave),并从calculatePreview方法中删除以下代码,就可以实现这个目的。

// if (newCell === this.currentCell) {
 //   return;
 // }

请检查并让我知道它是否解决了您的问题。

slsn1g29

slsn1g292#

我觉得你的代码太复杂了。如果只想得到“悬浮单元格”的位置,你可以使用

<!--see the template reference variable #cell-->
<td #cell class="cell" *ngFor="let place of places"
        (mouseenter)="getPosition(cell)"></td>

  getPosition(el:HTMLElement)
  {
    console.log(el.getBoundingClientRect())
  }

相关问题