Как я могу отображать изображения на основе названия изображения в javascript?

У меня есть папка с изображениями с каждой буквой. Учитывая предложение, я хочу иметь возможность перебирать все буквы в предложении и отображать каждое связанное с буквой изображение в течение 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>


person poromazh    schedule 27.09.2020    source источник
comment
Если вы хотите отобразить изображения для каждой буквы в phrase, вам нужно проверить, что это за буква. Переменная phrase вообще не используется в функции change().   -  person ATD    schedule 27.09.2020


Ответы (4)


Как было указано 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>

person Cedric Cholley    schedule 27.09.2020

Я предлагаю перебрать каждую букву предложения. Каждая буква будет отображаться с индексом * 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>

person Cedric Cholley    schedule 27.09.2020
comment
Как указывали другие на другие вопросы, setTimeout не гарантирует, что действие будет выполнено с запрошенным интервалом. Вы могли бы получить два изображения, отображаемые одновременно? - person ATD; 27.09.2020
comment
Кажется, это работает, но ответы только для кода не приветствуются. Может быть, какое-то объяснение setTimeout? - person HoldOffHunger; 27.09.2020
comment
спасибо! У меня также есть изображение, которое я хочу отобразить, если в предложении есть пробел. Изображение называется «Отдых». Поскольку в вашем коде используется буква =› /[a-z], могу ли я добавить проверку пробела? - person poromazh; 27.09.2020
comment
@poromazh Я добавил пробел в фильтр (например, для фильтрации пунктуации) и добавил строку для переименования буквы в Rest в случае пробела - person Cedric Cholley; 27.09.2020
comment
@CedricCholley Возможно, вам придется добавить последний тайм-аут, чтобы удалить последнюю отображаемую букву? - person ATD; 27.09.2020

Вот еще один подход. Загрузите все изображения, которые вам понадобятся, а затем просмотрите их все. Таким образом, вам не придется загружать дополнительные изображения. Если ваша фраза длинная, содержит повторяющиеся буквы и содержит большинство букв, подход 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>

person Jack    schedule 27.09.2020

Вам нужно перебирать буквы в переменной 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"; 
          }
        }
     }

Это невозможно проверить без наличия всех изображений. Код действительно работает, но вам нужно будет проверить его локально, чтобы быть абсолютно уверенным.

person ATD    schedule 27.09.2020
comment
цикл for(...) должен сначала скрывать все изображения — после этого должно отображаться только то, которое соответствует значению thisPos. - person ATD; 27.09.2020
comment
Я только что видел, что после отображения окончательного изображения оно останется видимым. Поэтому я обновил код, чтобы сделать последний цикл, чтобы убедиться, что все они скрыты. Однако начальное состояние в вашем HTML должно быть display:none - person ATD; 27.09.2020
comment
Когда я пытаюсь это сделать, все изображения отображаются на странице одно под другим - ни одно из них не меняется через 3 секунды. Это связано с тем, как у меня есть раздел изображений? - person poromazh; 27.09.2020
comment
Это не должно быть проблемой. Я просто скопировал/вставил ваш HTML-код в пустой HTML-код и запустил скрипт - я, конечно, не вижу изображений, но с помощью Inspector в браузере я вижу, что изображения отображаются правильно. Я только что обновил свой код, чтобы включить изображение rest при том понимании, что оно следует за изображением z (иначе алфавиты не будут связаны). - person ATD; 27.09.2020