338 lines
11 KiB
HTML
338 lines
11 KiB
HTML
<html>
|
|
<head>
|
|
<title>
|
|
Accelerometer
|
|
</title>
|
|
<meta http-equiv="ScreenOrientation" content="autoRotate:disabled"/>
|
|
<style>
|
|
html, body {
|
|
width: 100%;
|
|
height: 100%;
|
|
margin: 0px;
|
|
border: 0;
|
|
overflow: hidden;
|
|
display: block;
|
|
}
|
|
|
|
.greenSlider {
|
|
position: absolute;
|
|
width: 40%;
|
|
top: 20%;
|
|
-webkit-appearance: none;
|
|
border-radius: 20px;
|
|
height: 40px;
|
|
background: #d3d3d3;
|
|
outline: none;
|
|
opacity: 0.7;
|
|
-webkit-transition: .2s;
|
|
transition: opacity .2s;
|
|
transform: rotate(-90deg);
|
|
}
|
|
|
|
.greenSlider::-webkit-slider-thumb {
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
background: #00ff00;
|
|
border-radius: 50%;
|
|
width: 60px;
|
|
height: 60px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
t {
|
|
font-size: 45px;
|
|
position: absolute;
|
|
top: 5%;
|
|
left: 20%;
|
|
text-align: center;
|
|
vertical-align: center;
|
|
transform: translate(-50%, -50%);
|
|
}
|
|
|
|
#valueText {
|
|
top: 40%;
|
|
}
|
|
|
|
label {
|
|
font-size: 45px;
|
|
position: absolute;
|
|
left: 20%;
|
|
text-align: center;
|
|
vertical-align: center;
|
|
transform: translate(-50%, -50%);
|
|
}
|
|
|
|
input {
|
|
position: absolute;
|
|
transform: translate(-50%, -50%);
|
|
width: 10%;
|
|
height: 10%;
|
|
}
|
|
|
|
#label {
|
|
left: 20%;
|
|
top: 70%;
|
|
}
|
|
|
|
#t1 {
|
|
left: 20%;
|
|
top: 75%;
|
|
}
|
|
|
|
#label2 {
|
|
left: 20%;
|
|
top: 50%;
|
|
}
|
|
|
|
#t2 {
|
|
left: 20%;
|
|
top: 55%;
|
|
}
|
|
|
|
button {
|
|
position: absolute;
|
|
height: 10%;
|
|
right: 10%;
|
|
top: 50%;
|
|
font-size: large;
|
|
}
|
|
</style>
|
|
<link rel="shortcut icon" href="http://azgeorgis.net/rmg/favicon.ico" type="image/x-icon">
|
|
</head>
|
|
<body>
|
|
<canvas id="myCanvas" width="1" height="1" style="border:1px solid #ffffff;"></canvas>
|
|
<form id = "form">
|
|
<label for="t1" id="label">Graph</label>
|
|
<input type="checkbox" id="t1" onclick="t1Click()">
|
|
<label for="t2" id="label2">Pause</label>
|
|
<input type="checkbox" id="t2" onclick="t2Click()">
|
|
</form>
|
|
<div class="slidecontainer">
|
|
<t>Damping</t>
|
|
<input type="range" min="0" max="0.02" value="0.01" step = "0.001" class="greenSlider" id="dampingSlider">
|
|
<t id="valueText">0.01</t>
|
|
</div>
|
|
<button onclick="getAccel()" id="button">Get Accelerometer Permissions</button>
|
|
<script>
|
|
var c = document.getElementById("myCanvas");
|
|
var ctx = c.getContext("2d");
|
|
ctx.canvas.width = window.innerWidth;
|
|
ctx.canvas.height = window.innerHeight;
|
|
|
|
function Clear(ctx)
|
|
{
|
|
ctx.clearRect(-c.width, -c.height, c.width * 2, c.height * 2);
|
|
}
|
|
|
|
function getAccel(){
|
|
DeviceMotionEvent.requestPermission().then(response => {
|
|
if (response == 'granted') {
|
|
window.addEventListener("devicemotion", accelerometerUpdate, true);
|
|
document.getElementById("button").style.visibility = "hidden";
|
|
}
|
|
});
|
|
}
|
|
ctx.scale(1.5, 1.5);
|
|
|
|
var aX = 0;
|
|
var aY = 0;
|
|
var aZ = 0;
|
|
var yMass = 600;
|
|
var vMass = 0;
|
|
var m = 0;
|
|
var k = 0.05;
|
|
var xPos = 350;
|
|
var yPos = 500;
|
|
var nSteps = 2000;
|
|
var stepWidth = 0.5;
|
|
var damping = 0.01;
|
|
var dampingSlider = document.getElementById("dampingSlider");
|
|
var clickedOnSpring = false;
|
|
var drawing = false;
|
|
var mousePos = { x:0, y:0 };
|
|
var lastPos = mousePos;
|
|
var graph = false;
|
|
var pause = false;
|
|
var pastPositions = new Array(nSteps);
|
|
|
|
|
|
dampingSlider.oninput = function()
|
|
{
|
|
damping = this.value;
|
|
document.getElementById("valueText").textContent = damping.toString();
|
|
}
|
|
|
|
function t1Click()
|
|
{
|
|
graph = !graph;
|
|
}
|
|
|
|
function t2Click()
|
|
{
|
|
pause = !pause;
|
|
}
|
|
|
|
function accelerometerUpdate(event) {
|
|
aX = event.accelerationIncludingGravity.x;
|
|
aY = event.accelerationIncludingGravity.y;
|
|
aZ = event.accelerationIncludingGravity.z;
|
|
}
|
|
|
|
function Update()
|
|
{
|
|
if (!pause)
|
|
{
|
|
Clear(ctx);
|
|
m += 0.1;
|
|
if (aY == null)
|
|
{
|
|
aY = 9.8;
|
|
}
|
|
vMass += 0.1 * aY - (yMass - yPos) * k * 0.1 - damping * vMass;
|
|
yMass += vMass;
|
|
if (graph)
|
|
{
|
|
for (i = nSteps - 1; i > 0; i--)
|
|
{
|
|
pastPositions[i] = pastPositions[i - 1];
|
|
}
|
|
pastPositions[0] = yMass;
|
|
ctx.strokeStyle = "#ff0000";
|
|
ctx.beginPath();
|
|
ctx.moveTo(xPos, yMass);
|
|
for (i = 1; i < nSteps; i++)
|
|
{
|
|
ctx.lineTo(xPos + i * stepWidth, pastPositions[i]);
|
|
}
|
|
ctx.stroke();
|
|
} else
|
|
{
|
|
pastPositions = new Array(nSteps);
|
|
}
|
|
ctx.strokeStyle = "#000000";
|
|
drawSpring(1, 3, (yMass - yPos) / 18, 200, 10, xPos, yPos, 0.1);
|
|
ctx.beginPath();
|
|
ctx.arc(xPos, yMass, 10, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
ctx.beginPath();
|
|
ctx.moveTo(xPos - 12, -c.height);
|
|
ctx.lineTo(xPos - 12, c.height);
|
|
ctx.stroke();
|
|
ctx.beginPath();
|
|
ctx.moveTo(xPos + 12, -c.height);
|
|
ctx.lineTo(xPos + 12, c.height);
|
|
ctx.stroke();
|
|
if (drawing)
|
|
{
|
|
console.log("Drawing");
|
|
if (Math.sqrt(((mousePos.x / 1.5) - xPos) ** 2) <= 100)
|
|
{
|
|
console.log("mouse");
|
|
yMass = mousePos.y / 1.5;
|
|
vMass = 0;
|
|
}
|
|
}
|
|
}
|
|
setTimeout(Update, 1000/60);
|
|
}
|
|
|
|
Update();
|
|
|
|
function drawSpring(a, b, xSize, ySize, numLoops, x, y, tStep)
|
|
{
|
|
//Draws coiled spring using prolate cycloid
|
|
var tStart = Math.PI;
|
|
var tEnd = (3 * Math.PI / 2) + (2 * Math.PI * numLoops);
|
|
var yEnd = a * tEnd - b * Math.sin(tEnd);
|
|
var xEnd = a + b;
|
|
var yFactor = xSize / xEnd;
|
|
var xFactor = ySize / yEnd;
|
|
var xShift = x - a + b * Math.cos(Math.PI / 2);
|
|
var yShift = y - a * (Math.PI / 2) + b * Math.sin(Math.PI / 2);
|
|
for (t = tStart; t <= tEnd; t += tStep)
|
|
{
|
|
ctx.beginPath();
|
|
ctx.moveTo(xShift + xFactor * (a - b * Math.cos(t)), yShift + yFactor * (a * t - b * Math.sin(t)));
|
|
ctx.lineTo(xShift + xFactor * (a - b * Math.cos(t + tStep)), yShift + yFactor * (a * (t + tStep) - b * Math.sin(t + tStep)));
|
|
ctx.stroke();
|
|
}
|
|
}
|
|
|
|
window.addEventListener('resize', function(event) {
|
|
c.width = window.innerWidth;
|
|
c.height = window.innerHeight;
|
|
ctx.scale(1.5, 1.5);
|
|
}, true);
|
|
|
|
|
|
c.addEventListener("mousedown", function (e) {
|
|
drawing = true;
|
|
lastPos = getMousePos(c, e);
|
|
}, false);
|
|
c.addEventListener("mouseup", function (e) {
|
|
drawing = false;
|
|
}, false);
|
|
c.addEventListener("mousemove", function (e) {
|
|
mousePos = getMousePos(c, e);
|
|
}, false);
|
|
|
|
function getMousePos(cDom, mouseEvent) {
|
|
var rect = cDom.getBoundingClientRect();
|
|
return {
|
|
x: mouseEvent.clientX - rect.left,
|
|
y: mouseEvent.clientY - rect.top
|
|
};
|
|
}
|
|
|
|
c.addEventListener("touchstart", function (e) {
|
|
mousePos = getTouchPos(c, e);
|
|
var touch = e.touches[0];
|
|
var mouseEvent = new MouseEvent("mousedown", {
|
|
clientX: touch.clientX,
|
|
clientY: touch.clientY
|
|
});
|
|
c.dispatchEvent(mouseEvent);
|
|
}, false);
|
|
c.addEventListener("touchend", function (e) {
|
|
var mouseEvent = new MouseEvent("mouseup", {});
|
|
c.dispatchEvent(mouseEvent);
|
|
}, false);
|
|
c.addEventListener("touchmove", function (e) {
|
|
var touch = e.touches[0];
|
|
var mouseEvent = new MouseEvent("mousemove", {
|
|
clientX: touch.clientX,
|
|
clientY: touch.clientY
|
|
});
|
|
c.dispatchEvent(mouseEvent);
|
|
}, false);
|
|
|
|
function getTouchPos(cDom, touchEvent) {
|
|
var rect = cDom.getBoundingClientRect();
|
|
return {
|
|
x: touchEvent.touches[0].clientX - rect.left,
|
|
y: touchEvent.touches[0].clientY - rect.top
|
|
};
|
|
}
|
|
|
|
document.body.addEventListener("touchstart", function (e) {
|
|
if (e.target == c) {
|
|
e.preventDefault();
|
|
}
|
|
}, false);
|
|
document.body.addEventListener("touchend", function (e) {
|
|
if (e.target == c) {
|
|
e.preventDefault();
|
|
}
|
|
}, false);
|
|
document.body.addEventListener("touchmove", function (e) {
|
|
if (e.target == c) {
|
|
e.preventDefault();
|
|
}
|
|
}, false);
|
|
|
|
</script>
|
|
</body>
|
|
<p xmlns:cc="http://creativecommons.org/ns#" style="font-size: 2vw; bottom: 0px; position: absolute;">
|
|
This work is licensed under
|
|
<a href="http://creativecommons.org/licenses/by-nc-nd/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-ND 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1"><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nd.svg?ref=chooser-v1"></a></p>
|
|
</html> |