Anonymous
Анимация макета и визуальная анимация
Сообщение
Anonymous » 23 июл 2025, 13:14
Я пытаюсь сделать складную таблицу, используя сетку и подсепление. Проблема, которую я сталкиваюсь, заключается в том, что я пытаюсь свернуть таблицу, чтобы отобразить только три ряда. Эти ряды зависят от того, какой вы выбрали. Чтобы сделать анимацию коллапса, я использую Translatey , чтобы перемещать строки, которые ближе друг к другу в виде блока. Чтобы свернуть саму таблицу, я использую Max-height , рассчитанную на основе отображаемых строк. /> код: < /p>
Код: Выделить всё
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);
});
});< /code>
: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);
}< /code>
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 ... animations
1753265652
Anonymous
Я пытаюсь сделать складную таблицу, используя сетку и подсепление. Проблема, которую я сталкиваюсь, заключается в том, что я пытаюсь свернуть таблицу, чтобы отобразить только три ряда. Эти ряды зависят от того, какой вы выбрали. Чтобы сделать анимацию коллапса, я использую Translatey , чтобы перемещать строки, которые ближе друг к другу в виде блока. Чтобы свернуть саму таблицу, я использую Max-height , рассчитанную на основе отображаемых строк. /> код: < /p> [code]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); }); });< /code> :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); }< /code> 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 [/code] Подробнее здесь: [url]https://stackoverflow.com/questions/79711164/layout-animation-and-visual-animations[/url]