three.js SVG 学习绘制色块

1,771 阅读3分钟

three.js SVG 学习绘制色块

www.js-css.cn/jscode/othe… 找到一个不错的资源,不过每个色块的svg数据太小了,不精确。

在这里插入图片描述

主要的是这个js文件:chinaMapConfig.js,有了它我们就可以根据svg路径绘制三维模型了。

在这里插入图片描述

这个网站也有svg的地图。mapsvg.com/maps/,相对精确一些,投影方式也不一样。 在这里插入图片描述

先测试一下内蒙古,没有问题。

var neimongol= transformSVGPathExposed(chinaMapConfig.shapes.neimongol);
var extrudeSettings = {
    steps: 2,
    depth: 16,
    bevelEnabled: true,
    bevelThickness: 1,
    bevelSize: 1,
    bevelSegments: 1
};
var geometry = new THREE.ExtrudeGeometry( neimongol, extrudeSettings );
var materiala = new THREE.MeshPhongMaterial( {
    color: 0x00ffff ,
    // wireframe:true
} );
var mesha = new THREE.Mesh( geometry, materiala ) ;
scene.add( mesha );

在这里插入图片描述

接着我们开始利用svg绘制完整的三维色块: 在这里插入图片描述

三维色块绘制完成,有点单调,添加一个交互事件。点击每个色块可以触发一个事件。 在这里插入图片描述

由于svg的坐标和three.js的坐标不一样,所以需要转换。 我新建了两个group,一个是把所有的省份添加进去,然后进行缩放平移操作。平移的依据是添加的box3,它计算出了group的包围盒。因为色块的本地坐标系不在中心,所以又添加了一个group是用来旋转操作。 最后使用Raycaster来检测点击的色块,并改变颜色,同时绘制了一个长方体。传参数group.children。只检测色块,默认是scene.children。

var group = new THREE.Group();
var chinaMap = new THREE.Group();

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

var extrudeSettings = {
    steps: 2,
    depth: 8,
    bevelEnabled: false,
    bevelThickness: 1,
    bevelSize: 1,
    bevelSegments: 1
};

for (let shapesKey in chinaMapConfig.shapes) {
    var materiala = new THREE.MeshPhongMaterial( {
        color: 0xffffff*Math.random()
    } );
    var shapesvgs= $d3g.transformSVGPath(chinaMapConfig.shapes[shapesKey]);
    var geometry = new THREE.ExtrudeGeometry( shapesvgs.toShapes(true), extrudeSettings );
    var mesha = new THREE.Mesh( geometry, materiala ) ;
    group.add( mesha );
}
group.scale.set(0.05,0.05,0.05);
var box = new THREE.Box3().expandByObject(group);
var bx = box.max.x-box.min.x,by = box.max.y-box.min.y,bz = box.max.z-box.min.z;
group.position.set(-bx/2,-by/2,-bz/2);
chinaMap.add(group);
chinaMap.rotation.x = Math.PI/2;
scene.add(chinaMap);

function onDocumentMouseDown(event) {
    var vector = new THREE.Vector3(( event.clientX / window.innerWidth ) * 2 - 1, -( event.clientY / window.innerHeight ) * 2 + 1, 0.5);
    vector = vector.unproject(camera);
    var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());

    var intersects = raycaster.intersectObjects(group.children); 
    if(intersects.length>0){
        console.log(intersects[0].point);
        intersects[0].object.material.color.set(0xff0000*Math.random());
        cubeDr(4,intersects[0].point.x,intersects[0].point.y+4/2,intersects[0].point.z);
    }
}

哦,上面忘记了介绍svg插件了。github.com/asutherland… 这个插件也是7年没更新了,但是也不影响使用哈。 使用transformSVGPathExposed方法的时候需要引用下面的js插件。 <script src="../threejs/d3-three3D.js"></script>

两种常见的投影方式:

在这里插入图片描述右侧的是叫墨卡托投影,是正轴等角圆柱投影。由荷兰地图学家墨卡托(G.Mercator)于1569年创立。假想一个与地轴方向一致的圆柱切或割于地球,按等角条件,将经纬网投影到圆柱面上,将圆柱面展为平面后,即得本投影。墨卡托投影在切圆柱投影与割圆柱投影中,最早也是最常用的是切圆柱投影。 左侧地图中--的左边有一条经度线,是倾斜的。但是在右边的图中,经度线就会成为垂直的。


上面的方法是使用svg的方法,有点局限性,一个是svg的色块难找,而且精确度难以把握,另一个原因是在数据可视化中,经纬度用不上。所以我们得改进一下,在我的另外一篇博客中介绍了使用geojson的方法绘制色块,这种方式的可操作性更好,值得学习。

Three.js之GeoJson 3D-数据可视化飞行线实战

离谱,文章色块是什么意思和缺少的字你们自己补充吧。 所有图片全部删了 ,换成你们看到的样子。


文章首发:webgl.blog.csdn.net/article/det…