Как заставить движение SVG перемещаться по идеальному синусу (t) по 1 оси

Я пытаюсь заставить объект в анимированном изображении SVG двигаться по идеальному синусоидальному движению по одной оси (вверх и вниз или влево и вправо). Например: x(t) = a + b * sin(t * 2PI*f) (Я также пытаюсь анимировать таким образом один атрибут сплайна, но это кажется еще сложнее или невозможным).

Я знаю, что для облегчения движения можно использовать сплайны, но это лишь приближение. Мне нужен идеальный синус.

Я попробовал несколько вещей:

Сначала я попытался заставить animateMotion следовать по эллиптической траектории. Вы можете использовать два эллипса, чтобы создать идеальный круг. Проблема в том, что он линейно движется по своей траектории. Поэтому, если вы установите нулевую ширину или высоту, движение будет линейным!

Во-вторых, я попытался растянуть движение, масштабируя ширину окна просмотра независимо от высоты. Это правильно масштабирует движение, а также объект. Вы можете компенсировать масштабирование объекта, масштабируя объект с обратным масштабированием, но вы никогда не сможете добиться того, чтобы это масштабирование достигло 0, поскольку для этого потребуется объект конечного размера. Ниже приведен мой фрагмент кода, который делает это

<svg viewBox = "0 0 5000 5000" width = "2000" height = "200" preserveAspectRatio = "none">
   <path d = "M25,-250v500h-50v-500z">
       <animateMotion path = "M1000,600 A200,200 0 1 1 300,600 A200,200 0 1 1 1000,600"
           width = "5000"
           height = "500"
           preserveAspectRatio = "none"  
           begin = "0s" dur = "3s" repeatCount = "indefinite"/>
   </path>
   <path d = "M1000,600 A200,200 0 1 1 300,600 A200,200 0 1 1 1000,600" fill = "none"
   stroke = "black" stroke-width = "20"/>
</svg>

У меня недостаточно опыта работы с SVG-анимацией, чтобы решить эту проблему, но у меня возникли некоторые идеи:

  • Найдите способ масштабировать только положение движущегося объекта, не масштабируя размеры объекта, а затем масштабируйте ширину или высоту на 0.
  • Возможно, есть способ масштабировать только само движение, а не движущийся объект.
  • возможно, есть способ отменить x или y анимации и установить для них фиксированное значение.
  • объединить две анимации, которые движутся в противоположном направлении вдоль одной оси, чтобы они нейтрализовали друг друга

Как это можно сделать? (Опять же, я не ищу приближений.)

@Danny '365CSI' Энгельман, спасибо за исправление моего поста!

elechris 25.07.2024 14:35
Создание фильтров для вашего сайта
Создание фильтров для вашего сайта
Фильтры - удобный инструмент в арсенале веб-дизайнера. Они позволяют изменять элементы на странице с помощью всего нескольких строк кода. Эти...
Анимация SVG-узоров без единой строки CSS
Анимация SVG-узоров без единой строки CSS
Недавно я работал над веб-проектом, который позволил мне поэкспериментировать с шаблонами SVG. С SVG очень приятно работать, как только вы получите...
Как использовать d3.js для рисования 2D SVG-элементов в приложении Angular?
Как использовать d3.js для рисования 2D SVG-элементов в приложении Angular?
D3.js - это обширная библиотека, используемая для привязки произвольных данных к объектной модели документа (DOM). Мы разберем основные варианты...
1
1
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Мне удалось заставить его работать с помощью группировки. С помощью группировки вы можете вкладывать элементы, а затем дважды применять animateMotion к одному и тому же объекту.

Я использовал одну и ту же дугу для обеих анимаций, но одна перевернута по вертикали и обе имеют половинную амплитуду. По горизонтали они складываются до полной амплитуды, а по вертикали нейтрализуют друг друга.

Я использовал половину единичного круга и использовал поле просмотра для масштабирования, чтобы упростить расчеты (общая длина движения равна 1).

<svg xmlns = "http://www.w3.org/2000/svg" width = "175" height = "175" viewBox = "-0.1 -0.1 1.2 1.2" border = "1px solid blue">
    <path id = "lineAC" d = "M0,0.5 A0.5,0.5 0 1,1 1,0.5" stroke = "blue" stroke-width = "0.02" fill = "none"/>
    <path id = "lineAC" d = "M0,0.5 A0.5,0.5 0 1,0 1,0.5" stroke = "green" stroke-width = "0.02" fill = "none"/>
    <g>
    <g>
        <rect width = "0.1" height = "0.1" x = "-0.05" y = "-0.05" rx = "0" ry = "0" fill = "black" />
        <animateMotion path = "M0,0.25 A0.25,0.25 0 1,1 0.5,0.25 
                                     A0.25,0.25 0 1,1 0.0,0.25" dur = "3s" repeatCount = "indefinite"/> 
    </g>
        <animateMotion path = "M0,0.25 A0.25,0.25 0 1,0 0.5,0.25 
                                     A0.25,0.25 0 1,0 0.0,0.25" dur = "3s" repeatCount = "indefinite"/> 
    </g>
</svg>

Использование CSS для анимации атрибутов представления — гораздо более простое решение.

Начиная с Firefox 128, все основные браузеры поддерживают типизированные пользовательские свойства с помощью @property . Это позволяет передать анимированный <angle> в функцию CSS sin().

Полученное анимированное число можно использовать либо для анимации transform, либо для одного из свойств геометрии (здесь x). Следующий пример демонстрирует оба варианта.

@property --a {
  syntax: "<angle>";
  inherits: true;
  initial-value: 0deg;
}
@keyframes round {
  from {--a: 0deg}
  to {--a: 360deg}
}
#moved1 {
  animation: round 4s linear infinite;
  transform: translateX(calc(sin(var(--a)) * 250px));
}
#moved2 {
  animation: round 4s linear infinite;
  x: calc(sin(var(--a)) * 250px - 30px);
}
<svg viewBox = "-300 0 600 200">
  <path id = "moved1" d = "M-30 20h60v60h-60z"/>
  <rect id = "moved2" x = "-30" y = "120" width = "60" height = "60"/>
</svg>

Я искал способы сделать это в SVG, а не в CSS. Таким образом, это не анимированный SVG, а анимированная веб-страница.

elechris 26.07.2024 13:27

За пределами веб-браузеров не так уж много средств визуализации, поддерживающих анимацию. (Ява/Батик — единственное, о чем я могу думать). Если вы откроете изображение в браузере, оно будет работать независимо от того, имеет ли оно тип MIME text/html или image/svg+xml.

ccprog 26.07.2024 14:33

Я знаю, что не так уж много средств визуализации поддерживают анимацию SVG. На самом деле существует не так много средств визуализации, которые поддерживают полную спецификацию SVG. И у некоторых есть ошибки. Но я намерен разработать автономный механизм рендеринга SVG, который будет реализовывать большую часть крошечной спецификации SVG.

elechris 26.07.2024 15:23

Другие вопросы по теме