Skip to content
目录

行政区拔高并贴影像纹理图片

功能描述:

  • 行政区拔高
  • 用一个整体的行政区纹理贴图,然后每个子区域对这个纹理图片进行各自比列的切分和贴图
  • 鼠标放到行政区上去对应的行政区可以动画的方式浮起来成为显眼包

难点

  • 怎样将一个大的的纹理图片按照每个子区域的比例进行切分和贴图
  • 怎样制作这个大的行政区的纹理图片

解决难点方法

这里默认你懂纹理的uv的知识点,如果你不懂请查阅相关的资料

怎样将一个大的的纹理图片按照每个子区域的比例进行切分和贴图?

默认情况下行政区拔高的构造的几何体(Geometry)的纹理坐标值(UV),不是按照这种简单的按照行政区面积比列分布的, 所以需要我们对Geometry的顶面的纹理坐标值进行重计算

具体方法:

  • 求出所有行政区的边界的包围盒

  • 计算每个子区域的坐标点的值换算成在这个包围盒内的占比即可(就是求UV的值,也是对整个纹理图片的划分过程)

  • 更新每个子区域的Geometry的uv值就可以了

WARNING

注意只需要更新下顶面的uv坐标,判断一个顶点的坐标是否是顶面的可以根据顶点的z值来判断

js
function resetTopUV(extrudePolygons) {
    // console.log(geometries);
    //计算所有区域的总的包围盒
    let minx = Infinity,
        miny = Infinity,
        maxx = -Infinity,
        maxy = -Infinity,
        maxZ = -Infinity;
    extrudePolygons.forEach((extrudePolygon) => {
        const geometry = extrudePolygon.getObject3d().geometry;
        const center = extrudePolygon.getObject3d().position;
        const px = center.x,
            py = center.y;
        const position = geometry.attributes.position.array;
        for (let i = 0, len = position.length; i < len; i += 3) {
            const x = position[i] + px,
                y = position[i + 1] + py,
                z = position[i + 2];
            minx = Math.min(minx, x);
            miny = Math.min(miny, y);
            maxx = Math.max(maxx, x);
            maxy = Math.max(maxy, y);
            maxZ = Math.max(maxZ, z);
        }
    });
    console.log(minx, miny, maxx, maxy);
    //计算每个子区域的每个轮廓坐标点的在这个包围盒的百分比
    const dx = maxx - minx,
        dy = maxy - miny;
    extrudePolygons.forEach((extrudePolygon) => {
        const geometry = extrudePolygon.getObject3d().geometry;
        const position = geometry.attributes.position.array;
        const center = extrudePolygon.getObject3d().position;
        const px = center.x,
            py = center.y;
        const uv = geometry.attributes.uv.array;
        let idx = 0;
        for (let i = 0, len = position.length; i < len; i += 3) {
            const x = position[i] + px,
                y = position[i + 1] + py,
                z = position[i + 2];
            if (z === maxZ) {
                const u = (x - minx) / dx;
                const v = (y - miny) / dy;
                const index = idx * 2;
                uv[index] = u;
                uv[index + 1] = v;
            }
            idx++;
        }
    });
}

怎样制作这个大的行政区的纹理图片?

你可以使用自己的工具,这里我是自己手撸的

具体步骤:

  • 选择一个合适的地图缩放比例,用来抓取瓦片的集合
  • 将所有的瓦片按照行列号组装成一个大的图片

WARNING

注意这里的大图片是所有的瓦片集合的合并的,其包围盒是比行政区的包围盒要大的,用行政区的轮廓剪裁后四周会 留白的,所有需要我们二次剪裁

  • 将行政区的经纬坐标转换成像素坐标
  • 在这个图片上绘制行政区的像素坐标用来剪裁这个大图片

  • 去掉这个大图片周边的留白

  • 导出这个图片

具体代码

数据准备

这里我们以北京的行政区为例

  • 准备行政区的GeoJSON数据,数据来源 datav geo
  • 准备北京市整个行政区的纹理图片,该图片有上面我们制作纹理图片的方法生成

当然你也可以使用其他的专业工具,甚至可以对这个纹理做些特殊处理(PS等),滤镜,阴影,高光等效果,当然这些就不是本篇 文章要介绍的内容

TIP

瓦片数据来源:World_Imagery

beijing-texture.png

WARNING

注意:

  • 纹理图片可以等比缩放,但是不能改变纹理的长宽比例,即不能形变,要确保行政区的长宽比例,否则可能贴到 行政区上不能严丝合缝
  • 纹理图片内边距不能留白,即图片的长宽要正好覆盖主行政区即可

行政区上浮动画

maptalks内部自带了动画函数,maptalks.animate,具体请参考高级篇章里的 自定义动画

  • 监听行政区的mouseover,动画函数里动态改变行政区的海拔
  • mouseout事件里把行政区的海拔设为0即可

This document is generated by mdpress