Верстка нескольких картинок при выборе
Здравствуйте
Есть кнопка выбора нескольких картинок. <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, но, насколько я понял, там нужно изначально задавать высоту и ширину блоков. А в моем случае неизвестно же, что выберет пользователь. Заранее спасибо! |
|
Цитата:
(Контактами я не пользуюсь, и уж тем более не буду постить там несколько картинок, что бы посмотреть) Просто словами опишите, типа ТЗ Цитата:
(object-fit) Реальный размер изображения после загрузки можно узнать, используя свойства naturalWidth и naturalHeight. |
Цитата:
|
masrony интереснее. Там адаптивная верста.
В документации ( https://masonry.desandro.com/layout.html ) сказано, что masrony можно подключать и после загрузок всех картинок. Но все равно надо как то фиксировать максимальные возможные размеры <img>, ведь от юзера можно чего угодно ожидать, в том числе и картинки 4000х3000. |
Цитата:
Цитата:
https://javascript.ru/forum/showthread.php?p=357204 |
<!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,
Есть одна небольшая ошибочка. Сколько я не смотрел, у меня всегда показывалось только 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> |
По хорошему, надо учитывать, что какие то картинки могут не существовать (по разным причинам не загрузиться) Тогда нужна такая функция
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)) }) } |
Цитата:
Боком промисы, тут не это, этот код, это давняя "адаптация" РНР кода описанного на хабре. И что интересно, я его даже тогда не запускал, причин не помню, да и не важно. Это сегодня вспомнил о статье, запустил, явные баги убрал, чтобы немного дышало и все. Если интересен сам исходник "мысля по принципу расчета", то тут https://habr.com/ru/post/135421/ ссылка сохранилась. |
Часовой пояс GMT +3, время: 04:11. |