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

#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 изображения (в противном случае алфавиты не будут связываться).