При нажатии на кнопку стрелка (на клавиатуре) (keycode 37)
нужно показать иконку на на 300мс, замет скрыть её. И так на каждое нажатие кнопки.
Я создаю переменную с типом false
при нажатии кнопки, делаю её true
тем самым отображая иконку, при нажатии запускается запуская таймер на 300мс по истечению которого другая функция возвращает false
, тем самым пряча иконку.
Проблема заключается в том, что при частом многократном нажатии в какой-то момент иконка перестает появляться.
Может есть идеии как можно усовершенствовать этот подход или поменять на что-нибудь более толковое.
P.S.
В css
есть класс info_icons
для иконки. Когда иконка появляется для неё срабатывает анимация, то есть из прозрачной она становится не прозрачной и затем опять прозрачной.
Проще говоря она плавно появляется и исчезает.
P.P.S
Так же для других кнопок есть actions
. Суть такая же.
Я добавил один вариант, если получится придумать альтернативу или починить нижеизложенный код, то я смогу провернуть это дело с остальными кнопками :)
html
<v-icon v-if="replay_5" class="info_icons" size="50">
replay_5
</v-icon> //Material ui icon
Vue
data() {
return {
replay_5: false,
}
}
methods: {
show_replay_5() {
this.replay_5 = false;
},
onKeydown({
keyCode
}) {
switch (keyCode) {
case 37:
this.replay_5 = true;
/*some code*/
setTimeout(this.show_replay_5, 300);
break;
}
}
}
css
.info_icons {
animation-name: fadeInOpacity;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 0.3s;
background-color: rgba(255, 255, 255, 0.3);
border-radius: 100%;
transform: scale(1.2);
opacity: 0;
}
@keyframes fadeInOpacity {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
Спасибо за внимание!
При использовании setTimeout
и setInterval
лучше создавать ссылки на них и при необходимости удалять, тогда не будет "зацикливаний".
Оптимальным было бы воспользоваться стандартными средствами анимации Vue: используя хук, например, enter
, менять значение, отвечающее за показ элемента на противоположное и тем самым скрывать его. Демо:
// Создаем экземпляр приложения.
new Vue({
// Корневой элемент, определяется по css селектору.
el: '#app',
data: {
// Модель отображения кнопок-стрелок.
arrows: {
top: false,
bottom: false,
left: false,
right: false,
},
// Чтобы не перебирать "свитчами" и "кейсами".
keyMap: {
37: 'left',
38: 'top',
39: 'right',
40: 'bottom',
}
},
methods: {
onKeydown({
keyCode
}) {
if (keyCode in this.keyMap) {
this.arrows[this.keyMap[keyCode]] = true;
}
},
/**
* Появление.
*/
beforeEnter(el) {
// console.log('beforeEnter');
},
enter(el, done) {
// console.log('enter');
// Перебираем свойства объекта,
// устанавливаем для всех полей значение `false`.
for (let arrow in this.arrows) {
if ('object' === typeof this.arrows && this.arrows.hasOwnProperty(arrow)) {
this.arrows[arrow] = false;
}
}
// Коллбэк done не обязательно использовать, если
// анимация или переход также определены в CSS.
// done();
}
}
});
/**
* Стили для анимации.
*/
.fade-enter-active,
.fade-leave-active {
animation: fade-in .6s;
}
@keyframes fade-in {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
/* Или такой вариант
.fade-enter-active, .fade-leave-active { transition: opacity .6s;}
.fade-enter, .fade-leave-to { opacity: 0; }
*/
/**
* Дальше стили для демки.
*/
*,
::after,
::before {
box-sizing: border-box;
text-align: center;
}
.wrapper {
width: 188px;
border: 1px dashed #08c;
margin: 0 auto;
display: grid;
grid-template-areas: 'top top' 'left right' 'bottom bottom';
}
.wrapper:focus {
border: 1px solid #08c;
outline: none;
}
.icon {
line-height: 60px;
min-height: 60px;
color: #fff;
}
.icon-top {
grid-area: top;
}
.color-top {
background: #fbc531;
}
.icon-left {
grid-area: left;
}
.color-left {
background: #c23616;
}
.icon-right {
grid-area: right;
}
.color-right {
background: #487eb0;
}
.icon-bottom {
grid-area: bottom;
}
.color-bottom {
background: #5fba7d;
}
<div id="app">
<h3>Щелкните на блок для захвата ввода с клавиатуры</h3>
<h4>Используйте стрелки клавиатуры, чтобы отобразить элементы</h4>
<div class="wrapper" @keydown="onKeydown" tabindex="-1">
<div class="icon icon-top">
<transition name="fade" @enter="enter">
<div v-if="arrows.top" class="color-top">Север</div>
</transition>
</div>
<div class="icon icon-left">
<transition name="fade" @enter="enter">
<div v-if="arrows.left" class="color-left">Запад</div>
</transition>
</div>
<div class="icon icon-right">
<transition name="fade" @enter="enter">
<div v-if="arrows.right" class="color-right">Восток</div>
</transition>
</div>
<div class="icon icon-bottom">
<transition name="fade" @enter="enter">
<div v-if="arrows.bottom" class="color-bottom">Юг</div>
</transition>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
В данном примере использованы повторяющиеся конструкции в HTML разметке, чтобы сохранить каркас для блоков, размещенных по сторонам света, т.е. это не шаблон, которому вы должны строго следовать.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Подскажите что не так, при инициализации функции на input все работает, а вот через button нет, функция выполняется и сразу же "все пропадает"
У меня есть Timer, который по определенным причинам я проинициализировал в статическом конструктореПосле того как я добавил этот статический...
Пытаюсь c помощью XPath добавить песню в мои аудиозаписиПроблема в том, что кнопка добавления трека появляется только при наведении мышкой...
У меня есть кастомный TextBlock, который определяет ссылки в тексте и делает их кликабельнымиВозникла необходимость добавить возможность выделения...