在元素上设置 padding 时动画突然跳转
Animation suddenly jumps when padding is set on an element
在Animate Plus
的手风琴动画中,当在元素上设置padding
时,折叠动画在关闭时突然跳转...
未设置padding
时动画流畅...
设置 padding
后,我怎样才能流畅地设置手风琴的动画?
我的JavaScript代码:
const accordions = Array.from(document.querySelectorAll("dl")).map(dl => ({
element: dl,
translate: 0
}))
const getButtons = accordion =>
Array.from(accordion.element.getElementsByTagName("button"), element => ({
element,
translate: 0
}))
const timing = {
easing: "out-quartic",
duration: 400
}
const clear = element =>
Object.values(element.attributes).forEach(({ name }) =>
element.removeAttribute(name)
)
const hide = async (accordion, buttons, collapsing) => {
const objects = buttons.filter(({ translate }) => translate)
const direction = "reverse"
rotate(collapsing.previousElementSibling.lastElementChild, direction)
slide(accordion, objects)
await fold(collapsing, direction)
clear(collapsing)
}
const show = (accordion, buttons, expanding) => {
const button = expanding.previousElementSibling.lastElementChild
const index = buttons.findIndex(({ element }) => element == button)
const objects = buttons.slice(index + 1)
const { height } = expanding.getBoundingClientRect()
expanding.className = "open"
rotate(button)
slide(accordion, objects, height)
fold(expanding)
}
const slide = (accordion, array, to = 0) => {
center(accordion, to)
animate({
...timing,
elements: array.map(({ element }) => element.parentElement),
transform(index) {
const object = array[index]
const from = object.translate
object.translate = to
return [`translateY(${from}px)`, to]
}
})
}
const center = (accordion, height) => {
const from = accordion.translate
const to = Math.round(-height / 2)
accordion.translate = to
animate({
...timing,
elements: accordion.element,
transform: [`translateY(${from}px)`, to]
})
}
const fold = async (content, direction = "normal") => {
const scrollHeight = content.scrollHeight
await animate({
...timing,
direction,
elements: content,
opacity: [0, 1],
maxHeight: ["0px", scrollHeight + "px"],
transform: ["scaleY(0)", 1]
})
}
const rotate = ({ lastElementChild: elements }, direction = "normal") =>
animate({
elements,
direction,
easing: "out-cubic",
duration: 600,
transform: ["rotate(0turn)", 0.5]
})
const toggle = (accordion, buttons) => async ({ target }) => {
const collapsing = accordion.element.querySelector(".open")
const expanding = target.parentElement.nextElementSibling
if (collapsing) await hide(accordion, buttons, collapsing)
if (collapsing != expanding) show(accordion, buttons, expanding)
}
accordions.forEach(accordion => {
const buttons = getButtons(accordion)
buttons.forEach(({ element }) =>
element.addEventListener("click", toggle(accordion, buttons))
)
})
import animate from "https://cdn.jsdelivr.net/npm/animateplus@2/animateplus.js"
My full code for an accordion can be found on CodePen:
在fold()
方法中对填充进行动画处理;将您想要的测量值添加到 paddingBottom
和 paddingTop
属性。然后,您可以从 CSS 中的 .open
class 规则中删除填充 属性。
const fold = async (content, direction = "normal") => {
const scrollHeight = content.scrollHeight;
await animate({
...timing,
direction,
elements: content,
opacity: [0, 1],
maxHeight: ["0px", scrollHeight + "px"],
paddingTop: ["0em", "2em"],
paddingBottom: ["0em", "2em"],
transform: ["scaleY(0)", 1]
});
};
您必须将 paddingTop
和 paddingBottom
添加到 fold
函数中:
const fold = async (content, direction = "normal") => {
const scrollHeight = content.scrollHeight
await animate({
...timing,
direction,
elements: content,
opacity: [0, 1],
maxHeight: ['0px', scrollHeight + 'px'],
transform: ["scaleY(0)", 1],
paddingTop: ['0em', '2em'], // add this
paddingBottom: ['0em', '2em'] // add this
})
}
您可以将填充设置为新的子元素。因此,将内容包装在额外的 div
中,如下所示:
<dd><div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.</div></dd>
然后,而不是 .open
样式 div
里面的样式:
.open div {
padding: 2em 0;
}
不使用子跳
在Animate Plus
的手风琴动画中,当在元素上设置padding
时,折叠动画在关闭时突然跳转...
未设置padding
时动画流畅...
设置 padding
后,我怎样才能流畅地设置手风琴的动画?
我的JavaScript代码:
const accordions = Array.from(document.querySelectorAll("dl")).map(dl => ({
element: dl,
translate: 0
}))
const getButtons = accordion =>
Array.from(accordion.element.getElementsByTagName("button"), element => ({
element,
translate: 0
}))
const timing = {
easing: "out-quartic",
duration: 400
}
const clear = element =>
Object.values(element.attributes).forEach(({ name }) =>
element.removeAttribute(name)
)
const hide = async (accordion, buttons, collapsing) => {
const objects = buttons.filter(({ translate }) => translate)
const direction = "reverse"
rotate(collapsing.previousElementSibling.lastElementChild, direction)
slide(accordion, objects)
await fold(collapsing, direction)
clear(collapsing)
}
const show = (accordion, buttons, expanding) => {
const button = expanding.previousElementSibling.lastElementChild
const index = buttons.findIndex(({ element }) => element == button)
const objects = buttons.slice(index + 1)
const { height } = expanding.getBoundingClientRect()
expanding.className = "open"
rotate(button)
slide(accordion, objects, height)
fold(expanding)
}
const slide = (accordion, array, to = 0) => {
center(accordion, to)
animate({
...timing,
elements: array.map(({ element }) => element.parentElement),
transform(index) {
const object = array[index]
const from = object.translate
object.translate = to
return [`translateY(${from}px)`, to]
}
})
}
const center = (accordion, height) => {
const from = accordion.translate
const to = Math.round(-height / 2)
accordion.translate = to
animate({
...timing,
elements: accordion.element,
transform: [`translateY(${from}px)`, to]
})
}
const fold = async (content, direction = "normal") => {
const scrollHeight = content.scrollHeight
await animate({
...timing,
direction,
elements: content,
opacity: [0, 1],
maxHeight: ["0px", scrollHeight + "px"],
transform: ["scaleY(0)", 1]
})
}
const rotate = ({ lastElementChild: elements }, direction = "normal") =>
animate({
elements,
direction,
easing: "out-cubic",
duration: 600,
transform: ["rotate(0turn)", 0.5]
})
const toggle = (accordion, buttons) => async ({ target }) => {
const collapsing = accordion.element.querySelector(".open")
const expanding = target.parentElement.nextElementSibling
if (collapsing) await hide(accordion, buttons, collapsing)
if (collapsing != expanding) show(accordion, buttons, expanding)
}
accordions.forEach(accordion => {
const buttons = getButtons(accordion)
buttons.forEach(({ element }) =>
element.addEventListener("click", toggle(accordion, buttons))
)
})
import animate from "https://cdn.jsdelivr.net/npm/animateplus@2/animateplus.js"
My full code for an accordion can be found on CodePen:
在fold()
方法中对填充进行动画处理;将您想要的测量值添加到 paddingBottom
和 paddingTop
属性。然后,您可以从 CSS 中的 .open
class 规则中删除填充 属性。
const fold = async (content, direction = "normal") => {
const scrollHeight = content.scrollHeight;
await animate({
...timing,
direction,
elements: content,
opacity: [0, 1],
maxHeight: ["0px", scrollHeight + "px"],
paddingTop: ["0em", "2em"],
paddingBottom: ["0em", "2em"],
transform: ["scaleY(0)", 1]
});
};
您必须将 paddingTop
和 paddingBottom
添加到 fold
函数中:
const fold = async (content, direction = "normal") => {
const scrollHeight = content.scrollHeight
await animate({
...timing,
direction,
elements: content,
opacity: [0, 1],
maxHeight: ['0px', scrollHeight + 'px'],
transform: ["scaleY(0)", 1],
paddingTop: ['0em', '2em'], // add this
paddingBottom: ['0em', '2em'] // add this
})
}
您可以将填充设置为新的子元素。因此,将内容包装在额外的 div
中,如下所示:
<dd><div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.</div></dd>
然后,而不是 .open
样式 div
里面的样式:
.open div {
padding: 2em 0;
}
不使用子跳