英文:
How to only display Placemark names of points in MVT using mapbox?
问题
我正在尝试使用Mapbox来显示矢量瓦片集。矢量瓦片集是从kml文件转换而来的。我使用gdal将其转换为MVT,并在Mapbox上正常显示,除了一个问题:它还显示了所有线段点的名称作为标签。
我的kml文件中的LineString具有以下结构:
<Placemark>
<name>mainlayer_0</name>
<Style>
<LineStyle><color>ffffffff</color><width>1</width></LineStyle>
</Style>
<OvStyle>
<TrackStyle><type>5</type><width>79</width></TrackStyle>
</OvStyle>
<LineString>
<coordinates>
* 许多坐标 *
</coordinates>
</LineString>
</Placemark>
Mapbox显示“mainlayer_0”作为标签,并且相同的标签被放置在LineString中的每个坐标上(每个LineString中最多有数百个坐标),这是不希望的。我只想显示独立点的标签,具有以下结构:
<Placemark>
<name>First Label Name</name>
<description>I want to show this label</description>
<Style>
<IconStyle>
<Icon>
</Icon>
<color>ffffffff</color>
<scale>1.0</scale>
</IconStyle>
<LabelStyle>
<color>ffffffff</color>
</LabelStyle>
</Style>
<Point>
<coordinates>/* 点的坐标 */ </coordinates>
</Point>
</Placemark>
我首先做的是使用以下命令将kml文件转换为MVT:
ogr2ogr -f MVT output input.kml -dsco COMPRESS=NO -dsco MAXZOOM=15
然后使用下面的代码在mapbox中显示MVT。lineLayer显示了我需要显示的所有线条。在symbolLayer中,我使用["get", "Name"]
来获取文本,但是LineString的名称也在“Name”字段中。我认为这是问题所在,但我不知道如何解决它。
map.on("load", () => {
map.addSource("map_name", {
type: "vector",
tiles: ["http://127.0.0.1:8080/output/{z}/{x}/{y}.pbf"],
minzoom: 0,
maxzoom: 15,
});
map.addLayer({
id: "lineLayer",
type: "line",
source: "map_name",
"source-layer": "mainlayer",
});
map.addLayer({
id: "symbolLayer",
type: "symbol",
source: "map_name",
"source-layer": "mainlayer",
layout: {
"text-field": ["get", "Name"],
"text-anchor": "top",
},
});
});
使用上述代码,除了线条的名称反复显示在其中的每个点上以外,一切都看起来很好。
我尝试修改kml文件,将所有LineString的名称替换为空字符串,视觉效果符合预期。但是,我需要自动化这个过程,不想每次手动修改kml文件。当MapBox渲染标签时,我相信它知道这个点是一个点还是在LineString中,所以我的问题是:
- 是否有可能告诉Mapbox不要显示LineString的任何标签?
- 是否有可能告诉Mapbox只显示点的名称?
我还想知道在将kml转换为MVT的过程中是否有什么我可以做的,以帮助解决这个问题。感谢任何建议!
英文:
I am trying to use Mapbox to display a vector tileset. The vector tileset is converted from a kml file. I used gdal to convert it to MVT, and it displays on Mapbox fine, except for one thing: it also shows the name of all lineString points as labels.
A lineString in my kml file has following structure:
<Placemark>
<name>mainlayer_0</name>
<Style>
<LineStyle><color>ffffffff</color><width>1</width></LineStyle>
</Style>
<OvStyle>
<TrackStyle><type>5</type><width>79</width></TrackStyle>
</OvStyle>
<LineString>
<coordinates>
\* many coordinates *\
</coordinates>
</LineString>
</Placemark>
Mapbox shows the "mainlayer_0" as labels, and the same label was put on every single coordinate in the LineString (up to hundreds in each), which is undesired. The only labels I want to show are independent points, with following structure:
<Placemark>
<name>First Label Name</name>
<description>I want to show this label</description>
<Style>
<IconStyle>
<Icon>
</Icon>
<color>ffffffff</color>
<scale>1.0</scale>
</IconStyle>
<LabelStyle>
<color>ffffffff</color>
</LabelStyle>
</Style>
<Point>
<coordinates>/* coordinate of the point */ </coordinates>
</Point>
</Placemark>
What I did first was converting the kml file into MVT using following command:
ogr2ogr -f MVT output input.kml -dsco COMPRESS=NO -dsco MAXZOOM=15
And display the MVT in mapbox using code below. The lineLayer shows all the lines I need to display. In the symbolLayer, I used ["get", "Name"]
to get the text, but the lineString name are also in "Name" field. I think this is the problem, but I do not know how to solve it.
map.on("load", () => {
map.addSource("map_name", {
type: "vector",
tiles: ["http://127.0.0.1:8080/output/{z}/{x}/{y}.pbf"],
minzoom: 0,
maxzoom: 15,
});
map.addLayer({
id: "lineLayer",
type: "line",
source: "map_name",
"source-layer": "mainlayer",
});
map.addLayer({
id: "symbolLayer",
type: "symbol",
source: "map_name",
"source-layer": "mainlayer",
layout: {
"text-field": ["get", "Name"],
"text-anchor": "top",
},
});
});
With above code, everything looks fine except the names of lineStrings are repetitively displayed on every points in them.
I tried to modify the kml file by replacing all the lineString names to empty string, and the visual outcome met the expectation. However, I need to automate this process and I do not want to manually modify the kml file every time. When MapBox is rendering the labels, I believe it knows if this point is just a point or it is in a LineString, so my questions are:
- Is it possible to tell mapbox not to display any labels of a LineString?
- Is it possible to tell mapbox to only show name of points?
I also wonder if there is anything I can do in the process of converting kml to MVT that can help with this issue. Any suggestion is appreciated!
答案1
得分: 0
这有点尴尬,因为我在发布问题后五分钟就找到了答案。答案是一行代码,将以下内容添加到 map.addLayer({...})
中:
filter: ["==", ["get", "geometry-type"], "Point"],
详细信息可以在这里找到:setFilter
并且有一个解释用法的示例在这里:
使用新表达式按几何类型筛选
希望这对将来的某人有所帮助^_^
英文:
This is a bit akward as I found the answer five minutes after I post the question. The answer is one line, adding
filter: ["==", ["geometry-type"], "Point"],
in map.addLayer({...})
. Details can be found here: setFilter
And an explained usage is here:
Filter by geometry-type with new expressions
Hope this help someone in the future^_^
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论