ThreeJS:在鼠标点击坐标处绘制线条

时间:2016-05-31 08:41:08

标签: javascript 3d

我正与ThreeJS合作创建一个太阳能系统。我中间有一个太阳,周围有8个轨道。现在,当用户点击地图上的任何位置时,我想获得最近的环poisiton!

Here is an image to describe it visually what I mean

箭头代表"点击"对于用户来说,那么应该有一个函数来获得最近的轨道及其坐标(白点),点击点和中间点之间的线碰撞。

我尝试了很多我在这里找到的不同功能,但是他们没有给我我想要的结果。

感谢您的帮助!

代码看起来像这样:

            var container, stats, parent, pivots, domEvents, twins, planets, sun, fleets, raycaster, mouse;
            var camera, controls, scene, renderer;
            var cross;
            planets = new Array();

            init();
            animate();
            function init()
            {


                raycaster = new THREE.Raycaster();
                mouse = new THREE.Vector2();

                //init
                camera = new THREE.PerspectiveCamera(10, 1, 1, 4000);
                camera.position.z = 200;
                camera.position.x = 200;
                camera.position.y = 200;
                controls = new THREE.OrbitControls(camera);
                controls.addEventListener('change', render);
                scene = new THREE.Scene();
                scene.fog = new THREE.FogExp2(0x000000, 0);

                // renderer
                renderer = new THREE.WebGLRenderer({antialias: false, alpha: true});
                renderer.setSize(document.getElementById('canvasreference').offsetWidth, document.getElementById('canvasreference').offsetWidth);
                renderer.setClearColor(0x787878, 0.5); // the default

                container = document.getElementById('canvasreference');
                container.appendChild(renderer.domElement);
                window.addEventListener('resize', onWindowResize, false);
                domEvents = new THREEx.DomEvents(camera, renderer.domElement);

                //axihelper
                scene.add(new THREE.AxisHelper(130));

                // parent
                parent = new THREE.Object3D();
                scene.add(parent);

                //arrays
                orbits = new Array();



                addOrbit();

                window.addEventListener('click', onMouseMove, false);

            }


            function onMouseMove(event) {
                    canvas = renderer.domElement;
                raycaster = new THREE.Raycaster();
                mousePosition = new THREE.Vector2();
                canvasPosition = $("#canvasreference canvas").position();
                console.log(canvasPosition);
                mousePosition.x = ((event.clientX - canvasPosition.left) / canvas.width) * 2 - 1;
                mousePosition.y = -((event.clientY - canvasPosition.top) / canvas.height) * 2 + 1;

                raycaster.setFromCamera(mousePosition, camera);



                 var geometry = new THREE.Geometry();
                 var origin = new THREE.Vector3(raycaster.ray.origin.x, 0, raycaster.ray.origin.y);
                 geometry.vertices.push(origin);

                 var vektor = new THREE.Vector3(raycaster.ray.direction.x, 0, raycaster.ray.direction.y);

                 for (var i = 0; i < 1000; i++)
                 {
                 origin.add(vektor);
                 geometry.vertices.push(vektor);

                 }


                 var material = new THREE.LineBasicMaterial({
                 color: 0xffffff, linewidth: 20
                 });

                 var line = new THREE.Line(geometry, material);

                 scene.add(line);
                 renderer.render(scene, camera);




            }

            function onWindowResize() {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(600, 600);
                render();
            }

            function animate() {

                requestAnimationFrame(animate);
                controls.update();

                renderer.render(scene, camera);
            }

            function render() {
                renderer.render(scene, camera);
            }



            /**
             * add Orbit line
             * @param {type} orbit
             * @returns {undefined}
             */
            function addOrbit(orbit)
            {
                for (var i = 0; i < 8; i++)
                {
                    //make orbit line
                    var orbit = new THREE.EllipseCurve(
                            0, 0, // ax, aY
                            i * 10 + 30, i * 10 + 30, // xRadius, yRadius
                            0, 2 * Math.PI, // aStartAngle, aEndAngle
                            false, // aClockwise
                            0                 // aRotation 
                            );
                    var path = new THREE.Path(orbit.getPoints(100));
                    var geometry = path.createPointsGeometry(100);
                    var material = new THREE.LineBasicMaterial({color: 0xffffff});

                    var ellipse = new THREE.Line(geometry, material);
                    ellipse.rotation.x = 1.5708;
                    scene.add(ellipse);
                }

            }


        </script>

1 个答案:

答案 0 :(得分:0)

将相机中的光线投射到鼠标所在的位置。然后使用distanceToPoint函数检查从该光线到太阳系中间的最近距离。输出矢量的长度将是光线相切的球体半径。使用此长度,您可以确定您与轨道球体的距离以及是否应该选择它。这里有一些伪代码:

var length = getDistanceToCenter(...);
var closestSphere = _(orbits).min(function(orbit) { return Math.abs(length - orbit.radius); });
if (Math.abs(closestSphere.radius - length) < EPSILON) { 
    selectOrbit(closestSphere);
}