Three-fiber canvas size - reactjs

I have a question regarding the three-fiber canvas size. I need a fixed canvas width and height. Unfortunately I have not found out how to change the canvas width and height. Even though I can change the sizes with style={{width: 100px, height: 100px}}, it is not the right thing. The canvas should be bigger than the div. does anyone have an idea how to do this with three-fiber?
<Canvas
size={[`2000px`,`3000px`]}
style={{width: `100%`, height: `auto`, position: `relative` }}
ref={canvas}
shadows
camera={{position: [10, 0, 80], fov: 45}}
>
<Suspense fallback={false}>
<Content/>
</Suspense>
</Canvas>

React Three Fiber's canvas will take the width and height of the parent container.
Instead of setting the width and height on the Canvas component, try setting the width and height on the parent instead, like this:
<div style={{ width: "50vw", height: "50vh" }}>
<Canvas flat linear>
<App />
</Canvas>
</div>
View Demo

Canvas in three-fiber takes on the width of its parent container. just resize whatever div it is being contained by.

Related

make SVG document responsive with the viewbox based on aspect ratio

I have created this codesandbox to illustrate the problem.
I have this ResponsiveSVG component:
export function ResponsiveSVG({
height,
width,
children,
origin = { x: 0, y: 0 },
preserveAspectRatio = "xMidYMid meet",
innerRef,
className,
...props
}: ResponsiveSVGProps): JSX.Element {
const aspect = height === 0 ? 1 : width / height;
const adjustedHeight = Math.ceil(width / aspect);
return (
<div
data-testid="cutting-svg-container"
style={{
position: 'relative',
overflow: 'visible',
height: '1px',
}}
>
<svg
style={{ overflow: 'visible' }}
className={className}
preserveAspectRatio={preserveAspectRatio}
width={width}
height={adjustedHeight}
viewBox={`${origin.x} ${origin.y} ${width} ${height}`}
ref={innerRef}
{...props}
>
{children}
</svg>
</div>
);
}
I would like my ResponsiveSVG component to know how to fit its content to the full width of the container while keeping the aspect ratio the same.
In the example I have a circle as a child of the svg document:
<ResponsiveSVG width={width} height={height}>
<circle cx={width / 2} cy={height / 2} r={radius} />
</ResponsiveSVG>
On desktop, it looks like this:
But in mobile view, it looks like this:
My calculations make the viewBox width and height the same as the actual width and height I am passing in, so no change happens.
The viewBox coordinates are exactly the same as the viewport.
Passing the width and height of the containing element to the viewBox is actually the wrong direction. viewBox defines the canvas on which the svg content elements are drawn: if you draw a circle with r="50", the viewBox width value must be at least 100, otherwise, it will never fit. If the center is at cx=50, the viewBox x value must not be greater than 0, otherwise the left side is cut off.
Responsiveness in SVG is achieved because there needs not to be any relation between the viewBox values and the width and height of the <svg> element. The canvas the child elements are drawn on is always fitted to the parent element dimensions.
In short, if all you want to achieve is to fit a circle in a <svg> element, choose a arbitrary radius r, set cx=cy=r and viewBox="0 0 2r 2r", and it will work. There is no need to know anything explicit about the parent size.
If you want your <svg> element to be the width of the container, set it so: width: 100%. The default height is auto, so no need to write that or preserveAspectRatio. It will size itself such that the canvas defined by viewBox fits itself.
<div
style="
position: relative;
overflow: visible;
height: 1px;
"
>
<svg
style="
width: 100%;
overflow: visible;
"
viewBox="0 0 100 100"
>
<circle cx="50" cy="50" r="50" />
</svg>
</div>

Stretch a SVG image along the x-axis

I'm looking to stretch my SVG image along the horizontal axis, which is acting as a background for some HTML divs. It is a simple bar that takes up the middle third horizontally :
It must not move on the vertical, and when horizontal is stretched, the image also must stretch so that the bar takes up the middle third.
Currently if I stretch horizontally, it maintains its vertical position which is good, but the SVG does not take up a third but maintains its original width:
Here is the React code :
function BackgroundSVG() {
let outerDiv = {
position:"relative",
border: "3px solid red",
}
let svgStyle = {
position:"absolute",
top:"0px",
border: "3px solid pink",
zIndex: -1,
width: "100%",
height: "200px"
}
return (
<div style={outerDiv}>
<div>Lorem ipsum .......</div>
<svg style={svgStyle}
viewBox={`0 0 ${600} ${200} `}
xmlns="http://www.w3.org/2000/svg">
<path d={`M ${200} ${100} H ${400}`} strokeWidth={12} stroke="blue"/>
</svg>
</div>
);
}
Here is a code pen
https://codepen.io/oliverwatkins/pen/MWqWmQz
How do I stretch the image along the x-axis, while preserving things on the y-axis?
I have tried to play around with the widths and heights but that does not seem to work. I assume that if I keep width at 100% and height at a 200px that this would solve the problem.
Default preserveAspectRatio attribute value is xMidYMid meet
so that browser try to maintain image aspect ratio.
For stretching SVG image, we need to set
preserveAspectRatio="none"

React Native image: why does parent view stay same height as 'cover' when set to 'contain'?

I have the following image in my React Native app
I want to have this image inside a parent element with no space above or below it, and I want the image to not overshoot the left or right sides of the screen
When I have the code like this
<View style={{
marginTop: 100,
borderWidth: 2,
borderColor: 'red'
}}>
<Image
style={{
width: '100%'
}}
source={require('#images/swoosh-02.png')}
/>
</View>
I get this, because default for resizeMode is cover
When I change it to this (adding resizeMode='contain')
<View style={{
marginTop: 100,
borderWidth: 2,
borderColor: 'red'
}}>
<Image
style={{
width: '100%'
}}
resizeMode='contain'
source={require('#images/swoosh-02.png')}
/>
</View>
the image gets successfully contained horizontally, but the height of the parent element remains the same as it was when resizeMode was cover.
How can I get it so that the parent element shrinks vertically to contain only the image and not have that extra top/bottom padding?
De diference between contain and cover is :
resizeMode='contain' = Scale the image uniformly (maintain the image’s aspect ratio) so that both dimensions (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding).
resizeMode='cover' = Scale the image uniformly (maintain the image’s aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).
Maybe you should try to apply height in your View.
Read this article, should help you.

If i don't hardcode <div> height component inside is hidden

I like to make a div expand according to its content height but the hole Component inside that div is hidden if I use like height: '100%'. It's a bit complex and wish for some extra eyes!
I made a CodeSandbox
Looks like this in Chrome:
I can see during debug that the "hidden" Component is rendering ok so it's strange that it's "hidden"
If I set the same Style to height: 1000 the <ul> have Children:
But I want it to expand according to its content height so height: 1000 will not work.
In this CodeSandbox I set the height: 1000, to demonstrate what happens. The Component that refuse to expand height is a Masonry image gallery Component
style={{
width,
height: 1000,
position: 'relative',
margin: '0 auto',
}}
When you open the Sandbox you see in the left editor windows this TimeLineViewer.js and the Style code problem. The TimeLineViewer.js loads the Masonry image gallery Component Masonry.js
What I have tried is to set parent to also 100% height but with no luck.. I'm a little bit new to JavaScript and HTML so advice would be good
To debug this, start by taking off or commenting out the LeComponent and then testing your div actual height when you are implementing the 100% height.
<div
style={{
width,
height: !fullscreen && "100%",
position: fullscreen ? 'initial' : 'relative',
margin: '0 auto',
}}
>
{/* <LeComponent
infinite
items={items}
itemRenderer={ItemRenderer}
gutter={gutter}
outerGutter={outerGutter}
extraPx={0}
debug={debug}
rows={{
0: 1,
320: 2,
480: 3,
640: 4,
}}
cols={{
0: 1,
360: 2,
640: 2,
960: 3,
1280: 4,
1400: 5,
1720: 6,
2040: 7,
2360: 8,
}}
onEnd={() => {
// TODO possible when many items lazy load them
// this.addItems();
}}
/> */}
</div>
You will notice, that it still takes up no height at all and the component you created did not have any bearing to that. This is because it is a CSS issue. The height percentage cannot be determined because there is no parent or ancestor with a height definition. You are getting the percentage of void.
After that, we can take a glance at your Masonry component. Just by looking at the method identifiers (such as _getDimensions, _setContainerHeight) and further reviewing the code base, we can learn that this component is actually dependent on certain element dimensions (most likely the parent div dimension as well) - and from what we learned from the CSS issue awhile ago, the parent div actually has a height of 0.
At this point, I took out the style props on your Masonry Component so that it would not be dependent on the parent dimensions and that fixed the issue
<div ref={this.container}>
<ul ref={this.list}>
{mounted && items.map((item, index) => this.renderItem({ index, item, maxIndex }))}
</ul>
</div>

Autosizer making a div of height and width 0

My configuration goes as follows:
// Calling it
<div style={{ width: 1000, height: 800 }}>
<MyComponent />
</div>
// MyComponent.js
<InfiniteLoader { ...itsProps }>
{({ onRowsRendered }) => (
<AutoSizer>
{({ width, height }) => (
<Table
width={ width }
width={ height }
...
The problem is that this is what is being rendered:
<div style="overflow: visible; height: 0px; width: 0px;">
<div class="ReactVirtualized__Table" role="grid">
...
So nothing is seen in the screen.
Maybe I misunderstood Autosizer usage, so I set it up to adjust itself to the parent's width/height.
What am I missing?
The height: 0 style in the snippet of HTML you shared isn't actually a problem, because of the overflow: visible style. This is the way AutoSizer is meant to work.
I suggest you read the "Using AutoSizer" docs page. I suspect your problem is similar to one of the common issues mentioned there:
AutoSizer expands to fill its parent but it will not stretch the parent. This is done to prevent problems with flexbox layouts. If AutoSizer is reporting a height (or width) of 0- then it's likely that the parent element (or one of its parents) has a height of 0. One easy way to test this is to add a style property (eg background-color: red;) to the parent to ensure that it is the correct size. (eg You may need to add height: 100% or flex: 1 to the parent.)

Resources