Страницы

Поиск по вопросам

среда, 26 февраля 2020 г.

Математический маятник с шаром

#javascript #html #css


Итак, у нас есть математический маятник. Помогите реализовать, чтобы после запуска
программы можно было в ручную (мышкой) поднять шар и отпустить для колебания 
P.s. Либо можно еще CSS или JavaScript














    


Ответы

Ответ 1



Все, на самом деле, достаточно просто. Нужно сделать несколько вещей: определить обработчик нажатия на левую кнопку мыши (ЛКМ) определить обработчик отжатия ЛКМ определить обработчик перемещения мыши В обработчике нажатия ЛКМ нужно поменять режим (draggin <- true) и сохранить текущее положение центра канваса (относительно которого рисуется маятник) и угол направления от центра канваса на положение курсора мыши, а так же текущий угол поворота маятника. В обработчике отжатия ЛКМ нужно поменять режим (draggin <- false) и обнулить текущую скорость и ускорение - чтобы не поломать физику процесса. В обработчике перемещения мыши нужно понять в каком режиме мы сейчас находимся (если draggin === true - то нужно обрабатывать перемещение). При обработке перемещения вычисляется новый угол направления на курсор и разница между текущим и начальным углами направления вычитается из сохраненного положения маятника. Так же нужно не забыть запрещать пересчитывать механику при перемещении начальной точки. Мой вариант кода с коментариями приведен ниже: var canvas = document.getElementById("canvas"); var canvas2 = document.getElementById("canvas2"); var ctx = canvas.getContext("2d"); var ctx2 = canvas2.getContext("2d"); var h = canvas.height = 500; var w = canvas.width = 600; var h2 = canvas2.height = 300; var w2 = canvas2.width = 800; var draggin = false; // В режиме перемещения var dragX = 0; // Центр канваса, относительно которого будем считать поворот var dragY = 0; var dragPhi = 0; // Угол маятника при нажатии var dragKsy = 0; // Начальный угол при mousedown ctx.translate(w / 2, h / 2); ctx2.translate(0, h2 / 2); ctx2.beginPath(); ctx2.moveTo(0, 0); var initPhi = Math.PI * 0.2; var L = 200; var dt = 1 / 60; var g = 1500; var t = 0; bob = { phi: initPhi, v: 0, a: 0 }; //getPos - определение позиции относительно центра элемента function getPos(el) { var rect = el.getBoundingClientRect(); return { x: rect.left + rect.width / 2.0, y: rect.top + rect.height / 2.0 }; } // Определяем угол поворота относительно центра канваса function calcKsy(evt) { var deltaX = evt.clientX - dragX; var deltaY = evt.clientY - dragY; var Ksy = Math.atan2(deltaY, deltaX); return Ksy; } // Обрабатываем событие нажатия на левую кнопку мыши canvas.addEventListener("mousedown", function(evt) { var gpc = getPos(canvas); dragX = gpc.x; dragY = gpc.y; draggin = true; dragPhi = bob.phi; dragKsy = calcKsy(evt); }); // Поворачиваем маятник на угол между начальным углом при mousedown // и текущим после перемещения курсора canvas.addEventListener("mousemove", function(evt) { if(draggin){ var Ksy = calcKsy(evt); bob.phi = dragPhi - Ksy + dragKsy; } }); // Обрабатываем событие отжатия левой кнопки мыши canvas.addEventListener("mouseup", function(evt) { draggin = false; bob.v = 0; bob.a = 0; }); function drawPendulum() { ctx.beginPath() ctx.arc(Math.sin(bob.phi) * L, Math.cos(bob.phi) * L, 10, 0, 2 * Math.PI) ctx.fill() ctx.moveTo(0, 0) ctx.lineTo(Math.sin(bob.phi) * L, Math.cos(bob.phi) * L) ctx.stroke() } function update() { bob.a = -(g / L) * Math.sin(bob.phi) bob.v += bob.a * dt bob.phi += bob.v * dt t += dt } function drawGraph() { ctx2.lineTo(t * 20, (bob.phi % Math.PI) * 20) ctx2.stroke() } function draw() { ctx.clearRect(-w / 2, -h / 2, w, h) drawPendulum() // Если мы не в режиме перетаскивания, то качаем маятник if (draggin === false) { update() } drawGraph() requestAnimationFrame(draw) } draw() * { padding: 0; margin: 0; } canvas { display: block; margin: 0 auto; cursor: move; cursor: grab; cursor: -moz-grab; cursor: -webkit-grab; }

Комментариев нет:

Отправить комментарий