Прокрутка к первой картинке из добавленных через input[type='file']
В #bar отображается #box.scrollTop. <main> намеренно размещен так, чтобы были видны полосы прокрутки и была возможность увидеть что и куда сдвигается. #bar прокручивает список к текущей картинке img.c, чтобы она была первой в области просмотра. Но здесь вся страница сдвигается нежелательным образом.
Гипотетически, косяк может быть в том, что при переборе файлов нужна асинхронность. <!DOCTYPE html><meta charset='utf-8'> <style> body{margin: 0 } main{ width: 200px; display: grid; grid-template-rows: 24px 300px 24px; margin: 100px auto 50vh; user-select: none } #box{ border: 2px solid #000; overflow-y: auto; overscroll-behavior-y:contain } #bar,#bot{ border: 2px solid #777; padding-left: 1ch; } :is(#bar,#bot):hover{background-color: #eee;} :is(#bar,#bot):active{background-color: #ccc;} img{display: block; width: 100%;} .c{ outline: 5px solid #7cf; outline-offset: -5px; } </style> <main><div id=bar>0</div><div id=box></div><div id=bot>+ file</div></main> <script>'use strict'; const oo=console.log, {assign:set}=Object, {createObjectURL:url}=URL, {round}=Math, el=document.createElement.bind(document), cl_move=(from,to,...cl)=>( from.classList.remove(...cl), to.classList.add(...cl), to ), FI=set(el('input'),{ type:'file', multiple:true, accept:'image/*', onchange(){ let last=box.lastChild; for(let file of this.files){ let image=el('img'); image.src=url(file); box.append(image); }; if(last!==null){ oo('last',last); let next=last.nextSibling; oo('next',next); let c=box.getElementsByClassName('c'); if(0 in c){ cl_move(c[0],next,'c') }; next.scrollIntoView() } else{ (last=box.firstChild).classList.add('c'); last.scrollIntoView() } } }); set(box,{ onscroll(){ bar.textContent=round(box.scrollTop)+', '+'?' }, onclick({target:t}){ if(t==this||this.childElementCount<1){ return }; let c=this.getElementsByClassName('c'); if(0 in c){ [c]=c; if(t!=c){ cl_move(c,t,'c') } } else{ t.classList.add('c') } } }); bar.onclick=function(){ let c=box.getElementsByClassName('c'); if(0 in c){ c[0].scrollIntoView() } }; bot.onclick=function(){ FI.click() }; ondragstart=()=>false </script> Есть 3 проблемы: 1) Когда box пуст, нужно чтобы он не сдвигался вместе со страницей, а именно, чтобы overscroll-behavior-y:contain сработал и при пустом box 2) Чтобы scrollIntoView прокручивал только список и ничего более. При этом, первая из добавленных картинок была бы в начале области просмотра 3) Если картинка ( кроме самой первой в box ) своей нижней частью не смогла перекрыть область просмотра, то принудительно добавить margin-bottom необходимой высоты так, чтобы картинка подтянулась к верхней границе области просмотра. При этом, если снова добавить картинки, margin-bottom удаляется, чтобы не было прогала. И вместо знака вопроса во время прокрутки хотелось бы выводить расстояние от верхней границы области просмотра до текущей картинки ( img.c ). При этом, если она выше, то со знаком '-'. Надеюсь, что всё получится ! |
Что-то мало ответов, хотелось бы больше. Всё-таки, я описал проблемы и код приложил. Буду продолжать молиться )))
|
Цитата:
onscroll(){ let t = document.querySelector('img.c'); t = t ? (t.getBoundingClientRect().top - box.getBoundingClientRect().top)|0 : '?'; bar.textContent=round(box.scrollTop)+', '+ t; }, |
Teamur,
//next.scrollIntoView(); window.setTimeout(_ => box.scrollTop = box.scrollHeight, 300); |
рони, спасибо.
Правильно ли я понимаю, что scrollIntoView срабатывает раньше, чем подгружаются все картинки, в этом причина? Или причина в другом? И при переборе файлов действия выполнять при событии onload? Просто, хотелось бы обойтись без счётчиков setTimeout и тп. |
Teamur,
с помощью scrollIntoView затруднительно получить нужный вам эффект, и лучше управлять прокруткой в "ручном режиме", или по таймеру или по счётчику в onload. |
images preview
Teamur,
<!DOCTYPE html> <meta charset='utf-8'> <style> body { margin: 0 } main { width: 200px; display: grid; grid-template-rows: 24px 300px 24px; margin: 100px auto 50vh; user-select: none } #box { border: 2px solid #000; overflow-y: auto; overscroll-behavior-y: contain } #bar, #bot { border: 2px solid #777; padding-left: 1ch; } :is(#bar, #bot):hover { background-color: #eee; } :is(#bar, #bot):active { background-color: #ccc; } img { display: block; width: 100%; } .c { outline: 5px solid #7cf; outline-offset: -5px; } </style> <main> <div id=bar>0</div> <div id=box></div> <div id=bot>+ file</div> </main> <script> 'use strict'; const oo = console.log, { assign: set } = Object, { createObjectURL: url } = URL, { round } = Math, el = document.createElement.bind(document), mainViewTopCenter = function() { let main = document.querySelector('main'); let pos = main.getBoundingClientRect(); let y = (document.documentElement.clientHeight - main.scrollHeight) / 2 - pos.top; window.scrollBy(0, -y); }, imgViewCenter = function(img) { let y = (img.getBoundingClientRect().top - box.getBoundingClientRect().top) | 0; box.scrollTop += y }, imgToggle = function(img) { let old = box.querySelector('img.c'); if (old && old !== img) old.classList.remove('c'); img.classList.toggle('c') }, cl_move = (from, to, ...cl) => (from.classList.remove(...cl), to.classList.add(...cl), to), FI = set(el('input'), { type: 'file', multiple: true, accept: 'image/*', onchange() { for (let file of this.files) { let image = el('img'); image.onload = function() { imgToggle(image); imgViewCenter(image); } image.src = url(file); box.append(image); }; } }); set(box, { onscroll() { let t = box.querySelector('img.c'); t = t ? (t.getBoundingClientRect().top - box.getBoundingClientRect().top) | 0 : '?'; bar.textContent = round(box.scrollTop) + ', ' + t; }, onclick({ target: t }) { if (t = t.closest('img')) imgToggle(t) } }); bar.onclick = function() { let img = box.querySelector('img.c'); if (img) imgViewCenter(img); }; bot.onclick = function() { mainViewTopCenter(); FI.click(); }; ondragstart = () => false; mainViewTopCenter(); </script> |
рони, спасибо. Ваш код мне очень пригодится !
|
Часовой пояс GMT +3, время: 21:02. |