symbolizers
将会显示要素的 label
字段的值,
使用给定字体、字体大小、颜色。
无论什么时候创建一个 TextSymbolizer
对象,都必须提供这四项参数。
仔细看一看这些参数,还有哪些能够控制的显示文本。
选择将要显示的文本通过将一个字段或者属性名称作为TextSymbolizer构造中的第一个参数。 该文本始终来源于基础数据,没有将label强行连接到规则的选项。
对于许多数据源,名称是用来区分大小写的,
所以为了确保键入的字段的名称和属性是完全正确的。 MAME
与name
并不等同。
第二个参数是使用创建TextSymbolizer对象时进行定义的给定的字体和字体大小进行绘制的。 有两个选项来选择字体:可以使用Mapnik提供的内置字体中的一个,或者可以安装自己的自定义字体。
设置文字是透明或者不透明的程度,通过设置透明度属性,如下所示:
symbolizer.opacity = 0.5
透明度的范围是 0.0
(完全透明)到 1.0
(完全不透明)
注意:多边形的标记应沿着多边形的边界被绘制,并且标记与线条的方向一致。点要素没有被标记,因为在点要素中没有线条。
你通过设置symbolizer的 label_placement
属性来控制文本的位置。
虽然但是, 这里使用 XML 文件作为数据源:
import mapnik
import os
stylesheet = 'test_map_label_point.xml'
m = mapnik.Map(600, 200)
mapnik.load_map(m, stylesheet)
m.zoom_all()
env = m.envelope()
print(env)
box = mapnik.Box2d(env.minx - .2, env.miny - .2, env.maxx + .2, env.maxy + .2)
m.zoom_to_box(box)
mapnik.render_to_file(m,'xx_map_label_point.png')
Box2d(3.0,1.0,18.0,6.0)
结果如下:
查看这个 XML 文件:
!cat test_map_label_point.xml
<Map background-color="#ffffff" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"> <Style name="My Style"> <Rule> <PolygonSymbolizer fill="#efefef"/> <LineSymbolizer stroke="rgb(50%,50%,50%)" stroke-width="1" stroke-dasharray="8,20"/> <TextSymbolizer face-name="DejaVu Sans Book" size="10" fill="black" placement="point" allow-overlap="false">[name] </TextSymbolizer> </Rule> </Style> <Layer name="world" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"> <StyleName>My Style</StyleName> <Datasource> <Parameter name="type">shape</Parameter> <Parameter name="file">/data/gdata/fig_data/fig_data_poly.shp</Parameter> </Datasource> </Layer> </Map>
当使用 LINE_PLACEMENT
放置标记时,在默认情况下,在线条的中央 Mapnik 将会绘制一次标签。
在许多情况下,沿着线条的一段重复标记也是很有道理的。
要做到这一点,你就需要设置 symbolizer
的 label_spacing
属性表,如下所示:
symbolizer.label_spacing = 30
设置这个属性会导致线或多边形的边界被重复标记。 该值是重复标记之间的间隔量,以像元为单位。 使用以上的label spacing,我们的线条和多边形要素将用以下的方式显示:
下面是几种被用来微调显示重复标记的的属性:
symbolizer.force_odd_labels = True
:TextSymbolizer绘制奇数标记,这样可以使标记在某些情况下看起来更好。symbolizer.max_char_angle_delta = 45
:设置变化的最大夹角值(以度为单位)即从一个字符到下一个。使用这种方法可以防止Mapnik尖角附近被标记,例如:symbolizer.min_distance = 40
: 重复的标记之间的最小距离,以像元为单位。symbolizer.label_position_tolerance = 20
: 这设置的是能够沿着线条移动的最大距离来避开其他的标记和尖角的一个标记。这个值是以像元为单位的,默认为in_distance/2
。
使用文本标记的“字晕”
TextSymbolizer通常会直接在地图上绘制文本。 当文本被放置在地图上的浅色区域,但是如果地图被覆盖的区域是深色或者遥感影像等背景比较乱的情况, 文本将很难读出甚至显示。
当然,可以选择一个浅色的文本的颜色,但是你需要提前了解背景可能是什么样子的, 一个比较好的解决方式就是在文本周围绘制一个“字晕”。
mapnik.vertical_alignment.MIDDLE
是默认的,将标记垂直的放在点的中心。
如果你将垂直位移改变成mapnik.vertical_alignment.TOP
,标记将会被绘制到点的上部。反过来,如果你将垂直改变成mapnik.vertical_alignment.BOTTOM
,标记将被绘制到点的下部。
更细致的调整文本位置的其他选项就是使用displacement()
方法,
来用给定的像元数目显示文本。例如:
偏移的量从左上角算起。这会导致标记向右边偏向5个单位,从他的正常位置下移 10
个单位。
注意,
改变标注的垂直位移同样也会改变标记的默认的 vertical_alignment
值。
这会导致标记用你不想要的方式移动,因为标记的垂直走向被改变了
作为一个设置垂直位移的单方面影响因素。
为了避免这种情况的发生,你同时也应该明确的设置一下 vertical_alignment
属性,
无论你什么时候改变垂直位移。
还有一些属性可以控制文本显示的细节,如文本的宽度(自动换行)、字符间距等。
使用wrap_width
属性来强制标记在跨越多列时换行,指定的值就是文本每个行的最大值,以像元为单位。
symbolizer.character_spacing = 3
,在文本中你可以在字符之间添加额外的空隙。
你同样可以改变不同行之间的距离通过使用 line_spacing
属性。
字符间距和行间距的值都是以像元为单位的。
有些时候你想改变文本显示的状况。你可以做这件事情通过设置 text_convert
属性。
下面这个例子展示了几种不同的标准方式:
import os
import mapnik
stylesheet = 'test_fig_label_position.xml'
# image = 'xx_world_style_from_xml.png'
m = mapnik.Map(600, 150)
mapnik.load_map(m, stylesheet)
m.zoom_all()
# m.background = mapnik.Color('steelblue')
# bbox = mapnik.Box2d(118, 36.6, 124.6, 40.7)
bbox = mapnik.Box2d(-1, -1, 8, 1)
m.zoom_to_box(bbox)
mapnik.render_to_file(m, 'xx_fig_label_position.png')
以下为渲染的结果 :
查看这个 XML 文件:
!cat test_fig_label_position.xml
<Map background-color="#efefef" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"> <Style name="My Style"> <Rule> <PointSymbolizer/> <TextSymbolizer face-name="DejaVu Sans Book" size="20" placement="point" allow-overlap="true">[name] </TextSymbolizer> <Filter>[id] = 1</Filter> </Rule> <Rule> <PointSymbolizer/> <TextSymbolizer face-name="DejaVu Sans Book" size="20" placement="point" allow-overlap="true" vertical-alignment="MIDDLE">[name] </TextSymbolizer> <Filter>[id] = 2</Filter> </Rule> <Rule> <PointSymbolizer/> <TextSymbolizer face-name="DejaVu Sans Book" size="20" placement="point" allow-overlap="true" vertical-alignment="bottom" horizontal-alignment="right" justify-alignment="right">[name] </TextSymbolizer> <Filter>[id] = 3</Filter> </Rule> <Rule> <PointSymbolizer/> <TextSymbolizer face-name="DejaVu Sans Book" size="20" placement="point" allow-overlap="true" dx="2" dy="25" character-spacing="3">[name] </TextSymbolizer> <Filter>[id] = 4</Filter> </Rule> <Rule> <PointSymbolizer/> <TextSymbolizer face-name="DejaVu Sans Book" size="20" placement="point" allow-overlap="true" vertical-alignment="BOTTOM" orientation="45">[name] </TextSymbolizer> <Filter>[id] = 5</Filter> </Rule> <Rule> <PointSymbolizer/> <TextSymbolizer face-name="DejaVu Sans Book" size="20" halo-fill="red" halo-radius="2" placement="point" allow-overlap="true">[name] </TextSymbolizer> <Filter>[id] = 6</Filter> </Rule> </Style> <Layer name="world" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"> <StyleName>My Style</StyleName> <Datasource> <Parameter name="type">shape</Parameter> <Parameter name="file">/data/gdata/fig_data/fig_data_pt.shp</Parameter> </Datasource> </Layer> </Map>
文本的高级设置
将文本放置在道路上时,Mapnik 有很多专门的操作。
你会发现,在急转的角落里,文字会弯曲,这样会导致街名难看的扭结。
幸好,有一个max_char_angle_delta
属性,可以添加TextSymbolizer,
以使得标签远离急转弯,20度看起来很不错。
虽然仍然可以得到弯曲的道路标识,但是没有不和谐的角落。
如果发现数据集将较长的路段切割成较短的几部分, 会发现Mapnik不能使标签与之适应, 即使适应也会产生每个路段的不必要的重复。 我们的道路数据来源于商业, 这些道路数据已经被优化以便于灵活地制图, 许多较长的道路分支依据车道数量极其其他特征被分成许多小段。 我们对展现如此高层次的细节没有兴趣, 所以他们更愿意提供这样一个版本的数据, 同名且连接在一起道路融合成更长的线路。
路线和高速公路标签的常见的形式是“盾牌”, 由Mapnik作为ShieldSymbolizer应用。 盾牌是文字和图形的组合,意在表明短的道路号码, 与名称不同(如“加州13”与“沃伦高速公路”)。 像上面的顺序技巧,盾牌需要一些策略来得到正确的位置。 你可以使用常规的SQL LENGTH(名称)功能结合Mapnik样式的过滤器,来创建简单的条件: 例如,使用宽宽的盾牌图形标注长长的路线编号, 一个窄窄的盾牌图形标注较短的路线编号。
import mapnik
for font in mapnik.FontEngine.face_names():
print (font)
DejaVu Math TeX Gyre Regular DejaVu Sans Bold DejaVu Sans Bold Oblique DejaVu Sans Book DejaVu Sans Condensed DejaVu Sans Condensed Bold DejaVu Sans Condensed Bold Oblique DejaVu Sans Condensed Oblique DejaVu Sans ExtraLight DejaVu Sans Mono Bold DejaVu Sans Mono Bold Oblique DejaVu Sans Mono Book DejaVu Sans Mono Oblique DejaVu Sans Oblique DejaVu Serif Bold DejaVu Serif Bold Italic DejaVu Serif Book DejaVu Serif Condensed DejaVu Serif Condensed Bold DejaVu Serif Condensed Bold Italic DejaVu Serif Condensed Italic DejaVu Serif Italic Liberation Mono Bold Liberation Mono Bold Italic Liberation Mono Italic Liberation Mono Regular Liberation Sans Bold Liberation Sans Bold Italic Liberation Sans Italic Liberation Sans Regular Liberation Serif Bold Liberation Serif Bold Italic Liberation Serif Italic Liberation Serif Regular cmex10 LyX cmmi10 LyX cmr10 LyX cmsy10 LyX dsrom10 LyX esint10 LyX eufm10 LyX msam10 LyX msbm10 LyX rsfs10 LyX stmary10 LyX wasy10 LyX