参考的案例: https://www.x3dom.org/x3dom/example/MovingObjectsWithDOMEvents.html
源码:
<!DOCTYPE html>
<html style='width:100%; height:100%; border:0; margin:0; padding:0;'>
<head>
<meta http-equiv='X-UA-Compatible' content='chrome=1'></meta>
<meta http-equiv='Content-Type' content='text/html;charset=utf-8'></meta>
<title>Moving Objects with DOM Mouse Events</title>
<link rel='stylesheet' type='text/css' href='x3dom.css'></link>
<script type='text/javascript' src='x3dom.js'></script>
<!--small script that implements the dragging functionality-->
<script>
var cellSize = 1.0;
var lastMouseX = -1;
var lastMouseY = -1;
var draggedTransformNode = null;
//vectors in 3D world space, associated to mouse x/y movement on the screen
var draggingUpVec = null;
var draggingRightVec = null;
var unsnappedDragPos = null;
//------------------------------------------------------------------------------------------------------------------
var mouseMoved = function(event)
{
//offsetX / offsetY polyfill for FF
var target = event.target || event.srcElement;
var rect = target.getBoundingClientRect();
event.offsetX = event.clientX - rect.left;
event.offsetY = event.clientY - rect.top;
if (lastMouseX === -1)
{
lastMouseX = event.offsetX;
}
if (lastMouseY === -1)
{
lastMouseY = event.offsetY;
}
if (draggedTransformNode)
{
dragObject(event.offsetX - this.lastMouseX, event.offsetY - this.lastMouseY);
}
lastMouseX = event.offsetX;
lastMouseY = event.offsetY;
};
//------------------------------------------------------------------------------------------------------------------
var startDragging = function(transformNode)
{
//disable navigation during dragging
document.getElementById("navInfo").setAttribute("type", '"NONE"');
draggedTransformNode = transformNode;
unsnappedDragPos = new x3dom.fields.SFVec3f.parse(transformNode.getAttribute("translation"));
//compute the dragging vectors in world coordinates
//(since navigation is disabled, those will not change until dragging has been finished)
//get the viewer's 3D local frame
var x3dElem = document.getElementById("x3dElement");
var vMatInv = x3dElem.runtime.viewMatrix().inverse();
var viewDir = vMatInv.multMatrixVec(new x3dom.fields.SFVec3f(0.0, 0.0, -1.0));
//use the viewer's up-vector and right-vector
draggingUpVec = vMatInv.multMatrixVec(new x3dom.fields.SFVec3f(0.0, 1.0, 0.0));;
draggingRightVec = viewDir.cross(this.draggingUpVec);
//project a world unit to the screen to get its size in pixels
var x3dElem = document.getElementById("x3dElement");
var p1 = x3dElem.runtime.calcCanvasPos(unsnappedDragPos.x, unsnappedDragPos.y, unsnappedDragPos.z);
var p2 = x3dElem.runtime.calcCanvasPos(unsnappedDragPos.x + draggingRightVec.x,
unsnappedDragPos.y + draggingRightVec.y,
unsnappedDragPos.z + draggingRightVec.z)
var magnificationFactor = 1.0 / Math.abs(p1[0] - p2[0]);
//scale up vector and right vector accordingly
draggingUpVec = draggingUpVec.multiply(magnificationFactor);
draggingRightVec = draggingRightVec.multiply(magnificationFactor);
};
//------------------------------------------------------------------------------------------------------------------
var dragObject = function(dx, dy)
{
//scale up vector and right vector accordingly
var offsetUp = draggingUpVec.multiply(-dy);
var offsetRight = draggingRightVec.multiply(dx);
unsnappedDragPos = unsnappedDragPos.add(offsetUp).add(offsetRight);
var snappedDragPos;
//if enabled, take grid snapping into account
if (document.getElementById("snapCheckbox").checked)
{
snappedDragPos = new x3dom.fields.SFVec3f(cellSize * Math.ceil(unsnappedDragPos.x / cellSize),
cellSize * Math.ceil(unsnappedDragPos.y / cellSize),
cellSize * Math.ceil(unsnappedDragPos.z / cellSize));
draggedTransformNode.setAttribute("translation", snappedDragPos.toString());
}
else
{
draggedTransformNode.setAttribute("translation", unsnappedDragPos.toString());
}
}
//------------------------------------------------------------------------------------------------------------------
var stopDragging = function()
{
draggedTransformNode = null;
draggingUpVec = null;
draggingRightVec = null;
unsnappedDragPos = null;
//re-enable navigation after dragging
document.getElementById("navInfo").setAttribute("type", '"EXAMINE" "ANY"');
};
</script>
</head>
<body style='width:100%; height:100%; border:0; margin:0; padding:0; background: linear-gradient(Grey 0%, White 100%);'>
<div style="position:fixed;background:white;padding:16px;opacity:0.8;width:480px;z-index:10000">
<h1>DOM鼠标事件:移动实体</h1>
<p style="font-size:140%">
此例展示如何实现基础的3维交互,只是用少量的html和js代码
<br/>
因此,简单的 <strong>拖拽</strong>功能便实现了
</p>
<input id="snapCheckbox" type="checkbox"></input><span style="font-size:140%">Snap to grid(对齐到网格)</span>
</div>
<x3d id='x3dElement' style='width:100%; height:100%; border:0'
onmouseup ="stopDragging();"
"mouseMoved(event);">
<scene>
<!--view and navigation-->
<viewpoint position="5.09349 5.61586 13.27088" orientation="-0.71805 0.68885 0.09947 0.51301"></viewpoint>
<navigationInfo id="navInfo" type='"EXAMINE" "ANY"' typeParams="-0.4, 60, 0.5, 1.55"></navigationInfo>
<!--grid-->
<inline url="scene/grid_20x20.x3d"></inline>
<!--axes-->
<transform translation="0 0.002 0.0">
<inline url="scene/axis.x3d"></inline>
</transform>
<!--models-->
<transform translation="-2 0 1" onmousedown="startDragging(this);">
<inline url="scene/suzanne-ao-bg.x3d"></inline>
</transform>
<transform translation="0 1 -6" onmousedown="startDragging(this);">
<shape>
<appearance>
<material diffuseColor="1 0.5 0" specularColor="0.3 0.3 0.3"></material>
</appearance>
<cone></cone>
<shape>
</transform>
<transform translation="4 0 0" onmousedown="startDragging(this);">
<shape>
<appearance>
<material diffuseColor="0 0.7 0.5" specularColor="0.3 0.3 0.3"></material>
</appearance>
<sphere></sphere>
<shape>
</transform>
</scene>
</x3d>
</body>
</html>