279 lines
11 KiB
HTML
279 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html>
|
|
<head>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
|
|
<meta charset="utf-8" />
|
|
|
|
<title>Mini Skidi</title>
|
|
|
|
<style>
|
|
/* #container {
|
|
width: 100%;
|
|
height: 49vh;
|
|
background-color: #333;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
overflow: hidden;
|
|
border-radius: 7px;
|
|
touch-action: none;
|
|
} */
|
|
#outerContainer {
|
|
display: flex;
|
|
height: 100vh;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.le-stick {
|
|
width: 300px;
|
|
height: 300px;
|
|
}
|
|
|
|
/* #item {
|
|
width: 100px;
|
|
height: 100px;
|
|
background-color: rgb(245, 230, 99);
|
|
border: 10px solid rgba(136, 136, 136, 0.5);
|
|
border-radius: 50%;
|
|
touch-action: none;
|
|
user-select: none;
|
|
}
|
|
|
|
#item:active {
|
|
background-color: rgba(168, 218, 220, 1);
|
|
}
|
|
|
|
#item:hover {
|
|
cursor: pointer;
|
|
border-width: 20px;
|
|
}
|
|
|
|
#area {
|
|
position: fixed;
|
|
right: 0;
|
|
top: 0;
|
|
} */
|
|
</style>
|
|
|
|
<script type="text/javascript">
|
|
var JoyStick = function (t, e) {
|
|
var i = void 0 === (e = e || {}).title ? "joystick" : e.title,
|
|
n = void 0 === e.width ? 0 : e.width,
|
|
o = void 0 === e.height ? 0 : e.height,
|
|
h = void 0 === e.internalFillColor ? "#00AA00" : e.internalFillColor,
|
|
r = void 0 === e.internalLineWidth ? 2 : e.internalLineWidth,
|
|
d = void 0 === e.internalStrokeColor ? "#003300" : e.internalStrokeColor,
|
|
a = void 0 === e.externalLineWidth ? 2 : e.externalLineWidth,
|
|
l = void 0 === e.externalStrokeColor ? "#008000" : e.externalStrokeColor,
|
|
c = document.getElementById(t),
|
|
u = document.createElement("canvas");
|
|
(u.id = i), 0 == n && (n = c.clientWidth), 0 == o && (o = c.clientHeight), (u.width = n), (u.height = o), c.appendChild(u);
|
|
var s = u.getContext("2d"),
|
|
f = 0,
|
|
v = 2 * Math.PI,
|
|
g = (u.width - 110) / 2,
|
|
w = g + 5,
|
|
C = g + 30,
|
|
m = u.width / 2,
|
|
p = u.height / 2,
|
|
L = u.width / 10,
|
|
E = -1 * L,
|
|
S = u.height / 10,
|
|
k = -1 * S,
|
|
W = m,
|
|
G = p;
|
|
function x() {
|
|
s.beginPath(), s.arc(m, p, C, 0, v, !1), (s.lineWidth = a), (s.strokeStyle = l), s.stroke();
|
|
}
|
|
function y() {
|
|
s.beginPath(), W < g && (W = w), W + g > u.width && (W = u.width - w), G < g && (G = w), G + g > u.height && (G = u.height - w), s.arc(W, G, g, 0, v, !1);
|
|
var t = s.createRadialGradient(m, p, 5, m, p, 200);
|
|
t.addColorStop(0, h), t.addColorStop(1, d), (s.fillStyle = t), s.fill(), (s.lineWidth = r), (s.strokeStyle = d), s.stroke();
|
|
}
|
|
"ontouchstart" in document.documentElement
|
|
? (u.addEventListener(
|
|
"touchstart",
|
|
function (t) {
|
|
f = 1;
|
|
},
|
|
!1
|
|
),
|
|
u.addEventListener(
|
|
"touchmove",
|
|
function (t) {
|
|
t.preventDefault(), 1 == f && ((W = t.touches[0].pageX), (G = t.touches[0].pageY), (W -= u.offsetLeft), (G -= u.offsetTop), s.clearRect(0, 0, u.width, u.height), x(), y());
|
|
},
|
|
!1
|
|
),
|
|
u.addEventListener(
|
|
"touchend",
|
|
function (t) {
|
|
(f = 0), (W = m), (G = p), s.clearRect(0, 0, u.width, u.height), x(), y();
|
|
},
|
|
!1
|
|
))
|
|
: (u.addEventListener(
|
|
"mousedown",
|
|
function (t) {
|
|
f = 1;
|
|
},
|
|
!1
|
|
),
|
|
u.addEventListener(
|
|
"mousemove",
|
|
function (t) {
|
|
1 == f && ((W = t.pageX), (G = t.pageY), (W -= u.offsetLeft), (G -= u.offsetTop), s.clearRect(0, 0, u.width, u.height), x(), y());
|
|
},
|
|
!1
|
|
),
|
|
u.addEventListener(
|
|
"mouseup",
|
|
function (t) {
|
|
(f = 0), (W = m), (G = p), s.clearRect(0, 0, u.width, u.height), x(), y();
|
|
},
|
|
!1
|
|
)),
|
|
x(),
|
|
y(),
|
|
(this.GetWidth = function () {
|
|
return u.width;
|
|
}),
|
|
(this.GetHeight = function () {
|
|
return u.height;
|
|
}),
|
|
(this.GetPosX = function () {
|
|
return W;
|
|
}),
|
|
(this.GetPosY = function () {
|
|
return G;
|
|
}),
|
|
(this.GetX = function () {
|
|
return (((W - m) / w) * 100).toFixed();
|
|
}),
|
|
(this.GetY = function () {
|
|
return (((G - p) / w) * 100 * -1).toFixed();
|
|
}),
|
|
(this.GetDir = function () {
|
|
var t = "",
|
|
e = W - m,
|
|
i = G - p;
|
|
return i >= k && i <= S && (t = "C"), i < k && (t = "N"), i > S && (t = "S"), e < E && ("C" == t ? (t = "W") : (t += "W")), e > L && ("C" == t ? (t = "E") : (t += "E")), t;
|
|
});
|
|
};
|
|
</script>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="outerContainer">
|
|
<!-- <div style="height: 40vh;"></div> -->
|
|
<div id="joyMove" class="le-stick" ></div>
|
|
<div id="joyBucket" class="le-stick"></div>
|
|
</div>
|
|
|
|
<script>
|
|
const view = document.getElementById("stream");
|
|
const WS_URL = "ws://" + window.location.host + ":82";
|
|
const ws = new WebSocket(WS_URL);
|
|
|
|
ws.onmessage = (message) => {
|
|
if (message.data instanceof Blob) {
|
|
var urlObject = URL.createObjectURL(message.data);
|
|
view.src = urlObject;
|
|
}
|
|
};
|
|
|
|
var lastText, lastSend, sendTimeout;
|
|
// limit sending to one message every 30 ms
|
|
// https://github.com/neonious/lowjs_esp32_examples/blob/master/neonious_one/cellphone_controlled_rc_car/www/index.html
|
|
function send(txt) {
|
|
var now = new Date().getTime();
|
|
if (lastSend === undefined || now - lastSend >= 30) {
|
|
try {
|
|
ws.send(txt);
|
|
lastSend = new Date().getTime();
|
|
return;
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
}
|
|
lastText = txt;
|
|
if (!sendTimeout) {
|
|
var ms = lastSend !== undefined ? 30 - (now - lastSend) : 30;
|
|
if (ms < 0) ms = 0;
|
|
sendTimeout = setTimeout(() => {
|
|
sendTimeout = null;
|
|
send(lastText);
|
|
}, ms);
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
|
|
<script type="text/javascript">
|
|
// Create JoyStick object into the DIV 'joyDiv'
|
|
var move = new JoyStick("joyMove");
|
|
var bucket = new JoyStick("joyBucket")
|
|
// var inputPosX = document.getElementById("posizioneX");
|
|
// var inputPosY = document.getElementById("posizioneY");
|
|
// var direzione = document.getElementById("direzione");
|
|
// var fuerzaI = document.getElementById("fuerzaI");
|
|
// var fuerzaD = document.getElementById("fuerzaD");
|
|
// var x = document.getElementById("X");
|
|
// var y = document.getElementById("Y");
|
|
|
|
//Steering control program, based on :
|
|
// Differential Steering Joystick Algorithm
|
|
// by Calvin Hass
|
|
// https://www.impulseadventure.com/elec/
|
|
|
|
function getparams(MoveJoyX, MoveJoyY, bucketJoyX, bucketJoyY) {
|
|
var nMotMixL;
|
|
var nMotMixR;
|
|
var fPivYLimit = 32.0; //The threshold at which the pivot action starts
|
|
// This threshold is measured in units on the Y-axis
|
|
// away from the X-axis (Y=0). A greater value will assign
|
|
// more of the joystick's range to pivot actions.
|
|
// Allowable range: (0..+127)
|
|
|
|
// TEMP VARIABLES
|
|
var nMotPremixL; // Motor (left) premixed output (-128..+127)
|
|
var nMotPremixR; // Motor (right) premixed output (-128..+127)
|
|
var nPivSpeed; // Pivot Speed (-128..+127)
|
|
var fPivScale; // Balance scale b/w drive and pivot ( 0..1 )
|
|
|
|
// Calculate Drive Turn output due to Joystick X input
|
|
if (MoveJoyY >= 0) {
|
|
// Forward
|
|
nMotPremixL = MoveJoyX >= 0 ? 100.0 : 100.0 + parseFloat(MoveJoyX);
|
|
nMotPremixR = MoveJoyX >= 0 ? 100.0 - MoveJoyX : 100.0;
|
|
} else {
|
|
// Reverse
|
|
nMotPremixL = MoveJoyX >= 0 ? 100.0 - MoveJoyX : 100.0;
|
|
nMotPremixR = MoveJoyX >= 0 ? 100.0 : 100.0 + parseFloat(MoveJoyX);
|
|
}
|
|
|
|
// Scale Drive output due to Joystick Y input (throttle)
|
|
nMotPremixL = (nMotPremixL * MoveJoyY) / 100.0;
|
|
nMotPremixR = (nMotPremixR * MoveJoyY) / 100.0;
|
|
|
|
// Now calculate pivot amount
|
|
// - Strength of pivot (nPivSpeed) based on Joystick X input
|
|
// - Blending of pivot vs drive (fPivScale) based on Joystick Y input
|
|
nPivSpeed = MoveJoyX;
|
|
fPivScale = Math.abs(MoveJoyY) > fPivYLimit ? 0.0 : 1.0 - Math.abs(MoveJoyY) / fPivYLimit;
|
|
|
|
// Calculate final mix of Drive and Pivot
|
|
nMotMixL = (1.0 - fPivScale) * nMotPremixL + fPivScale * nPivSpeed;
|
|
nMotMixR = (1.0 - fPivScale) * nMotPremixR + fPivScale * -nPivSpeed;
|
|
|
|
return Math.round(nMotMixL * 2.55) + "," + Math.round(nMotMixR * 2.55) + "," + bucketJoyX + "," + bucketJoyY; // The function returns the product of p1 and p2
|
|
}
|
|
|
|
setInterval(function () {
|
|
send(getparams(move.GetX(), move.GetY(), bucket.GetX(), bucket.GetY()));
|
|
}, 300);
|
|
</script>
|
|
</html>
|