Wątek przeniesiony 2023-09-10 22:34 z JavaScript przez Riddle.

Jak poprawie dodać procentowe odległości pomiędzy elementami w liście?

0

Witam.
Mam taki problemik jak przesuwam elementy to pierwszy element listy łączonej pobierający położenie ostatniego ma dziwne przesunięcie.
Każdy element ma szerokość 10% + odległość między nimi 2%

<!DOCTYPE html>
<html>
<head>
<style>
  input {
    border: 1px solid black;
    font: 26px italic arial;
    display: inline;
    width: 16%;
    height: 4%;
    margin-left: 1%;
    margin-right: 1%;
  }
  label {
    border: 0px solid white;
    font: 26px italic arial;
  }
  body {
    font: 24px italic arial, serif;
    background-color: RGB(200, 200, 200);
    color: black;
    display: flex;
    flex-direction: column;
  }



  button#compile {
    position: absolute;
    bottom: 1%;
    right: 1%;
    width: 14%;
    height: 7%;
    cursor: pointer;
  }
 
  img {
    width: 20%;
    height: 25%;
  }


</style>
</head>
<body>

<label>if(</lablel><input style="font:30px italic arial,serif;color:black;" value=""/><label>){usun();}</lablel>
<div style="display:flex;position:absolute;bottom:20%;height:13%;left:0%;width:100%;border:2px solid red;">


<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>2</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>3</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>4</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>5</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>6</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>7</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>8</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>9</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>10</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>11</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>12</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>13</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>14</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>15</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>16</div>





</div>

<button style="display:block;position:absolute;top:82%;left:70%;font:30px italic arial,serif;" onClick="clearInterval(loop);">||||||||</button>
<button id="compile" onClick="start();">Start</button>

<script>
class tvset{
constructor(start_pos,obj){
this.start_position=start_pos;
this.position=start_pos;
this.obj=obj;
this.obj.style.left=this.position+"%";
this.obj_poprz=null;
}}



var tab=[];


for(let i=0;i<16;i++){
var x = i*12;

tab.push(new tvset(-x,document.querySelectorAll("DIV")[i+1]));}
for(let i=1;i<16;i++){tab[i].obj_poprz=tab[i-1];}
tab[0].obj_poprz=tab[15];



var loop;

var size;
document.querySelectorAll("INPUT")[0].value="";
var number_of_tvs_visible=0;
function start(){



loop=setInterval(function(){

for(let i=0;i<tab.length;i++){
                              tab[i].position++;if(tab[i].position>70){
                              tab[i].position=tab[i].obj_poprz.position-12;};
                              tab[i].obj.style.left=tab[i].position+"%";};},50);}



</script>
</body>
</html>

111111.jpg
Zielony kwadrat.
Pierwszy (zerowy) ma położenie 0, ostatni 15*12%. Pierwszy po dojechaniu do końca powinien pobrać położenie ostatniego - odjąć 12 i się tam umieścić. A umieszcza się jakby 13?14?

0

co ci devtoolsy pokazują?

for(let i=0;i<tab.length;i++){
                              tab[i].position++;if(tab[i].position>70){
                              tab[i].position=tab[i].obj_poprz.position-12;};

Jak wrzucasz na forum, to przynajmniej byś to normalnie sformatował... Nie wiem, czy taki masz bałagan w kodzie, czy coś ci się rozwaliło przy wklejaniu, ale ciężko to czytać.

Poza tym:

  tab[i].position=tab[i].obj_poprz.position-12;};

Skąd to 12 wynika? Czemu akurat odejmujesz 12 (jak rozumiem to liczba procentów)? Może tutaj jest coś nie tak.

0

@LukeJL: Myślałem że to zrozumiałe - pierwsza linijka "Każdy element ma szerokość 10% + odległość między nimi 2%" a ostatnia kodu to

 tab[i].obj.style.left=tab[i].position+"%";

Położenie ostatniego 15 * 12.
Położenie pierwszego powinno być 15*12 (na minusie) - 12 - czyli przesunięcie dodatkowo o szerokość i odstęp jednego elementu i tam umieszczenie.

To jest bardzo prosty kod.

0
for(let i=0;i<tab.length;i++){

Tak mi przyszło - a jakbyś spróbował to iterować od końca?

Tzn.

for (let i = tab.length - 1; i >= 0; i--){

Bo może nie uaktualniasz prostokątów we właściwej kolejności i nie pobierasz aktualnej wartości tab[i].obj_poprz.position. Chociaż nie wiem, czy to to, bo wtedy różnica byłaby tylko 1%, a tu jest więcej.

Dobrym pomysłem może być przelecenie się po wartościach, które ustawiasz. Bo może coś ustawiasz w innej liczbie, niż powinieneś. Ja bym w tej pętli poumieszczał console.logi i printowałbym np.

 console.log(tab[i].position);

wtedy łatwiej zobaczyć (jak chcesz, to debuggerem możesz też w DevToolsach).

0

Ale położenie ostatniego jest 15 * 12 - tak?

for(let i=0;i<16;i++){
                      var x = i*12;
                      tab.push(new tvset(-x,document.querySelectorAll("DIV")[i+1]));} 
                      // tab[15].position = 15 * 12 (na minusie)

Ustawienie poprzednika w liście (tu gdzie się pojawia problem)

tab[0].obj_poprz=tab[15];

Ustawunie elementu zerowego na nową pozycję za ostatnim elementem

tab[i].position=tab[i].obj_poprz.position-12;  // czyli 15 * 12 (pozycja ostatniego) + przesunięcie (12) - na minusie
tab[i].obj.style.left=tab[i].position+"%";

A wychodzi to dziwne przesunięcie.

0
document.querySelectorAll("DIV")[i+1]

To jazda na krawędzi. Może zadziała. Ale coś zmienisz w HTML i nie zadziała. Bo przecież pobierasz z całego dokumentu divy (czy na pewno dobre divy ci łapie w ogóle? w końcu jeden z divów to kontener, więc już samo to ci może zaburzyć). Jak chcesz się coś takiego bawić, to już lepiej robić querySelectorAll na kontenerze, a nie na całym dokumencie. Czyli w tym miejscu co masz kontener:

<label>if(</lablel><input style="font:30px italic arial,serif;color:black;" value=""/><label>){usun();}</lablel>
<div style="display:flex;position:absolute;bottom:20%;height:13%;left:0%;width:100%;border:2px solid red;">

możesz dodać jakieś id np. container:

<label>if(</lablel><input style="font:30px italic arial,serif;color:black;" value=""/><label>){usun();}</lablel>
<div id="container" style="display:flex;position:absolute;bottom:20%;height:13%;left:0%;width:100%;border:2px solid red;">

a potem to łapać w JS:

const container = document.getElementById('container');
// ....
container.querySelectorAll("DIV")[i+1]

Dalej będzie to nie najlepsza praktyka, ale przynajmniej przewidywalna, bo teraz opierasz logikę swojej animacji na tym, ile będziesz miał divów w całym dokumencie.

BTW tam są literówki w tym HTML! Masz </lablel> zamiast </label>. Czyli masz błędny HTML. Ogólnie robisz strasznie chaotycznie i prosisz się o problemy.

0

@LukeJL: rozmawiałem z GPT i kazał użyć tego

tab[i].position -= 16 * 12;

I działa, ale jednakowoż chciałbym wiedzieć co poszło nie tak.
Ten kod to niecałe 30 linijek samego JS.

"Ogólnie robisz strasznie chaotycznie"

Pisałeś kiedyś symulator if'owania z || && przedziałami żeby wyszła atrakcyjna forma ?
Rozumiesz, potrzebuję zaifować ify a raczej przedziały ifów wykluczających się wkluczających.

Powinieneś spróbować.

To jest działający kod

<!DOCTYPE html>
<html>
<head>
<style>
 input {
   border: 1px solid black;
   font: 26px italic arial;
   display: inline;
   width: 16%;
   height: 4%;
   margin-left: 1%;
   margin-right: 1%;
 }
 label {
   border: 0px solid white;
   font: 26px italic arial;
 }
 body {
   font: 24px italic arial, serif;
   background-color: RGB(200, 200, 200);
   color: black;
   display: flex;
   flex-direction: column;
 }



 button#compile {
   position: absolute;
   bottom: 1%;
   right: 1%;
   width: 14%;
   height: 7%;
   cursor: pointer;
 }

 img {
   width: 20%;
   height: 25%;
 }


</style>
</head>
<body>

<label>if(</label><input style="font:30px italic arial,serif;color:black;" value=""/><label>){usun();}</label>

<div style="display:flex;position:absolute;bottom:20%;height:13%;left:0%;width:100%;border:2px solid red;">


<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>
<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>
i=1</div>





</div>

<button style="display:block;position:absolute;top:82%;left:70%;font:30px italic arial,serif;" onClick="clearInterval(loop);">||||||||</button>
<button id="compile" onClick="start();">Start</button>

<script>
class tvset{
constructor(start_pos,obj){
this.start_position=start_pos;
this.position=start_pos;
this.obj=obj;
this.obj.style.left=this.position+"%";
this.obj_poprz=null;
}}



var tab=[];


for(let i=0;i<16;i++){
var x = i*12;

tab.push(new tvset(-x,document.querySelectorAll("DIV")[i+1]));}
for(let i=1;i<16;i++){tab[i].obj_poprz=tab[i-1];}
tab[0].obj_poprz=tab[15];



var loop;

var size;
document.querySelectorAll("INPUT")[0].value="";
var number_of_tvs_visible=0;
function start(){



loop=setInterval(function(){

for(let i=0;i<tab.length;i++){
                             tab[i].position++;if(tab[i].position>70){
                             
                             tab[i].position=tab[i].obj_poprz.position-12;};
                             
                             tab[i].obj.style.left=tab[i].position+"%";};},50);}



</script>
</body>
</html>
0

Problem znajduje się w pętli:

function start()
{   loop = setInterval( () =>
      {   for( let i = 0; i !== tab.length; i++ )
          {   tab[i].position++;
              if( tab[i].position > 70 )
                  tab[i].position = tab[i].obj_poprz.position - 12;
              tab[i].obj.style.left = tab[i].position +"%";
          }
      }
    , 50
    );
}

Chodzi o to, że zanim zaktualizujesz o jeden procent w górę pozycję elementu poprzedniego dla numeru 0., którym jest element numer 15., to ją czytasz.
Rozwiązaniem może być na przykład:

function start()
{   loop = setInterval( () =>
      {   for( let i = 0; i !== tab.length; i++ )
              tab[i].position++;
          for( let i = 0; i !== tab.length; i++ )
          {   if( tab[i].position > 70 )
                  tab[i].position = tab[i].obj_poprz.position - 12;
              tab[i].obj.style.left = tab[i].position +"%";
          }
      }
    , 50
    );
}
2

Wiem, że istnieje mln sposobów na wykonanie czegoś takiego, ale czemu wybrałeś najgorszy z możliwych?
Tzn. rozumiem że chatGPT wymyślił tak.

Ręczne pozycjonowanie elementów z pozycjonowaniem absolutnych, można tak, ale przeglądarka za ciebie sama może ogarnąć pozycjonowanie elementów po to używa się tego css.
Mógłbyś w pamięci sobie operacje przeprowadzić i potem dodać elementy, które same by się wy pozycjonowały względem pozycji w drzewie DOM.
Rozdzieliłbyś tak widok od danych.

Czemu do css takie ładne formatowanie, a do js już taka katastrofa? zasada jest przecież taka sama w obu przypadkach.

Jest taka zasada w programowaniu DRY i np. jak masz dużo styli dla tego samego elementu.
Np. Element listy, ma zawsze taki sam styl. to możesz zamienić:

<div style="display:block;position:absolute;left:0%;width:10%;height:90%;bottom:0%;border:2px solid black;background-color:white;"/>1</div>

Na

<style>
.list-item {
  display:block;
  position:absolute;
  left:0%;
  width:10%;
  height:90%;
  bottom:0%;
  border:2px solid black;
  background-color:white;
}
</style>

<div style="list-item">1</div>
1
GodOfCode. napisał(a):

Ręczne pozycjonowanie elementów z pozycjonowaniem absolutnych, można tak
ale przeglądarka za ciebie sama może ogarnąć pozycjonowanie elementów po to używa się tego css.

np. można użyć display: flex
https://css-tricks.com/snippets/css/a-guide-to-flexbox/

1 użytkowników online, w tym zalogowanych: 0, gości: 1