|
CSS animation математический маятник
Есть специалисты по физике?
сделать анимацию не сложно, вопрос в другом, чисто по физике, как рассчитать траекторию маятника если известны первоначальный угол отклонения 90° длина нити 1м и ускорение под действием земного притяжения 9.8м/с. надо высчитать на какой угол отклониться в противоположную сторону, и сколько надо времени для достижения этого угла, и второй момент - надо высчитать угол поворота через равные промежутки времени(например 0.1сек) для задания шагов анимации просто дайте формулы для этих рассчётов. |
Дифференциальное уравнение, описывающее движение маятника
Если вам не нужна большая точность (для первоначального угла 90°), то можно ограничиться таким приближением (приближённым решением уравнения, выдаёт более точные результаты от -20° до 20°, вне пределов с некой погрешностью) <div class="pendulum"></div> <style> .pendulum { width: 1px; height: 200px; background: red; display: flex; flex-direction: column; justify-content: flex-end; transform-origin: 50% 0; margin: auto; } .pendulum::after { content: ""; display: block; width: 10px; height: 10px; margin-left: -4.5px; border-radius: 100%; background: inherit; } </style> <script>(function loop() { document.querySelector(".pendulum").style.transform = `rotate(${0.5*Math.PI*Math.cos(Math.sqrt(9.8) * Date.now() / 1000)}rad)`; requestAnimationFrame(loop); })();</script> Если необходимы более точные результаты, воспользуйтесь разложением Фурье... en.wikipedia.org/wiki/Pendulum_(mathematics) (или просмотрите всю статью) Графики к упомянутому маятнику wolframalpha.com |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Математический маятник</title> <style> #a { width: 255px; height: 125px; background: #cfe6cf; border-radius: 15px/12px; border: 1px solid #c0c0c0; position: absolute; } #b { width: 25px; height: 100px; display: inline-block; position: absolute; top: 15px; left: 122.5px; -webkit-transform-origin: 50% 0 ;-moz-transform-origin: 50% 0; -o-transform-origin: 50% 0; -ms-transform-origin: 50% 0; transform-origin: 50% 0; -webkit-animation: pendulum-1 1.79s linear 0s 1 normal forwards; -moz-animation: pendulum-1 1.79s linear 0s 1 normal forwards; -o-animation: pendulum-1 1.79s linear 0s 1 normal forwards; -ms-animation: pendulum-1 1.79s linear 0s 1 normal forwards; animation: pendulum-1 1.79s linear 0s 1 normal forwards; } #c { width: 1px; height: 75px; background: #999999; position: absolute; left: 12px; } #d { width: 1px; height: 1px; background: transparent; border-top: 15px solid #000080; border-left: 15px solid transparent; border-right: 15px solid transparent; border-bottom: 15px solid transparent; position: absolute; left: 120px; } #U_2e { width: 25px; height: 25px; display: inline-block; border-radius: 50%; background: -moz-radial-gradient(60% 40%, circle cover, #9999ff 0%, #0000ff 100%); background: -webkit-radial-gradient(60% 40%, circle cover, #9999ff 0%, #0000ff 100%); background: -o-radial-gradient(60% 40%, circle cover, #9999ff 0%, #0000ff 100%); background: -ms-radial-gradient(60% 40%, circle cover, #9999ff 0%, #0000ff 100%); background: radial-gradient(60% 40%, circle cover, #9999ff 0%, #0000ff 100%); position: absolute; top: 75px; } @-webkit-keyframes pendulum-1 { 0% { -moz-transform: rotate(90deg); -ms-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg); transform: rotate(90deg); } 100% { -moz-transform: rotate(-45deg); -ms-transform: rotate(-45deg); -webkit-transform: rotate(-45deg); -o-transform: rotate(-45deg); transform: rotate(-45deg); } } @-moz-keyframes pendulum-1 { 0% { -moz-transform: rotate(90deg); -ms-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg); transform: rotate(90deg); } 100% { -moz-transform: rotate(-45deg); -ms-transform: rotate(-45deg); -webkit-transform: rotate(-45deg); -o-transform: rotate(-45deg); transform: rotate(-45deg); } } @-o-keyframes pendulum-1 { 0% { -moz-transform: rotate(90deg); -ms-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg); transform: rotate(90deg); } 100% { -moz-transform: rotate(-45deg); -ms-transform: rotate(-45deg); -webkit-transform: rotate(-45deg); -o-transform: rotate(-45deg); transform: rotate(-45deg); } } @-ms-keyframes pendulum-1 { 0% { -moz-transform: rotate(90deg); -ms-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg); transform: rotate(90deg); } 100% { -moz-transform: rotate(-45deg); -ms-transform: rotate(-45deg); -webkit-transform: rotate(-45deg); -o-transform: rotate(-45deg); transform: rotate(-45deg); } } @keyframes pendulum-1 { 0% { -moz-transform: rotate(90deg); -ms-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg); transform: rotate(90deg); } 100% { -moz-transform: rotate(-45deg); -ms-transform: rotate(-45deg); -webkit-transform: rotate(-45deg); -o-transform: rotate(-45deg); transform: rotate(-45deg); } } </style> </head> <body> <div id="a"> <span id="d"></span> <span id="b"> <span id="c"></span> <span id="U_2e"></span> </span> </div> </body> </html> вот анимация, надо высчитать правильный угол а не взятый примерно 45градусов и точное время вместо 1.79сек. просто дайте формулы для этих расчётов. |
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Подставим ваши данные, получается T = 2π ⋅ sqrt(1 / 9.8) ≈ 2 (сек.) В CSS есть функция cubic-bezier(x₁, y₁, x₂, y₂), возможно ли при помощи неё выразить половину периода колебания маятника? Да, возможно! (Я не буду описывать, как это получается, вот рабочий лист с графиками https://www.desmos.com/calculator/qxtb8h7li7) Математический маятник <div class="pendulum"></div> <style> .pendulum { width: 255px; height: 125px; background: #cfe6cf; border-radius: 15px / 12px; border: 1px solid #c0c0c0; } .pendulum::before { content: ""; display: block; width: 0; margin: auto; border: 15px solid transparent; border-top-color: #000080; border-bottom-width: 0; } .pendulum::after { content: ""; display: block; margin: auto; width: 25px; height: 100px; background: radial-gradient(closest-side circle at 50% 87.5%, #0000ff 90%, transparent), linear-gradient(to right, transparent 47%, #999, transparent 53%) ; --mask: radial-gradient(closest-side circle at 45% 84.5%, rgba(0, 0, 0, .3), black 136%); -webkit-mask: var(--mask); mask: var(--mask); transform-origin: 50% 0; animation: pendulum 1s alternate infinite cubic-bezier(0.36, 0, 0.646, 1); } @keyframes pendulum { from { transform: rotate(90deg); } to { transform: rotate(-90deg); } } </style> Цитата:
Цитата:
Цитата:
Вот переделанный пример из поста №2... (с применением выше написанного) Маятник с затухающим колебанием, запускается заново при нажатии на него <button class="pendulum"></button> <style> .pendulum { width: 255px; background: #cfe6cf; border-radius: 15px / 12px; border: 1px solid #c0c0c0; padding: 0; display: block; } .pendulum::before { content: ""; display: block; width: 0; margin: auto; border: 15px solid transparent; border-top-color: #000080; border-bottom-width: 0; } .pendulum::after { content: ""; display: block; margin: auto; margin-bottom: 8px; width: 25px; height: 100px; background: radial-gradient(closest-side circle at 50% 87.5%, #0000ff 90%, transparent), linear-gradient(to right, transparent 47%, #999, transparent 53%) ; --mask: radial-gradient(closest-side circle at 45% 84.5%, rgba(0, 0, 0, .3), black 136%); -webkit-mask: var(--mask); mask: var(--mask); transform: rotate(var(--θ)); transform-origin: 50% 0; } </style> <script>{ const pendulumElement = document.querySelector(".pendulum"); var startTime; function setNewStartTime() { startTime = Date.now() / 1000 } setNewStartTime(); (function loop() { const t = Date.now() / 1000 - startTime; const θ = 0.5 * Math.PI * Math.cos(Math.sqrt(9.8) * t); const f = Math.exp(-.25 / Math.PI * t * t); pendulumElement.style.setProperty("--θ", `${f * θ}rad`); requestAnimationFrame(loop); })(); pendulumElement.addEventListener("click", setNewStartTime); }</script> Вы просите одно, а ожидаете другое. Формулируйте свои вопросы более точно, указывайте все подробности. Указывайте, что вы делали, что именно у вас не получается, и пусть это будет в одной теме! UPD Цитата:
|
Malleys,
почему Цитата:
|
Цитата:
Если я применю transform к .pendulum, то повернётся подставка, поэтому я придумал своё собственное свойство --θ, которое наследуется, и поэтому доступно в .pendulum::after, где я его могу применить в объявлении transform: rotate(var(--θ)); (обратите внимание, маятник представлен при помощи псевдо-элемента) |
Malleys,
спасибо, я упустил что там ::after, а для него нет отдельного style. |
Malleys, пока я не могу посмотреть примеры, из-за браузера, надо скопировать на "сайт" и добавить префиксы, я хотела сама все высчитать, типа зная время и угол можно высчитать вторую анимацию с задержкой, хотела сначала высчитать сколько шагов анимации надо высчитав углы для шагов 0,20,40,60,80 100%, если результат не понравится добавить шаги 10,30,50,70,90%, если опять не понравится добавить еще промежуточные шаги по 5% и тд, это для одного колебания, для второго колебания (-45град 30 град образно) добавить вторую анимацию где начальный угол не 90гр а взят из результата расчётов первой анимации, также высчитать шаги для второй анимации, потом для третьей и так до полного затухания
про скрипт для обновления анимации я спрашивала не только для этой конкретной анимации, а чтобы можно было бы добавить и для других анимаций который не имеют бесконечного повтора |
Цитата:
Или вы любитель адского ☣CSS☣ с префиксами? Цитата:
|
Цитата:
Цитата:
Цитата:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Математический маятник</title> <style> #mathematics_pendulum { width: 930px; height: 500px; background: -webkit-linear-gradient(top, #ade6ad, #e6e6cc); background: -moz-linear-gradient(top, #ade6ad, #e6e6cc); background: -o-linear-gradient(top, #ade6ad, #e6e6cc); background: linear-gradient(to top, #ade6ad, #e6e6cc); -webkit-border-radius: 50px/35px; border-radius: 50px/35px; border: 1px solid #c0c0c0; position: absolute; } #still_point { width: 1px; height: 1px; background: transparent; border-top: 45px solid #000080; border-left: 45px solid transparent; border-right: 45px solid transparent; border-bottom: 45px solid transparent; position: absolute; left: 420px; } #pendulum { width: 75px; height: 400px; display: inline-block; position: absolute; left: 428px; top: 45px; -webkit-transform-origin: 50% 0; -ms-transform-origin: 50% 0; transform-origin: 50% 0; } #mathematics_pendulum.animation_demo #pendulum { -webkit-animation: pendulum-1 1.79s linear 0s 1 normal forwards; animation: pendulum-1 1.79s linear 0s 1 normal forwards; } #pendulum_rod { width: 3px; height: 325px; background: #999999; border-radius: 2px; position: absolute; left: 36px; } #point_pendulum { width: 75px; height: 75px; display: inline-block; -webkit-border-radius: 50%; border-radius: 50%; background: -webkit-radial-gradient(60% 40%, circle, #bfbfff, #00f); background: -o-radial-gradient(60% 40%, circle, #bfbfff, #00f); background: radial-gradient(circle at 60% 40%, #bfbfff, #00f); position: absolute; top: 325px; } @-webkit-keyframes pendulum-1 { 0% { -webkit-transform: rotate(90deg); transform: rotate(90deg); } 100% { -webkit-transform: rotate(-45deg); transform: rotate(-45deg); } } @keyframes pendulum-1 { 0% { -webkit-transform: rotate(90deg); transform: rotate(90deg); } 100% { -webkit-transform: rotate(-45deg); transform: rotate(-45deg); } } </style> </head> </head> <body> <div id="mathematics_pendulum" class="animation_demo"> <span id="still_point"></span> <span id="pendulum"> <span id="pendulum_rod"></span> <span id="point_pendulum"></span> </span> </div> <script> var a = document.querySelector("#mathematics_pendulum"); a.addEventListener("click", function() { a.classList.remove("animation_demo"); document.documentElement.clientWidth; a.classList.add("animation_demo"); }); </script> </body> </html> Цитата:
<script>{ const pendulumElement = document.querySelector(".pendulum"); var startTime; function setNewStartTime() { startTime = Date.now() / 1000 } setNewStartTime(); (function loop() { const t = Date.now() / 1000 - startTime; const θ = 0.5 * Math.PI * Math.cos(Math.sqrt(9.8) * t); const f = Math.exp(-.25 / Math.PI * t * t); pendulumElement.style.setProperty("--θ", `${f * θ}rad`); requestAnimationFrame(loop); })(); pendulumElement.addEventListener("click", setNewStartTime); }</script> |
Часовой пояс GMT +3, время: 01:51. |
|