Download script.js from OzoneAsai/Phisics: direct link, hf CLI and curl.
- Browser
- Download file 5.07 kB
-
https://huggingface.co/spaces/OzoneAsai/Phisics/resolve/main/script.js
- Command line
-
hf download hf://spaces/OzoneAsai/Phisics/script.js
-
curl -L -o script.js https://huggingface.co/spaces/OzoneAsai/Phisics/resolve/main/script.js
5.07 kB
| // モジュールの設定 | |
| const { Engine, Render, Runner, Bodies, World, Events } = Matter; | |
| // エンジンとワールドの作成 | |
| const engine = Engine.create(); | |
| const world = engine.world; | |
| // レンダラの作成 | |
| const render = Render.create({ | |
| element: document.body, | |
| engine: engine, | |
| canvas: document.getElementById('world'), | |
| options: { | |
| width: 800, | |
| height: 600, | |
| wireframes: false, | |
| background: '#ffffff' | |
| } | |
| }); | |
| Render.run(render); | |
| const runner = Runner.create(); | |
| Runner.run(runner, engine); | |
| // シミュレーションに必要な変数 | |
| let ball = null; | |
| let vxData = []; | |
| let vyData = []; | |
| let xData = []; | |
| let tData = []; | |
| let vxyData = []; | |
| let breadcrumbs = []; | |
| let startTime = null; | |
| // キャンバスの境界を取得する関数 | |
| function getCanvasBounds() { | |
| return render.canvas.getBoundingClientRect(); | |
| } | |
| // クリックイベントで小球を生成 | |
| document.addEventListener('click', (event) => { | |
| const canvasBounds = getCanvasBounds(); | |
| // キャンバス内のクリックのみ反応 | |
| if (event.clientX < canvasBounds.left || event.clientX > canvasBounds.right || | |
| event.clientY < canvasBounds.top || event.clientY > canvasBounds.bottom) { | |
| return; | |
| } | |
| // 既存のボールがあれば新しいボールを生成しない | |
| if (ball) { | |
| return; | |
| } | |
| const x = event.clientX - canvasBounds.left; | |
| const y = event.clientY - canvasBounds.top; | |
| const velocityX = parseFloat(document.getElementById('vx').value); // ユーザー入力の初速度X | |
| const velocityY = parseFloat(document.getElementById('vy').value); // ユーザー入力の初速度Y | |
| ball = Bodies.circle(x, y, 20, { restitution: 0.8 }); | |
| Matter.Body.setVelocity(ball, { x: velocityX, y: velocityY }); | |
| World.add(world, ball); | |
| // データの初期化 | |
| startTime = new Date().getTime(); | |
| }); | |
| // シミュレーションのアップデート | |
| Events.on(engine, 'beforeUpdate', () => { | |
| if (ball) { | |
| const elapsedTime = (new Date().getTime() - startTime) / 1000; | |
| vxData.push(ball.velocity.x); | |
| vyData.push(ball.velocity.y); | |
| xData.push(ball.position.x); | |
| tData.push(elapsedTime); | |
| vxyData.push({ x: ball.velocity.x, y: ball.velocity.y }); | |
| // BreadCrumbsの追加 | |
| breadcrumbs.push(Bodies.circle(ball.position.x, ball.position.y, 2, { isStatic: true })); | |
| World.add(world, breadcrumbs[breadcrumbs.length - 1]); | |
| // 画面外に出た場合、ボールを削除 | |
| if (ball.position.x < 0 || ball.position.x > render.options.width || | |
| ball.position.y < 0 || ball.position.y > render.options.height) { | |
| World.remove(world, ball); | |
| ball = null; | |
| plotGraphs(); | |
| resetVariables(); | |
| } | |
| } | |
| }); | |
| // 変数をリセットする関数 | |
| function resetVariables() { | |
| vxData = []; | |
| vyData = []; | |
| xData = []; | |
| tData = []; | |
| vxyData = []; | |
| breadcrumbs.forEach(breadcrumb => World.remove(world, breadcrumb)); | |
| breadcrumbs = []; | |
| } | |
| // グラフ描画の関数 | |
| function plotGraphs() { | |
| plotChart('vxChart', 'Velocity-X vs Time', tData, vxData); | |
| plotChart('vyChart', 'Velocity-Y vs Time', tData, vyData); | |
| plotChart('xtChart', 'Position-X vs Time', tData, xData); | |
| plotScatterChart('vxyChart', 'Velocity-Y vs Velocity-X', vxyData); | |
| } | |
| function plotChart(canvasId, label, xData, yData) { | |
| const ctx = document.getElementById(canvasId).getContext('2d'); | |
| new Chart(ctx, { | |
| type: 'line', | |
| data: { | |
| labels: xData, | |
| datasets: [{ | |
| label: label, | |
| data: yData, | |
| borderColor: 'rgba(75, 192, 192, 1)', | |
| borderWidth: 1, | |
| fill: false | |
| }] | |
| }, | |
| options: { | |
| scales: { | |
| x: { | |
| beginAtZero: true | |
| }, | |
| y: { | |
| beginAtZero: true | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| function plotScatterChart(canvasId, label, data) { | |
| const ctx = document.getElementById(canvasId).getContext('2d'); | |
| new Chart(ctx, { | |
| type: 'scatter', | |
| data: { | |
| datasets: [{ | |
| label: label, | |
| data: data, | |
| borderColor: 'rgba(75, 192, 192, 1)', | |
| backgroundColor: 'rgba(75, 192, 192, 0.5)', | |
| borderWidth: 1 | |
| }] | |
| }, | |
| options: { | |
| scales: { | |
| x: { | |
| type: 'linear', | |
| position: 'bottom', | |
| beginAtZero: true, | |
| title: { | |
| display: true, | |
| text: 'Velocity-X' | |
| } | |
| }, | |
| y: { | |
| beginAtZero: true, | |
| title: { | |
| display: true, | |
| text: 'Velocity-Y' | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| } | |