216 lines
6.3 KiB
HTML
216 lines
6.3 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta
|
||
name="viewport"
|
||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||
/>
|
||
<title>3D Model Interaction</title>
|
||
<style>
|
||
body {
|
||
margin: 0;
|
||
overflow: hidden;
|
||
background-color: #ffffff00;
|
||
}
|
||
|
||
#container {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow: hidden;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
background-color: #ffffff00;
|
||
}
|
||
|
||
.layer-container {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
pointer-events: auto; /* 允许触摸事件 */
|
||
}
|
||
|
||
.layer {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: contain;
|
||
pointer-events: none; /* 禁止图层响应触摸事件 */
|
||
}
|
||
|
||
#controls {
|
||
position: absolute;
|
||
right: 10px;
|
||
bottom: 20px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
button {
|
||
/* 文字垂直方向; */
|
||
writing-mode: vertical-rl;
|
||
font-size: 12px;
|
||
border-radius: 16px;
|
||
padding: 10px 6px;
|
||
margin-bottom: 10px;
|
||
border: 1px solid rgba(145, 66, 197, 0.5);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="container">
|
||
<div class="layer-container" id="layer-container">
|
||
<img
|
||
class="layer"
|
||
id="layer-body"
|
||
src="{{ url_for('static', filename='images/3d_model/back.png') }}"
|
||
alt="body"
|
||
/>
|
||
<img
|
||
class="layer"
|
||
id="layer-line"
|
||
src="{{ url_for('static', filename='images/3d_model/line.png') }}"
|
||
alt="line"
|
||
style="display: block"
|
||
/>
|
||
<img
|
||
class="layer"
|
||
id="layer-sphere"
|
||
src="{{ url_for('static', filename='images/3d_model/sphere.png') }}"
|
||
alt="sphere"
|
||
style="display: block"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="controls">
|
||
<button
|
||
id="toggle-layer-line"
|
||
style="
|
||
background: linear-gradient(
|
||
to right bottom,
|
||
rgb(212, 96, 241),
|
||
rgba(145, 66, 197, 0.5)
|
||
);
|
||
color: rgb(255, 255, 255);
|
||
"
|
||
>
|
||
经络
|
||
</button>
|
||
<button
|
||
id="toggle-layer-sphere"
|
||
style="
|
||
background: linear-gradient(
|
||
to right bottom,
|
||
rgb(212, 96, 241),
|
||
rgba(145, 66, 197, 0.5)
|
||
);
|
||
color: rgb(255, 255, 255);
|
||
"
|
||
>
|
||
穴位点
|
||
</button>
|
||
</div>
|
||
|
||
<script src="{{ url_for('static', filename='js/model/hammer.min.js') }}"></script>
|
||
<script>
|
||
const layerContainer = document.getElementById("layer-container");
|
||
const layerLine = document.getElementById("layer-line");
|
||
const layerSphere = document.getElementById("layer-sphere");
|
||
const toggleLineButton = document.getElementById("toggle-layer-line");
|
||
const toggleSphereButton = document.getElementById("toggle-layer-sphere");
|
||
|
||
let scale = 5; // 初始缩放比例设置为2,更接近图片
|
||
let lastScale = scale;
|
||
let translateX = 0,
|
||
translateY = 0;
|
||
let lastTranslateX = 0,
|
||
lastTranslateY = 0;
|
||
|
||
// 设置平移的最大范围
|
||
const maxTranslateX = 500; // 最大水平平移
|
||
const maxTranslateY = 50; // 最大垂直平移
|
||
|
||
// 初始设置缩放,使图片接近
|
||
layerContainer.style.transform = `scale(${scale})`;
|
||
|
||
// 切换经络和穴位图层显示/隐藏
|
||
toggleLineButton.addEventListener("click", () => {
|
||
toggleLineButton.style.background =
|
||
toggleLineButton.style.background === "rgb(255, 255, 255)"
|
||
? "linear-gradient(to right bottom, rgb(212, 96, 241), rgba(145, 66, 197, 0.5))"
|
||
: "rgb(255, 255, 255)";
|
||
toggleLineButton.style.color =
|
||
toggleLineButton.style.color === "rgb(255, 255, 255)"
|
||
? "rgba(145, 66, 197, 0.5)"
|
||
: "rgb(255, 255, 255)";
|
||
layerLine.style.display =
|
||
layerLine.style.display === "none" ? "block" : "none";
|
||
});
|
||
|
||
toggleSphereButton.addEventListener("click", () => {
|
||
toggleSphereButton.style.background =
|
||
toggleSphereButton.style.background === "rgb(255, 255, 255)"
|
||
? "linear-gradient(to right bottom, rgb(212, 96, 241), rgba(145, 66, 197, 0.5))"
|
||
: "rgb(255, 255, 255)";
|
||
toggleSphereButton.style.color =
|
||
toggleSphereButton.style.color === "rgb(255, 255, 255)"
|
||
? "rgba(145, 66, 197, 0.5)"
|
||
: "rgb(255, 255, 255)";
|
||
layerSphere.style.display =
|
||
layerSphere.style.display === "none" ? "block" : "none";
|
||
});
|
||
|
||
// 使用 Hammer.js 绑定手势事件
|
||
const mc = new Hammer.Manager(layerContainer);
|
||
|
||
// 添加平移识别器
|
||
mc.add(new Hammer.Pan({ threshold: 0 }));
|
||
|
||
// 添加缩放识别器
|
||
mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith(mc.get("pan"));
|
||
|
||
// 处理平移事件
|
||
mc.on("pan", (e) => {
|
||
translateX = lastTranslateX + e.deltaX;
|
||
translateY = lastTranslateY + e.deltaY;
|
||
// 限制平移范围
|
||
translateX = Math.max(
|
||
Math.min(translateX, maxTranslateX),
|
||
-maxTranslateX
|
||
);
|
||
translateY = Math.max(
|
||
Math.min(translateY, maxTranslateY),
|
||
-maxTranslateY
|
||
);
|
||
layerContainer.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`;
|
||
});
|
||
|
||
// 处理缩放事件
|
||
mc.on("pinch", (e) => {
|
||
scale = lastScale * e.scale;
|
||
scale = Math.max(4, Math.min(scale, 6)); // 增大最大缩放范围到6
|
||
layerContainer.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`;
|
||
});
|
||
|
||
// 触摸结束,保存最后的平移和缩放值
|
||
mc.on("panend pinchend", () => {
|
||
lastTranslateX = translateX;
|
||
lastTranslateY = translateY;
|
||
lastScale = scale;
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|