使用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>