Прокрутка к первой картинке из добавленных через 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, время: 08:10. |