Javascript: маятник или как повернуть систему координат
На канве HTML рисовать удобно под любым углом, ведь можно не вычислять угол поворота, а повернуть систему координат и отрисовать "вдоль осей".
Для иллюстрации этого подхода - небольшой скрипт, рисующий известный маятник (учитывается только сила тяжести и, условно, трение).
Ниже приводятся скрипт в работе и исходник файла на момент написания, предполагается, что он будет сохранён как документ .html
в кодировке Юникода UTF-8.
По клику на канве движение начинается заново, остальное легко увидеть из комментариев в листинге.
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Pendulum</title> </head> <body> <div id="center"> <canvas id="pendCanvas" width="600" height="600"></canvas> </div> <script> function Simulation (len, grav, angle0, tstep, callback) { //Аргументы: длина (м), ускорение свободного падения (м/c^2), //начальный угол (рад.), шаг по времени (мс), функция отрисовки var velocity = 0; var angle = angle0; var k = - grav / len; var tsec = tstep / 1000; var coeffT = 0.999; //"трение" из интервала ]0;1], =1 - без замедления return setInterval (function () { var acceleration = k * Math.sin(angle); velocity += acceleration * tsec; angle += velocity * tsec; angle *= coeffT; callback (angle); }, tstep); } var canvas = document.getElementById('pendCanvas'); var context = canvas.getContext('2d'); var prev=0, simId = null; function myAngle (angle) { var size = Math.min (canvas.width, canvas.height); //размер, относительно которого считаем var rPend = size * 0.35; //длина плеча маятника var rBar = size * 0.005; //толшина плеча маятника var rBall = size * 0.03; //размер шарика var ballX = Math.sin(angle) * rPend; var ballY = Math.cos(angle) * rPend; context.fillStyle = 'rgba(255,255,255,0.51)'; context.globalCompositeOperation = 'destination-out'; //Целевое изображение отображается вне границ исходного context.fillRect (0, 0, canvas.width, canvas.height); //очистить context.fillStyle = "yellow"; //цвет заливки context.strokeStyle = "rgba(0,0,0,"+Math.max(0,1-Math.abs(prev-angle)*10)+")"; context.globalCompositeOperation = "source-over"; //Исходное изображение накрывает целевое context.save(); context.translate (canvas.width/2, canvas.height/2); //начало координат context.rotate(angle); //поворот системы координат context.beginPath(); context.rect (-rBar, -rBar, rBar*2, rPend+rBar*2); //плечо context.fill(); context.stroke(); context.beginPath(); context.arc (0, rPend, rBall, 0, Math.PI*2, false); //шарик context.fill(); context.stroke(); context.restore(); prev = angle; } canvas.onclick = function (event) { if (simId) { clearInterval (simId); simId = null; } simId = Simulation(0.75, 9.80665, Math.PI*0.9, 10, myAngle); } window.addEventListener('load', function (e) { simId = Simulation(0.75, 9.80665, Math.PI*0.9, 10, myAngle); }, false); </script> <noscript> <div align="center"> Извините, для работы приложения нужен включённый Javascript </div> </noscript> </body></html>
13.06.2019, 12:18 [2303 просмотра]