Показать сообщение отдельно
  #1 (permalink)  
Старый 29.03.2022, 13:10
Профессор
Отправить личное сообщение для Teamur Посмотреть профиль Найти все сообщения от Teamur
 
Регистрация: 08.06.2015
Сообщений: 206

Прокрутка к первой картинке из добавленных через 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 ). При этом, если она выше, то со знаком '-'.

Надеюсь, что всё получится !

Последний раз редактировалось Teamur, 29.03.2022 в 20:34.
Ответить с цитированием