Changing single contour svg image fill color in QML - svg

I have made a single contour .svg cursor (basically a triangle curved at the bottom) without any fill, and I want to be able to change its fill color. I can't just make few different svgs for this, due to fill color being picked by user.
QtGraphicalEffects library is not supported since Qt6, so all I could find on this topic was of little use. The solution for this might be to just drop my svg over a colored rectangle, but then I'll have to mask out the area outside of my cursor to make it transparent(or vice-versa), and I'm not sure if it's even possible. I also found some shader-based solutions but none of then seem to work for my case (might just be me being new to QML)
SVG:
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600" viewBox="0 0 600 600">
<defs>
<style>
.cls-1 {
fill: none;
stroke: #414141;
stroke-width: 44px;
fill-rule: evenodd;
}
</style>
</defs>
<path id="Pointer_1" data-name="Pointer 1" class="cls-1" d="M300.291,48.248L556.347,560.4s-127.234-47.825-255.133-47.825c-128.157,0-256.979,47.825-256.979,47.825Z"/>
</svg>

[MULTIPLE EDITS]
Firstly, the latest builds of Qt6 do support QtGraphicalEffects via Qt5Compat.GraphicalEffects. https://doc.qt.io/qt-6/qtgraphicaleffects5-
The approach I prefer to use is to leverage the fact that most components have an icon property which has a built-in mechanism for recoloring an SVG. You set the following properties:
icon.source
icon.width
icon.height
icon.color
By creating two SVGs we can use the above approach to control the fill and stroke independently.
The typical component I use is Button, but, I strip off the default Button UI/UX and just leverage from the icon property as follows:
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
SplitView {
anchors.fill: parent
orientation: Qt.Horizontal
Item {
SplitView.preferredWidth: parent.width / 2
SplitView.fillHeight: true
Item {
anchors.centerIn: parent
width: parent.width * 8 / 10
height: parent.height * 8 / 10
Button {
anchors.centerIn: parent
visible: fillCombo.currentText !== 'none'
background: Item { }
icon.source: "shape-fill.svg"
icon.width: Math.min(parent.width, parent.height)
icon.height: icon.width
icon.color: fillCombo.currentText
}
Button {
anchors.centerIn: parent
visible: strokeCombo.currentText !== 'none'
background: Item { }
icon.source: "shape-outline.svg"
icon.width: Math.min(parent.width, parent.height)
icon.height: icon.width
icon.color: strokeCombo.currentText
}
}
}
Item {
SplitView.fillWidth: true
SplitView.fillHeight: true
ColumnLayout {
anchors.centerIn: parent
Label {
text: qsTr("Stroke")
}
ComboBox {
id: strokeCombo
model: [ "lightsteelblue", "red", "orange", "yellow", "green", "blue" ]
}
Label {
Layout.topMargin: 20
text: qsTr("Fill")
}
ComboBox {
id: fillCombo
model: [ "none", "red", "orange", "yellow", "green", "blue" ]
}
}
}
}
}
// shape-outline.svg
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600" viewBox="0 0 600 600">
<path stroke="red" stroke-width="44" fill="none" d="M300.291,48.248L556.347,560.4s-127.234-47.825-255.133-47.825c-128.157,0-256.979,47.825-256.979,47.825Z"/>
</svg>
// shape-fill.svg
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600" viewBox="0 0 600 600">
<path stroke="none" fill="black" d="M300.291,48.248L556.347,560.4s-127.234-47.825-255.133-47.825c-128.157,0-256.979,47.825-256.979,47.825Z"/>
</svg>
You can Try it Online!
Alternatively, another approach is you can build your SVG as a data uri by adding a "data:image/svg+xml," prefix to your SVG string. Because you're using a data uri, you can make a function that generates the SVG based on use input:
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
SplitView {
anchors.fill: parent
orientation: Qt.Horizontal
Item {
SplitView.preferredWidth: parent.width / 2
SplitView.fillHeight: true
Image {
anchors.centerIn: parent
width: parent.width * 8 / 10
height: parent.height * 8 / 10
source: todatauri(getsvg(strokeCombo.currentText, fillCombo.currentText))
fillMode: Image.PreserveAspectFit
}
}
Item {
SplitView.fillWidth: true
SplitView.fillHeight: true
ColumnLayout {
anchors.centerIn: parent
Label {
text: qsTr("Stroke")
}
ComboBox {
id: strokeCombo
model: [ "black", "red", "orange", "yellow", "green", "blue" ]
}
Label {
Layout.topMargin: 20
text: qsTr("Fill")
}
ComboBox {
id: fillCombo
model: [ "none", "red", "orange", "yellow", "green", "blue" ]
}
}
}
}
function todatauri(svg) {
return "data:image/svg+xml," + svg;
}
function getsvg(stroke, fill) {
return `<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600" viewBox="0 0 600 600">
<defs>
<style>
.cls-1 {
fill: none;
stroke: #414141;
stroke-width: 44px;
fill-rule: evenodd;
}
</style>
</defs>
<path id="Pointer_1" data-name="Pointer 1" class="cls-1" stroke="${stroke}" stroke-width="44" fill="${fill}" d="M300.291,48.248L556.347,560.4s-127.234-47.825-255.133-47.825c-128.157,0-256.979,47.825-256.979,47.825Z"/>
</svg>
`;
}
}
You can Try it Online!

Related

Colored SVG icons in Leaflet

I have added a SVG icon to leaflet as follows:
var myIcon = L.icon({
iconUrl: `data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 512 512"><path d="M224 387.814V512L32 320l192-192v126.912C447.375 260.152 437.794 103.016 380.931 0 521.286 151.707 491.481 394.785 224 387.814z"/></svg>`,
});
this.myMarker = L.marker([50.505, 30.57], { icon: myIcon }).addTo(map);
It is showing up as expected:
Now, when you add color to the SVG as follows, the icon disappears in the map:
iconUrl: `data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 512 512"><path d="M224 387.814V512L32 320l192-192v126.912C447.375 260.152 437.794 103.016 380.931 0 521.286 151.707 491.481 394.785 224 387.814z" fill="#fdbf00"/></svg>`,
Any thought about this?
I prepared an example instead of iconUrl I used html Then you can easily use colors in hex ;)
// config map
let config = {
minZoom: 7,
maxZomm: 18,
};
// magnification with which the map will start
const zoom = 13;
// co-ordinates
const lat = 52.237049;
const lon = 21.017532;
// calling map
const map = L.map('map', config).setView([lat, lon], zoom);
// Used to load and display tile layers on the map
// Most tile servers require attribution, which you can set under `Layer`
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
const svgTemplate = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" class="marker">
<path fill-opacity=".25" d="M16 32s1.427-9.585 3.761-12.025c4.595-4.805 8.685-.99 8.685-.99s4.044 3.964-.526 8.743C25.514 30.245 16 32 16 32z"/>
<path fill="#F7FADA" stroke="#000" d="M15.938 32S6 17.938 6 11.938C6 .125 15.938 0 15.938 0S26 .125 26 11.875C26 18.062 15.938 32 15.938 32zM16 6a4 4 0 100 8 4 4 0 000-8z"/>
</svg>`;
const icon = L.divIcon({
className: "marker",
html: svgTemplate,
iconSize: [40, 40],
iconAnchor: [12, 24],
popupAnchor: [7, -16]
});
const marker = L.marker([lat, lon], {
icon: icon
})
.bindPopup('#F7FADA')
.addTo(map);
* {
margin: 0;
padding: 0
}
html {
height: 100%
}
body,
html,
#map {
height: 100%;
margin: 0;
padding: 0
}
body {
height: 100%;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.6.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.6.0/dist/leaflet.js"></script>
<div id="map"></div>
Modified #IvanSanche example below
var map = new L.Map('leaflet', {
layers: [
new L.TileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
'attribution': 'Map data © OpenStreetMap contributors'
})
],
center: [0, 0],
zoom: 0
});
var myIcon = L.icon({
iconUrl: `data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 512 512"><path d="M224 387.814V512L32 320l192-192v126.912C447.375 260.152 437.794 103.016 380.931 0 521.286 151.707 491.481 394.785 224 387.814z"/></svg>`,
});
var myIcon2 = L.icon({
iconUrl: `data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 512 512"><path d="M224 387.814V512L32 320l192-192v126.912C447.375 260.152 437.794 103.016 380.931 0 521.286 151.707 491.481 394.785 224 387.814z" fill="%23fdbf00" stroke="red" /></svg>`,
});
this.myMarker = L.marker([50.505, 30.57], { icon: myIcon }).addTo(map);
this.myMarker2 = L.marker([50.505, 130.57], { icon: myIcon2 }).addTo(map);
body {
margin: 0;
}
html, body, #leaflet {
height: 100%
}
<script src="https://unpkg.com/leaflet/dist/leaflet-src.js"></script>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" /><div id="leaflet"></div>

SVG logo animation to fill and disappear at the end

I need to animate this logo to fill smoothly and disappear on the end of animation, for example like on this website: https://largo.studio/ I'm trying all of the combination of css, but nothing works.
.path {
stroke-dasharray: 1300;
stroke-dashoffset: 1500;
animation: dash 4s linear forwards;
}
#keyframes dash {
0% {
stroke-dashoffset: 822;
fill: white;
}
50% {
stroke-dashoffset: 600;
}
70% {
fill: #db0d83;
stroke-dashoffset: 400;
}
100% {
fill: white;
}
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:serif="http://www.serif.com/" width="100%" height="100%" viewBox="0 0 1824 485" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-miterlimit:22.926;"><path class="path" fill="white" stroke="#db0d83" stroke-width="4" d="M327.236,354.205c0,46.271 -17.896,80.534 -53.581,102.797c-24.88,15.278 -67.548,22.917 -128.113,22.917l-143.064,0l0,-470.769l128.659,0c57.946,0 98.431,6.764 121.567,20.297c33.501,19.643 50.306,51.726 50.306,96.25c0,51.944 -26.736,87.736 -80.316,107.379c69.731,13.531 104.542,53.907 104.542,121.129m-45.833,-229.818c0,-36.229 -12.221,-61.548 -36.774,-75.953c-22.263,-13.093 -59.692,-19.642 -112.182,-19.642l-108.362,0l0,197.738l109.671,0c98.432,0 147.647,-34.049 147.647,-102.143m22.917,225.89c0,-37.976 -13.095,-65.258 -39.286,-81.844c-26.189,-16.587 -67.439,-24.881 -123.749,-24.881l-117.2,0l0,216.725l116.546,0c51.508,0 86.864,-3.929 106.071,-11.786c38.412,-15.715 57.618,-48.452 57.618,-98.214m377.139,-46.611c0,55.437 -13.422,98.976 -40.267,130.623c-26.845,31.647 -63.402,47.47 -109.672,47.47c-45.832,0 -82.175,-15.825 -109.017,-47.47c-26.842,-31.642 -40.267,-75.186 -40.267,-130.623c0,-55.435 13.422,-98.978 40.267,-130.625c26.845,-31.645 63.185,-47.469 109.017,-47.469c46.27,0 82.831,15.829 109.672,47.469c26.841,31.645 40.267,75.19 40.267,130.625m-21.607,0c0,-49.762 -11.571,-88.832 -34.811,-117.2c-23.241,-28.369 -54.454,-42.561 -93.521,-42.561c-39.067,0 -70.172,14.192 -93.194,42.561c-23.021,28.368 -34.483,67.438 -34.483,117.2c0,49.761 11.458,88.829 34.483,117.203c23.025,28.371 54.127,42.557 93.194,42.557c39.067,0 70.278,-14.186 93.521,-42.557c23.243,-28.374 34.811,-67.442 34.811,-117.203m345.71,168.928l-20.298,0l0,-53.037c-21.387,41.468 -59.581,62.202 -114.581,62.202c-77.697,0 -116.547,-40.595 -116.547,-121.783l0,-227.2l20.297,0l0,220.215c0,37.86 7.453,65.566 22.263,82.935c14.865,17.434 39.285,26.191 73.332,26.191c38.412,0 67.747,-11.277 87.737,-33.938c11.869,-13.452 19.718,-29.89 23.572,-49.107c2.687,-13.404 3.927,-34.373 3.927,-62.637l0,-183.659l20.298,0l0,339.818Zm356.842,-109.346c-3.928,36.668 -17.9,65.589 -41.904,86.757c-24.004,21.165 -54.782,31.754 -92.321,31.754c-44.522,0 -80.316,-15.933 -107.379,-47.796c-27.062,-31.864 -40.595,-75.298 -40.595,-130.297c0,-55.435 13.536,-98.98 40.595,-130.625c27.059,-31.64 63.511,-47.469 109.344,-47.469c35.793,0 65.042,9.389 87.738,28.154c22.694,18.769 36.447,44.96 41.249,78.571l-20.953,0c-4.365,-27.062 -16.372,-48.564 -36.011,-64.492c-19.64,-15.93 -43.651,-23.9 -72.023,-23.9c-39.285,0 -70.496,14.187 -93.631,42.561c-23.133,28.371 -34.701,67.438 -34.701,117.2c0,49.761 11.57,88.831 34.701,117.203c23.131,28.368 54.346,42.557 93.631,42.557c29.682,0 54.894,-9.171 75.624,-27.5c20.731,-18.328 33.066,-42.559 36.993,-72.678l19.643,0Zm96.249,109.346l-20.298,0l0,-470.116l20.298,0l0,470.116Zm273.687,-470.116l-59.582,87.738l-20.953,0l50.416,-87.738l30.119,0Zm88.392,302.498l-265.831,0l0,5.237c0,46.263 11.567,83.373 34.594,111.308c23.025,27.938 52.489,41.905 88.501,41.905c28.155,0 52.601,-8.079 73.442,-24.227c20.839,-16.145 35.247,-38.192 43.105,-66.129l20.297,0c-7.42,33.174 -23.597,59.561 -48.562,79.227c-24.898,19.61 -54.235,29.462 -87.955,29.462c-44.195,0 -79.305,-15.854 -105.306,-47.47c-26.045,-31.67 -39.067,-75.186 -39.067,-130.623c0,-55.435 12.99,-98.98 38.958,-130.625c25.969,-31.64 61.001,-47.469 105.088,-47.469c44.087,0 78.902,14.627 104.433,43.869c25.533,29.243 38.303,70.285 38.303,123.094l0,12.441Zm-21.606,-19.642c0,-43.433 -10.917,-77.921 -32.629,-103.343c-21.712,-25.423 -49.87,-38.086 -84.573,-38.086c-36.011,0 -65.37,12.553 -88.173,37.758c-22.804,25.205 -35.576,59.802 -38.194,103.671l243.569,0Z" style="fill-rule:nonzero;"></path><path d="M327.236,354.205c0,46.271 -17.896,80.534 -53.581,102.797c-24.88,15.278 -67.548,22.917 -128.113,22.917l-143.064,0l0,-470.769l128.659,0c57.946,0 98.431,6.764 121.567,20.297c33.501,19.643 50.306,51.726 50.306,96.25c0,51.944 -26.736,87.736 -80.316,107.379c69.731,13.531 104.542,53.907 104.542,121.129Zm-45.833,-229.818c0,-36.229 -12.221,-61.548 -36.774,-75.953c-22.263,-13.093 -59.692,-19.642 -112.182,-19.642l-108.362,0l0,197.738l109.671,0c98.432,0 147.647,-34.049 147.647,-102.143Zm22.917,225.89c0,-37.976 -13.095,-65.258 -39.286,-81.844c-26.189,-16.587 -67.439,-24.881 -123.749,-24.881l-117.2,0l0,216.725l116.546,0c51.508,0 86.864,-3.929 106.071,-11.786c38.412,-15.715 57.618,-48.452 57.618,-98.214Zm377.139,-46.611c0,55.437 -13.422,98.976 -40.267,130.623c-26.845,31.647 -63.402,47.47 -109.672,47.47c-45.832,0 -82.175,-15.825 -109.017,-47.47c-26.842,-31.642 -40.267,-75.186 -40.267,-130.623c0,-55.435 13.422,-98.978 40.267,-130.625c26.845,-31.645 63.185,-47.469 109.017,-47.469c46.27,0 82.831,15.829 109.672,47.469c26.841,31.645 40.267,75.19 40.267,130.625Zm-21.607,0c0,-49.762 -11.571,-88.832 -34.811,-117.2c-23.241,-28.369 -54.454,-42.561 -93.521,-42.561c-39.067,0 -70.172,14.192 -93.194,42.561c-23.021,28.368 -34.483,67.438 -34.483,117.2c0,49.761 11.458,88.829 34.483,117.203c23.025,28.371 54.127,42.557 93.194,42.557c39.067,0 70.278,-14.186 93.521,-42.557c23.243,-28.374 34.811,-67.442 34.811,-117.203Zm345.71,168.928l-20.298,0l0,-53.037c-21.387,41.468 -59.581,62.202 -114.581,62.202c-77.697,0 -116.547,-40.595 -116.547,-121.783l0,-227.2l20.297,0l0,220.215c0,37.86 7.453,65.566 22.263,82.935c14.865,17.434 39.285,26.191 73.332,26.191c38.412,0 67.747,-11.277 87.737,-33.938c11.869,-13.452 19.718,-29.89 23.572,-49.107c2.687,-13.404 3.927,-34.373 3.927,-62.637l0,-183.659l20.298,0l0,339.818Zm356.842,-109.346c-3.928,36.668 -17.9,65.589 -41.904,86.757c-24.004,21.165 -54.782,31.754 -92.321,31.754c-44.522,0 -80.316,-15.933 -107.379,-47.796c-27.062,-31.864 -40.595,-75.298 -40.595,-130.297c0,-55.435 13.536,-98.98 40.595,-130.625c27.059,-31.64 63.511,-47.469 109.344,-47.469c35.793,0 65.042,9.389 87.738,28.154c22.694,18.769 36.447,44.96 41.249,78.571l-20.953,0c-4.365,-27.062 -16.372,-48.564 -36.011,-64.492c-19.64,-15.93 -43.651,-23.9 -72.023,-23.9c-39.285,0 -70.496,14.187 -93.631,42.561c-23.133,28.371 -34.701,67.438 -34.701,117.2c0,49.761 11.57,88.831 34.701,117.203c23.131,28.368 54.346,42.557 93.631,42.557c29.682,0 54.894,-9.171 75.624,-27.5c20.731,-18.328 33.066,-42.559 36.993,-72.678l19.643,0Zm96.249,109.346l-20.298,0l0,-470.116l20.298,0l0,470.116Zm273.687,-470.116l-59.582,87.738l-20.953,0l50.416,-87.738l30.119,0Zm88.392,302.498l-265.831,0l0,5.237c0,46.263 11.567,83.373 34.594,111.308c23.025,27.938 52.489,41.905 88.501,41.905c28.155,0 52.601,-8.079 73.442,-24.227c20.839,-16.145 35.247,-38.192 43.105,-66.129l20.297,0c-7.42,33.174 -23.597,59.561 -48.562,79.227c-24.898,19.61 -54.235,29.462 -87.955,29.462c-44.195,0 -79.305,-15.854 -105.306,-47.47c-26.045,-31.67 -39.067,-75.186 -39.067,-130.623c0,-55.435 12.99,-98.98 38.958,-130.625c25.969,-31.64 61.001,-47.469 105.088,-47.469c44.087,0 78.902,14.627 104.433,43.869c25.533,29.243 38.303,70.285 38.303,123.094l0,12.441Zm-21.606,-19.642c0,-43.433 -10.917,-77.921 -32.629,-103.343c-21.712,-25.423 -49.87,-38.086 -84.573,-38.086c-36.011,0 -65.37,12.553 -88.173,37.758c-22.804,25.205 -35.576,59.802 -38.194,103.671l243.569,0Z" style="fill:none;fill-rule:nonzero;stroke:#e5097f;stroke-width:0.22px;"></path></svg>
If I understand correctly, the problem you have is that not everything disappears (or rather becomes white) when the animation ends. In that case, I would think that the problem is in the stroke declaration in the path
.path {
stroke-dasharray: 1300;
stroke-dashoffset: 1500;
animation: dash 4s linear forwards;
}
#keyframes dash {
0% {
stroke:#e5097f;
stroke-dashoffset: 822;
fill: white;
}
50% {
stroke-dashoffset: 600;
}
70% {
fill: #db0d83;
stroke-dashoffset: 400;
}
100% {
fill: white;
stroke: white;
}
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:serif="http://www.serif.com/" width="100%" height="100%" viewBox="0 0 1824 485" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-miterlimit:22.926;"><path class="path" fill="white" stroke="#db0d83" stroke-width="4" d="M327.236,354.205c0,46.271 -17.896,80.534 -53.581,102.797c-24.88,15.278 -67.548,22.917 -128.113,22.917l-143.064,0l0,-470.769l128.659,0c57.946,0 98.431,6.764 121.567,20.297c33.501,19.643 50.306,51.726 50.306,96.25c0,51.944 -26.736,87.736 -80.316,107.379c69.731,13.531 104.542,53.907 104.542,121.129m-45.833,-229.818c0,-36.229 -12.221,-61.548 -36.774,-75.953c-22.263,-13.093 -59.692,-19.642 -112.182,-19.642l-108.362,0l0,197.738l109.671,0c98.432,0 147.647,-34.049 147.647,-102.143m22.917,225.89c0,-37.976 -13.095,-65.258 -39.286,-81.844c-26.189,-16.587 -67.439,-24.881 -123.749,-24.881l-117.2,0l0,216.725l116.546,0c51.508,0 86.864,-3.929 106.071,-11.786c38.412,-15.715 57.618,-48.452 57.618,-98.214m377.139,-46.611c0,55.437 -13.422,98.976 -40.267,130.623c-26.845,31.647 -63.402,47.47 -109.672,47.47c-45.832,0 -82.175,-15.825 -109.017,-47.47c-26.842,-31.642 -40.267,-75.186 -40.267,-130.623c0,-55.435 13.422,-98.978 40.267,-130.625c26.845,-31.645 63.185,-47.469 109.017,-47.469c46.27,0 82.831,15.829 109.672,47.469c26.841,31.645 40.267,75.19 40.267,130.625m-21.607,0c0,-49.762 -11.571,-88.832 -34.811,-117.2c-23.241,-28.369 -54.454,-42.561 -93.521,-42.561c-39.067,0 -70.172,14.192 -93.194,42.561c-23.021,28.368 -34.483,67.438 -34.483,117.2c0,49.761 11.458,88.829 34.483,117.203c23.025,28.371 54.127,42.557 93.194,42.557c39.067,0 70.278,-14.186 93.521,-42.557c23.243,-28.374 34.811,-67.442 34.811,-117.203m345.71,168.928l-20.298,0l0,-53.037c-21.387,41.468 -59.581,62.202 -114.581,62.202c-77.697,0 -116.547,-40.595 -116.547,-121.783l0,-227.2l20.297,0l0,220.215c0,37.86 7.453,65.566 22.263,82.935c14.865,17.434 39.285,26.191 73.332,26.191c38.412,0 67.747,-11.277 87.737,-33.938c11.869,-13.452 19.718,-29.89 23.572,-49.107c2.687,-13.404 3.927,-34.373 3.927,-62.637l0,-183.659l20.298,0l0,339.818Zm356.842,-109.346c-3.928,36.668 -17.9,65.589 -41.904,86.757c-24.004,21.165 -54.782,31.754 -92.321,31.754c-44.522,0 -80.316,-15.933 -107.379,-47.796c-27.062,-31.864 -40.595,-75.298 -40.595,-130.297c0,-55.435 13.536,-98.98 40.595,-130.625c27.059,-31.64 63.511,-47.469 109.344,-47.469c35.793,0 65.042,9.389 87.738,28.154c22.694,18.769 36.447,44.96 41.249,78.571l-20.953,0c-4.365,-27.062 -16.372,-48.564 -36.011,-64.492c-19.64,-15.93 -43.651,-23.9 -72.023,-23.9c-39.285,0 -70.496,14.187 -93.631,42.561c-23.133,28.371 -34.701,67.438 -34.701,117.2c0,49.761 11.57,88.831 34.701,117.203c23.131,28.368 54.346,42.557 93.631,42.557c29.682,0 54.894,-9.171 75.624,-27.5c20.731,-18.328 33.066,-42.559 36.993,-72.678l19.643,0Zm96.249,109.346l-20.298,0l0,-470.116l20.298,0l0,470.116Zm273.687,-470.116l-59.582,87.738l-20.953,0l50.416,-87.738l30.119,0Zm88.392,302.498l-265.831,0l0,5.237c0,46.263 11.567,83.373 34.594,111.308c23.025,27.938 52.489,41.905 88.501,41.905c28.155,0 52.601,-8.079 73.442,-24.227c20.839,-16.145 35.247,-38.192 43.105,-66.129l20.297,0c-7.42,33.174 -23.597,59.561 -48.562,79.227c-24.898,19.61 -54.235,29.462 -87.955,29.462c-44.195,0 -79.305,-15.854 -105.306,-47.47c-26.045,-31.67 -39.067,-75.186 -39.067,-130.623c0,-55.435 12.99,-98.98 38.958,-130.625c25.969,-31.64 61.001,-47.469 105.088,-47.469c44.087,0 78.902,14.627 104.433,43.869c25.533,29.243 38.303,70.285 38.303,123.094l0,12.441Zm-21.606,-19.642c0,-43.433 -10.917,-77.921 -32.629,-103.343c-21.712,-25.423 -49.87,-38.086 -84.573,-38.086c-36.011,0 -65.37,12.553 -88.173,37.758c-22.804,25.205 -35.576,59.802 -38.194,103.671l243.569,0Z" style="fill-rule:nonzero;"></path><path d="M327.236,354.205c0,46.271 -17.896,80.534 -53.581,102.797c-24.88,15.278 -67.548,22.917 -128.113,22.917l-143.064,0l0,-470.769l128.659,0c57.946,0 98.431,6.764 121.567,20.297c33.501,19.643 50.306,51.726 50.306,96.25c0,51.944 -26.736,87.736 -80.316,107.379c69.731,13.531 104.542,53.907 104.542,121.129Zm-45.833,-229.818c0,-36.229 -12.221,-61.548 -36.774,-75.953c-22.263,-13.093 -59.692,-19.642 -112.182,-19.642l-108.362,0l0,197.738l109.671,0c98.432,0 147.647,-34.049 147.647,-102.143Zm22.917,225.89c0,-37.976 -13.095,-65.258 -39.286,-81.844c-26.189,-16.587 -67.439,-24.881 -123.749,-24.881l-117.2,0l0,216.725l116.546,0c51.508,0 86.864,-3.929 106.071,-11.786c38.412,-15.715 57.618,-48.452 57.618,-98.214Zm377.139,-46.611c0,55.437 -13.422,98.976 -40.267,130.623c-26.845,31.647 -63.402,47.47 -109.672,47.47c-45.832,0 -82.175,-15.825 -109.017,-47.47c-26.842,-31.642 -40.267,-75.186 -40.267,-130.623c0,-55.435 13.422,-98.978 40.267,-130.625c26.845,-31.645 63.185,-47.469 109.017,-47.469c46.27,0 82.831,15.829 109.672,47.469c26.841,31.645 40.267,75.19 40.267,130.625Zm-21.607,0c0,-49.762 -11.571,-88.832 -34.811,-117.2c-23.241,-28.369 -54.454,-42.561 -93.521,-42.561c-39.067,0 -70.172,14.192 -93.194,42.561c-23.021,28.368 -34.483,67.438 -34.483,117.2c0,49.761 11.458,88.829 34.483,117.203c23.025,28.371 54.127,42.557 93.194,42.557c39.067,0 70.278,-14.186 93.521,-42.557c23.243,-28.374 34.811,-67.442 34.811,-117.203Zm345.71,168.928l-20.298,0l0,-53.037c-21.387,41.468 -59.581,62.202 -114.581,62.202c-77.697,0 -116.547,-40.595 -116.547,-121.783l0,-227.2l20.297,0l0,220.215c0,37.86 7.453,65.566 22.263,82.935c14.865,17.434 39.285,26.191 73.332,26.191c38.412,0 67.747,-11.277 87.737,-33.938c11.869,-13.452 19.718,-29.89 23.572,-49.107c2.687,-13.404 3.927,-34.373 3.927,-62.637l0,-183.659l20.298,0l0,339.818Zm356.842,-109.346c-3.928,36.668 -17.9,65.589 -41.904,86.757c-24.004,21.165 -54.782,31.754 -92.321,31.754c-44.522,0 -80.316,-15.933 -107.379,-47.796c-27.062,-31.864 -40.595,-75.298 -40.595,-130.297c0,-55.435 13.536,-98.98 40.595,-130.625c27.059,-31.64 63.511,-47.469 109.344,-47.469c35.793,0 65.042,9.389 87.738,28.154c22.694,18.769 36.447,44.96 41.249,78.571l-20.953,0c-4.365,-27.062 -16.372,-48.564 -36.011,-64.492c-19.64,-15.93 -43.651,-23.9 -72.023,-23.9c-39.285,0 -70.496,14.187 -93.631,42.561c-23.133,28.371 -34.701,67.438 -34.701,117.2c0,49.761 11.57,88.831 34.701,117.203c23.131,28.368 54.346,42.557 93.631,42.557c29.682,0 54.894,-9.171 75.624,-27.5c20.731,-18.328 33.066,-42.559 36.993,-72.678l19.643,0Zm96.249,109.346l-20.298,0l0,-470.116l20.298,0l0,470.116Zm273.687,-470.116l-59.582,87.738l-20.953,0l50.416,-87.738l30.119,0Zm88.392,302.498l-265.831,0l0,5.237c0,46.263 11.567,83.373 34.594,111.308c23.025,27.938 52.489,41.905 88.501,41.905c28.155,0 52.601,-8.079 73.442,-24.227c20.839,-16.145 35.247,-38.192 43.105,-66.129l20.297,0c-7.42,33.174 -23.597,59.561 -48.562,79.227c-24.898,19.61 -54.235,29.462 -87.955,29.462c-44.195,0 -79.305,-15.854 -105.306,-47.47c-26.045,-31.67 -39.067,-75.186 -39.067,-130.623c0,-55.435 12.99,-98.98 38.958,-130.625c25.969,-31.64 61.001,-47.469 105.088,-47.469c44.087,0 78.902,14.627 104.433,43.869c25.533,29.243 38.303,70.285 38.303,123.094l0,12.441Zm-21.606,-19.642c0,-43.433 -10.917,-77.921 -32.629,-103.343c-21.712,-25.423 -49.87,-38.086 -84.573,-38.086c-36.011,0 -65.37,12.553 -88.173,37.758c-22.804,25.205 -35.576,59.802 -38.194,103.671l243.569,0Z" style="fill:none;fill-rule:nonzero;stroke-width:0.22px;"></path></svg>

Aligning text around center in pie chart using svg circle and text

I've created a pie chart using react and svg circles. Now I want to position the text labels so that the text starts close to the middle of the circle and continue outwards, wheel of fortune style.
This is my code, rendering the svgs. In chrome dev tools I tried to apply tranform: rotate(45deg); and adjusting the number but the text keeps flyying away outside the circle.
<svg viewBox="0 0 32 32">
{elements.map((element, index) => (
<g>
<circle
key={_id}
r={16 / 1.0053}
cx={'50%'}
cy={'50%'}
style={{
strokeDasharray: `${percentage}, 100.53`,
strokeDashoffset: -offset,
stroke: segmentColor,
}}
textAnchor="middle"
></circle>
<text
textAnchor="middle"
x={'50%'}
y={'50%'}
fontFamily={'sans-serif'}
fontSize={'20px'}
fill="black"
textAnchor="start"
>
{title}
</text>
</g>
))}
</svg>
```
The issue is that rotation is about the origin, which is the top left of your image. The easiest way around this is to change the viewBox so the origin is in the center of your SVG: viewBox="-16 -16 32 32".
Then you calculate the angle based on the offset and the percentage.
I assume you have some elements like this:
const elements = [
{ percentage: 15, offset: 0, title: 'title', segmentColor: 'red' },
{ percentage: 40, offset: 15, title: 'another title', segmentColor: 'blue' },
{ percentage: 25, offset: 55, title: 'and another', segmentColor: 'green' },
{ percentage: 20, offset: 80, title: 'yet another', segmentColor: 'black' },
];
So something like this would work:
<svg viewBox="-16 -16 32 32">
{elements.map((element, index) => {
const angle = (element.offset + element.percentage / 2) * 360 / 100;
return <g key={index}>
<circle
r={15.5}
style={{
fill: 'none',
strokeDasharray: `${element.percentage}, 100.53`,
strokeDashoffset: -element.offset,
stroke: element.segmentColor,
}}
textAnchor="middle"
></circle>
<text
x="10%"
transform={`rotate(${angle})`}
fontFamily={'sans-serif'}
fontSize={'2px'}
fill="black"
textAnchor="start"
alignmentBaseline="middle"
>
{element.title}
</text>
</g>
})}
</svg>
Now the x value on the text determined how from the center the text starts.

Leaflet : Easier to select Circle Markers

I work with a Leaflet map that displays multiple circle markers when page is loaded. But users have found it a bit difficult to click/touch on the circle markers on mobiles and Ipads. Is there a way to increase the select "area" for these circle markers?
This runnable code demonstrates the use of SVG to make the marker's icon that can be your solution:
var clatlng = [15, 100];
var zoom = 8;
var mymap = L.map("mapid").setView(clatlng, zoom);
//This map tiles is simple and no hassles.
L.tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: "Map data © OpenStreetMap contributors"
}).addTo(mymap);
const svg_O =
'<svg width="100" height="100" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="50" stroke="none" opacity="0.35" fill="yellow"/><circle cx="50" cy="50" r="15" stroke="blue" fill="green"/></svg>';
const svgpin_O = encodeURI("data:image/svg+xml;utf-8," + svg_O);
const icon_O = L.icon({
iconUrl: svgpin_O,
iconSize: [100, 100],
iconAnchor: [50, 50]
});
var marker1 = L.marker(clatlng, {
icon: icon_O,
draggable: true,
autoPan: true
}).addTo(mymap);
const svg_pin =
'<svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z" fill="firebrick"></path></svg>';
const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin);
const svgpin_Icon = L.icon({
iconUrl: svgpin_Url,
iconSize: [24, 24],
iconAnchor: [12, 24],
popupAnchor: [0, -22]
});
var marker2 = L.marker(clatlng, {
icon: svgpin_Icon,
draggable: true,
autoPan: true
}).addTo(mymap);
#mapid {
height: 200px;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.5.1/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin="" />
<script src="https://unpkg.com/leaflet#1.5.1/dist/leaflet.js"
integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="
crossorigin=""></script>
<div id="mapid"></div>

CSS Sprites horrible slow using Edge or Internet Explorer 11

We have a Singe Page Application using AngularJS 1.5 and it works smoothly using Chrome but unfortunately we also support IE 11+ and probably Edge and using these browsers, the performance is close to horrible (more than two seconds delay). It seems that it has something to do with the way we are using css sprites because if I remove the background-image property everything works smoothly again. My experience on css is not very high thus I hope that somebody with a deeper insight has a hint about performance optimizations. The sprite svg file (325KB 2350px x 2340px) looks like this
<?xml version="1.0" encoding="utf-8"?>
<!-- SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 2350 2340" enable-background="new 0 0 2350 2340" xml:space="preserve">
<symbol id="ic_x5F_website_x5F_blk" viewBox="0 -50 50 50">
...
<use xlink:href="#ic_x5F_website_x5F_blk" width="50" height="50" id="XMLID_496_" x="0" y="-50" transform="matrix(1 0 0 -1 284.9999 155)" overflow="visible"/>
...
</svg>
And the relevant css/ less styles are
.ico() {
&:extend(.ic-mixin);
}
.ic {
.ic-mixin;
}
.ic-mixin {
background-image: url('../icons/spritesheet.svg');
background-size: #spritesheet-width #spritesheet-height;
display: inline-block;
width: 50px;
height: 50px;
}
.icon(#column, #row, #color: blk, #offset: 0px, #offsetY: #offset) {
.createIcon(#column, #row, #color, #offset, #offsetY);
}
.createIcon(#column, #row, #color, #offsetX: 0, #offsetY: #offsetX) {
#positionX: #initIconGapX + #iconColumnWidth * (#column - 1);
#positionY: #initIconGapY + #iconOuterSize * (#row - 1);
& when (#color = wht) {
background-position: -(#positionX + #iconOuterSize + #offsetX) -(#positionY + #offsetY);
}
& when (#color = blu) {
background-position: -(#positionX + #iconOuterSize * 2 + #offsetX) -(#positionY + #offsetY);
}
}
.icon-virtual {
&:after {
.ico();
.icon(4, 23, wht, 15px);
content: ' ';
width: 20px;
height: 20px;
background-color: #green;
position: absolute;
top: 2px;
right: 2px;
}
}
Why is Chrome so much faster? Is this a cache problem? Is IE trying to fetch the huge file over and over again? Could there be a problem with the svg file itself? Or is the css to complicated? Are we missing some important properties? Is IE too slow finding the correct background position?
Thanks a lot for any hint!
UPDATE
Exchanging the big file with a different much smaller svg does not help in improving the performance.

Resources