Text around the SVG - html

I'm absolutely beginner with SVG, and I need to put text around this moon...
I tried to make text around a path and could not get the right sizes and match it with the moon.
<svg viewBox="-6 -6 30 40">
<defs>
<mask id="earth">
<rect fill="white" x="-5" y="-5" width="10" height="10"></rect>
<circle fill="black" cx="3.141592654" r="5" />
</mask>
</defs>
<circle r="5" fill="currentColor" mask="url(#earth)" transform="rotate(-25)"/>
</svg>

Draw the moon with a path. (and edit in: https://yqnn.github.io/svg-path-editor/)
The path is drawn counter-clockwise, if you want to draw the innermoon text like your design, it is easier to add a 2nd path drawn clockwise.
Setting pathLength helps in positioning with startoffset
Look up all attributes you don't know in the docs.
<svg viewBox="0 0 80 60">
<rect width="100%" height="100%" fill="skyblue"/>
<path id="Moon" pathLength="10" d="m16 2a12 12 0 1018 13 1 1 0 01-18-13z"/>
<text>
<textPath href="#Moon"
startoffset="1" text-anchor="left" dominant-baseline="hanging"
fill="blue" font-size="3px">Outside moon</textPath>
</text>
<text>
<textPath href="#Moon"
startoffset="6" text-anchor="right" dominant-baseline="hanging"
fill="rebeccapurple" font-size="4">Inside moon</textPath>
</text>
</svg>

Related

SVG fill of nested pattern

I'm currently working on nested pattern in svg where the first pattern is used to fill the second shape which is used to fill the third.
The following code snippet run perfectly on a website like w3schools, but once converted to a file and to use on a browser it only shows an empty box, with no error code.
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 100 100">
<pattern id="a" viewBox="0 0 12 12" width="135%" height="150%">
<g stroke="black" stroke-width="1">
<circle cx="6" cy="6" r="4" fill="red"/>
<circle cx="6" cy="6" r="2" fill="yellow"/>
</g>
<animate attributeName="x" from="0" to="1.35" dur="5s" repeatCount="indefinite"/>
</pattern>
<pattern id="b" viewBox="0 0 50 50" width="100%" height="100%">
<Polygon points="0.05,0 0.05,50 50.05,50" fill="url(#a)"/>
<Polygon points="0.05,0 0.05,50 50.05,50" fill="url(#a)" transform="scale(-1,1) rotate(90 50 50) translate(0,100)"/>
</pattern>
<polygon points="0,0 0,50 50,50 50,0" fill="url(#b)"/>
<polygon points="0,0 0,50 50,50 50,0" fill="url(#b)" transform="rotate(90 50 50)"/>
<polygon points="0,0 0,50 50,50 50,0" fill="url(#b)" transform="rotate(180 50 50)"/>
<polygon points="0,0 0,50 50,50 50,0" fill="url(#b)" transform="rotate(270 50 50)"/>
<rect width="100" height="100" fill="transparent" stroke="black" stroke-width="3"/>
</svg>
Here is the following output:
I tried to use diverse way to use the pattern "a" like using <defs> or <use xlinks:href>, the code still run but it doesn't give the expected output or any errors. I tried using diverse browser (Chrome, Opera, Edge, Firefox), but they all give the same empty box. When I copy and paste the code while inspecting the element, to the w3school website, it all works fine.

Failure to animate a g element in SVG by animating its "top" property

So, if you check the fiddle, (https://jsfiddle.net/xXnikosXx/6jx2rpsf/3/)
I have an SVG image, with a couple of objects, and a mask. It's masking the text (colorful lines) which are hidden below it, and the plan was to animate their top position to make the text from below appear and the text from the top to disappear, to make a text scrolling effect. The text without the mask is shown in the image below, in case it helps.
here
I thought the text would appear when the animation occurs, but it doesnt (if you remove the mask, the text is shown and animated properly but they layers are wrong so the text appears above everything else)
I cant figure out a way to make the text animate properly using the mask, is there something i can use instead of the mask to get the same result, but without the text issue?
relevant code:
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="354" y="174" width="733" height="344">
<rect id="laptop-screen-front" x="354" y="174" width="733" height="344" fill="white" />
</mask>
<g mask="url(#mask0)">
<!-- some of the lines that represent text: -->
<g id="text-lines">
<line id="Line 3" x1="408" y1="194.5" x2="433" y2="194.5" stroke="#E06C60" stroke-width="5" />
<line id="Line 23" x1="438" y1="194.5" x2="463" y2="194.5" stroke="#D18C4C" stroke-width="5" />
<line id="Line 35" x1="469" y1="194.5" x2="542" y2="194.5" stroke="#7BC379" stroke-width="5" />
<line id="Line 36" x1="469" y1="209.5" x2="525" y2="209.5" stroke="#7BC379" stroke-width="5" />
</g>
Your code doesn't animate the mask. It attempts to animate the position of the text-lines g element. But SVG is not HTML. It is its own thing and doesn't support many common CSS properties: e.g. most relevant for you - there is no "top" property in SVG. The easiest way to do what you want is to get rid of all the CSS animations, and add a transform and a SMIL animation directly into the following part of the SVG.
<g mask="url(#mask0)">
<g id="text-lines" transform="translate(0 0)">
<animateTransform attributeName="transform" type="translate" values="0 0; 0 -150; 0 0" dur="11s" repeatCount="indefinite"/>
<line id="Line 3" x1="408" .... etc.
BTW - one of the reasons to use transforms for animation is that browsers can often optimize things by doing the animation on the GPU - so it's better than viewBox or top animations.
2 methods:
with SMIL
svg#parent {
background-color: rgba(100, 148, 237, 0.3);
}
<svg id="parent" width="200" height="100" viewBox="0 0 200 100">
<rect x="10" y="10" width="180" height="20" fill="white" />
<svg x="10" y="10" width="180" height="20" viewBox="0 0 180 20" >
<text x="20" y="15" > hello </text>
<text x="20" y="35" > world </text>
<animate attributeName="viewBox"
values="0 0 180 20; 0 20 180 20; 0 0 180 20"
begin="1s" dur="2s" repeatCount="indefinite" />
</svg>
</svg>
with javascript - requestAnimationFrame
(function()
{
const
svgInside = document.querySelector('#insideSVG')
, moving = .7 // change the value to slow down or speed up
;
let
stepVal = moving
, stepPos = 0
;
requestAnimationFrame(step)
;
function step()
{
stepPos += stepVal
if (stepPos<=0) stepVal = moving
if (stepPos>=20) stepVal = -moving
svgInside.setAttribute('viewBox',`0 ${stepPos} 180 20`)
requestAnimationFrame(step)
}
}
)()
svg#parent {
background-color: rgba(100, 148, 237, 0.3);
}
<svg id="parent" width="200" height="100" viewBox="0 0 200 100">
<rect x="10" y="10" width="180" height="20" fill="white" />
<svg x="10" y="10" width="180" height="20" viewBox="0 0 180 20"
id="insideSVG" >
<text x="20" y="15" > hello </text>
<text x="20" y="35" > world </text>
</svg>
</svg>
For your SVG the values should be around:
<svg x="354" y="174" width="733" height="344" viewBox="354 174 733 344" >
<line x1="419" y1="187.5" ..... />
/.../
<animate attributeName="viewBox"
values="354 174 733 344; 354 520 733 344; 354 174 733 344"
begin="1s" dur="8s" repeatCount="indefinite" />
</svg>
how does <animate> work ?
– Paul LeBeau
the mdn documentation is quite complete: :
SVG animation with SMIL
<animate>
do not hesitate to consult the links to additional information pages
but if you want a general vision of the animation possibilities of your SVGs, the Wikipedia page is ideal
There is even a part showing the use of the requestAnimationFrame(), which I am using here.
PS:The Whitesmith style has been around since 1978, and no, I don't use it for aesthetic reasons but because it checks that the right pairs of braces frame the right pieces of code. For the same reasons, I put the commas in front of data lines (they are invisible [and often forgotten] at the end of the line), as well as the column alignment (both in a similar way used in Haskell)
No, the K&R is not a foolproof style, nor is it more legitimate than any other.

How to draw S- Curve in SVG?

Please help me to draw something like this using SVG.
<svg class="slide__overlay" viewbox="0 0 100 100" preserveAspectRatio="none"><path class="slide__overlay-path" d="M0,0 L100,0 C25,50 50,75 0,100z" /></svg>
I got this code from an old question. But i need to rotate this.
Thanks
so the easiest way to do this is to just rotate your shape:
transform="(-90, 50, 50)"
<svg viewbox="0 0 100 100" width="200" height="200">
<path transform="rotate(-90, 50, 50)" d="M0,0 L100,0 C25,50 50,75 0,100z"/>
</svg>
but let me explain to you how the path commands work... in the end, we will have a much nicer solution to your rotation problem...
so let's look at your path commands.
"M0,0 L100,0 C25,50 50,75 0,100z"
M0,0 means move to the coordinate 0,0 which is the top left corner of your image.
L100,0 is the line to command which draws a line from our current point (0,0) to point 100,0. 100 to the right and 0 down is the right to corner.
next up is the curve to command C25,50 50,75 0,100. the last two numbers are the coordinates your path will end at. 0,100 is your bottom left corner. and then you have the two control points. to understand these a bit better I have added a circle at each of these coordinates to your original drawing:
<svg viewbox="0 0 100 100" width="200" height="200">
<path d="M0,0 L100,0 C25,50 50,75 0,100z" opacity="0.5"/>
<g>
<line x1="100" y1="0" x2="25" y2="50" stroke="green" stroke-width="0.5"/>
<circle cx="25" cy="50" r="2" fill="green"/>
</g>
<g>
<line x1="0" y1="100" x2="50" y2="75" stroke="blue" stroke-width="0.5"/>
<circle cx="50" cy="75" r="2" fill="blue"/>
</g>
</svg>
as you can see, the control points determine the angle of the curve at the endpoints as well as the slope of the curve itself.
so to rotate your curve we start with the endpoints again:
what was your top left corner (0,0) will end up on the bottom left (0,100).
M0,100
then the line to command will end up in the top left corner L0,0
and the curve to command will end up in the bottom right corner (100,100)
Cx1,y1 x2,y2 100,100
but where to draw your control points?
your first control point (25,50) will end up 25 from the bottom and 50 from the left so at 50,75
your second control point will have to end up 25 from the right and 50 from the bottom. so at 75,50
so the curve to command looks like this: C50,75 75,50 100,100
to wrap it all up, here is your rotated path:
<svg viewbox="0 0 100 100" width="200" height="200">
<path d="M0,100 L0,0 C50,75 75,50 100,100z" opacity="0.5" fill="red" />
<g>
<line x1="0" y1="0" x2="50" y2="75" stroke="red" stroke-width="0.5"/>
<circle cx="50" cy="75" r="2" fill="red"/>
</g>
<g>
<line x1="100" y1="100" x2="75" y2="50" stroke="red" stroke-width="0.5"/>
<circle cx="75" cy="50" r="2" fill="red"/>
</g>
</svg>
In order to exactly repeat the shape of the curve as in the figure, you need to load the image into a vector editor.
And draw nodal points along the contour
Save file as SVG.
And copy only path to another file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100vw" height="100vh" viewBox="0 0 688 535" preserveAspectRatio="xMinYMin meet">
<path d="m4.8 11.6c0 0 34.3 55.4 56.1 79.3 25.6 28.2 55.7 52.3 86.6 74.5 36.1 26 75.7 46.7 114.6 68.1 26.5 14.5 54 27.3 81 40.9 27 13.6 54.2 26.8 81 40.9 23.2 12.2 46.6 23.9 68.9 37.7 27.6 17 54.9 35 80.1 55.3 25.6 20.6 50.3 42.7 72.1 67.3 13.2 14.9 35.3 48.1 35.3 48.1H4.8Z" style="fill:#5B7E95;stroke:none"/>
</svg>
You can use any of the online PNG to SVG convertor tools available. Also there are many opensource sites available for free hand drawing.
Examples
https://shapeshifter.design/
https://editor.method.ac/
For conversion of PNG to SVG you can use
https://image.online-convert.com/convert-to-svg
https://www.pngtosvg.com/

Rendering RTL text along an SVG Path

Trying to render a Hebrew text along a path in SVG causes a bug in Chrome - the glyphs are rendered backwards (left-to-right), making the text unreadable.
<svg height="220" width="190">
<defs>
<path id="MyPath2" d="M0,100 L200,100" />
</defs>
<use xlink:href="#MyPath2" fill="none" stroke="red" />
<text text-anchor="middle" dx="100" dy="0" writing-mode="rl" direction="rtl">
<textPath xlink:href="#MyPath2">
הטקסט הזה ייראה הפוך
</textPath>
</text>
</svg>
Is there a way to get around this? Is this a known bug or is there an attribute I should've used?
JSFIddle: http://jsfiddle.net/j9RnL/
After not finding an elegant solution myself, I just reversed the characters.
function reverse(s, languageCode) {
if (['he', 'ar'].indexOf(languageCode) === -1)
return s;
return s.split("").reverse().join("");
}
I modified your SVG and it seems to render correctly on Chrome 100 and Firefox 100:
<svg viewBox="0 0 190 220" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="MyPath2" d="M0,100 L200,100"/>
</defs>
<use href="#MyPath2" fill="none" stroke="red"/>
<text text-anchor="middle" dx="100" dy="0" writing-mode="rl" direction="rtl">
<textPath href="#MyPath2">
הטקסט הזה ייראה הפוך
</textPath>
</text>
</svg>

Elliptical path is cut off

I need all the text displayed in this elliptical, but it is not.
Code
<embed width="1000" height="1000" type="image/svg+xml" src="path.svg">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="textPath"
d = "M 50 250
a 250 250 0 1 1 575 0"
/>
</defs>
<text fill="red">
<textPath xlink:href="#textPath">Foobarcs. All your favorites in one place.
</textPath>
</text>
</svg>
</embed>
Your fiddle is a bit broken, but when fixed, everything looks okay. All the text is visible.
http://jsfiddle.net/usVuq/1/
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="textPath"
d = "M 50 250
a 250 250 0 1 1 575 0" />
</defs>
<use xlink:href="#textPath" stroke="blue" fill="none" />
<text fill="red">
<textPath xlink:href="#textPath">Foobarcs. All your favorites in one place.
</textPath>
</text>
</svg>
Or is there something else you need that I don't understand?