threejs 使用SVG格式绘制地图

使用SVG绘制图形很简单,绘制地图也是一样。
首先需要一个地图的SVG格式配置文件,我这里找了一个

<script type="text/javascript" src="js/0_public/chinaMapConfig.js" ></script>//中国地图

然后将SVG格式的字符串转换为THREE.Shape对象,此时需要引入插件

<script type="text/javascript" src="js/d3-threeD.js" ></script>//别找了threejs文档里面没有,需要的留言
var sichuan=transformSVGPathExposed(chinaMapConfig.shapes.sichuan);//
console.log(sichuan);

在这里插入图片描述
最后使用ExtrudeGeometry拉伸即可呈现三维地图。

//介绍一下ExtrudeGeometry的参数
				var extrudeSettings={	
					steps:2,// int. 物体本身在厚度上的分层数量
					depth:16,//挤出的形状的深度,默认值为100
					bevelEnabled:true,// 是否允许边角圆滑过度(开启bevelEnabled,其实物体本身是没有变化的,而是在物体的前后加上一个薄层,用来实现圆角)
					bevelThickness:1,//float. 附加层的厚度
					bevelSize:1,// float. 附加层的圆角的斜面长度
					bevelSegments:1//int. 附加的圆角的层数
				}
				
				var geometry=new THREE.ExtrudeGeometry(sichuan,extrudeSettings);
				geometry.center();//位置置中
				var mesh=new THREE.Mesh(geometry,new THREE.MeshLambertMaterial({
						color:0x8FBC8F
					}));
				scene.add(mesh);

下面做了一些增加,对单个省份操作,记录上一个省份信息,点击下一个省份,状态还原
在这里插入图片描述

完整代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<title>中国地图SVG</title>
		<script type="text/javascript" src="js/WebGL.js" ></script>
		<script type="text/javascript" src="js/three.js" ></script>
		<script type="text/javascript" src="js/controls/OrbitControls.js" ></script>
		<script type="text/javascript" src="js/libs/stats.min.js" ></script>
		<script type="text/javascript" src="js/libs/dat.gui.min.js" ></script>	
		<script type="text/javascript" src="js/0_public/chinaMapConfig.js" ></script>
		<script type="text/javascript" src="js/0_public/d3-threeD.js" ></script>
		
		<style>
			body{
				padding: 0;
				margin: 0;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		<script>
			if(WEBGL.isWebGLAvailable()===false) document.body.appendChild(WEBGL.getWebGLErrorMessage());
			
			var scene,renderer,camera,controls,stats;	
			function init(){
				scene=new THREE.Scene();
				scene.background=new THREE.Color(0xD6D6D6);
				
				renderer=new THREE.WebGLRenderer({
					antialias:true,
				});
				renderer.setSize(window.innerWidth,window.innerHeight);
				renderer.setPixelRatio(window.devicePixelRatio);
				document.body.appendChild(renderer.domElement);
				
				camera=new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.1,1000);
				camera.position.set(0,80,200);
				camera.lookAt(scene.position);
				
				controls=new THREE.OrbitControls(camera,renderer.domElement);
				controls.enableDamping=true;
				controls.minDistance=0.1;
				controls.maxDistance=1000;
				
				stats=new Stats();
				document.body.appendChild(stats.domElement);
				
				scene.add(new THREE.AmbientLight(0xffffff));
			};
			
			var axes;
			var chinaMapGroup=new THREE.Group();
			function initModel(){
				axes=new THREE.AxesHelper(30);
				axes.visible=false;
				scene.add(axes);

				//将SVG字符串转换为THREE.Shape对象
				var sichuan=transformSVGPathExposed(chinaMapConfig.shapes.sichuan);
				//console.log(sichuan);
				var extrudeSettings={	
					steps:2,// int. 物体本身在厚度上的分层数量
					depth:16,//挤出的形状的深度,默认值为100
					bevelEnabled:true,// 是否允许边角圆滑过度(开启bevelEnabled,其实物体本身是没有变化的,而是在物体的前后加上一个薄层,用来实现圆角)
					bevelThickness:1,//float. 附加层的厚度
					bevelSize:1,// float. 附加层的圆角的斜面长度
					bevelSegments:1//int. 附加的圆角的层数
				}
				
/*				var geometry=new THREE.ExtrudeGeometry(sichuan,extrudeSettings);
				geometry.center();
				var mesh=new THREE.Mesh(geometry,new THREE.MeshLambertMaterial({
						color:0x8FBC8F
					}));
				scene.add(mesh);*/
			
			//循环遍历省份的svg参数
				for(var index in chinaMapConfig.shapes){
					var shape=transformSVGPathExposed(chinaMapConfig.shapes[index]);
					var geometry=new THREE.ExtrudeGeometry(shape,extrudeSettings);
					var material=new THREE.MeshPhongMaterial({
						color:0xffffff*Math.random()
					});
					var province=new THREE.Mesh(geometry,material);
					province.name=chinaMapConfig.names[index];//获取省份名字
					chinaMapGroup.add(province);
				}
				chinaMapGroup.scale.set(0.5,0.5,0.5);
				chinaMapGroup.rotation.x=Math.PI/2;
				//计算地图包围盒,根据边界值计算,获取坐标,置于中央
				var box3=new THREE.Box3().expandByObject(chinaMapGroup);
				var bx=box3.max.x-box3.min.x;
				var by=box3.max.y-box3.min.y;
				var bz=box3.max.z-box3.min.z;
				chinaMapGroup.position.set(-bx/2,-by/2,-bz/2);
				scene.add(chinaMapGroup);
			}
			
			var mouse=new THREE.Vector2();
			var raycaster=new THREE.Raycaster();
			var intersected;
			function raycasterEvent(event){				
				if(event.touches){
					var touchE=event.touches[0];
					mouse.x=(touchE.pageX/window.innerWidth)*2-1;
					mouse.y=-(touchE.pageY/window.innerHeight)*2+1;
				}else{
					mouse.x=(event.clientX/window.innerWidth)*2-1;
					mouse.y=-(event.clientY/window.innerHeight)*2+1;
				}
				
				raycaster.setFromCamera(mouse,camera);
				
				var intersects=raycaster.intersectObjects(chinaMapGroup.children,true);
				if(intersects.length>0){
					if(intersected!==intersects[0].object){
						if(intersected){
							intersected.material.color=intersected.currentColor;
							intersected.position.z=0;
						}
						intersected=intersects[0].object;
						intersected.currentColor=intersects[0].object.material.color;
						intersected.material.color=new THREE.Color(0xff0000);
						intersected.position.z=-100;
						alert(intersected.name);
					}									
				}else{
					console.log("未检测到物体!");
					if(intersected){
						intersected.material.color=intersected.currentColor;
						intersected.position.z=0;
					}
					intersected=null;
				}
			}
			window.addEventListener("click",raycasterEvent,false);
			window.addEventListener("touchstart",raycasterEvent,false);
				
			var setting;	
			function initGui(){
				setting={
					axesVisible:false,
					resetControls:function (){
						controls.reset();
					}
				};
				var gui=new dat.GUI();
				gui.add(setting,"axesVisible").onChange(function(e){
					axes.visible=e;
				});
				gui.add(setting,"resetControls").name("位置重置");
			}
						
			function onWindowResize(){
				camera.aspect=window.innerWidth/window.innerHeight;
				camera.updateProjectionMatrix();
				renderer.setSize(window.innerWidth,window.innerHeight);
			}
			
			function render(){
				renderer.render(scene,camera);
			}
			
			function animate(){
				render();
				stats.update();
				controls.update();				
				window.onresize=onWindowResize();
				requestAnimationFrame(animate);
			}
			
			(function threeStart(){
				init();
				initModel();
				initGui();
				animate();
			}());
		</script>
	</body>
</html>
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值