如何让OpenLayers Icon中SVG图片的文本达到预期尺寸?
问题描述
运行以下代码后,地图上的SVG文本显示尺寸极小(仅8-9像素高),几乎无法辨认。而在Google Docs中使用10号Roboto字体时,文本高度可达12像素,清晰可读。推测存在缩放因子导致文本缩小,需要消除该因子以达到预期的可读尺寸。
运行代码
JavaScript
const osm = new ol.source.OSM(); osm.setTileGridForProjection( "EPSG:4326", ol.tilegrid.createXYZ({ extent: [-180, -90, 180, 90] }) ); const tileLayer = new ol.layer.Tile({ source: osm }); const coordinate = [-97, 38]; const coordinate2 = [-97, 37]; const text = "99"; const padding = 4; const rectSize = [20, 20]; const svg = '<?xml version="1.0"?>' + `<svg width="${rectSize[0]}" height="${rectSize[1]}" viewBox="0 0 ${rectSize[0]} ${rectSize[1]}" version="1.1" xmlns="http://www.w3.org/2000/svg">` + `<rect width="${rectSize[0]}" height="${rectSize[1]}" style="fill:black" />` + `<text x="50%" y="50%" font-family="Roboto" font-size="10" fill="white" dominant-baseline="central" text-anchor="middle">${text}</text>` + "</svg>"; const svgPoint = new ol.Feature({ geometry: new ol.geom.Point(coordinate2), properties: { name: "svgPoint" } }); const layer = new ol.layer.Vector({ source: new ol.source.Vector({ features: [svgPoint] }), style: (feature) => { const properties = feature.getProperties(); let style; style = new ol.style.Style({ image: new ol.style.Icon({ opacity: 1, src: "data:image/svg+xml;base64," + btoa(svg) }) }); return style; } }); const map = new ol.Map({ target: "map", layers: [tileLayer, layer], view: new ol.View({ projection: "EPSG:4326", center: coordinate, zoom: 5 }), controls: ol.control.defaults.defaults({ attribution: false, zoom: false }) }); ol.proj.get("EPSG:4326").setExtent([-180, -85, 180, 85]);
CSS
#map { height: 256px; width: 256px; }
HTML
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/dist/ol.min.js"></script> <div id="map"></div>
解决方案
文本缩小的核心原因是OpenLayers对Icon的默认尺寸适配:当未指定Icon的size属性时,OpenLayers会自动调整SVG的显示尺寸,导致内部文本被缩放。以下两种方法可以解决问题:
方法一:指定Icon的显示尺寸
在创建ol.style.Icon时,添加size属性明确指定SVG的显示尺寸,同时设置scale:1确保不额外缩放:
style = new ol.style.Style({ image: new ol.style.Icon({ opacity: 1, src: "data:image/svg+xml;base64," + btoa(svg), size: rectSize, // 明确指定图标尺寸 scale: 1 // 禁用自动缩放 }) });
这样SVG会以20x20的实际像素显示,内部10号Roboto字体的尺寸会和Google Docs中的效果一致,达到可读的12像素高度。
方法二:直接使用OpenLayers文本样式(更可控)
放弃SVG方式,直接用ol.style.Text搭配图形样式,避免SVG的缩放问题,文本尺寸更可控:
style = new ol.style.Style({ // 替换SVG矩形为圆形(也可以用自定义图形) image: new ol.style.Circle({ radius: rectSize[0]/2, // 和原SVG矩形尺寸对应 fill: new ol.style.Fill({ color: 'black' }) }), text: new ol.style.Text({ text: text, font: '10px Roboto', fill: new ol.style.Fill({ color: 'white' }), textAlign: 'center', textBaseline: 'middle' }) });
这种方式不需要处理SVG的编码和缩放问题,文本渲染完全由OpenLayers控制,尺寸精度更高。
内容的提问来源于stack exchange,提问作者Eric G
相关产品推荐
相关产品推荐

