How to position absolutely positioned element relative to ref position - reactjs

I've got a bit of a problem here, hope I get help :0
well I am building a pretty little App on React and I have a navbar which includes an absolutely positioned div and two images for now... I have refs on these images and I want this navbar div to be positioned with the same top coordinates upon render...
Here is how I'm trying:
this code sets top state property to refs position:
componentDidMount() {
this.fetchApi();
this.setState({
scrolling: { top: this.first.current.offsetTop },
});
}
this is basically navbar
let { top } = this.state.scrolling;
<div className="map__left-column__logos">
<img
ref={this.first}
onClick={this.linkContainerClick}
className="img-svg"
src={pin}
alt="pingreen"
/>
<img onClick={this.linkContainerClick} src={logo} alt="logo" />
<div
ref={this.myRef}
className="link-container"
style={{ transform, top }}
>
<div className="link-container__upcurve"></div>
<div className="link-container__wrapper"></div>
<a href="#" id="container-href">
{" "}
<img
style={{
top: img1,
transition: "all linear .2s",
}}
className="img-svg"
src={chosenImg}
alt=""
/>
</a>
<div className="link-container__downcurve"></div>
</div>
</div>
</div>
and this is the linKContainerClick function trying to calculate where to scroll after I click the images
linkContainerClick = ({ target }) => {
let id = target.offsetTop;
let pixel = id - this.state.scrolling.top;
this.setState({ innerHtml: target.alt });
this.setState({
scrolling: {
...this.state.scrolling,
transform: `translateY(${pixel}px)`,
},
});
};
The problem is that on the first render of the App the link-container element is misplaced by 20 pixels... after refresh it moves to the right place

Related

react-image-crop will not provide initial crop on canva

Have an issue with react-image-crop. If I change the crop, it works perfectly, but if I just load and then hit save, I get an empty image back. At first I thought maybe its just not loading it, but I can see the croped image on load. And I don't get an "undefined" image back, I get an image with no data in it.
This is how I read the image:
useEffect(() => {
console.log("Got completed crop")
const canvas: HTMLCanvasElement = document.getElementById('canvas') as HTMLCanvasElement
if (canvas) {
console.log("Got canvas")
console.log(canvas.toDataURL())
setCroppedImgUrl(canvas.toDataURL())
} else {
}
}, [completedCrop])
This code gets called every time completedCrop is updated, and I can see that it works when the image is first loaded, BUT, the image it returns on load (independent on what image I am cropping) is
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAACWCAYAAABkW7XSAAAAAXNSR0IArs4c6QAABGJJREFUeF7t1AEJAAAMAsHZv/RyPNwSyDncOQIECEQEFskpJgECBM5geQICBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAAYPlBwgQyAgYrExVghIgYLD8AAECGQGDlalKUAIEDJYfIEAgI2CwMlUJSoCAwfIDBAhkBAxWpipBCRAwWH6AAIGMgMHKVCUoAQIGyw8QIJARMFiZqgQlQMBg+QECBDICBitTlaAECBgsP0CAQEbAYGWqEpQAgQdWMQCX4yW9owAAAABJRU5ErkJggg==
To initiate the crop, I use the following code:
<div className='d-flex align-items-center gap-4'>
<div className='text-center'>
<p>Crop:</p>
{Boolean(posterSrc) && (
<ReactCrop
crop={crop}
onChange={(_, percentCrop) => {
setCrop(percentCrop)
}}
onComplete={(crop) => setCompletedCrop(crop)}
aspect={aspect}>
<img
style={{maxHeight: previewHeight, maxWidth: previewWidth, objectFit: "cover"}}
ref={imgRef}
alt="Crop me"
src={posterSrc}
onLoad={onImageLoad}/>
</ReactCrop>
)}
</div>
<div className='text-center'>
<p>Preview:</p>
{Boolean(completedCrop) && (
<canvas
id='canvas'
ref={previewCanvasRef}
style={{
objectFit: 'contain',
width: previewWidth,
height: previewHeight,
}}
/>
)}
</div>
</div>
Anyone have any idea what I'm doing so wrong

How to show couple images in preview of ANTD carousel

I was wondering is it possible to show couple images on single preview of ANTD carousel.
For insrance i have a carousel on which i may have different amount of immages.
The problem is that i want to show all avaliable images in preview without heving to schroll through them.
I tried to change size of immages but that didn't help.
Also i haven't found any properties in ANTD for that.
Does anyone know is it possible?
import { Carousel } from 'antd';
const contentStyle = {
height: '160px',
color: '#fff',
lineHeight: '160px',
textAlign: 'center',
background: '#364d79',
};
ReactDOM.render(
<Carousel effect="fade">
<div>
<h3 style={contentStyle}>1</h3>
</div>
<div>
<h3 style={contentStyle}>2</h3>
</div>
<div>
<h3 style={contentStyle}>3</h3>
</div>
<div>
<h3 style={contentStyle}>4</h3>
</div>
</Carousel>,
mountNode,
);
Here's what seemed to work.
Mainly just added an extra item to my array in 0th position and conditionally rendered a preview frame which included all the images in a grid.
Sample:
const images = [...new Array(5).keys()].map((rowIndex, _, array) => {
if (rowIndex === 0) {
return (
<React.Fragment>
<div key={rowIndex} style={previewStyle}>
{array.map((colIndex) => (
<h3 key={(rowIndex + 1) * (colIndex + 1)} style={h3Style}>
Preview: {colIndex}
</h3>
))}
</div>
</React.Fragment>
);
}
return (
<React.Fragment>
<h3 key={rowIndex} style={{...h3Style, lineHeight: '160px',}}>
{rowIndex}
</h3>
</React.Fragment>
);
});

React accordion with correlating image outside accordion section

I can't find any examples of accordions where the active class is related to an element outside of the accordion. I'm trying to get an image to change on the side of the accordion, where each image is related to a specific object. I managed to get something working using absolute positioning, but I'm looking for a more elegant solution so I can manipulate styling better.
I can get it to work while the image is inside the accordion under the info text, but can't figure out the styling issue. I think I need to do some refactoring or do away with the array mapping to get it to work but I'm not sure.
Here is a codesandbox of more or less what I want to achieve but without the restriction of absolute positioning - https://codesandbox.io/s/ecstatic-taussig-f084t?file=/src/App.js
You can remove your img tag from your renderedItems and do something like this:
import React, { useState } from "react";
const Accordion = ({ items }) => {
const [activeIndex, setActiveIndex] = useState(0);
const onTitleClick = (index) => {
setActiveIndex(index);
};
const renderedItems = items.map((item, index) => {
const active = index === activeIndex ? "active" : "";
return (
<div key={item.title}>
<div className={`title ${active}`} onClick={() => onTitleClick(index)}>
<i className="dropdown icon"></i>
{item.title}
</div>
<div className={`content ${active}`}>
<p>{item.content}</p>
</div>
</div>
);
});
return (
<div className="container-gallery">
<div className="ui styled accordion">{renderedItems}</div>
<img
className={`content `}
src={`${items[activeIndex].image}`}
style={{
height: "200px",
width: "200px"
}}
alt="img"
/>
</div>
);
};
export default Accordion;
And for the style I don't know what you are using so I made css for the example:
.container-gallery{
display:flex;
flex-wrap:no-wrap;
justify-content: space-between;
}
here a sandBox link

How to make the text on React Bootstrap 4 Carousel stay, while the images move?

Basically this is the same question as this one, but for the React Bootstrap Carousel component.
So I have a working carousel but I want a text to be on top of it, that doesn't move while the images change.
This is my working Carousel code snippet - as you can see I added my overlay text at the bottom of the loop. It does stay on top, just like I want, but it also adds an additional empty carousel item, which I don't want. (I tried making this work in js-fiddle and codesandbox.io but I'm not smart enough...)
import React from "react";
import Carousel from "react-bootstrap/Carousel";
import "./styles.css";
export default function App() {
let carouselImgs = [
{
title: "Test1",
img: "https://images.app.goo.gl/FrGs95rzsNfc6YkW8"
},
{
title: "Test2",
img: "https://images.app.goo.gl/tPkFSMH796PmV3pq9"
}
];
return (
<Carousel className="App" interval={3000}>
{carouselImgs.map(carouselImg => (
<Carousel.Item
key={carouselImg.title}
className="oneness-container mb-2"
>
<img src={carouselImg.img} className="img-fluid rounded-lg" alt="" />
<Carousel.Caption>
<div className="bottom-center">
<h3 className="rounded px-2 py-1 d-inline">
{carouselImg.title}
</h3>
</div>
</Carousel.Caption>
</Carousel.Item>
))}
{<h1 className="overlay">Overlay title</h1>}
</Carousel>
);
}
CSS of .overlay:
.overlay {
position: absolute;
top: 0;
width: 100%;
}
I like the comment on that answer - that says to this:
<div id="carousel" class="carousel slide">
<!-- Wrapper for slides -->
<div class="carousel-inner" >
<!-- items -->
</div>
</div>
...place [the overlay div] inside the carousel-inner, but still in a div separate from your "item" divs...
But unfortunately I don't know how to get inside the carousel-inner since the React Bootstrap component doesn't show it like that.

react: fade-in/slide-in animation when render component

I'm new in React. I have made a small app with a button and a list of image urls. When button is clicked, an image url is added to the list. I render the list of image urls with standard .map function.
I would like to make a fast ui animation effect when the image is displayed: a combination of fade-in and slide-in from left. I tried Velocity.js and found the velocity-react wrapper. But I can not understand how to use it. The same goes for the 'standard' velocity-animate library.
What is best? velocity-react, velocity-animate or something else?
And how do I do it?
JSX
<div className="row">
{
this.state.images.map( (image, index) => { return this.renderThumb(image, index); } )
}
</div>
renderThumb function
renderThumb(image, index) {
return (
<div ref="tweetImage" key={`image-${index}`} className="col-xs-3 tweetImage">
<img className="img-thumbnail" src={image} alt="my pic"/>
</div>
);
}
velocity-react
I tried to wrap <img> animation opacity from 0 to 1 like this (copied from docs):
<VelocityComponent animation={{ opacity: 1 }} duration={ 500 }>
<img className="img-thumbnail" src={image} alt="my pic"/>
</VelocityComponent
I keep getting this error:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object
No luck with ReactCSSTransitionGroup either (like suggestions below). Images are shown but without animation:
renderThumb(image, index) {
return (
<div ref="tweetImage" key={`image-${index}`} className="col-xs-3">
<ReactCSSTransitionGroup
transitionName="example">
<img className="img-thumbnail" src={image} alt="Ole Frank Jensen"/>
</ReactCSSTransitionGroup>
</div>
);
}
SOLVED:
I moved <ReactCSSTransitionGroup transitionName="example"> outside of the fading component and voilá :-)
render()
<div className="row">
<ReactCSSTransitionGroup transitionName="example">
{
this.state.images.map( (image, index) => { return this.renderThumb(image, index); } )
}
</ReactCSSTransitionGroup>
</div>
renderThumb()
renderThumb(image, index) {
return (
<div key={`image-${index}`} className="col-xs-3">
<img className="img-thumbnail" src={image} alt="Ole Frank Jensen"/>
</div>
);
}
You can use the CSSTransitionGroup provided by react.
https://facebook.github.io/react/docs/animation.html
a simple todo exammple from the docs
class TodoList extends React.Component {
constructor(props) {
super(props);
this.state = {items: ['hello', 'world', 'click', 'me']};
this.handleAdd = this.handleAdd.bind(this);
}
handleAdd() {
const newItems = this.state.items.concat([
prompt('Enter some text')
]);
this.setState({items: newItems});
}
handleRemove(i) {
let newItems = this.state.items.slice();
newItems.splice(i, 1);
this.setState({items: newItems});
}
render() {
const items = this.state.items.map((item, i) => (
<div key={item} onClick={() => this.handleRemove(i)}>
{item}
</div>
));
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
<ReactCSSTransitionGroup
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}>
{items}
</ReactCSSTransitionGroup>
</div>
);
}
}
i'd recommend going with React CSS Transistion Group module. It provides an high level animation wrapper for simple animations.
EDIT:
The link will permanently redirect to Animation Add-Ons
ReactTransitionGroup and ReactCSSTransitionGroup have been moved to the react-transition-group package that is maintained by the community.
From the docs
.example-enter {
opacity: 0.01;
}
.example-enter.example-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}
.example-leave {
opacity: 1;
}
.example-leave.example-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
}
Where example will be the transistionName for the component that you wish to paint. and -enter,enter-active,-leave,-leave-active stand for the corresponding ticks of the animation cycle. These will be added by React internally as class names to the items.
You can use them to achieve the desired effect in question. A small demo here.
P.S: not sure if this outperforms Velocity.js, havent used that.

Resources