Дано:
Кастомный аудиоплеер в виде vue-компонента с листалкой записей, кнопкой play / pause, перемоткой.
Проблема:
Встречается только на iOS устройствах, в chrome/safari + MacOS safari. Между переключением и тогглингом происходит какой-то длительный интервал времени, которого нет ни на android устройствах, ни на десктопах windows/linux. MacOS Safari вообще не производит музыку.
Разметка контролсов компонента:
<div class='audio-gallery__main-panel'>
<div class='audio-gallery__control-btns'>
<div class="audio-gallery__icon audio-gallery__icon--prev"
:class='{"audio-gallery__icon--disabled": isSingle}'
@click='moveSource("prev")'>
<svg><use :xlink:href='"/images/sprite.svg#next" | imgPath'></use></svg>
</div>
<div class="audio-gallery__play" @click='togglePlayState($event)'
:class='{"audio-gallery__play--stopped": !states.play}'>
<svg v-if='!states.play'>
<use :xlink:href='"/images/sprite.svg#play" | imgPath'></use>
</svg>
<svg v-else>
<use :xlink:href='"/images/sprite.svg#pause" | imgPath'></use>
</svg>
</div>
<div class="audio-gallery__icon audio-gallery__icon--next"
:class='{"audio-gallery__icon--disabled": isSingle}'
@click='moveSource("next")'>
<svg><use :xlink:href='"/images/sprite.svg#next" | imgPath'></use></svg>
</div>
</div>
</div>
Методы включения и отключения:
export default Vue.component( 'v-audio', {
mixins: [playerMixin],
data() {
return {
isAudio: true,
soundAxis: 'x',
metaArray: [],
loading: false,
}
},
watch: {
'valuesArray'() {
if (this.isSingle) {
return
}
this.metaArray = [];
this.collectMeta();
},
'isSingle'(oldVal, newVal) {
if (newVal === true && oldVal === false) {
this.$set(this, 'metaArray', []);
}
}
},
methods: {
collectMeta() {
this.$nextTick( () => {
const setMeta = (item, idx) => {
const collector = this.$refs[`metaCollector-${idx}`][0];
collector.load();
const pushMeta = () => {
let obj = {
path: item.path,
duration: this.convertTimeHHMMSS(collector.duration)
};
this.metaArray.push(obj);
collector.removeEventListener('loadedmetadata', pushMeta);
this.$emit('init-meta', this.metaArray);
};
collector.addEventListener('loadedmetadata', pushMeta)
};
this.valuesArray.forEach((item, idx) => {
setMeta(item, idx);
});
})
},
setPause() {
this.$refs.player.pause();
this.states.isPlaying = false;
},
togglePlayState(event) {
if (this.states.play === true) {
this.states.play = false;
this.setPause();
} else {
this.states.play = true;
this.playMedia();
}
},
playMedia() {
this.loading = true;
this.$refs.player.play().then( () => {
this.loading = false;
this.states.isPlaying = true;
}).catch( err => {
console.warn(err);
});
},
moveSource(side, customSource) {
// console.log(customSource)
let isPlayedBefore = false;
if (this.isAudio && this.states.play) {
setTimeout( () => {
this.setPause();
}, 0)
isPlayedBefore = true;
};
if (customSource !== undefined) {
//move to custom
this.valuesArray.forEach((item, idx) => {
item.active = false;
if (item.path === customSource) {
item.active = true;
}
});
} else {
//move to next or prev
let activeIdx = 0;
this.valuesArray.forEach((item, idx) => {
if (item.active) {
activeIdx = idx;
};
item.active = false;
});
if (side === 'next') {
if (activeIdx === this.valuesArray.length - 1) {
this.valuesArray[0].active = true;
} else {
this.valuesArray[activeIdx + 1].active = true;
}
} else {
if (activeIdx === 0) {
console.log(this.valuesArray.length - 1)
this.valuesArray[this.valuesArray.length - 1].active = true;
} else {
this.valuesArray[activeIdx - 1].active = true;
}
}
}
this.$refs.player.currentTime = 0;
this.$refs.player.load();
if (this.isAudio && isPlayedBefore) {
setTimeout( () => {
this.playMedia()
}, 0)
}
},
}
})
Не могу побороть проблему уже часа два. Инфы в гугле мало. На задержку скорости загрузки грешить не стоит. Я тестил на локалке - поднял приложение на browserSync и тестил на iPhone и ноуте в локальной сети. Задержка в промисе this.$refs.player.play()
При этом в коде не встречается ошибок, во всяком случае консоль молчит.
Сначала я вообще вешал методы playMedia и setPause на вотчер стейта. Ни одно устройство apple не желало воспроизводиться вообще. Прочёл где-то на qaru что нужно вешать методы в callback события click и тогда работать будет. Это решило проблему но появилась эта задержка.
Тимми, почему я страдаю?