2025-05-27 15:46:31 +08:00

266 lines
8.4 KiB
HTML
Executable File

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<title>Arrow Button Layout</title>
<script src="{{ url_for('static', filename='js/socketio/socket.io.min.js') }}"></script>
<style>
/* 禁用用户选择 */
* {
-webkit-user-select: none;
/* Chrome, Opera, Safari */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently supported by Chrome, Opera and Firefox */
-webkit-tap-highlight-color: transparent;
/* 禁用触控点击的蓝色叠加层 */
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 180px;
margin: 0;
background-color: #f3f4f600;
font-family: Arial, sans-serif;
overflow: hidden;
}
.button-container {
display: grid;
grid-template-columns: 45px 45px 45px;
grid-template-rows: 45px 45px 45px;
gap: 8px;
align-items: center;
justify-items: center;
padding: 20px;
background-color: #bb29ff13;
border-radius: 50%;
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.1);
transform: scale(0.8);
}
.arrow-button {
width: 110px;
height: 110px;
cursor: pointer;
transition: opacity 0.1s;
}
/* SVG 的渐变颜色 */
.gradient-fill {
fill: url(#gradient);
stroke: none; /* 移除边框 */
opacity: 0.45; /* 默认透明度提高 */
transition: all 0.1s;
}
.active .gradient-fill {
opacity: 1; /* 点击后透明度变高 */
}
#up-button {
grid-column: 2 / 3;
grid-row: 1 / 2;
transform: rotate(180deg);
}
#left-button {
grid-column: 1 / 2;
grid-row: 2 / 3;
transform: rotate(90deg);
}
#right-button {
grid-column: 3 / 4;
grid-row: 2 / 3;
transform: rotate(-90deg);
}
#down-button {
grid-column: 2 / 3;
grid-row: 3 / 4;
transform: rotate(0deg);
}
</style>
</head>
<body>
<div class="button-container">
<div class="arrow-button" id="up-button" data-direction="up">
<svg
id="图层_1"
data-name="图层 1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 87.65 41.25"
width="110"
height="110"
>
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color: #d460f1; stop-opacity: 1" />
<stop
offset="100%"
style="stop-color: #9142c5; stop-opacity: 0.5"
/>
</linearGradient>
</defs>
<path
class="gradient-fill"
d="M7218.47,7153.94a5.51,5.51,0,0,0-6.19-1.09,31.16,31.16,0,0,1-25.53,0,5.51,5.51,0,0,0-6.16,1.07l-22.87,22.62a5.48,5.48,0,0,0,.33,8.1,65.7,65.7,0,0,0,82.87.27,5.47,5.47,0,0,0,.39-8.09Z"
transform="translate(-7155.59 -7151.85)"
/>
</svg>
</div>
<div class="arrow-button" id="left-button" data-direction="left">
<svg
id="图层_1"
data-name="图层 1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 87.65 41.25"
width="110"
height="110"
>
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color: #d460f1; stop-opacity: 1" />
<stop
offset="100%"
style="stop-color: #9142c5; stop-opacity: 0.5"
/>
</linearGradient>
</defs>
<path
class="gradient-fill"
d="M7218.47,7153.94a5.51,5.51,0,0,0-6.19-1.09,31.16,31.16,0,0,1-25.53,0,5.51,5.51,0,0,0-6.16,1.07l-22.87,22.62a5.48,5.48,0,0,0,.33,8.1,65.7,65.7,0,0,0,82.87.27,5.47,5.47,0,0,0,.39-8.09Z"
transform="translate(-7155.59 -7151.85)"
/>
</svg>
</div>
<div class="arrow-button" id="right-button" data-direction="right">
<svg
id="图层_1"
data-name="图层 1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 87.65 41.25"
width="110"
height="110"
>
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color: #d460f1; stop-opacity: 1" />
<stop
offset="100%"
style="stop-color: #9142c5; stop-opacity: 0.5"
/>
</linearGradient>
</defs>
<path
class="gradient-fill"
d="M7218.47,7153.94a5.51,5.51,0,0,0-6.19-1.09,31.16,31.16,0,0,1-25.53,0,5.51,5.51,0,0,0-6.16,1.07l-22.87,22.62a5.48,5.48,0,0,0,.33,8.1,65.7,65.7,0,0,0,82.87.27,5.47,5.47,0,0,0,.39-8.09Z"
transform="translate(-7155.59 -7151.85)"
/>
</svg>
</div>
<div class="arrow-button" id="down-button" data-direction="down">
<svg
id="图层_1"
data-name="图层 1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 87.65 41.25"
width="110"
height="110"
>
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color: #d460f1; stop-opacity: 1" />
<stop
offset="100%"
style="stop-color: #9142c5; stop-opacity: 0.5"
/>
</linearGradient>
</defs>
<path
class="gradient-fill"
d="M7218.47,7153.94a5.51,5.51,0,0,0-6.19-1.09,31.16,31.16,0,0,1-25.53,0,5.51,5.51,0,0,0-6.16,1.07l-22.87,22.62a5.48,5.48,0,0,0,.33,8.1,65.7,65.7,0,0,0,82.87.27,5.47,5.47,0,0,0,.39-8.09Z"
transform="translate(-7155.59 -7151.85)"
/>
</svg>
</div>
</div>
<script>
const socket = io();
document.querySelectorAll(".arrow-button").forEach((button) => {
const svgPath = button.querySelector("path");
const direction = button.getAttribute("data-direction");
button.addEventListener("touchstart", function (event) {
const touch = event.touches[0];
if (isInsidePath(svgPath, touch.clientX, touch.clientY)) {
button.classList.add("active");
socket.emit("send_command", `adjust:pose:move ${direction}:mid`);
}
});
button.addEventListener("touchend", function (event) {
if (button.classList.contains("active")) {
button.classList.remove("active");
}
event.preventDefault();
});
button.addEventListener("mousedown", function (event) {
if (isInsidePath(svgPath, event.clientX, event.clientY)) {
button.classList.add("active");
socket.emit("send_command", `adjust:pose:move ${direction}:mid`);
}
});
button.addEventListener("mouseup", function (event) {
if (button.classList.contains("active")) {
button.classList.remove("active");
}
});
button.addEventListener("mouseleave", function () {
button.classList.remove("active");
});
});
function isInsidePath(path, x, y, tolerance = 5) {
const point = path.ownerSVGElement.createSVGPoint();
point.x = x;
point.y = y;
const matrix = path.getScreenCTM().inverse();
const transformedPoint = point.matrixTransform(matrix);
if (path.isPointInFill(transformedPoint)) {
return true;
}
const bbox = path.getBBox();
const expandedBBox = {
x: bbox.x - tolerance,
y: bbox.y - tolerance,
width: bbox.width + 2 * tolerance,
height: bbox.height + 2 * tolerance,
};
return (
transformedPoint.x >= expandedBBox.x &&
transformedPoint.x <= expandedBBox.x + expandedBBox.width &&
transformedPoint.y >= expandedBBox.y &&
transformedPoint.y <= expandedBBox.y + expandedBBox.height
);
}
</script>
</body>
</html>