我想把一个div放在一个物体的最高点,稍微向左上方偏移一点,以免直接覆盖顶点。你可以在这里看到。如果jsfiddle链接不再有效,请查看下面的不使用场景旋转的工作示例片段。我可以告诉你,它的效果非常好。
然而,在工作中的一个项目中,我需要旋转场景本身。显然,这会破坏将其转换为2D屏幕坐标。您可以在这里查看。您还可以在下面查看不适用于场景旋转的示例片段。正如您所看到的,该标签在垂直(“y-”)方向上未更新,但在“水平”方向上确实更新了。“这是因为相机的位置确实围绕x-z平面(phi改变)发生了变化,但它从不改变y位置(theta从不改变),而是当鼠标拖动时旋转场景。正如我所写的,我需要旋转场景来实现所需的效果。
如果有人能指导我正确的方向或在任何html/js/css片段网站(如jsfiddle等)上进行快速示例,他将是个救星!
附注:我尝试过(显然没有成功)通过将每个顶点的x和y坐标转换为“正确旋转”的位置来跳跃(即通过乘以
另外注意:我还花了一个小时旋转场景中的每个对象,但由于对象实际上存储在
工作示例(不使用场景旋转)
点击下面的运行片段
然而,在工作中的一个项目中,我需要旋转场景本身。显然,这会破坏将其转换为2D屏幕坐标。您可以在这里查看。您还可以在下面查看不适用于场景旋转的示例片段。正如您所看到的,该标签在垂直(“y-”)方向上未更新,但在“水平”方向上确实更新了。“这是因为相机的位置确实围绕x-z平面(phi改变)发生了变化,但它从不改变y位置(theta从不改变),而是当鼠标拖动时旋转场景。正如我所写的,我需要旋转场景来实现所需的效果。
如果有人能指导我正确的方向或在任何html/js/css片段网站(如jsfiddle等)上进行快速示例,他将是个救星!
附注:我尝试过(显然没有成功)通过将每个顶点的x和y坐标转换为“正确旋转”的位置来跳跃(即通过乘以
sin(sceneRotation)
和cos(sceneRotation)
),但这只会使情况更糟。另外注意:我还花了一个小时旋转场景中的每个对象,但由于对象实际上存储在
THREE.Group
中,所以其效果完全相同。工作示例(不使用场景旋转)
点击下面的运行片段
var scene = new THREE.Scene();
var w = window.innerWidth, h = window.innerHeight;
var camera = new THREE.PerspectiveCamera(60, w / h, 1, 1000);
camera.position.set(0, 0, -60);
var renderer = new THREE.WebGLRenderer({
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.domElement.style.backgroundColor = "#bbbbbb"
document.body.appendChild(renderer.domElement);
var label = document.getElementById("label");
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener("change", updateLabel);
var geom = new THREE.Geometry();
geom.vertices.push(new THREE.Vector3(-10, 10, -10));
geom.vertices.push(new THREE.Vector3(10, 10, -10));
geom.vertices.push(new THREE.Vector3(10, -10, -10));
geom.vertices.push(new THREE.Vector3(-10, -10, -10));
geom.vertices.push(new THREE.Vector3(-10, 10, 10));
geom.vertices.push(new THREE.Vector3(10, 10, 10));
geom.vertices.push(new THREE.Vector3(10, -10, 10));
geom.vertices.push(new THREE.Vector3(-10, -10, 10));
geom.faces.push(new THREE.Face3(0, 1, 2));
geom.faces.push(new THREE.Face3(0, 2, 3));
geom.faces.push(new THREE.Face3(7, 6, 5));
geom.faces.push(new THREE.Face3(7, 5, 4));
geom.faces.push(new THREE.Face3(4, 5, 1));
geom.faces.push(new THREE.Face3(4, 1, 0));
geom.faces.push(new THREE.Face3(3, 2, 6));
geom.faces.push(new THREE.Face3(3, 6, 7));
geom.faces.push(new THREE.Face3(4, 0, 3));
geom.faces.push(new THREE.Face3(4, 3, 7));
geom.faces.push(new THREE.Face3(1, 5, 6));
geom.faces.push(new THREE.Face3(1, 6, 2));
var mat = new THREE.MeshBasicMaterial({ color: 0x3377dd, transparent: true, opacity: .65, wireframe: false });
var cube = new THREE.Mesh(geom, mat);
scene.add(cube);
var matWire = new THREE.MeshBasicMaterial({ color: 0xffffff, wireframe: true });
var cube1 = new THREE.Mesh(geom, matWire);
scene.add(cube1);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function getScreenPosition(position) {
var vector = new THREE.Vector3( position.x, position.y, position.z );
vector.project(camera);
vector.x = Math.round( ( vector.x + 1 ) * w / 2 );
vector.y = Math.round( ( - vector.y + 1 ) * h / 2 );
return vector;
}
function updateLabel() {
var minY = null, x = null,
verts = cube.geometry.vertices;
for (var i = 0, iLen = verts.length; i < iLen; i++) {
var pos = getScreenPosition(verts[i]);
if (minY === null || pos.y < minY) {
minY = pos.y;
x = pos.x;
}
}
label.style.left = (x - 3) + "px";
label.style.top = (minY - 28) + "px";
}
body {
overflow: hidden;
margin: 0;
}
#label {
position: absolute;
left: 20px; top: 20px;
}
<div id="label">label</div>
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
无法与场景旋转配合使用
点击下方的运行片段
/* "globals" */
/* ~~~~~~~~~ */
var PI = Math.PI;
/* camera stuff */
var lastX, lastY, r = 60, phi = 0, c = new THREE.Vector3(0, 0, 0);
/* three.js stuff */
var scene = new THREE.Scene();
var w = window.innerWidth, h = window.innerHeight;
var camera = new THREE.PerspectiveCamera(60, w / h, 1, 1000);
//camera.position.set(0, 0, -60);
updateCamera();
var renderer = new THREE.WebGLRenderer({
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.domElement.style.backgroundColor = "#bbbbbb"
document.body.appendChild(renderer.domElement);
var label = document.getElementById("label");
//var controls = new THREE.OrbitControls(camera, renderer.domElement);
//controls.addEventListener("change", updateLabel);
document.body.addEventListener("mousedown", handleMouseDown);
document.body.addEventListener("touchstart", handleTouchStart);
var geom = new THREE.Geometry();
geom.vertices.push(new THREE.Vector3(-10, 10, -10));
geom.vertices.push(new THREE.Vector3(10, 10, -10));
geom.vertices.push(new THREE.Vector3(10, -10, -10));
geom.vertices.push(new THREE.Vector3(-10, -10, -10));
geom.vertices.push(new THREE.Vector3(-10, 10, 10));
geom.vertices.push(new THREE.Vector3(10, 10, 10));
geom.vertices.push(new THREE.Vector3(10, -10, 10));
geom.vertices.push(new THREE.Vector3(-10, -10, 10));
geom.faces.push(new THREE.Face3(0, 1, 2));
geom.faces.push(new THREE.Face3(0, 2, 3));
geom.faces.push(new THREE.Face3(7, 6, 5));
geom.faces.push(new THREE.Face3(7, 5, 4));
geom.faces.push(new THREE.Face3(4, 5, 1));
geom.faces.push(new THREE.Face3(4, 1, 0));
geom.faces.push(new THREE.Face3(3, 2, 6));
geom.faces.push(new THREE.Face3(3, 6, 7));
geom.faces.push(new THREE.Face3(4, 0, 3));
geom.faces.push(new THREE.Face3(4, 3, 7));
geom.faces.push(new THREE.Face3(1, 5, 6));
geom.faces.push(new THREE.Face3(1, 6, 2));
var mat = new THREE.MeshBasicMaterial({ color: 0x3377dd, transparent: true, opacity: .65, wireframe: false });
var cube = new THREE.Mesh(geom, mat);
//cube.translateX(10);
scene.add(cube);
var matWire = new THREE.MeshBasicMaterial({ color: 0xffffff, wireframe: true });
var cube1 = new THREE.Mesh(geom, matWire);
//cube1.translateX(10);
scene.add(cube1);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function getScreenPosition(position) {
var vector = new THREE.Vector3( position.x, position.y, position.z );
vector.project(camera);
vector.x = Math.round( ( vector.x + 1 ) * w / 2 );
vector.y = Math.round( ( - vector.y + 1 ) * h / 2 );
return vector;
}
function updateLabel() {
var minY = null, x = null,
verts = cube.geometry.vertices;
for (var i = 0, iLen = verts.length; i < iLen; i++) {
var pos = getScreenPosition(verts[i]);
if (minY === null || pos.y < minY) {
minY = pos.y;
x = pos.x;
}
}
label.style.left = (x - 3) + "px";
label.style.top = (minY - 28) + "px";
}
function handleMouseDown(ev) {
ev.preventDefault();
mouseOrTouchDown(ev.pageX, ev.pageY);
}
function handleTouchStart(ev) {
var touches = ev.touches;
if (touches.length !== 1) {
return;
}
ev.preventDefault();
mouseOrTouchDown(touches.item(0).pageX, touches.item(0).pageY, true);
}
function mouseOrTouchDown(downX, downY, touch) {
if (touch === undefined) { touch = false; }
lastX = downX;
lastY = downY;
if (touch) {
document.ontouchmove = handleTouchMove;
document.addEventListener("touchend", function(ev) {
document.ontouchmove = null;
});
document.addEventListener("touchcancel", function(ev) {
document.removeEventListener("touchmove", handleTouchMove);
});
} else {
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", function(ev) {
document.removeEventListener("mousemove", handleMouseMove);
});
}
}
function handleMouseMove(ev) {
ev.preventDefault();
mouseOrTouchMove(ev.pageX, ev.pageY);
}
function handleTouchMove(ev) {
var touches = ev.touches;
if (touches.length !== 1) {
return;
}
ev.preventDefault();
mouseOrTouchMove(touches.item(0).pageX, touches.item(0).pageY);
}
function mouseOrTouchMove(x, y) {
var dx = lastX - x, dy = y - lastY; /* change in {x, y} */
phi -= dx / 100;
if (phi > 2 * PI) {
phi -= 2 * PI;
} else if (phi < 0) {
phi += 2 * PI;
}
if (phi < PI / 2 || phi > 3 * PI / 2) {
sign = -1;
} else {
sign = 1;
}
if (scene.rotation.z + sign * dy / 100 < -PI) {
scene.rotation.z = -PI;
} else if (scene.rotation.z + sign * dy / 100 > 0) {
scene.rotation.z = 0;
} else {
scene.rotateZ(sign * dy / 100);
}
lastX = x;
lastY = y;
updateCamera();
updateLabel();
}
function updateCamera() {
var z = r * Math.sin(phi); /* new y pos (z-axis) in x-z plane */
var x = r * Math.cos(phi); /* new x pos (x-axis) in x-z plane */
camera.position.set(x, 1, z);
camera.lookAt(c);
}
body {
overflow: hidden;
margin: 0;
}
#label {
position: absolute;
left: 20px; top: 20px;
}
<div id="label">label</div>
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>