在这里,我创建了一个rect,在其中可以放大到场景的中点。在这里,我希望将对象的矩形区域(我们选择对象)的中心放大。
我有一个想法,求出矩形的中心点,然后将其传递给我苦苦挣扎的缩放功能。
请帮帮我
在此处摘录
/**
* @author HypnosNova / https://www.threejs.org.cn/gallery
* This is a class to check whether objects are in a selection area in 3D space
*/
THREE.SelectionBox = (function() {
var frustum = new THREE.Frustum();
var center = new THREE.Vector3();
function SelectionBox(camera, scene, deep) {
this.camera = camera;
this.scene = scene;
this.startPoint = new THREE.Vector3();
this.endPoint = new THREE.Vector3();
this.collection = [];
this.deep = deep || Number.MAX_VALUE;
}
SelectionBox.prototype.select = function(startPoint, endPoint) {
this.startPoint = startPoint || this.startPoint;
this.endPoint = endPoint || this.endPoint;
this.collection = [];
this.updateFrustum(this.startPoint, this.endPoint);
this.searchChildInFrustum(frustum, this.scene);
return this.collection;
};
SelectionBox.prototype.updateFrustum = function(startPoint, endPoint) {
startPoint = startPoint || this.startPoint;
endPoint = endPoint || this.endPoint;
this.camera.updateProjectionMatrix();
this.camera.updateMatrixWorld();
var tmpPoint = startPoint.clone();
tmpPoint.x = Math.min(startPoint.x, endPoint.x);
tmpPoint.y = Math.max(startPoint.y, endPoint.y);
endPoint.x = Math.max(startPoint.x, endPoint.x);
endPoint.y = Math.min(startPoint.y, endPoint.y);
var vecNear = this.camera.position.clone();
var vecTopLeft = tmpPoint.clone();
var vecTopRight = new THREE.Vector3(endPoint.x, tmpPoint.y, 0);
var vecDownRight = endPoint.clone();
var vecDownLeft = new THREE.Vector3(tmpPoint.x, endPoint.y, 0);
vecTopLeft.unproject(this.camera);
vecTopRight.unproject(this.camera);
vecDownRight.unproject(this.camera);
vecDownLeft.unproject(this.camera);
var vectemp1 = vecTopLeft.clone().sub(vecNear);
var vectemp2 = vecTopRight.clone().sub(vecNear);
var vectemp3 = vecDownRight.clone().sub(vecNear);
vectemp1.normalize();
vectemp2.normalize();
vectemp3.normalize();
vectemp1.multiplyScalar(this.deep);
vectemp2.multiplyScalar(this.deep);
vectemp3.multiplyScalar(this.deep);
vectemp1.add(vecNear);
vectemp2.add(vecNear);
vectemp3.add(vecNear);
var planes = frustum.planes;
planes[0].setFromCoplanarPoints(vecNear, vecTopLeft, vecTopRight);
planes[1].setFromCoplanarPoints(vecNear, vecTopRight, vecDownRight);
planes[2].setFromCoplanarPoints(vecDownRight, vecDownLeft, vecNear);
planes[3].setFromCoplanarPoints(vecDownLeft, vecTopLeft, vecNear);
planes[4].setFromCoplanarPoints(vecTopRight, vecDownRight, vecDownLeft);
planes[5].setFromCoplanarPoints(vectemp3, vectemp2, vectemp1);
planes[5].normal.multiplyScalar(-1);
};
SelectionBox.prototype.searchChildInFrustum = function(frustum, object) {
if (object.isMesh) {
if (object.material !== undefined) {
object.geometry.computeBoundingSphere();
center.copy(object.geometry.boundingSphere.center);
center.applyMatrix4(object.matrixWorld);
if (frustum.containsPoint(center)) {
this.collection.push(object);
}
}
}
if (object.children.length > 0) {
for (var x = 0; x < object.children.length; x++) {
this.searchChildInFrustum(frustum, object.children[x]);
}
}
};
return SelectionBox;
})();
/**
* @author HypnosNova / https://www.threejs.org.cn/gallery
*/
THREE.SelectionHelper = (function() {
function SelectionHelper(selectionBox, renderer, cssClassName) {
this.element = document.createElement('div');
this.element.classList.add(cssClassName);
this.element.style.pointerEvents = 'none';
this.renderer = renderer;
this.startPoint = new THREE.Vector2();
this.pointTopLeft = new THREE.Vector2();
this.pointBottomRight = new THREE.Vector2();
this.isDown = false;
this.renderer.domElement.addEventListener('mousedown', function(event) {
this.isDown = true;
this.onSelectStart(event);
}.bind(this), false);
this.renderer.domElement.addEventListener('mousemove', function(event) {
if (this.isDown) {
this.onSelectMove(event);
}
}.bind(this), false);
this.renderer.domElement.addEventListener('mouseup', function(event) {
this.isDown = false;
this.onSelectOver(event);
}.bind(this), false);
}
SelectionHelper.prototype.onSelectStart = function(event) {
this.renderer.domElement.parentElement.appendChild(this.element);
this.element.style.left = event.clientX + 'px';
this.element.style.top = event.clientY + 'px';
this.element.style.width = '0px';
this.element.style.height = '0px';
this.startPoint.x = event.clientX;
this.startPoint.y = event.clientY;
};
SelectionHelper.prototype.onSelectMove = function(event) {
this.pointBottomRight.x = Math.max(this.startPoint.x, event.clientX);
this.pointBottomRight.y = Math.max(this.startPoint.y, event.clientY);
this.pointTopLeft.x = Math.min(this.startPoint.x, event.clientX);
this.pointTopLeft.y = Math.min(this.startPoint.y, event.clientY);
this.element.style.left = this.pointTopLeft.x + 'px';
this.element.style.top = this.pointTopLeft.y + 'px';
this.element.style.width = (this.pointBottomRight.x - this.pointTopLeft.x) + 'px';
this.element.style.height = (this.pointBottomRight.y - this.pointTopLeft.y) + 'px';
};
SelectionHelper.prototype.onSelectOver = function() {
this.element.parentElement.removeChild(this.element);
};
return SelectionHelper;
})();
var container;
var camera, scene, renderer;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 5000);
camera.position.z = 1000;
scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);
scene.add(new THREE.AmbientLight(0x505050));
var light = new THREE.SpotLight(0xffffff, 1.5);
light.position.set(0, 500, 2000);
light.angle = Math.PI / 9;
light.castShadow = true;
light.shadow.camera.near = 1000;
light.shadow.camera.far = 4000;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
scene.add(light);
var geometry = new THREE.BoxBufferGeometry(20, 20, 20);
for (var i = 0; i < 200; i++) {
var object = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
color: Math.random() * 0xffffff
}));
object.position.x = Math.random() * 1600 - 800;
object.position.y = Math.random() * 900 - 450;
object.position.z = Math.random() * 900 - 500;
object.rotation.x = Math.random() * 2 * Math.PI;
object.rotation.y = Math.random() * 2 * Math.PI;
object.rotation.z = Math.random() * 2 * Math.PI;
object.scale.x = Math.random() * 2 + 1;
object.scale.y = Math.random() * 2 + 1;
object.scale.z = Math.random() * 2 + 1;
object.castShadow = true;
object.receiveShadow = true;
scene.add(object);
}
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
container.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
var selectionBox = new THREE.SelectionBox(camera, scene);
var helper = new THREE.SelectionHelper(selectionBox, renderer, 'selectBox');
document.addEventListener('mousedown', function(event) {
for (var item of selectionBox.collection) {
item.material.emissive = new THREE.Color(0x000000);
}
selectionBox.startPoint.set(
(event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1,
0.5);
});
document.addEventListener('mousemove', function(event) {
if (helper.isDown) {
for (var i = 0; i < selectionBox.collection.length; i++) {
selectionBox.collection[i].material.emissive = new THREE.Color(0x000000);
}
selectionBox.endPoint.set(
(event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1,
0.5);
var allSelected = selectionBox.select();
for (var i = 0; i < allSelected.length; i++) {
allSelected[i].material.emissive = new THREE.Color(0x0000ff);
}
}
});
document.addEventListener('mouseup', function(event) {
selectionBox.endPoint.set(
(event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1,
0.5);
var allSelected = selectionBox.select();
for (var i = 0; i < allSelected.length; i++) {
allSelected[i].material.emissive = new THREE.Color(0x0000ff);
}
});
body {
background-color: #f0f0f0;
color: #000;
margin: 0;
}
canvas {
display: block;
}
a {
color: #08e;
}
.selectBox {
border: 1px solid #55aaff;
background-color: rgba(75, 160, 255, 0.3);
position: fixed;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/105/three.min.js"></script>
答案 0 :(得分:0)
您要放大所选区域吗?根据您的操作,您可以尝试执行以下操作:
function zoomToSelection() {
topLeft = helper.pointTopLeft;
bottomRight = helper.pointBottomRight;
// Get the centerpoint of the selection.
let center = new THREE.Vector2(topLeft.x + (bottomRight.x - topLeft.x) / 2, topLeft.y + (bottomRight.y - topLeft.y) / 2);
// Get the center position in world space.
var vector = new THREE.Vector3(
(center.x / window.innerWidth) * 2 - 1,
-(center.y / window.innerHeight) * 2 + 1,
0.5
);
vector.unproject(camera);
camera.lookAt(vector);
var movement = vector.clone();
// Get the ratio between the box size and the window.
let zoomNeeded = (bottomRight.y - topLeft.y) / window.innerHeight;
// Get a scalar by which to move the camera in the direction it's looking.
let distanceToOrigin = camera.position.distanceTo(new THREE.Vector3(0, 0, 0))
let distance = distanceToOrigin - distanceToOrigin * zoomNeeded;
movement.sub(camera.position).normalize().multiplyScalar(-zoom);
var toDirection = camera.position.clone().sub(movement);
camera.position.set(toDirection.x, toDirection.y, toDirection.z);
}
现在只需添加到您的'mouseup'
事件监听器中即可:
document.addEventListener('mouseup', function(event) {
//...
zoomToSelection();
});