#javascript #html #loops #time #display
#javascript #HTML #циклы #время #отображение
Вопрос:
У меня есть папка с изображениями с каждой буквой. Учитывая предложение, я хочу иметь возможность перебирать все буквы в предложении и отображать изображение, связанное с каждой буквой, в течение 3 секунд за раз. Например, для предложения «виноград» картинка с названием «g» будет отображаться в течение 3 секунд, затем перейдет к следующей букве и т.д. Прямо сейчас я показываю изображения в том порядке, в котором они размещены в папке. Я в замешательстве от того, как я могу реализовать изменения, которые я ищу, поскольку я новичок в javascript. Заранее благодарю вас, вот что у меня есть сейчас:
var index = 0;
change();
var phrase = "my sentence";
function change() {
var pics = document.getElementsByClassName('pictures');
for(var i = 0; i < pics.length; i ) {
pics[i].style.display = "none";
}
for (var j = 0; j < phrase.length; j ) {
for (var k = 0; k < pictures.length; k ) {
var image = pictures[k].getElementsByTagName("img")[0];
var title = image.getAttribute("title");
if (phrase[j] == title) {
pictures[k].style.display = "block";
}
}
}
setTimeout(change, 3000);
}
<section>
<img class="slides" src="letter_images/a.jpg" style="width:50%">
<img class="slides" src="letter_images/b.jpg" style="width:50%">
<img class="slides" src="letter_images/c.jpg" style="width:50%">
<img class="slides" src="letter_images/d.jpg" style="width:50%">
<img class="slides" src="letter_images/e.jpg" style="width:50%">
<img class="slides" src="letter_images/f.jpg" style="width:50%">
<img class="slides" src="letter_images/g.jpg" style="width:50%">
<img class="slides" src="letter_images/h.jpg" style="width:50%">
<img class="slides" src="letter_images/i.jpg" style="width:50%">
<img class="slides" src="letter_images/j.jpg" style="width:50%">
<img class="slides" src="letter_images/k.jpg" style="width:50%">
<img class="slides" src="letter_images/l.jpg" style="width:50%">
<img class="slides" src="letter_images/m.jpg" style="width:50%">
<img class="slides" src="letter_images/n.jpg" style="width:50%">
<img class="slides" src="letter_images/o.jpg" style="width:50%">
<img class="slides" src="letter_images/p.jpg" style="width:50%">
<img class="slides" src="letter_images/q.jpg" style="width:50%">
<img class="slides" src="letter_images/r.jpg" style="width:50%">
<img class="slides" src="letter_images/s.jpg" style="width:50%">
<img class="slides" src="letter_images/t.jpg" style="width:50%">
<img class="slides" src="letter_images/u.jpg" style="width:50%">
<img class="slides" src="letter_images/v.jpg" style="width:50%">
<img class="slides" src="letter_images/w.jpg" style="width:50%">
<img class="slides" src="letter_images/x.jpg" style="width:50%">
<img class="slides" src="letter_images/y.jpg" style="width:50%">
<img class="slides" src="letter_images/z.jpg" style="width:50%">
</section>
Комментарии:
1. Если вы хотите отображать изображения для каждой буквы
phrase
, вам нужно проверить, что это за буква.phrase
Переменная вообще не используется вchange()
функции.
Ответ №1:
Я предлагаю перебирать все буквы предложения. Каждая буква будет отображаться с индексом * 3000 мс (где индекс — это индекс буквы в предложении — индекс первой буквы = 0, индекс второй буквы = 1, …)
Вот пример кода
const imgLetter = document.getElementById('letter');
const sentence = 'hello world';
sentence
.split('')
.filter(letter => /[a-z ]/i.test(letter)) // consider only letters and space
.forEach((letter, index) => {
setTimeout(_ => {
letter = letter !== ' ' ? letter : 'Rest';
imgLetter.src = `letter_images/${letter}.jpg`;
imgLetter.alt = letter;
}, index * 3000);
});
<section>
<img class="slides" src="" style="width:50%" id="letter">
</section>
Комментарии:
1. Как указывали другие по другим вопросам, setTimeout не гарантирует, что действие будет выполнено с запрошенным интервалом. В итоге может одновременно отображаться два изображения?
2. Кажется, это работает, но ответы только для кода не приветствуются. Может быть, какое-то объяснение по setTimeout?
3. Спасибо! У меня также есть изображение, которое я хочу отобразить, если в предложении есть пробел. Изображение называется «Rest». Поскольку в вашем коде используется «letter => / [a-z]», могу ли я каким-либо образом добавить проверку на пробел?
4. @poromazh Я добавил пробел в фильтр (например, для фильтрации текста) и добавил строку для «переименования» буквы в «Rest» в случае пробела
5. @CedricCholley Возможно, вам потребуется добавить последний тайм-аут, чтобы удалить последнюю отображаемую букву?
Ответ №2:
Как было указано ATD, setTimeout
не гарантирует, что действие будет выполнено с запрошенным интервалом, поэтому я попытался найти решение без setTimeout
.
Моя идея состоит в том, чтобы создать полное предложение с помощью цикла в javascript, а затем использовать анимацию CSS для отображения одного изображения за раз
const sentence = document.getElementById('sentence');
const mySentence = 'hello world';
const letters = mySentence.split('').filter(letter => /[a-z ]/i.test(letter));
sentence.style.setProperty('--letter-count', letters.length);
letters.forEach(letter => {
const imgLetter = document.createElement('img');
letter = letter !== ' ' ? letter : 'Rest';
imgLetter.src = `letter_images/${letter}.jpg`;
imgLetter.alt = letter;
sentence.append(imgLetter);
});
#sentence {
display: flex;
overflow: hidden;
}
/* images must have #sentence same size */
#sentence,
#sentence > img {
width: 200px;
height: 200px;
}
#sentence > img:first-child {
animation-name: slide;
animation-duration: calc(3s * var(--letter-count));
animation-timing-function: steps(var(--letter-count), end);
animation-fill-mode: forwards;
}
/* -200px = minus the width of #sentence */
@keyframes slide {
from {margin-left: 0}
to {margin-left: calc(-200px * var(--letter-count))}
}
<section id="sentence"></section>
Ответ №3:
Вот другой подход. Загрузите все изображения, которые вам понадобятся, а затем просмотрите их все. Таким образом, вам не придется загружать дополнительные изображения. Если ваша фраза длинная, содержит повторяющиеся буквы и содержит большинство букв, подход ATD может быть лучше.
let phrase = 'grape',
index = 0;
output = document.querySelector('#output');
//Frist we create the phrase with images, all hidden
for (let i = 0; i < phrase.length; i ) {
output.innerHTML = `<img class="slides" src="letter_images/${phrase[i]}.jpg" style="width:50%" alt="${phrase[i]}">`
}
//Now we show each one, one at a time
var loop = window.setInterval(showNextLetter, 3000 /*3 sec*/);
showNextLetter();
function showNextLetter() {
let nextLetter = output.children[index],
oldLetter = document.querySelector('.slides.shown');
//Make sure it exists
if (oldLetter) oldLetter.classList.remove('shown');
nextLetter.classList.add('shown');
index ;
if (index >= phrase.length) index = 0;
}
.slides {
display: none;
}
.slides.shown {
display: block;
}
<div id="output"></div>
Ответ №4:
Вам нужно перебирать буквы в phrase
переменной, чтобы найти каждую букву, одну за другой. Исходя из этого, вам нужно выяснить, где оно будет отображаться в алфавите ( letters
строка ниже). Это должно дать вам число от 0 до 25. Это должно соответствовать номеру индекса в вашей slides
коллекции, чтобы вы могли показать тот, у которого соответствующий номер индекса.
var index = 0;
var phrase = "my sentence";
var letters = "abcdefghijklmnopqrstuvwxyz";
var tt;
function change() {
var pics = document.getElementsByClassName('slides');
for(var i = 0; i < pics.length; i ) {
pics[i].style.display = "none";
}
let thisLetter = phrase.substr(index, 1);
if (thisLetter != " ") {
let thisPos = letters.indexOf(thisLetter);
pics[thisPos].style.display = "block";
} else {
pics[pics.length - 1].style.display = "block";
}
index ;
if (index != phrase.length) {
tt = setTimeout(change, 3000);
} else {
for(var i = 0; i < pics.length; i ) {
pics[i].style.display = "none";
}
}
}
Это невозможно протестировать без доступности всех изображений. Код выполняется, но вам нужно будет проверить его локально, чтобы быть абсолютно уверенным.
Комментарии:
1. сначала
for(...)
цикл должен скрывать все изображения —thisPos
после этого должно отображаться только то, которое соответствует значению.2. Я только что увидел, что после отображения окончательного изображения оно останется видимым. Итак, я обновил код, чтобы выполнить последний цикл, чтобы убедиться, что все они скрыты. Однако начальное состояние в вашем HTML должно быть
display:none
3. Когда я пытаюсь это сделать, все изображения отображаются на странице одно под другим — ни одно из них не меняется через 3 секунды. Связано ли это с тем, как у меня есть раздел изображений?
4. Это не должно быть проблемой. Я просто скопировал / вставил ваш HTML-код в пустой HTML-код и запустил скрипт — я, конечно, не вижу изображений, но, используя Inspector в браузере, я вижу, что изображения отображаются правильно. Я только что обновил свой код, чтобы включить
rest
изображение, понимая, что оно находится послеz
изображения (в противном случае алфавиты не будут связываться).