Since yesterday I've been trying to find a solution for my SVG Path..
It’s not displaying on Safari (Desktop & Mobile).
Before creating this post, I checked few topics where someone was facing the same problem, but by applying the recommended solutions in theses topics, it didn’t change anything.
I also added the xlink: in front of the :href which apparently should solve the problem, but there is no change..
I would appreciate your help 🙏
<svg width="auto" height="auto" viewBox="0 0 1770 1229.5">
<path id="curve" fill="transparent" d="M20,293.2 C20,770.9 407.3,1158.2 885,1158.2 C1362.7,1158.2 1750,770.9 1750,293.2 V71.2 H20Z"></path>
<text width="100%" style="scale(-2,-2) translate(-100,-100);">
<textPath
startOffset=79.4751%
opacity="100%"
style="
font-size: 40px;
fill-opacity: 0;
stroke: #030303;
stroke-width: 1px;
stroke-opacity: 1;"
xlink:href="#curve">Réserver un appel Réserver un appel Réserver un appel Réserver un appel
Réserver un appel
Réserver un appel
Réserver un appel
Réserver un appel
Réserver un appel
<animate
attributeName="startOffset" from="0%" to="-13%"
dur="12s" repeatCount="indefinite" />
</textPath>
</text>
</svg>
Related
So I have been asked to make a section number that is constructed as a non-filled circle with a 2px border containing a number. The range of the numbers is 1 to 999.
As you can see from the example below, it looks pleasing at one & two digit section numbers, but when we hit three digits the number is clipped.
My thinking is that there needs to be a process where the text is drawn, measured, then scaled to fit into the target space inside the circle, where the target space is effectively a square rect 60% of the diameter of the circle.
However, no JS is allowed in the solution.
I thought it might be possible using SVG and its scaling capabilities via the 'preserveAspectRatio' parameter. However the image above is a screen grab of my SVG results. Working snippet below.
My intention with the code was to have the inner SVG containing the text resize proportionally so that it would fit the width of the parent, with the height set to auto so that it would change in proportion.
Can anyone tell me where I am going wrong?
PS. I am using Chrome on PC to test.
Note: In the following snippet the output looks like the image, so 8, then 88, then 888. The markup is the same for each case - only the text content changes.
body {
padding: 20px;
overflow: hidden;
background-color: #f0f0f0;
}
.counterDiv {
width: 44px;
max-width: 44px;
min-width: 44px;
height: 44px;
max-height: 44px;
min-height: 44px;
margin: 0;
padding: 0;
}
svg {
width: 100%;
height: 100%;
}
text {
font: normal normal 18pt Helvetica, Arial, Verdana;
}
<div class='counterDiv' style='position: relative;'>
<svg viewbox="0 0 44 44">
<g>
<circle cx="22" cy="22" r="20" stroke="#cd1041" stroke-width="2px" fill-opacity="0" />
<svg viewBox="0 0 100 auto" x="20%" width="60%" preserveAspectRatio="xMidYMid meet">
<text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle" fill="#cd1041" dy=".1em">8</text>
</svg>
</g>
</svg>
</div>
<div class='counterDiv' style='position: relative;'>
<svg viewbox="0 0 44 44">
<g>
<circle cx="22" cy="22" r="20" stroke="#cd1041" stroke-width="2px" fill-opacity="0" />
<svg viewBox="0 0 100 auto" x="20%" width="60%" preserveAspectRatio="xMidYMid meet">
<text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle" fill="#cd1041" dy=".1em">88</text>
</svg>
</g>
</svg>
</div>
<div class='counterDiv' style='position: relative;'>
<svg viewbox="0 0 44 44">
<g>
<circle cx="22" cy="22" r="20" stroke="#cd1041" stroke-width="2px" fill-opacity="0" />
<svg viewBox="0 0 100 auto" x="20%" width="60%" preserveAspectRatio="xMidYMid meet">
<text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle" fill="#cd1041" dy=".1em">888</text>
</svg>
</g>
</svg>
</div>
A posible solution would be using textLength and lengthAdjust. The lengthAdjust attribute controls how the text is stretched into the length defined by the textLength attribute. One inconvinient would be that the 1 digit numbers would be stretched.
An alternative solution would be using a smaller font size.
Also you may want to use javascript to target only the 3 digit text elements.
body {
padding: 20px;
overflow: hidden;
background-color: #f0f0f0;
}
.counterDiv {
width: 44px;
max-width: 44px;
min-width: 44px;
height: 44px;
max-height: 44px;
min-height: 44px;
margin: 0;
padding: 0;
}
svg {
width: 100%;
height: 100%;
}
text {
font: normal normal 18pt Helvetica, Arial, Verdana;
}
<div class='counterDiv' style='position: relative;'>
<svg viewbox="0 0 44 44">
<g>
<circle cx="22" cy="22" r="20" stroke="#cd1041" stroke-width="2px" fill-opacity="0" />
<svg viewBox="0 0 100 auto" x="20%" width="60%" preserveAspectRatio="xMidYMid meet">
<text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle" fill="#cd1041" dy=".1em" textLength="25" lengthAdjust="spacingAndGlyphs">8</text>
</svg>
</g>
</svg>
</div>
<div class='counterDiv' style='position: relative;'>
<svg viewbox="0 0 44 44">
<g>
<circle cx="22" cy="22" r="20" stroke="#cd1041" stroke-width="2px" fill-opacity="0" />
<svg viewBox="0 0 100 auto" x="20%" width="60%" preserveAspectRatio="xMidYMid meet">
<text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle" fill="#cd1041" dy=".1em" textLength="25" lengthAdjust="spacingAndGlyphs">88</text>
</svg>
</g>
</svg>
</div>
<div class='counterDiv' style='position: relative;'>
<svg viewbox="0 0 44 44">
<g>
<circle cx="22" cy="22" r="20" stroke="#cd1041" stroke-width="2px" fill-opacity="0" />
<svg viewBox="0 0 100 auto" x="20%" width="60%" preserveAspectRatio="xMidYMid meet">
<text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle" fill="#cd1041" dy=".1em" textLength="25" lengthAdjust="spacingAndGlyphs">888</text>
</svg>
</g>
</svg>
</div>
Not for OP,
but for all those SVG loving people who have an inner-guide (or sensible boss)
that tells them: "JavaScript is fine, when applied with common sense"
customElements.define("svg-counter", class extends HTMLElement {
connectedCallback() {
this.render();
}
render(
val = this.getAttribute("value") || "888",
color = "green",
circlestrokewidth = 4,
circlestroke = "red",
circlefill = "none"
){
let id = "P" + (new Date() / 1); // uniqueid
let singleDigit = val.length == 1;
this.innerHTML = `
<svg viewbox="0 0 100 100">
<circle cx="50" cy="50" r="${50-circlestrokewidth}" stroke="${circlestroke}"
fill="${circlefill}" stroke-width="${circlestrokewidth}"/>
<path id="${id}" pathLength="100" d="M0 60H100" stroke="none"/>
<text transform="scale(${singleDigit?1:.7})" transform-origin="50 50">
<textPath href="#${id}" method="stretch"
textlength="100" lengthAdjust="${singleDigit?"":"spacingAndGlyphs"}"
startoffset="50" text-anchor="middle" dominant-baseline="middle"
font-family="Helvetica"
fill="${color}" font-size="${100}px">${val}</textPath>
</text>
</svg>`;
}
});
svg {
width: 20%;
}
<svg-counter value="8"></svg-counter>
<svg-counter value="88"></svg-counter>
<svg-counter value="888"></svg-counter>
<svg-counter value="8888"></svg-counter>
Alas FireFox has some issues, slight tweaked version to make it work in FireFox:
Alas I have a boss who says "We don't care about FireFox customers"
customElements.define("svg-counter", class extends HTMLElement {
connectedCallback() {
this.render();
}
render(
val = this.getAttribute("value") || "888",
color = "green",
circlestrokewidth = 4,
circlestroke = "red",
circlefill = "none"
){
let id = "P" + (new Date() / 1) + val.length; // uniqueid
let singleDigit = val.length == 1;
this.innerHTML = `
<svg viewbox="0 0 100 100">
<circle cx="50" cy="50" r="${50-circlestrokewidth}" stroke="${circlestroke}"
fill="${circlefill}" stroke-width="${circlestrokewidth}"/>
<path id="${id}" pathLength="100" d="M0 55H100" stroke="blue"/>
<text transform="scale(${[0,1.7,1.2,.9,.7][val.length]})" transform-origin="50 50">
<textPath href="#${id}" method="stretch"
textlength="100" lengthAdjust="${singleDigit?"":"spacingAndGlyphs"}"
startoffset="50" text-anchor="middle" dominant-baseline="middle"
font-family="Helvetica"
fill="${color}" font-size="50px">${val}</textPath>
</text>
</svg>`;
}
});
svg {
width: 20%;
}
<svg-counter value="8"></svg-counter>
<svg-counter value="88"></svg-counter>
<svg-counter value="888"></svg-counter>
<svg-counter value="8888"></svg-counter>
enter image description here
I wanna make circle chart like this.
below is my code.
If I invert up and down in that code, i get the shape you want.
But what I really want is a graph with the yellow graph pointing further to the right. How do I adjust the spacing?
Please help me
<svg width="4.5rem" height="4.5rem" viewBox="0 0 40 40">
<circle class="pieSegment segment1" cx="20" cy="20" r="15.915494309189533" fill="transparent" stroke="#1a0d1c" stroke-dashoffset="11" stroke-dasharray="74" stroke-width="5"></circle>
<circle class="pieSegment segment3" cx="20" cy="20" r="15.915494309189533" fill="transparent" stroke="#e9ad61" stroke-dashoffset="14" stroke-dasharray="25 75" stroke-width="5"></circle>
</svg>
Edit (missed the previous answer by #jeremy-denis also using pathLength)
Here is another approach also using pathLength value:
See also MDN Docs: pathLength
example horse shoe gauge
let progress = document.querySelector("#progress");
let svgGauges = document.querySelectorAll(".svgGauge");
let gauges = document.querySelectorAll(".gaugePercent");
let percentText = document.querySelector(".percentText");
progress.addEventListener("change", function(e) {
let percent = e.target.value;
if (svgGauges.length) {
svgGauges.forEach(function(item, i) {
let currentGauge = svgGauges[i];
let gauge = currentGauge.querySelector(".gaugePercent");
let dashGap = gauge.getAttribute("stroke-dasharray").split(" ")[1];
// console.log(gauge);
gauge.setAttribute("stroke-dasharray", percent + " " + dashGap);
gauge.setAttribute("style", "animation-fill-mode: none");
percentText.textContent = percent;
});
}
});
.gaugeWrap {
display: inline-block;
width: 10rem;
}
.layout {
width: 50%;
margin: 0 auto;
display: flex;
justify-content: center;
}
.txt-cnt {
text-align: center;
}
.circle {
transition: 0.3s;
stroke-width: 15;
}
.linecap-round .circle {
stroke-linecap: round;
shape-rendering: geometricPrecision;
}
.linecap-round .circle[stroke-dasharray^="0 "] {
stroke-linecap: unset;
}
<p class="txt-cnt">Progress (<span class="percentText">50</span> %) <input id="progress" style="width:100px" type="range" min="0" max="100" step="10" value="50" />
</p>
<div class="layout">
<div class="gaugeWrap">
<p>horse shoe gauge 270°</p>
<svg class="svgGauge linecap-round" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" transform="scale(-1 1) rotate(-225) ">
<circle class="circle gaugeBG" id="gaugeBG" cx="50%" cy="50%" r="45" pathLength="133.333" fill="none" stroke="#000" stroke-dasharray="100 100" />
<circle class="circle gaugePercent " id="gauge" cx="50%" cy="50%" r="45" pathLength="133.333" fill="none" stroke-dasharray="50 133.333" stroke="#e9ad61" />
</svg>
</div>
<div class="gaugeWrap">
<p>Semi-circle gauge 180°</p>
<svg class="svgGauge linecap-round" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" transform="scale(-1 1) rotate(-180)">
<circle class="circle gaugeBG " id="gaugeBG" cx="50%" cy="50%" r="45" pathLength="200" fill="none" stroke="#000" stroke-dasharray="100 200" />
<circle class="circle gaugePercent" id="gauge" cx="50%" cy="50%" r="45" pathLength="200" fill="none" stroke-dasharray="50 200" stroke="#e9ad61" />
</svg>
</div>
<div class="gaugeWrap">
<p>Full-circle gauge 360°</p>
<svg class="svgGauge" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" transform="rotate(-90)">
<circle class="circle gaugeBG" id="gaugeBG" cx="50%" cy="50%" r="45" pathLength="100" fill="none" stroke="#000" stroke-dasharray="100 100" />
<circle class="circle gaugePercent" id="gauge" cx="50%" cy="50%" r="45" pathLength="100" fill="none" stroke-linecap="butt" stroke-dasharray="50 100" stroke="#e9ad61" />
</svg>
</div>
</div>
Your example has approximately a 270° range (3/4 of 360°).
By setting pathLengthto 133 (360/270*100) we change the computation of the dash lengths.
Since we don't use the complete circumference of the circle (see the full circle example with pathLength=100) we increase the pathlength to make this 3/4 segment to have a length of 100 units.
We can set the first stroke-dasharray value e.g. to 50 (display 50% progress).
The 2nd value 133 ensures the dash gap is large enough to fill the rest of the circle gauge.
To make the horse shoe gauge stand upright we need to calculate a rotation like this:
(360 + 270)/2 - 90 = -225
So we can rotate the parent svg by setting the transform attribute to
transform="scale(-1 1) rotate(-225)"
Gauge generator pen
an idea can be to use pathLength="100" to your circle
that allow you to give a percent in the attribute stroke-dashoffset with 100% - {percent of circle to fill}
then we can imagine rotate the circle to the correct shape
#mySvg {
transform: rotate(-125deg) scaleX(-1);
}
to round the border of your line you can use
stroke-linecap: round;
#mySvg {
transform: rotate(-125deg) scaleX(-1);
}
#mySvg circle {
stroke-linecap: round;
shape-rendering: geometricPrecision;
}
<svg id="mySvg" width="4.5rem" height="4.5rem" viewBox="0 0 40 40">
<circle class="pieSegment segment1" cx="20" cy="20" r="15.915494309189533" fill="transparent" stroke="#1a0d1c" stroke-dashoffset="20" stroke-dasharray="100" stroke-width="5" pathLength="100"></circle>
<circle class="pieSegment segment3" cx="20" cy="20" r="15.915494309189533" fill="transparent" stroke="#e9ad61" stroke-dashoffset="80" stroke-dasharray="100" stroke-width="5" pathLength="100"></circle>
</svg>
I've googled but got this:
https://codepen.io/felipe_matos/pen/pMrXpK
html, body, svg {
height: 200px;
}
text {
font: bold 8px Verdana, Helvetica, Arial, sans-serif;
}
.flex {
display: flex;
}
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/dominant-baseline -->
<div class="flex">
<div>
<h2>Dominant-baseline</h2>
<svg viewBox="0 0 200 120" xmlns="http://www.w3.org/2000/svg">
<path d="M20,15 L180,15 M20,30 L180,30 M20,45 L180,45 M20,60 L180,60 M20,75 L180,75 M20,90 L180,90" stroke="grey" />
<text dominant-baseline="ideographic" x="30" y="30">Ideographic</text>
<text dominant-baseline="baseline" x="30" y="45">Baseline</text>
<text dominant-baseline="middle" x="30" y="60">Middle</text>
<text dominant-baseline="hanging" x="30" y="75">Hanging</text>
<text dominant-baseline="text-before-edge" x="30" y="90">text-before-edge</text>
<text dominant-baseline="text-after-edge" x="30" y="15">text-after-edge</text>
</svg>
</div>
<div>
<h2>Alignment-baseline</h2>
<svg viewBox="0 0 200 120" xmlns="http://www.w3.org/2000/svg">
<path d="M20,15 L180,15 M20,30 L180,30 M20,45 L180,45 M20,60 L180,60 M20,75 L180,75 M20,90 L180,90" stroke="grey" />
<text alignment-baseline="ideographic" x="30" y="30">Ideographic</text>
<text alignment-baseline="baseline" x="30" y="45">Baseline</text>
<text alignment-baseline="middle" x="30" y="60">Middle</text>
<text alignment-baseline="hanging" x="30" y="75">Hanging</text>
<text alignment-baseline="text-before-edge" x="30" y="90">text-before-edge</text>
<text alignment-baseline="text-after-edge" x="30" y="15">text-after-edge</text>
</svg>
</div>
</div>
it seems the two properties are exactly the same. Then why do we have two different types?
The distinction is that dominant-baseline is the baseline used to calculate the baseline table. Specifically the distinction will be found when you mix different fonts, for example, if you are using a roman font like English and quote something in an Indic Script, "অসমীয়া লিপিবাংলা লিপি". The baseline in the script is visible there, but it's different than the English baseline. Though in practice it tends to do the same thing probably because the distinction is pretty minor and involves building an adjustment table first vs. adjusting for the baseline.
I tried to draw a shape using html/svg. It is a volume control, see below
<svg height="20" width="90" style="background-color: #ccc;">
<g>
<rect x="10" y="0" width="80" height="20" style="stroke: #000; stroke-width: 1; fill: #fff;"></rect>
<!-- Example two of four -->
<polygon points="10,20 50,10 50,20" style="fill: rgba(128,128,128,128)"></polygon>
<line x1="30" y1="0" x2="30" y2="20" style="stroke: #000; stroke-width: 1;"></line>
<line x1="50" y1="0" x2="50" y2="20" style="stroke: #000; stroke-width: 1;"></line>
<line x1="70" y1="0" x2="70" y2="20" style="stroke: #000; stroke-width: 1;"></line>
</g>
</svg>
All browsers draw the horzontal lines double width, except the last one. I even added "stroke-width: 1", but that doesn't work.
I guess anti-aliasing? How can I fix this?
There is a difference in how svg of the same code is displayed when checked in chrome and safari.
<svg width="600" height="600" xmlns="http://www.w3.org/2000/svg" class="svg4"
style="border: 1px solid rgb(0, 0, 0); overflow: hidden; position: relative; float: left;">
<rect width="100" height="100" x="300" y="300" fill="red"
style="transform-origin:50px 50px;transform: rotate(-40deg);"></rect>
<text x="300" y="300" text-anchor="middle" fill="#000000" font-size="40px" font-style="normal"
style="transform-origin: 50px 50px;transform: rotate(-10deg);"
>
<tspan dy="0">jon doe 10</tspan>
</text>
<text x="300" y="300" text-anchor="middle" fill="#000000" font-size="40px" font-style="normal"
style="transform-origin: 50px 50px;transform: rotate(-20deg);"
>
<tspan dy="0">jon doe 20</tspan>
</text>
<text x="300" y="300" text-anchor="middle" fill="#000000" font-size="40px" font-style="normal"
style="transform-origin: 50px 50px;transform: rotate(-30deg);"
>
<tspan dy="0">jon doe 30</tspan>
</text>
<text x="300" y="300" text-anchor="middle" fill="#000000" font-size="40px" font-style="normal"
style="transform-origin: 50px 50px;transform: rotate(-40deg);"
>
<tspan dy="0">jon doe 40</tspan>
</text>
<text x="300" y="300" text-anchor="middle" fill="#000000" font-size="40px" font-style="normal"
style="transform-origin: 10px 10px;transform: rotate(-10deg);"
>
<tspan dy="0">jon doe 10</tspan>
</text>
<text x="300" y="300" text-anchor="middle" fill="#000000" font-size="40px" font-style="normal"
style="transform-origin: 10px 10px;transform: rotate(-20deg);"
>
<tspan dy="0">jon doe 20</tspan>
</text>
<text x="300" y="300" text-anchor="middle" fill="#000000" font-size="40px" font-style="normal"
style="transform-origin: 10px 10px;transform: rotate(-30deg);"
>
<tspan dy="0">jon doe 30</tspan>
</text>
<text x="300" y="300" text-anchor="middle" fill="#000000" font-size="40px" font-style="normal"
style="transform-origin: 10px 10px;transform: rotate(-40deg);"
>
<tspan dy="0">jon doe 40</tspan>
</text>
</svg>
When checked in chrome, the transform-orgin value is applied and rotated.
chrome
When checked in Safari, the transform-orgin value is not applied at all and is displayed the same.
safari
However, this phenomenon is only seen in the text of the svg element, and elements such as rect are normally displayed.
Is there any way to ensure that the transform-orgin is applied normally in Safari?