Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 04.12.2020, 20:42
Новичок на форуме
Отправить личное сообщение для tovarz Посмотреть профиль Найти все сообщения от tovarz
 
Регистрация: 13.02.2011
Сообщений: 6

Верстка нескольких картинок при выборе
Здравствуйте
Есть кнопка выбора нескольких картинок.
<input type="file" id="myfiles" accept="image/*" multiple="true">


Картинки с большой вероятностью имеют разные размеры.

Обрабатываю выборку:

$('#myfiles').on('change', function () { 
     var files = this.files;
     $.each(files, function(i, file) {      
		var img = new Image();
		
		img.onload = function(){
                            /*Здесь нужен какой-то скрипт для красивого расположения картинок*/
		}

               img.src = URL.createObjectURL(file);
	});
       
       /*Или вот здесь нужен какой-то скрипт для красивого расположения картинок*/
});


Подскажите, пожалуйста, методы для красивого расположения картинок после выборки (например, как ВКонтакте при выборе нескольких картинок для поста). Пробовал masonry, но, насколько я понял, там нужно изначально задавать высоту и ширину блоков. А в моем случае неизвестно же, что выберет пользователь.
Заранее спасибо!
Ответить с цитированием
  #2 (permalink)  
Старый 04.12.2020, 21:22
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,123

tovarz,
https://imagesloaded.desandro.com/
Ответить с цитированием
  #3 (permalink)  
Старый 04.12.2020, 21:43
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,750

Сообщение от tovarz
Подскажите, пожалуйста, методы для красивого расположения картинок
Опишите, что вы считаете красивым
(Контактами я не пользуюсь, и уж тем более не буду постить там несколько картинок, что бы посмотреть)
Просто словами опишите, типа ТЗ
Сообщение от рони
но, насколько я понял, там нужно изначально задавать высоту и ширину блоков. А в моем случае неизвестно же, что выберет пользователь.
В этом случае картинкам (<img>) можно задавать фиксированный размер и масштабировать реальное изображение, используя стили
(object-fit)
Реальный размер изображения после загрузки можно узнать, используя свойства naturalWidth и naturalHeight.

Последний раз редактировалось voraa, 04.12.2020 в 21:50.
Ответить с цитированием
  #4 (permalink)  
Старый 04.12.2020, 22:06
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Сообщение от voraa
что вы считаете красивым
Такое - http://jquery-gp-gallery.ionelmc.ro/demo/
Ответить с цитированием
  #5 (permalink)  
Старый 04.12.2020, 22:20
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,750

masrony интереснее. Там адаптивная верста.
В документации ( https://masonry.desandro.com/layout.html ) сказано, что masrony можно подключать и после загрузок всех картинок.
Но все равно надо как то фиксировать максимальные возможные размеры <img>, ведь от юзера можно чего угодно ожидать, в том числе и картинки 4000х3000.
Ответить с цитированием
  #6 (permalink)  
Старый 04.12.2020, 22:26
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,123

Сообщение от voraa
masrony можно подключать и после загрузок всех картинок.
Сообщение от рони
https://imagesloaded.desandro.com/

https://javascript.ru/forum/showthread.php?p=357204

Последний раз редактировалось рони, 04.12.2020 в 22:31.
Ответить с цитированием
  #7 (permalink)  
Старый 05.12.2020, 05:02
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

<!DOCTYPE HTML>
<html>
<body>
<div id="show" style="width:700px;"></div>

<script>
let ims = [
        'https://icdn.lenta.ru/images/2020/09/11/13/20200911130707980/pic_d755b4d0cfe191965282d20cf7f15929.png',
        'https://images.pexels.com/photos/5393597/pexels-photo-5393597.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
        'https://s1.stc.all.kpcdn.net/russia/wp-content/uploads/2020/05/devushka-v-shlyape.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_01.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_10.jpg',
        'https://cdn.footballua.tv/i/image_650x360/uploads/football-media/image/5e9/97d/394/5e997d3944244_.jpeg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_57.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_47.jpg',
        'https://veasy.ru/wp-content/uploads/1-69.png',
        'https://images.pexels.com/photos/5644323/pexels-photo-5644323.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
        'https://vjoy.cc/wp-content/uploads/2019/07/1-47.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_14.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_37.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_39.jpg'
    ],
    width_box = 700,
    height_line = 150,
    margin = 1,
    count = ims.length,
    first = 1,
    box = document.getElementById('show'),
    data = {};


function preload(ret) {
    
    ims.forEach((e, i)=> {
        load(e, function() {
            data[i+1] = {src: this.src, w: this.width, h: this.height};
            if(i == count-1) ret()
        })
    });
        
    function load(im, f) {
        let img = new Image;
        img.onload = f;
        img.src = im
    }
}

preload( _=> { 
    while(first <= count) {
	   let im = first - 1,
	       H = height_line + 1;
		
        while(H > height_line && im < count) {
			im++;
			let width = width_box - (im - first + 1) * margin * 2;
			
			let del = width * data[first].h,
				dev = data[first].w;
	
			for(let i = first+1; i <= im; ++i) dev = dev + data[i].w * (data[first].h / data[i].h);

            H = Math.floor(del / dev);
        
            if(H <= height_line) {
                
                for(let i = first; i <= im; ++i) {
					
                    ims = new Image;
                    ims.src = data[i].src;
                    ims.height = H;
                    ims.style.margin = margin + 'px';
                    
                    box.appendChild(ims);
                    
                }
			
                first = im + 1;
		
            } else { 

                if(im == count) {
			 
                    for(let i = first; i <= im; ++i) {
					
                        ims = new Image;
                        ims.src = data[i].src;
                        ims.height = H;
                        ims.style.margin = margin + 'px';
                    
                        box.appendChild(ims);
				    }
				
                    first = im + 1;
				
                }
            }
        }
    }
});
</script>
</body>
</html>

Последний раз редактировалось laimas, 05.12.2020 в 06:01.
Ответить с цитированием
  #8 (permalink)  
Старый 05.12.2020, 09:08
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,750

laimas,
Есть одна небольшая ошибочка.
Сколько я не смотрел, у меня всегда показывалось только 8 картинок, почему то.
А если посмотреть в отладчике, то там выплевывается ошибка, что data[9] есть undefined
А дело в строке 37.
if(i == count-1) ret()
Как только загрузилась последняя картинка (с i == 13) то вызывается ret (). Не дожидаясь того, что предыдущие картинки еще могут быть не загружены.
Файл 8-й (data[9]) картинки "https://veasy.ru/wp-content/uploads/1-69.png" наверно слишком большой, и он загружается последним, поэтому и не готов ко времени выполнения ret.
Я немного поменял код, что бы грузилось все, используя Promise.all.
В компоновку не вдавался, поэтому выглядит немного странно.

<!DOCTYPE HTML>
<html>
<body>
<div id="show" style="width:700px;"></div>
 
<script>
let ims = [
        'https://icdn.lenta.ru/images/2020/09/11/13/20200911130707980/pic_d755b4d0cfe191965282d20cf7f15929.png',
        'https://images.pexels.com/photos/5393597/pexels-photo-5393597.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
        'https://s1.stc.all.kpcdn.net/russia/wp-content/uploads/2020/05/devushka-v-shlyape.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_01.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_10.jpg',
        'https://cdn.footballua.tv/i/image_650x360/uploads/football-media/image/5e9/97d/394/5e997d3944244_.jpeg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_57.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_47.jpg',
        'https://veasy.ru/wp-content/uploads/1-69.png',
        'https://images.pexels.com/photos/5644323/pexels-photo-5644323.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
        'https://vjoy.cc/wp-content/uploads/2019/07/1-47.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_14.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_37.jpg',
        'https://cdn.trinixy.ru/pics5/20180420/thousand_words_39.jpg'
    ],
    width_box = 700,
    height_line = 150,
    margin = 1,
//    count = ims.length,
//    first = 1,
    box = document.getElementById('show')
//    data = [];
	;
 
function preload(ret) {
     
    Promise.all(
		ims.map((src, i)=> {
			let im = new Image
			im.src = src
			return im.decode().then (_ => { return {src: src, w: im.width, h: im.height, img:im}});
		})
	).then ( data => ret(data)) 
         
}
 
preload( data => {
    const count = data.length;
    let first = 1;
    while(first <= count) {
       let im = first - 1,
           H = height_line + 1;
         
        while(H > height_line && im < count) {
            im++;
            let width = width_box - (im - first + 1) * margin * 2;
             
            let del = width * data[first-1].h,
                dev = data[first-1].w;
     
            for(let i = first+1; i <= im; ++i) dev = dev + data[i-1].w * (data[first-1].h / data[i-1].h);
 
            H = Math.floor(del / dev);
         
            if(H <= height_line) {
                 
                for(let i = first; i <= im; ++i) {
                     
                    let ims = data[i-1].img;
                    ims.height = H;
                    ims.style.margin = margin + 'px';
                     
                    box.appendChild(ims);
                     
                }
             
                first = im + 1;
         
            } else {
 
                if(im == count) {
              
                    for(let i = first; i <= im; ++i) {
                     
                        let ims = data[i-1].img;
                        ims.height = H;
                        ims.style.margin = margin + 'px';
                     
                        box.appendChild(ims);
                    }
                 
                    first = im + 1;
                 
                }
            }
        }
    }
});
</script>
</body>
</html>

Последний раз редактировалось voraa, 05.12.2020 в 09:32.
Ответить с цитированием
  #9 (permalink)  
Старый 05.12.2020, 09:26
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,750

По хорошему, надо учитывать, что какие то картинки могут не существовать (по разным причинам не загрузиться) Тогда нужна такая функция

function preload(ret) {
     
    Promise.allSettled(
		ims.map((src, i)=> {
			let im = new Image
			im.src = src
			return im.decode().then (_ => { return {src: src, w: im.width, h: im.height, img:im}});
		})
	).then ( data => { 
		ret(data.filter(d => d.status == 'fulfilled').map(d => d.value))
	}) 
         
}
Ответить с цитированием
  #10 (permalink)  
Старый 05.12.2020, 11:52
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Сообщение от voraa
Сколько я не смотрел, у меня всегда показывалось только 8 картинок, почему то.
А если выполнить не в песочнице, то все. Ошибки есть, и они возникают либо при определенном количестве изображений, либо при определенных параметрах.

Боком промисы, тут не это, этот код, это давняя "адаптация" РНР кода описанного на хабре. И что интересно, я его даже тогда не запускал, причин не помню, да и не важно. Это сегодня вспомнил о статье, запустил, явные баги убрал, чтобы немного дышало и все.

Если интересен сам исходник "мысля по принципу расчета", то тут https://habr.com/ru/post/135421/ ссылка сохранилась.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Новый input при выборе определенного option SLameN Элементы интерфейса 4 03.07.2015 16:29
Действие при одновременном выборе в разных выпадающих списках Oresama Элементы интерфейса 1 28.06.2015 20:22
jquery действие при выборе или вводе mali Общие вопросы Javascript 7 03.11.2014 16:18
Меняющейся текст при выборе select ainur777 Общие вопросы Javascript 0 24.10.2014 22:01
смена картинок при нажатии sdff Общие вопросы Javascript 15 08.02.2014 17:08