Arhn - архитектура программирования

Примените значение css с помощью jQuery, но проверьте, не указано ли оно уже

Я использую jQuery для применения фоновых изображений к случайно выбранным элементам DIV.

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

При поиске решения я собрал фрагмент кода с большой помощью других, но он не проверяет, использует ли какой-либо из DIV это изображение в данный момент. В результате часто случается, что два или более DIV имеют одно и то же фоновое изображение одновременно...

Вот мой код:

var urls = [
    	'url(https://placekitten.com/g/350/150)',
    	'url(https://placekitten.com/g/300/550)',
    	'url(https://placekitten.com/g/400/200)',
    	'url(https://placekitten.com/g/350/750)',
    	'url(https://placekitten.com/g/250/600)',
    	'url(https://placekitten.com/g/400/150)',
    	'url(https://placekitten.com/g/300/600)',
    	'url(https://placekitten.com/g/450/350)'
	  ];
	  // Select the next image
	  var active = Math.floor(Math.random() * (urls.length - 4)) + 1

	  setInterval(function() {

		// Select randomnly the next div to change
		var rand = Math.floor(Math.random() * 4);
		
		// Store this list, so that we only make one call to the page
		let images = $('.image');
		
		let datachanged = images.attr("data-changed");
		
		while(rand == datachanged)
		rand = Math.floor(Math.random() * 4);
	  
		let current = $('.image:nth-child('+(rand+1)+')');
		
		current.toggleClass("show hide");
		
		// The fade effect takes 400ms
		
		setTimeout(function(){
		
		  current.css('background-image', urls[active]);
		  
		  images[0].setAttribute("data-changed", rand);
		
		  current.toggleClass("hide show");
		
		},400);
	  
		// Change active value so that the background will not be same next time
		active++;
		
		active = (active == urls.length) ? 0 : active ;
		
	  }, 2000);
body { margin: 0; font-size: 0;}

.image {
  background-size: cover;
  display: inline-block;
  width: 23%;
  padding-top: 23%;
  margin: 1%;
  transition: opacity 0.4s ease;
}

.image:nth-of-type(1) { 
  background-image: url(https://placekitten.com/g/350/150); 
}
.image:nth-of-type(2) { 
  background-image: url(https://placekitten.com/g/300/550); 
}
.image:nth-of-type(3) { 
  background-image: url(https://placekitten.com/g/400/200); 
}
.image:nth-of-type(4) { 
  background-image: url(https://placekitten.com/g/350/750); 
}

.show {
      opacity: 1;
}

.hide {
  opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id="images">
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
</div>

А вот тот же код на jsFiddle.


  • Вы хотите менять по одному изображению за раз (при срабатывании таймера) или одновременно может быть много замен? 16.05.2020
  • Что, если вы сохранили числа rand в массиве, каждый раз, когда истекает время ожидания, вставляйте новое значение rand в массив и проверяйте следующее значение, сгенерированное случайным образом, чтобы увидеть, является ли оно .inArray(), если оно находится в массиве , не помещайте это значение в массив. Продолжайте использовать эту логику, пока в вашем массиве не будет 4 значений. Проверьте длину массива, если она меньше 4, вставьте новое значение в массив, если оно равно 4, вставьте новую длину, а затем удалите последнее значение, чтобы у вас всегда было 4 значения, которые не совпадают. 17.05.2020
  • Привет, @dalelandry, я открыт для любого работающего решения. Просто имейте в виду, что он также должен работать с любым количеством DIV. У меня есть пример с 8 DIV: jsfiddle.net/sublines/bdtq5cnz/2 17.05.2020

Ответы:


1

Вы можете использовать данные для хранения индекса используемого изображения. Затем в каждом интервале вы можете исключить один раз из основного массива URL-адресов. Затем выберите случайный индекс для хранения в данных элемента.

Кроме того, я изменил переключатель класса на jQuery .fadeIn() и .fadeOut(), чтобы обеспечить более стабильный подход с обратными вызовами.

Убедитесь, что массив URL-адресов изображений больше, чем у вас есть div.

let urls = [
  'https://source.unsplash.com/5E5N49RWtbA/300x300',
  'https://source.unsplash.com/G85VuTpw6jg/300x300',
  'https://source.unsplash.com/fIq0tET6llw/300x300',
  'https://source.unsplash.com/P_0R02ArdLE/300x300',
  'https://source.unsplash.com/PC_lbSSxCZE/300x300',
  'https://source.unsplash.com/nptLmg6jqDo/300x300',
  'https://source.unsplash.com/1_CMoFsPfso/300x300',
  'https://source.unsplash.com/mk7D-4UCfmg/300x300'
];

// Get reference to divs and assign images on inital load
let images = $('.image');
let unusedDivs;

images.each(function(i, e) {
  jQuery(this).css('background-image', `url(${urls[i]})`);
  jQuery(this).data("image-index", i).data("div-used", false);
});

let lastImageIndex = null;

setInterval(function() {
  // Get indexes that are already in ue
  const usedIdx = images.map(function(i, e) {
    return jQuery(e).data("image-index");
  }).get();

  // Filter indexes of urls that are not displayed yet
  const unusedIdx = [];
  urls.forEach(function(url, i) {
    if (usedIdx.indexOf(i) == -1)
      unusedIdx.push(i);
  });

  // get images div that not in use yet
  unusedDivs = jQuery('.image').filter(function(i, e) {
    return $(e).data("div-used") == false;
  });

  // Choose a random index from the unused indexes array
  const randUnsedIdx = Math.floor(Math.random() * unusedIdx.length);

  // Chose a random image div to apply image to
  const randDivIdx = Math.floor(Math.random() * unusedDivs.length);
  const current = unusedDivs.eq(randDivIdx);
  lastImageIndex = randDivIdx;

  // Get index number
  const imgUrlIdx = unusedIdx[randUnsedIdx];

  // fade out old image then on callback set the url of the new image
  // then fade it in and assign the index to the dive so in next 
  // iteration we can filter it out
  current.fadeOut(400, function() {
    current.css('background-image', `url(${urls[imgUrlIdx]})`);
    current.fadeIn();
    current.data("image-index", imgUrlIdx).data("div-used", true);
    
    // if all unsed divs have been used then reset
    if (unusedDivs.length == 1)
      jQuery('.image').data("div-used", false);

  });

}, 2000);
body {
  margin: 0;
  font-size: 0;
}

.image {
  background-size: cover;
  display: inline-block;
  width: 23%;
  padding-top: 23%;
  margin: 1%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="images">
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
</div>

17.05.2020
  • Эй, спасибо за хорошо документированный код! Использование Unsplash также очень умно, так как помогает увидеть, используется ли изображение уже или нет. Я попробовал ваш код в jsFiddle, и он работает довольно хорошо, за исключением того, что иногда он выбирает DIV, который был выбран в последний раз. Я не хочу, чтобы он дважды подряд выбирал один и тот же DIV, но я думаю, что должен был четко указать это в своем вопросе. Вот ваш код на jsFiddle: jsfiddle.net/sublines/5ghcv3yu/5 Не могли бы вы обновить это решить последнюю проблему? 17.05.2020
  • Без проблем. Я обновил свой ответ. Я добавил данные div-used, которые уменьшаются с каждым интервалом, а затем сбрасываются, когда они все используются. Таким образом, все div-изображения будут использоваться до начала. 17.05.2020

  • 2

    Вместо сохранения «последнего активного индекса img» в качестве атрибута данных я только что создал selectedImages, который содержит состояние изображений, отображаемых в div: начальным является [1,2,3,4]

    И при поиске следующего уникального рандома я просто смотрю, пока не получу значение, которого нет в selectedImages:

    do{
          active = Math.floor(Math.random() * (urls.length - 2)) + 1
        } while(selectedImages.indexOf(active) != -1)
    

    Вот полный фрагмент

    var urls = [
            	'url(https://placekitten.com/g/350/150)',
            	'url(https://placekitten.com/g/300/550)',
            	'url(https://placekitten.com/g/400/200)',
            	'url(https://placekitten.com/g/350/750)',
            	'url(https://placekitten.com/g/250/600)',
            	'url(https://placekitten.com/g/400/150)',
            	'url(https://placekitten.com/g/300/600)',
            	'url(https://placekitten.com/g/450/350)'
        	  ];
        	  // Select the next image
            var selectedImages = [1,2,3,4] // initial state of divs img urls
            var lastSelectedDiv = -1; // initial state of last selected div
    
        	  setInterval(function() {
        	  var active; 
            do{
              active = Math.floor(Math.random() * (urls.length - 2)) + 1
            } while(selectedImages.indexOf(active) != -1) // get a unique image (not in current ones that are displayed)
        		// Select randomnly the next div to change which is diffrent than the lastSelectedDiv
            var rand;
            do{
        		  rand = Math.floor(Math.random() * 4); // get a random value until its not the same as lastSelectedDiv
            } while(rand == lastSelectedDiv)
            selectedImages[rand] = active;
    
            lastSelectedDiv = rand; // override lastSelectedDiv to new random value so that next time it must be different
        		let current = $('.image:nth-child('+(rand+1)+')');
        		
        		current.toggleClass("show hide");
        		
        		// The fade effect takes 400ms
        		
        		setTimeout(function(){
        		
        		  current.css('background-image', urls[active]);
          
        		
        		  current.toggleClass("hide show");
        		
        		},400);
    
        		
        	  }, 2000);
    body { margin: 0; font-size: 0;}
    
        .image {
          background-size: cover;
          display: inline-block;
          width: 23%;
          padding-top: 23%;
          margin: 1%;
          transition: opacity 0.4s ease;
        }
    
        .image:nth-of-type(1) { 
          background-image: url(https://placekitten.com/g/350/150); 
        }
        .image:nth-of-type(2) { 
          background-image: url(https://placekitten.com/g/300/550); 
        }
        .image:nth-of-type(3) { 
          background-image: url(https://placekitten.com/g/400/200); 
        }
        .image:nth-of-type(4) { 
          background-image: url(https://placekitten.com/g/350/750); 
        }
    
        .show {
              opacity: 1;
        }
    
        .hide {
          opacity: 0;
        }
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
        <div id="images">
          <div class="image"></div>
          <div class="image"></div>
          <div class="image"></div>
          <div class="image"></div>
        </div>

    Отредактируйте здесь скрипт для 8 разделов: https://jsfiddle.net/pascrzx9/1/ - Я пометил каждый div img другим номером, поэтому мы не используем только цвета (иногда я думал, что я дальтоник или это код с ошибками :P)

    16.05.2020
  • Итак, если у меня более четырех DIV, я просто меняю эту строку, верно?: var selectedImages = [1,2,3,4] 16.05.2020
  • Я пробовал это с 9 DIV и изменил эту строку на: var selectedImages = [1,2,3,4,5,6,7,8,9], но по какой-то причине иногда выбирается изображение, которое уже используется одним из других DIV в этот момент. 16.05.2020
  • Если у вас есть 9 div и только 8 изображений, невозможно иметь все div с уникальными изображениями: P 16.05.2020
  • но да, вам придется изменить этот var selectedImages = [1,2,3,4], чтобы поддерживать более 4 элементов 16.05.2020
  • У меня есть 8 DIV и 11 изображений, и я также изменил эту строку кода, но он по-прежнему выбирает изображения, которые уже используются: jsfiddle.net/sublines/bdtq5cnz/2 Кроме того, иногда он выбирает DIV, который был выбран в последний раз. Я не хочу, чтобы он дважды подряд выбирал один и тот же DIV, но я думаю, что должен был четко указать это в своем вопросе. 16.05.2020
  • правда, в этом случае вам придется сохранить lastSelectedDiv, а затем получить var rand = Math.floor(Math.random() * 4); в do{ ..} while(rand != lastSelectedDiv) 16.05.2020
  • Звучит хорошо, но я этого не понимаю. Не будете ли вы так любезны и обновите свой ответ, включив в него решение ОБЕИХ проблем (не выбирая уже используемое изображение + не выбирая DIV дважды подряд)? Тогда я смогу пометить его как решенный и с радостью дам вам награду. 17.05.2020
  • Я скорректировал код в соответствии с вашими потребностями, а также добавил несколько комментариев, чтобы вы могли самостоятельно анализировать код ;p 17.05.2020
  • Спасибо за обновление вашего кода. Я вставил его в эту скрипку, но проблема все еще сохраняется. Он по-прежнему часто выбирает изображение, которое в этот момент уже используется другим DIV: jsfiddle.net/sublines/ bdtq5cnz/6 17.05.2020
  • В вашем коде была небольшая ошибка, я исправил ее и подготовил еще одну скрипту: jsfiddle.net/25jebsmz/1 - также каждое изображение имеет свой собственный размер, поэтому мы не ориентируемся только на цвет (иногда они сбивают с толку, чтобы заметить разницу) 17.05.2020
  • Привет, спасибо за проверку и обновление кода. Кажется, в вашей скрипке есть ошибка. Когда я запускаю код, он теперь всегда выбирает одно и то же изображение каждый раз. 17.05.2020
  • Упс, вставлена ​​неправильная скрипка: P моя ошибка здесь правильная: jsfiddle.net/pascrzx9/1 17.05.2020
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..