Angular mouseevent on: элемент after дает неправильное значение для event.toelement.clientwidth

У меня есть элемент аудиоплеера, который я разрабатываю в Angular, который имитирует проигрыватель soundcloud, который находится внизу страницы soundcloud.

На нем есть оранжевая линия (игрок-прогресс-текущий), которая отображает элементы трека, которые уже были воспроизведены. На нем также есть оранжевый кружок, обозначающий текущее положение трека.

Когда я щелкаю в любом месте div 'контейнер-прогресс-игрока' (см. Ниже), он дает текущую позицию, позицию event.layerX и event.toElement.clientWidth, который является шириной его родительского элемента игрок-прогресс-контейнер. Я использую это, чтобы затем изменить положение аудиоплеера.

Однако, когда я нажимаю на круговой элемент, я представляю текущую позицию трека, который является элементом player-progress-current: после ниже, он правильно вычисляет позицию event.layerX, но event.toElement.clientWidth теперь, кажется, задается как ширина текущего хода игрока, вместо его родителя.

Кто-нибудь знает, почему он это делает и как это обойти? Я включил все соответствующие CSS, HTML и Angular вещи ниже.

changePosition(event: MouseEvent) {
    console.log("event.layerX  = " + event.layerX);
    console.log("event.clientWidth = " + event.toElement.clientWidth);
}

HTML выглядит так:

<div class="player-progress-container" (click)="changePosition($event)">
    <div class="player-progress-background"></div>
    <div class="player-progress-current"
        [style.width.%]="(position * 100)/length"></div>
</div>

CSS выглядит так:

.player-progress-container {
  width: 400px;
  flex-grow: 1;
  padding: 10px 0px 2px 0px;
  margin: 0px 10px 0 10px;
  display: flex;
  flex-direction: column;
  position: relative;
  cursor: pointer;
}

.player-progress-background {
  width: 100%;
  height: 1px;
  background-color: #ccc;
}

.player-progress-current {
  position: relative;
  width: 50%;
  height: 1px;
  background: red;
  bottom: 1px;
}

.player-progress-current:after {
  content: '';
  position: absolute;
  right:-3px; top: -3.5px;
  border: 1px solid #f50;
  border-radius: 55%;
  height: 8px;
  width: 8px;
  background-color: #f50;
  box-sizing: border-box;
}

В дополнение к ответу @ConnorsFan ниже я бы также добавил вопрос по этому поводу: [style.width.%]="(position * 100)/length" Почему бы не выполнить это вычисление в функции вашего компонента, передавая значения, как он сказал ниже?

jmbmage 13.08.2018 14:45

@ jmb.mage, почему лучше сделать это в функции, чем в html?

Tom O'Brien 15.08.2018 15:54

@ tom-obrien Это выбор практики кодирования. Причина №1: область видимости, наличие переменных JS внутри файла HTML затрудняет определение того, в какой области они находятся. Сохранение JS в файле JS просто упрощает и упрощает область видимости. Причина 2: если код JS растет или изменяется, лучше иметь его в компоненте.

jmbmage 15.08.2018 16:38
1
3
277
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы убедиться, что вы всегда получаете ширину контейнера, вы можете передать этот элемент в качестве аргумента в changePosition с помощью ссылочная переменная шаблона:

<div #container class="player-progress-container" (click)="changePosition($event, container)">
  ...
</div>
changePosition(event: MouseEvent, container: HTMLElement) {
  console.log("event.layerX  = " + event.layerX);
  console.log("clientWidth = " + container.clientWidth);
}

См. этот stackblitz для демонстрации.


В качестве альтернативы вы можете передать layerX и clientWidth напрямую в changePosition:

<div #container (click)="changePosition($event.layerX, container.clientWidth)" ...>
  ...
</div>
changePosition(layerX: number, clientWidth: number) {
  console.log("layerX  = " + layerX);
  console.log("clientWidth = " + clientWidth);
}

См. этот stackblitz для демонстрации.

Другие вопросы по теме