In CSS/SVG, how to rotate each character of a word? - html

Here is a Jsfiddle demo
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<svg width="100%" height="100%" viewBox="0 0 1000 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="MyPath" d="M 100 200
C 200 100 300 0 400 100
C 500 200 600 300 700 200
C 800 100 900 100 900 100" />
</defs>
<use xlink:href="#MyPath" fill="none" stroke="red" />
<text class="material-icons">
<textPath xlink:href="#MyPath">   </textPath>
</text>
<!-- Show outline of the viewport using 'rect' element -->
<rect x="1" y="1" width="998" height="298" fill="none" stroke="black" stroke-width="2" />
</svg>
 is a special character which is displayed as an "arrow".
There is a problem in the demo above: The direction of the arrow in the <textPath> is perpendicular to the <path>, while I need to set its direction to be the same (in parallel) as the path.
Therefore, I need to rotate 90 degree for each character in the text     (not the whole sentence)..
I found this post about rotating characters, but it looks not ideal because it needs to "Encapsule each letter in a element with jQuery". Maybe there is a way to do this easier in SVG?
Does anyone have ideas about how to rotate each character of a word in <textPath> node?

Just add this style="writing-mode: tb; glyph-orientation-vertical: 180;" to text
I hope this is what you wanted :
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<svg width="100%" height="100%" viewBox="0 0 1000 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="MyPath" d="M 100 200
C 200 100 300 0 400 100
C 500 200 600 300 700 200
C 800 100 900 100 900 100" />
</defs>
<use xlink:href="#MyPath" fill="none" stroke="red" />
<text class="material-icons" style="writing-mode: tb; glyph-orientation-vertical: 180;">
<textPath xlink:href="#MyPath">   </textPath>
</text>
<!-- Show outline of the viewport using 'rect' element -->
<rect x="1" y="1" width="998" height="298" fill="none" stroke="black" stroke-width="2" />
</svg>

Related

Is SVG ellipse with "reverse fill" possible?

<svg viewBox="0 0 600 1200" xmlns="http://www.w3.org/2000/svg">
<image x="0" y="0" height="200" width ="100" xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/IKB_191.jpg/1200px-IKB_191.jpg" />
<ellipse cx="50" cy="100" rx="50" ry="62" fill="grey" />
</svg>
In the example above, we want to be able to see the image (the blue box) inside of the ellipse, and have the grey of the ellipse only show in the corners / on the outside. You could think of this like a portrait of a person (the image) with a border (the inverse-of-ellipse).
We have an SVG with an image and an ellipse. The SVG image doesn't have many attributes (no border radius), and so we thought to use an "inverse-filled" ellipse, where the fill color is on the outside of the ellipse rather than inside. Unfortunately this is not happening in our example. Is this possible with svg:ellipse? Or is there some other approach? We need the image in the SVG, and our goal is to create a curved "border" (think border-radius 50%) of a certain fill color placed in front of the image.
Edit: I could create an svg:path, or maybe there is some sort of clipping that can be placed over the image?
Edit2: this path is close but not quite there because there shouldn't be any blue inside of the ellipse created by the path...
<svg height="200">
<path
stroke="black" fill="blue" stroke-width="2" fill-opacity="0.5"
d="
M0 80
a40 80 0 0 0 80 0
a40 80 1 0 0 -80 0
l0 80
l80 0
l0 -160
l-80 0
"
/>
</svg>
There are a few ways to achieve the deired result. Here are a couple
With a mask
<svg viewBox="0 0 600 1200" xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="ellipse-mask">
<ellipse cx="50" cy="100" rx="50" ry="62" fill="white" />
</mask>
</defs>
<rect x="0" y="38" width="100" height="124" fill="gray"/>
<image x="0" y="0" height="200" width ="100"
xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/IKB_191.jpg/1200px-IKB_191.jpg"
mask="url(#ellipse-mask)"/>
</svg>
With a path or clipping path
Your path was close. But you needed to close each subpath with a Z or z) so that they are individually filled.
<svg height="200">
<path
stroke="black" fill="blue" stroke-width="2" fill-opacity="0.5"
d="
M0 80
a40 80 0 0 0 80 0
a40 80 1 0 0 -80 0
Z
M0 0
l80 0
l0 160
l-80 0
Z
"
/>
</svg>

SVG - Line becomes thicker as I rotate it

I need multiple straight lines, and I have set the stroke-width to 4, but when I try to rotate them, the lines get thicker. Also when I try to set a negative value, for example <path d="M0 -10 20 0" stroke-width="4" stroke="red"></path> the line almost completely dissapears
<svg id="svg" width="100%" height="50">
<path d="M0 10 40 0" stroke-width="4" stroke="red"></path>
<path d="M40 0 80 0" stroke-width="4" stroke="blue"></path>
<path d="M80 0 120 0" stroke-width="4" stroke="green"></path>
</svg>
As said #Temani Afif half the width of the line goes beyond the border of the canvas of the SVG
Look please, I showed the borders of the canvas of the SVG with a gray line
<svg id="svg" width="100%" height="50" style="border:1px solid gray;">
<path d="M0 10 40 0" stroke-width="4" stroke="red"></path>
<path d="M40 0 80 0" stroke-width="4" stroke="blue"></path>
<path d="M80 0 120 0" stroke-width="4" stroke="green"></path>
</svg>
You can solve this problem by adding a viewBox and moving down the whole picture by adding the value -10 to the viewBox parameter
By setting the width and height of the SVG canvas as a percentage, you make your application responsive
<svg id="svg" width="100%" height="100%" viewBox="0 -10 150 50" style="border:1px solid gray;">
<path d="M0 10 40 0" stroke-width="4" stroke="red"></path>
<path d="M40 0 80 0" stroke-width="4" stroke="blue"></path>
<path d="M80 0 120 0" stroke-width="4" stroke="green"></path>
</svg>
You can also move the whole picture down 10 pixels with the command transform="translate(0 10)"
<svg id="svg" width="100%" height="100%" viewBox="0 0 150 50" style="border:1px solid gray;">
<g transform="translate(0 10)">
<path d="M0 10 40 0" stroke-width="4" stroke="red"></path>
<path d="M40 0 80 0" stroke-width="4" stroke="blue"></path>
<path d="M80 0 120 0" stroke-width="4" stroke="green"></path>
</g>
</svg>

Image not centering in SVG arc (HTML)

The background picture is not centering behind my SVG circle arc. You can see the image:
I want something like this:
obviously without the red cut part.
My HTML is as follows:
<svg width="200" height="200">
<defs>
<pattern id="image" x="0" y="0" width="1" height="1">
<image x="0%" y="0%" width="100%" height="100%" xlink:href="Assets/Images/RoundSlider.png"></image>
</pattern>
</defs>
<g transform="translate(100,100)" stroke="black" stroke-width="2">
<path d="M 0 0 -70 70 A 99 99 0 1 0 -70 -70 Z" fill="url(#image)" />
</g>
</svg>
This happens because your path's bounding box actually starts more on the right than if it were a full circle:
const bbox = document.querySelector('path').getBBox();
const rect = document.querySelector('rect');
rect.setAttribute('x', bbox.x);
rect.setAttribute('y', bbox.y);
rect.setAttribute('width', bbox.width);
rect.setAttribute('height', bbox.height);
<h3>The red rectangle represents your <path> BBox.</h3>
<svg width="200" height="200">
<g transform="translate(100,100)" stroke="black" stroke-width="2" fill="none">
<path d="M 0 0 -70 70 A 99 99 0 1 0 -70 -70 Z"/>
<rect stroke="red"/>
<circle stroke="green" r="100" cx="0" cy="0"/>
</g>
</svg>
So you can simply adjust your image's x attribute so it takes this offset into account (assuming you got a square image):
<svg width="200" height="200">
<defs>
<pattern id="image" width="1" height="1">
<!--
#mypath.getBBox().x = -70
Add 100 from translate(100, 100)
and we got our 30 units offset
-->
<image x="-30" y="0" width="200" height="200" xlink:href="https://upload.wikimedia.org/wikipedia/commons/9/95/Clock-green.png"/>
</pattern>
</defs>
<g transform="translate(100,100)" stroke="red" stroke-width="2">
<path id="mypath" d="M 0 0 -70 70 A 99 99 0 1 0 -70 -70 Z" fill="url(#image)"/>
</g>
</svg>
Or you could also just display this <image> and clip it (might be easier with more complex pathes):
<svg width="200" height="200">
<defs>
<clipPath id="myclip">
<use xlink:href="#mypath"/>
</clipPath>
</defs>
<image x="0" y="0" width="200" height="200" xlink:href="https://upload.wikimedia.org/wikipedia/commons/9/95/Clock-green.png" clip-path="url(#myclip)"/>
<path id="mypath" d="M 0 0 -70 70 A 99 99 0 1 0 -70 -70 Z" fill="transparent" transform="translate(100,100)" stroke="red" stroke-width="2"/>
</svg>

SVG path not showing same diffrent browser

I am trying to create an SVG Button with a shape arrow, I am using path here my code, anyone suggest me to solve this problem
<svg height="100" width="300">
<path id="lineAB" d="M0 1 l 280 0 l50 50 l-50 50 l-280 0 z" stroke="gray" stroke-width="2" fill="red" />
</svg>
Here my screenshot:
I added a css border to your svg and it reveals the following:
<svg height="100" width="300" style="border: 1px solid black;">
<path id="lineAB" d="M0 1 l 280 0 l50 50 l-50 50 l-280 0 z" stroke="gray" stroke-width="2" fill="red" />
</svg>
The tip of your arrow gets cut of because the svg container is not big enough.
That's because 280 + 50 is 330 and you are limiting the size of the svg to 300.
The fix is either decreasing the button size to 300 or increasing the svg containers size:
smaller button:
<svg height="100" width="300" style="border: 1px solid black;">
<path id="lineAB" d="M0 1 l 250 0 l50 50 l-50 50 l-250 0 z" stroke="gray" stroke-width="2" fill="red" />
</svg>
bigger container:
<svg height="100" width="330" style="border: 1px solid black;">
<path id="lineAB" d="M0 1 l 280 0 l50 50 l-50 50 l-280 0 z" stroke="gray" stroke-width="2" fill="red" />
</svg>
Don't ask me what's going on with the IE. I guess it has different defaults for overflow, increases the element width along with the content or fits the svg to the container by decreasing its size.
Update:
I tested this with the IE. It looks like it is the overflow :).
Also the IE-test revealed a small failure when I decreased your button width: I forgot to decrease the length line back to the left (l-280 0). I updated the snippet.
Please try this SVG.
Hope this help.
<svg height="100" width="300">
<path id="lineAB" d='M0 1 l 250 0 l50 50 l-50 50 l-280 0 z' stroke="gray" stroke-width="2" fill="red" />
</svg>

SVG not changing size

I have created an svg heart with a background image inside.
I'm trying to make the svg larger, but changing the width and height on both the pattern and the svg itself does not work.
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" height="315" width="345" >
<!-- START SVG RULES -->
<defs>
<!-- DEFINE IMAGE INSIDE PATTERN -->
<pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="https://images.pexels.com/photos/325185/pexels-photo-325185.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260" x="0" y="0" width="100" height="100" /></pattern>
<!-- SVG SHAPE CREATION -->
<g id="heart">
<path
d="M0 200 v-200 h200
a100,100 90 0,1 0,200
a100,100 90 0,1 -200,0
z" />
</g>
</defs>
<use xlink:href="#heart" class="outline" fill="url(#img1)" />
</svg>
For a resizable SVG use viewBox="0 0 315 345"instead height="315" width="345"
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" viewBox="0 0 315 345" >
<!-- START SVG RULES -->
<defs>
<!-- DEFINE IMAGE INSIDE PATTERN -->
<pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="https://images.pexels.com/photos/325185/pexels-photo-325185.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260" x="0" y="0" width="100" height="100" /></pattern>
<!-- SVG SHAPE CREATION -->
<g id="heart">
<path
d="M0 200 v-200 h200
a100,100 90 0,1 0,200
a100,100 90 0,1 -200,0
z" />
</g>
</defs>
<use xlink:href="#heart" class="outline" fill="url(#img1)" />
</svg>
Click the resize button to see if this is what you need.
https://jsfiddle.net/gbxquc05/29/
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100%" height="100%" preserveAspectRatio="none" viewBox="0 0 400 400">
Drawing paths in SVG is unfortunately limitted to absolute units. This is a workaround using viewBox to create coordinate system that transforms to percentage.