Макет и визуальная анимация не синхронизированы.Html

Программисты Html
Ответить
Anonymous
 Макет и визуальная анимация не синхронизированы.

Сообщение Anonymous »

Я пытаюсь создать складную таблицу, используя сетку и подсетку. Я пытаюсь свернуть таблицу, чтобы отобразить только три строки. Эти строки зависят от того, какую из них вы выбрали. Чтобы создать анимацию свертывания, я использую TranslateY, чтобы переместить строки, расположенные ближе друг к другу, как блок. Чтобы свернуть саму таблицу, я использую максимальную высоту, рассчитанную на основе отображаемых строк.
Я использую подсетку, а не гибкость, поскольку не могу установить жесткое ограничение для каждого столбца. Мне нужно, чтобы правый столбец адаптировался к его содержимому, а левый столбец рос как мог. Вот скриншот анимации, отстающей в середине свертывания:
Изображение

Код:

Код: Выделить всё

let isOpen = false;
let state = {
items: [],
visibleRows: 3,
isMultiSelect: false,
};

// Initialize state
function initializeState() {
const rows = document.querySelectorAll('.table-row');
state.items = Array.from(rows).map((row, index) => ({
id: index,
selected: row.querySelector('input').checked,
transformMultiplier: 0,
element: row,
}));
calculateTransforms();
}

// Port of the calculateTransforms function from React component
function calculateTransforms() {
const selectedRows = state.items.reduce(
(count, item) => count + (item.selected ? 1 : 0),
0,
);
let gracePortion = Math.max(0, 3 - selectedRows);
let distance = 0;
const distances = [];

const firstPass = state.items.map((item, index) => {
let transformMultiplier = null;

if (item.selected) {
transformMultiplier = distance;
distances.push(distance);
} else if (gracePortion > 0) {
transformMultiplier = distance;
distances.push(distance);
gracePortion--;
} else if (state.items.length === index + 1) {
distance++;
transformMultiplier = distance;
distances.push(distance);
} else {
distance++;
}

return { ...item, transformMultiplier: transformMultiplier };
});

let distancePosition = 0;
const items = firstPass.map((item) => {
let transformMultiplier = item.transformMultiplier;
if (transformMultiplier === null) {
transformMultiplier = distances[distancePosition];
} else {
distancePosition++;
}

return { ...item, transformMultiplier: transformMultiplier };
});

state.items = items;
state.visibleRows = Math.max(3, selectedRows);

updateTransforms();
}

function updateTransforms() {
const table = document.getElementById('table');
const totalRows = isOpen ? state.items.length : state.visibleRows;

// Update CSS custom property for table height
table.style.setProperty('--number-of-rows', totalRows);

state.items.forEach((item, index) => {
const translateY = isOpen ? 0 : -item.transformMultiplier * 100;
item.element.style.transform = `translateY(${translateY}%)`;
item.element.style.zIndex = state.items.length - index;
});
}

function toggleRows() {
isOpen = !isOpen;
const button = document.querySelector('.footer-button');
const chevron = document.getElementById('chevron');

button.innerHTML = isOpen
? 'Show less '
: 'Show more ';

calculateTransforms();
}

// Handle radio button changes
function handleSelectionChange() {
const rows = document.querySelectorAll('.table-row');
rows.forEach((row, index) => {
const input = row.querySelector('input');
state.items[index].selected = input.checked;
});
calculateTransforms();
}

// Initialize on page load
document.addEventListener('DOMContentLoaded', function () {
initializeState();

// Add event listeners to radio buttons
const inputs = document.querySelectorAll('input[type="radio"]');
inputs.forEach((input) =>  {
input.addEventListener('change', handleSelectionChange);
});
});

Код: Выделить всё

:root {
--duration: 5000ms;
}

.table-container {
display: flex;
flex-direction: column;
width: 100%;
max-width: 600px;
margin: 20px auto;
}

.table {
--number-of-rows: 3;
position: relative;
display: grid;
grid-template-columns: auto max-content;
overflow: hidden;
height: calc(var(--number-of-rows) * 51px + 42px);
transition: height var(--duration) ease;
}

.table-header {
display: grid;
grid-template-columns: subgrid;
grid-column: span 2;
background-color: grey;
height: 40px;
align-items: center;
color: white;
font-weight: bold;
border: solid 1px black;
z-index: 9999;
}

.table-row {
display: grid;
grid-template-columns: subgrid;
grid-column: span 2;
height: 50px;
align-items: center;
border-inline: solid 1px red;
border-bottom: solid 1px red;
transition: transform var(--duration) ease;
}

.table-row:nth-child(even) {
background-color: #f8f8f8;
}

.table-row:nth-child(odd) {
background-color: #e8e8e8;
}

.table-row input[type="radio"] {
position: absolute;
opacity: 0;
width: 0;
height: 0;
margin: 0;
}

.table-row:has(:checked) {
outline: 2px solid green;
outline-offset: -2px;
}

.footer-button {
width: 100%;
padding: 10px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
text-align: center;
transition: background-color 0.2s ease;
}

.footer-button:hover {
background-color: #0056b3;
}

.item {
padding: 10px;
}

.chevron {
display: inline-block;
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid white;
transition: transform 0.3s ease;
}

.chevron.open {
transform:  rotate(180deg);
}

Код: Выделить всё



Index
Test



1
Test



2
Test



3
Test



4
Test



5
Test



6
Test



7
Test



8
Test



9
Test



10
Test



11
Test



12
Test



Show more 




Подробнее здесь: https://stackoverflow.com/questions/797 ... ut-of-sync
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Html»