$(function () { var $wrap = $('#earth-box') var width = $wrap.width(), height = $wrap.height(); var earth_radius = 100; //场景 const scene = new THREE.Scene(); //透视相机 fov(视野角度) 长宽比,近截面,远截面 const camera = new THREE.PerspectiveCamera(40, width / height, 1, 1000); //渲染器 const renderer = new THREE.WebGLRenderer({ // 抗锯齿性 antialias: true }); //渲染器尺寸 renderer.setSize(width, height); //将渲染器添加到html $wrap[0].appendChild(renderer.domElement); const geometry = new THREE.SphereGeometry(earth_radius, 1024, 1024); //立方体 const texture = new THREE.TextureLoader().load('../template/zh-cn/images/map.png'); // 立即使用纹理进行材质创建 const material = new THREE.MeshBasicMaterial({map: texture}); const earth = new THREE.Mesh(geometry, material); //网格(物体对象) earth.name = 'earth' scene.add(earth); scene.background = new THREE.Color(0xf5f7fa) //旋转 const controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = false; controls.dampingFactor = 1; controls.screenSpacePanning = false; controls.minDistance = 100; controls.maxDistance = 500; // controls.maxPolarAngle = Math.PI / 2; controls.enableZoom = false camera.position.z = 320 // scene.position.y = -40 // scene.position.x = 30 scene.rotation.y = Math.PI //公司坐标 var company_list = [ [114.085249,22.670432,0,'深圳'], //深圳 [114.173468,22.274636, 0,'香港'], //香港 [113.756118,23.028106, 0,'东莞'], //东莞 [77.864195,18.346112, 0,'印度'], //印度 [-101.823898,35.92576, 0,'美国'], //美国 [5.954085,52.67985, 0,'荷兰'], //荷兰 [4.954085,51.67985, 0,'欧洲'], //欧洲 [10.212736,51.195635, 0,'德国'], //德国 [21.734043,39.226764, 0,'希腊'] //希腊 ] company_list.map(item => { var position = createPosition(item) createHexagon(position,item[3]) let geometry = new THREE.TorusGeometry(0.005, 0.01, 16, 100); let material = new THREE.MeshBasicMaterial({color: 0xf4d96a}); let circleMesh = new THREE.Mesh(geometry, material); circleMesh.position.x = position.x circleMesh.position.y = position.y circleMesh.position.z = position.z scene.add(circleMesh); }) // 坐标转换, function createPosition(lnglat) { let spherical = new THREE.Spherical spherical.radius = earth_radius; const lng = lnglat[0] const lat = lnglat[1] const theta = (lng + 90) * (Math.PI / 180) const phi = (90 - lat) * (Math.PI / 180) spherical.phi = phi; // phi是方位面(水平面)内的角度,范围0~360度 spherical.theta = theta; // theta是俯仰面(竖直面)内的角度,范围0~180度 let position = new THREE.Vector3() position.setFromSpherical(spherical) return position } //公司标记点 function createHexagon(position,name) { var hexagon = new THREE.Object3D() let hexagonPlane = new THREE.CircleGeometry(0.5, 50) let material = new THREE.MeshBasicMaterial({ color: name === '深圳' ? 0xff6a00 : 0x00246e, side: THREE.DoubleSide, transparent: true, opacity: 0.5 }) let circlePlane = new THREE.Mesh(hexagonPlane, material) circlePlane.position.copy(position) circlePlane.lookAt(new THREE.Vector3(0, 0, 0)) circlePlane.name = name const ring = new THREE.RingGeometry(1, 1.2, 32 ); const ringMesh = new THREE.Mesh( ring, material ); ringMesh.position.copy(position) ringMesh.lookAt(new THREE.Vector3(0, 0, 0)) scene.add(circlePlane); scene.add(ringMesh); var texture = new THREE.CanvasTexture(getCanvasFont()); var fontMesh = new THREE.Sprite(new THREE.SpriteMaterial({map: texture})); // 放大 fontMesh.scale.x = 16; fontMesh.scale.y = 8; // 在原位置各加 2px ,避免文字与地标重叠 if(name === '香港'){ fontMesh.position.x = (position.x >0 ? position.x+5 : position.x-5); fontMesh.position.y = (position.y >0 ? position.y-4 : position.y-5); fontMesh.position.z = (position.z >0 ? position.z+2 : position.z-2); } else if(name === '东莞'){ fontMesh.position.x = (position.x >0 ? position.x-3 : position.x+3); fontMesh.position.y = (position.y >0 ? position.y+3 : position.y-3); fontMesh.position.z = (position.z >0 ? position.z+5 : position.z-5); } else if(name === '欧洲'){ fontMesh.position.x = (position.x >0 ? position.x+3 : position.x-3); fontMesh.position.y = (position.y >0 ? position.y+3 : position.y-3); fontMesh.position.z = (position.z >0 ? position.z-6 : position.z+6); } else if (name === '深圳'){ fontMesh.position.x = (position.x >0 ? position.x+5 : position.x+5); fontMesh.position.y = (position.y >0 ? position.y-3: position.y+15); fontMesh.position.z = (position.z >0 ? position.z+5 : position.z-8); } else { fontMesh.position.x = (position.x >0 ? position.x+2 : position.x-2); fontMesh.position.y = (position.y >0 ? position.y+2 : position.y-2); fontMesh.position.z = (position.z >0 ? position.z+2 : position.z-2); } // fontMesh.position.copy(position); //原位置 scene.add(fontMesh); // canvas生成图片实现文字函数 function getCanvasFont() { let w = 600; let h = 300; let canvas = document.createElement("canvas"); let ctx = canvas.getContext('2d'); canvas.width = w; canvas.height = h; //制作矩形 ctx.fillStyle = "rgba(0,0,0,0)"; ctx.fillRect(0, 0, w, h) //设置文字 ctx.fillStyle = name === '深圳' ? 'rgba(255, 106, 0,1)' : '#00246e'; ctx.font = h/3 + 'px "微软雅黑"'; ctx.textAlign = 'center'; ctx.fillText(name, w/2, h/2+20 ) return canvas; } } //计算坐标中心点 function computedCenter(start, end) { return [((start[0] * 1 + end[0] * 1) / 2).toFixed(6) * 1, ((start[1] * 1 + end[1] * 1) / 2).toFixed(6) * 1] } //经纬度转坐标 function pointTransform(point) { var lng = point[0] var lat = point[1] var alt = point[2] var phi = (90 - lat) * (Math.PI / 180), theta = (lng + 180) * (Math.PI / 180), radius = alt + earth_radius, x = -(radius * Math.sin(phi) * Math.cos(theta)), z = (radius * Math.sin(phi) * Math.sin(theta)), y = (radius * Math.cos(phi)); return new THREE.Vector3(x, y, z); } //曲线 function getFivePoint(p1, p5) { var p3 = computedCenter(p1, p5) var p2 = computedCenter(p1, p3) var p4 = computedCenter(p5, p3) var height = (Math.abs(p1[0] - p5[0])) / 3 if (height > 40) { height = 65 } if (p5[3] === '墨西哥'){ height = 120 } if (p5[3] === 'height'){ height = 80 } if (p5[3] === 'height2'){ height = 100 } p2.push(height) p3.push(height) p4.push(height) var v1 = pointTransform(p1) var v2 = pointTransform(p2) var v3 = pointTransform(p3) var v4 = pointTransform(p4) var v5 = pointTransform(p5) var line = createFlyCurve(v1, v2, v4, v5) const curve = new THREE.CubicBezierCurve3( v1, v2, v4, v5 ); const points = curve.getPoints(50); const geometry = new THREE.BufferGeometry().setFromPoints(points); const material = new THREE.LineBasicMaterial({ color: 0x0052d9, vertexColors: THREE.VertexColors, side: THREE.DoubleSide, transparent: true, opacity: 0.1, alphaTest: 1, linewidth: 10, }); const curveObject = new THREE.Line(geometry, material); curveObject.name = p1[3]+'_线' line.name = p1[3]+'_线2' scene.add(curveObject) scene.add(line) } // company_list.map((item,index) => { // if (company_list[index+1]){ // getFivePoint(company_list[2],company_list[index+1]) // } // }) // company_list.map((item,index) => { // if (company_list[index+1]){ // getFivePoint(company_list[3],company_list[index+1]) // } // }) //点击公司 var raycaster = new THREE.Raycaster() var mouse = new THREE.Vector2() $wrap.on('click',function(e){ console.log(123) onMouseClick(e) }) $('body').on('click','.company-list span',function(){ $(this).addClass('on').siblings().removeClass('on') var name = $(this).attr('data-name') for (let j = 0; j < 5; j++) { scene.children.map(e => { if (e.name.indexOf('线') !== -1){ scene.remove(e) } }) } var click_index = '' company_list.map((item,index) => { if (item[3] === name ){ click_index = index } }) var length = company_list.length for (let j = 0; j < length; j++) { if (j !== click_index){ getFivePoint(company_list[click_index],company_list[j]) } } }) function onMouseClick(event){ var x = event.clientX - $wrap.offset().left var y = event.clientY - $wrap.offset().top + $(window).scrollTop() mouse.x = (x/width)*2-1 mouse.y = -((y/height)*2-1) // 通过鼠标点的位置和当前相机的矩阵计算出raycaster raycaster.setFromCamera( mouse, camera ); var intersects = raycaster.intersectObjects( scene.children ); for ( var i = 0; i < intersects.length; i++ ) { if (intersects[ i ].object.name && intersects[ i ].object.name !== 'earth' && intersects[ i ].object.name.indexOf('线') === -1){ } // intersects[ i ].object.material.color.set( 0xff0000 ); } } //开始渲染显示 function animate() { requestAnimationFrame(animate); //移动起来 scene.rotation.y += 0.005; controls.update() renderer.render(scene, camera); } animate(); window.addEventListener( 'resize', onWindowResize ); function onWindowResize() { var width = $wrap.width(), height = $wrap.height(); camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize( width, height ); } });