Анимация внезапно скачет, когда для элемента задано заполнение - PullRequest
0 голосов
/ 22 февраля 2019

В аккордеоне, анимированном с помощью Animate Plus, когда для элемента установлено значение padding, при закрытии внезапно скачет анимация свертывания…

jumping animation

Анимация плавная, когда padding не установлен…

smooth animation

Как плавно анимировать аккордеон, когда 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"

Мой полный код для аккордеона можно найти в CodePen:

https://codepen.io/anon/pen/KJjYba

Ответы [ 3 ]

0 голосов
/ 22 февраля 2019

вам нужно будет добавить 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
    })
}

Кодовое перо

0 голосов
/ 22 февраля 2019

Вы можете установить заполнение для нового дочернего элемента.Итак, оберните содержимое в 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;
}

Это нене прыгай, используя ребенка.

0 голосов
/ 22 февраля 2019

Анимируйте отступы по методу fold();добавьте нужные измерения в свойства * paddingBottom и paddingTop.Затем вы можете удалить свойство padding из правила класса .open в CSS.

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]
  });
};

CodePen

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...