I'm trying to display text in Leaflet using a marker layer with icon as L.divIcon (with svg text). This works fine. However when the text is rotated the text is clipped outside the viewport. I've tried to adjust this in several ways, but to no avail. For example, I've tried to extract the BBox after rotation, and then update the svg viewBox parameters, but this doesn't work as expected.
Here you can see the viewbox of the svg containing rotated text. The text content 125BET is clipped. The text 10665 is barely rotated, and is displayed correctly.
Here is the viewbox of the text component, and I want to use this information to avoid clipping:
Code:
let svgIcon = L.divIcon({
html: `
<svg
version="1.1"
id="${svgGcTextId}"
preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg"
>
<text width="5000" height="5000" x="0" y="${fontSize}" transform="rotate(${rotation})" font-size="${fontSize}">${text}</text>
</svg>`,
className: "",
iconSize: [24, 10],
iconAnchor: [0, fontSize],
});
let marker = L.marker(latlng, { icon: svgIcon, interactive: false });
Edit:
Tried adding transform-origin as per Peters suggestion. Although this seems to work, it shifts the insertion point of the text which isn't desirable. See pic below, where the "1" in 125BET is translated south of the building. It's possible to see more of the text though, as more of it is inside the viewbox.
Edit2:
Here is a fiddle. Change the rotation and fontSize values to test different scenarios. Note that I have code for scaling the font size when zooming (but that shouldn't be relevant here)
CodePudding user response:
Originally, I thought that all you needed to do was add: transform-origin="120 60"
(or something similar) to the <text>
element of your svg
code.
However, once you updated your question, it appears that the problem may well be with setting the height
and width
on the svg
itself.
You can still probably move the origin with transform-origin
or just set the x
and y
on the <text>
element.
Here is my code snippet (based on your jsFiddle). Please look for the rotated LONDON.
var map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(map);
let fontSize = "60px";
let svgGcTextId = "";
let rotation = "45";
let text = "LONDON";
let latlng = [51.505, -0.09];
let svgIcon = L.divIcon({
html: `
<svg
version="1.1"
id="${svgGcTextId}"
preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg"
width="300"
height="300"
>
<text width="5000" height="5000" x="30" y="30" transform="rotate(${rotation})" font-size="${fontSize}">${text}</text>
</svg>`,
className: "",
iconSize: [24, 10],
iconAnchor: [0, 0],
});
let marker = L.marker(latlng, {
icon: svgIcon,
interactive: true
});
map.addLayer(marker);
let referenceMarker = L.circleMarker(latlng, {radius: 5});
map.addLayer(referenceMarker);
#map {
height: 400px;
}
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9 580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==" crossorigin="" />
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==" crossorigin=""></script>
<body>
<div id="map"></div>
</body>
</head>
</html>