Is SVG ellipse with "reverse fill" possible? - html

<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>

Related

Animating an SVG pattern background

I'm currently designing a new website with NextJS and Tailwind and I would like to make a background that is infinitely translating to the bottom right, just like in this example (but with my own pattern):
https://codepen.io/kootoopas/pen/reyqg
I've actually never worked with SVG patterns before. Though I've managed to display an SVG pattern as follows, I can't seem to find how to animate it.
The SVG is displayed in a flexbox div like so:
<div className="opacity-50 absolute inset-0 scale-150">
<svg width="100%" height="100%">
<defs>
<pattern id="p" width="100" height="100" patternUnits="userSpaceOnUse">
<path id="a" data-color="fill" fill="#FFF" d="M0 50v50h50C22.386 100 0 77.614 0 50zM100 50C72.386 50 50 27.614 50 0v50h50zM50 25V0C22.386 0 0 22.386 0 50h25c0-13.807 11.193-25 25-25zM100 75V50c-27.614 0-50 22.386-50 50h25c0-13.807 11.193-25 25-25zM25 50c0 13.807 11.193 25 25 25V50H25zM75 0c0 13.807 11.193 25 25 25V0H75z"></path>
</pattern>
</defs>
<rect fill="#EEB400" width="100%" height="100%"></rect>
<rect fill="url(#p)" width="100%" height="100%"></rect>
</svg>
</div>
I've tried to apply CSS classes, custom React components on it, with no avail.
Thank you very much for your time :)
<svg width="100%" height="100%">
<defs>
<pattern id="p" width="100" height="100" patternUnits="userSpaceOnUse">
<path data-color="fill" fill="#FFF" d="M0 50v50h50C22.386 100 0 77.614 0 50zM100 50C72.386 50 50 27.614 50 0v50h50zM50 25V0C22.386 0 0 22.386 0 50h25c0-13.807 11.193-25 25-25zM100 75V50c-27.614 0-50 22.386-50 50h25c0-13.807 11.193-25 25-25zM25 50c0 13.807 11.193 25 25 25V50H25zM75 0c0 13.807 11.193 25 25 25V0H75z"></path>
<animateTransform attributeName="patternTransform" type="translate" by="100 100" dur="10s" repeatCount="indefinite"></animateTransform>
</pattern>
</defs>
<rect fill="#EEB400" width="100%" height="100%"></rect>
<rect fill="url(#p)" width="100%" height="100%"></rect>
</svg>

Emoji character outline in SVG

I'm trying to create an outline of an emoji character (meaning I want to draw just the outer shape of the emoji) in SVG. The best I could come up with so far is to use two masked rectangles, scaled and super-imposed on each other.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100">
<defs>
<filter id="filter">
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0" />
</filter>
<mask id="mask" x="0" y="0" width="100" height="100">
<text filter="url(#filter)" x="0" y="80" font-family="Helvetica" font-weight="bold" font-size="7em" fill="#000000">🦄</text>
</mask>
</defs>
<path fill="#fff" d="M0 0 L0 100 L100 100 L100 0z"/>
<path fill="#000000" d="M0 0 L0 100 L100 100 L100 0z" mask="url(#mask)"/>
<g transform="translate(5, 5) scale(0.9)">
<path d="M0 0 L100 0 L100 100 L0 100z" mask="url(#mask)" fill="#fff"/>
</g>
</svg>
Depending on the particular emoji the result isn't very satisfactory though because not all emojis fill width and height equally.
Is there a better way to achieve an outline effect for emoji characters?
You need a viewBox for the svg element and I am using viewBox="0 -30 157 140" slightly bigger than the bounding box of the text element.
instead of a mask I'm using clipPath to clip a white rectangle
The filter I'm using is feMorphology operator="dilate" and I'm applying the filter to a group wrapping the clipped rectangle.
svg{border:solid}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" viewBox="0 -30 157 140">
<defs>
<filter id="outline-indigo">
<feMorphology in="SourceAlpha" result="expanded"
operator="dilate" radius="3"/>
<feFlood flood-color="indigo" result="indi" />
<feComposite in ="indi" in2="expanded" operator="in" />
<feComposite in="SourceGraphic"/>
</filter>
<clipPath id='emojiClipPath'>
<text filter="url(#filter)" x="0" y="80" font-family="Helvetica" font-weight="bold" font-size="7em" fill="#000000">🦄</text>
</clipPath>
</defs>
<g filter="url(#outline-indigo)">
<rect y="-30" width="157" height="140" fill="white" clip-path='url(#emojiClipPath)'/>
</g>
</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>

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>

Hexagon + Border-radius + Background-image, how can i do this?

i have a question for u. For example i got this picture, and need to do background image width box-shadow (yellow) on It with photo of someone (doesn't matter). How can i do it right?
*Updated Image!
A task like this is best achieved with SVG, as it allows you to define complex shapes.
<svg viewBox="0 0 120 100" style="width:120px;height:100px">
<defs>
<clipPath id="hexagon_clip">
<path id="hexagon" d="M38,2
L82,2
A12,12 0 0,1 94,10
L112,44
A12,12 0 0,1 112,56
L94,90
A12,12 0 0,1 82,98
L38,98
A12,12 0 0,1 26,90
L8,56
A12,12 0 0,1 8,44
L26,10
A12,12 0 0,1 38,2" />
<!-- SVG Hexagon path from http://stackoverflow.com/a/36842587/507674 -->
</clipPath>
</defs>
<image xlink:href="http://placehold.it/120x100" x="0" y="0" width="120px" height="100px" clip-path="url(#hexagon_clip)" />
<use xlink:href="#hexagon" x="0" y="0" stroke="orange" stroke-width="5" fill="transparent" />
</svg>
What happens here is that a clipping path is defined for the hexagon, then applied to the image. Finally, the hexagon is drawn again over the top to make the border.