Does a svg compute outside of viewbox? [duplicate] - reactjs

This question already has answers here:
svg out of screen, is rendered?
(2 answers)
Closed 1 year ago.
I have several objects moving outside of the viewbox of a svg in react. For the sake of optimisation, I would like to conditionally render it. So the objects outside would not be rendered. But I'm asking myself if it's really needed. Does an SVG compute what is outside of a viewbox?

Yes, the browser computes everything outside the viewport for rendering. Calculates but does not display in the viewbox. Therefore, the question is relevant only in terms of rendering performance. If a part of a very large svg file with a lot of small details is outside the viewBox then rendering will be difficult. Although this will only show the visible part of the SVG.
comments of the author of the question:
I just do a 2.5d effect, so I have a prop for the pixels parcoured in
the x axis. I know where is everything that way, and just need some
calculation regarding the width of the viewbox
Calculating the width of the viewport
Below is an example with two SVG shapes. One figure is inside the svg viewBox, the second is outside
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="600" height="300" viewBox="0 0 600 300" style="border:1px solid" >
<g>
<rect x="20" y="50" width="200" height="200" rx="5%" fill="purple" />
<!-- Circle cx = "800" outside viewBox = "0 0 600 300" -->
<circle cx="800" cy="150" r="140" fill="greenyellow" />
</g>
</svg>
The circle is outside the svg of the canvas so it is not rendered in the browser
This is how it looks in the vector editor
In order for both figures to be inside the svg canvas, you need to calculate the parameters of the viewBox.
To do this, put both shapes in the group tag <g> and calculate the parameters of the viewBox
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="600" height="300" viewBox="0 0 600 300" style="border:1px solid" >
<g id="group">
<rect x="20" y="50" width="200" height="200" rx="5%" fill="purple" />
<!-- Circle cx = "800" outside viewBox = "0 0 600 300" -->
<circle cx="800" cy="150" r="140" fill="greenyellow" />
</g>
</svg>
<script>
console.log(group.getBBox())
</script>
Setting the computed viewBox attributes
It was: viewBox="0 0 600 300"
Now: viewBox = "20 10 920 280"
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="600" height="300" viewBox="20 10 920 280" style="border:1px solid" >
<g id="group">
<rect x="20" y="50" width="200" height="200" rx="5%" fill="purple" />
<!-- Circle cx = "800" inside viewBox = "0 0 920 280" -->
<circle cx="800" cy="150" r="140" fill="greenyellow" />
</g>
</svg>

Related

How to remove the shadow from the text of the svg and make it visible over it?

This is my code in my React app and I find it difficult to make the text appear on the svg, and also want to remove the shadow from the text so that only the shape is having the shadow.
<div className='overflow-hidden'>
<svg
className='fill-green block m-auto'
viewBox='0 0 500 150'
preserveAspectRatio='none'
xmlns='http://www.w3.org/2000/svg'
>
<g filter='url(#shadow)'>
<path
id='footer-shadow'
className='stroke-none'
d='M29.86,179.11 C100.86,200.36 200.94,60.48 450.84,180.09 L363.96,855.44 L0.00,190.00 Z'
></path>
<text
className='fill-modern-green text-sm'
x='50%'
y='100%'
dominant-baseline='middle'
text-anchor='middle'
>
All rights reserved.
</text>
<use xlinkHref='#footer-shadow'></use>
</g>
<filter id='shadow'>
<feDropShadow
dx='0'
dy='0'
stdDeviation='0.8'
flood-color='black'
/>
</filter>
</svg>
</div>
Your stacking order isn't ideal.
The <use> element overlays you text – so swap the order and apply the drop shadow filter to your ` element.
svg{
width:50em;
overflow:visible;
border:1px solid red;
}
<div className='overflow-hidden'>
<svg className='fill-green block m-auto' viewBox='0 0 500 150' preserveAspectRatio='none' xmlns='http://www.w3.org/2000/svg'>
<defs>
<filter id='shadow'>
<feDropShadow dx='0' dy='0' stdDeviation='2' flood-color='black' />
</filter>
<!-- path is only visible if referenced by <use> element -->
<path id='footer-shadow' className='stroke-none' d='M29.86,179.11 C100.86,200.36 200.94,60.48 450.84,180.09 L363.96,855.44 L0.00,190.00 Z'></path>
</defs>
<g >
<use href='#footer-shadow' filter='url(#shadow)'></use>
<!-- The text is now in the foreground -->
<text fill="#fff" className='fill-modern-green text-sm' x='50%' y='100%' dominant-baseline='middle' text-anchor='middle'>
All rights reserved.
</text>
</g>
</svg>
</div>
I also recommend to put your filters inside a <defs> element at the beginning of your svg. Some app frameworks (e.g flutter) struggle with defs placed after the elements these defs (e.g. filters, gradients etc.) are applied to.
So it's just a best practice for better compatibility.

SVG prevent scaling when zooming page

I wanna know, is there any way to prevent scaling my SVG when zooming page in a browser?
Let's just say my SVG image is a measuring image and I want to keep the same size of my SVG independently from zoom in or zoom out page.
I'm using React
Style
svg: {
height: 150,
width: 150,
},
Example Code
<svg className={classes.svg} viewBox="0 0 150 150">
<g>
<circle cx={70} cy={70} r={32} fill="white" stroke="black"/>
<circle cx={70} cy={70} r={8} fill="black"/>
</g>
</svg>
You might use a viewport related unit like vw, vh.
<svg viewBox="0 0 150 150" style="width:5vw">
<g>
<circle cx="70" cy="70" r="32" fill="white" stroke="black"/>
<circle cx="70" cy="70" r="8" fill="black"/>
</g>
</svg>
Your svg element will keep it's initial size of 5vw.

React Native svg clip path on image not working

Trying to clip an Image component with an svg ClipPath is proving problematic. I can clip a Rect no problem, but when I replace the Rect with an Image, nothing shows up.
octogon.points = "80,0.3 23.6,23.6 0.3,80 23.6,136.4 80,159.7 136.4,136.4 159.7,80 136.4,2 3.6";
props.photoUri = "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252Fhalt-c46ef35c-1897-441e-840e-28147c0de5a9/ImagePicker/d68a7ddd-807e-4d26-95c2-bd47ddca803e.jpg"
<View style={styles.container}>
<Svg width={160} height={160} viewBox={`0 0 160 160`}>
<Defs>
<ClipPath id="clip">
<Polygon points={octogon.points} />
</ClipPath>
</Defs>
{/* <Rect x="0" y="0" width="160" height="160" fill="red" clipPath="#clip" /> */}
<Image x="0" y="0" width="160" height="160" source={{ uri: props.photoUri }} clipPath="#clip" />
</Svg>
</View>
The commented out Rect worked as intended and creates a red octogon. The Image returns blank.
I feel like I'm overlooking something simple. Any help is appreciated.
Answering my own question because I'm an idiot and hopefully it will help someone in the future. Be mindful of which components you are importing. I was using Image from 'react-native' instead of Image from 'react-native-svg'.
Once I swapped it over and changed source={{ uri: props.photoUri }} to href={{ uri: props.photoUri }}, it started working.

SVG image is escaping the SVG boundary

I am using SVG to display profile picture of the user in one of the Ionic applications. The image sometimes escapes the SVG boundary when I navigate to the screen. I also have attached the screenshots of the same.Not working....
Correct or intended working
<svg viewBox="0 0 120 100" style="width: 200px; height: 200px; overflow: hidden" ng-click="openProfileModal()">
<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" />
</clipPath>
</defs>
<image ng-href="{{ userPics.photo1 }}" xlink:href="" x="0" y="0" width="100%" height="100%" clip-path="url(#hexagon_clip)" preserveAspectRatio="xMinYMin slice"/>
<use xlink:href="#hexagon" x="0" y="0" stroke="gray" stroke-width="1" fill="transparent" />
</svg>
note: userPics.photo1 -> it is url of the image which I am loading using AngularJS.
I tried applying the style overflow: hidden to SVG, but image still exit the boundary of SVG. I am new to using SVG. Thanks in advance guys :)

Defs pattern with css module - modify point in c3.js line chart to have an image inside

I am using c3.js and my components are using CSS Modules. I wanted to modify the fill of points in the line chart with an image. For that in the render method I had added defs-pattern -
render(){
return (
<div>
<defs>
<pattern id="image" x="0" y="0" patternUnits="userSpaceOnUse" height="1" width="1">
<image x="0" y="0" src="http://dummyimage.com/20x20/faf2fa/0011ff.png&text=x" />
</pattern>
</defs>
<C3Chart {...this.getConfig()}/>
</div>
);
}
In the styles css file I had added -
container :global(.c3-target-subscriber .c3-circle-5) {
fill: url(#image) !important;
}
But nothing happens. I just want to show an image inside the point of the line chart.
Any help is highly appreciated.
A <defs> element must have a parent that is a SVG element and not a HTML element. You need something like this:
<svg>
<defs>
<pattern id="image" x="0" y="0" patternUnits="userSpaceOnUse" height="1" width="1">
<image x="0" y="0" src="http://dummyimage.com/20x20/faf2fa/0011ff.png&text=x" />
</pattern>
</defs>
<svg>
Also your CSS points to something with a id of gradient but your pattern's id is image.

Resources