Can't resize React-Player Video - javascript

Can't resize React-Player Video.
I change the width to any number and the video stays unchanged.
I am trying to optimize it for computer view and then add breakpoints to resize for smaller screens like phones.
Bellow is the file where I render the React-Player video inside a on which I apply the desired height and width I would like my react-player video to adopt.
import React, { useContext, useEffect, useState } from 'react'
import { makeStyles } from '#material-ui/core/styles'
import Modal from '#material-ui/core/Modal'
import { MovieContext } from './MovieContext'
import ReactPlayer from 'react-player'
import { getTrailer } from '../utils/movieDB'
// potential of adding controls
// import { Slider, Direction } from 'react-player-controls'
//slider to be implemented
//https://www.npmjs.com/package/react-player-controls#playericon-
const useStyles = makeStyles((theme) => ({
video: {
width: 'auto',
height: 'auto',
top: '25%',
right: '25%',
position: 'fixed',
[theme.breakpoints.down('xs')]: {},
},
}))
const styles = {
player: {
width: '300px',
},
}
export default function SimpleModal({ open }) {
const classes = useStyles(),
//receives movie from Home > DisplayCard > MovieContext
{ setOpenTrailer, movie, setMovie } = useContext(MovieContext),
[trailer, setTrailer] = useState(),
[key, setKey] = useState(),
[modalStyle] = useState()
useEffect(() => {
if (movie) {
getTrailer(movie).then((data) => {
setKey(data.videos.results[0].key)
setTrailer(data)
})
}
}, [movie])
const handleOpen = () => {
setOpenTrailer(true)
}
const handleClose = () => {
setOpenTrailer(false)
setMovie(undefined)
setTrailer(undefined)
setKey(undefined)
}
const renderVideo = (
<>
{key && (
<div className={classes.video}>
<ReactPlayer style={styles.player} url={`https://www.youtube.com/watch?v=${key}`} />
</div>
)}
</>
)
return (
<div>
<Modal
open={open || false}
onClose={handleClose}
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
>
{renderVideo}
</Modal>
</div>
)
}
Which is the proper way to set the dimensions on a react-player object?

Using the width and height props as such:
<ReactPlayer
width={“300px”}
url={`https://www.youtube.com/watch?v=${key}`} />

this code is from the react-player library. This made my video responsive
its from: https://github.com/cookpete/react-player
class ResponsivePlayer extends Component {
render () {
return (
<div className='player-wrapper'>
<ReactPlayer
className='react-player'
url='https://www.youtube.com/watch?v=ysz5S6PUM-U'
width='100%'
height='100%'
/>
</div>
)
}
}
----- CSS ------
.player-wrapper {
position: relative;
padding-top: 56.25% /* Player ratio: 100 / (1280 / 720) */
}
.react-player {
position: absolute;
top: 0;
left: 0;
}

Related

How to make different durations with useSpring?

I want my component to have an animation that if my mouse enter,it will be fully displayed in 0.3s,and if my mouse leave,it will disappear in 0.1s.But useSpring can just define one duration just like the code below,which cause that the component will be displayed and disappear all in 0.3s.How can I define different duration for from->to and to->from?Thanks for anyone who can help.
const animationStyle = useSpring({
bottom: show ? 0 : -71,
from: {
bottom: -71
},
config: { duration: 300 }
})
Like this
import import React, { useState } from 'react';
import { animated, useSpring } from '#react-spring/web';
const SuspendedComponent: React.FC = ({ children }) => {
const [isMouseEnter, setMouseEnter] = useState<boolean>(false);
const _style = useSpring({
bottom: isMouseEnter ? 0 : -71,
from: {
bottom: -71,
},
config: { duration: 300 },
});
function onMouseHandler(isEnter: boolean) {
setMouseEnter(isEnter);
}
return (
<div
style={{ display: 'block', width: '100px', height: '100px' }}
onMouseEnter={() => onMouseHandler(true)}
onMouseLeave={() => onMouseHandler(false)}
>
{isMouseEnter && <animated.div style={_style}>{children}</animated.div>}
</div>
);
};
export default SuspendedComponent;
You can control animated.div element display by onMouseEnter and onMouseLeave event.

Question about the animation effect of the React carousel component

I wrote a carousel component with react and react-transition-group, but the animation of the carousel is not working properly. When the image changes from 0 to 1, the 0 will disappear immediately, instead of waiting for the animation to end and then disappear.
The Code Link is as follow
https://stackblitz.com/edit/react-ts-eawtuk?file=CarouselItem.tsx
The core codes are as follow
Carousel Component
import React, {
FC,
Fragment,
ReactNode,
useMemo,
useState,
} from 'react';
import CarouselItem, { ItemProps } from './CarouselItem';
import './Carousel.scss';
export interface Props {}
const Component: FC<Props> = (props) => {
const { children } = props;
const [curIndex, setCurIndex] = useState(1);
const length = useMemo(() => {
return Array.from(children as ReactNode[]).length;
}, [children]);
const onNext = () => {
setCurIndex((curIndex + 1 + length) % length);
};
const onPrev = () => {
setCurIndex((curIndex - 1 + length) % length);
};
setTimeout(onNext, 3000);
return (
<Fragment>
<button onClick={onPrev}>prev</button>
<button onClick={onNext}>next</button>
<div className="g-carousel">
<div className="g-carousel-window">
<div className="g-carousel-wrapper">
{React.Children.map(children, (child, index) => {
const ChildElement = child as FC<ItemProps>;
if (child.type !== CarouselItem) throw new Error('必须是Item');
return React.cloneElement(ChildElement, { index, curIndex });
})}
</div>
</div>
</div>
</Fragment>
);
};
type CarouselType = {
Item: FC<ItemProps>;
} & FC<Props>;
const Carousel: CarouselType = Component as CarouselType;
Carousel.Item = CarouselItem;
export default Carousel;
CarouselItem Component
import React, { CSSProperties, FC, Fragment, useMemo } from 'react';
import { CSSTransition } from 'react-transition-group';
export interface ItemProps {
curIndex?: number;
index?: number;
style?: CSSProperties;
}
const carouselItem: FC<ItemProps> = (props) => {
const { children, index, curIndex } = props;
const visible = useMemo(() => curIndex === index, [curIndex]);
return (
<Fragment>
<CSSTransition
in={visible}
classNames="carousel"
timeout={500}
key={index}
>
<div
className="g-carousel-item"
style={{ display: curIndex !== index && 'none' }}
>
{children}
</div>
</CSSTransition>
</Fragment>
);
};
export default carouselItem;
And css
.g-carousel {
&-window {
overflow: hidden;
}
&-wrapper {
position: relative;
}
}
.carousel-exit {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.carousel-enter,
.carousel-exit {
transition: all 0.5s;
}
.carousel-enter-active {
transform: translateX(-100%);
}
.carousel-enter.reverse {
transform: translateX(100%);
}
.carousel-exit-done {
transform: translateX(100%);
}
.carousel-exit-done.reverse {
transform: translateX(-100%);
}

How to switch image on scroll in React (like on Apple website)?

I try to switch from an image to another one when scrolling with React but I don't know how to do this... maybe with React hook. I know it's possible with jQuery but I don't want to use it.
Example here: https://www.apple.com/iphone-12/, look at the "Five fresh finishes".
import React, {useState} from 'react';
import './BackgroundDiscover.css';
import logoOrdiW from "../../images/mathis_computer_white.jpg";
import logoOrdiB from "../../images/mathis_computer_black.jpg";
const BackgroundDiscover = () => {
const [imageSrc, SetSrc] = useState(logoOrdiW);
const switchBrackground = () => {
SetSrc(logoOrdiB);
}
return (
<>
<div className="container-discover">
<div className='container-logo-white'>
<img src={imageSrc} alt="logo ordinateur mathis blanc" onScroll={switchBrackground}/>
</div>
</div>
</>
);
};
export default BackgroundDiscover;
.container-discover {
display: flex;
flex-direction: column;
}
.container-logo-white img {
width: 100%;
}
.container-logo-black img {
width: 100%;
}
You don't need jQuery or something like this. You could subscribe to scroll event in useEffect() hook with addEventListener and check scrollTop of a scrolling container.
If you want to do the same effect as the Apple website has, you could add some magic with position: sticky, height in vh units and checking window.innerHeight.
Note that this code is simplified, not optimized, and only needed to understand the idea:
CodeSandbox
index.js:
import { useLayoutEffect, useState } from "react";
import { render } from "react-dom";
import classnames from "classnames";
import "./index.css";
const images = [0, 1, 2, 3, 4];
const App = () => {
const [visibleImagesMap, setVisibleImagesMap] = useState(
images.reduce((map, image) => {
map[image] = false;
return map;
}, {})
);
useLayoutEffect(() => {
const handleScroll = () => {
const scrollTop = document.documentElement.scrollTop;
const viewportHeight = window.innerHeight;
const newVisibleImagesMap = images.reduce((map, image) => {
map[image] = scrollTop >= image * viewportHeight;
return map;
}, {});
setVisibleImagesMap(newVisibleImagesMap);
};
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => window.removeEventListener("scroll", handleScroll);
}, []);
return (
<div className="app">
<div className="sticky">
<div className="frame">
{images.map((image) => (
<div
className={classnames("image", `image_${image}`, {
image_visible: visibleImagesMap[image]
})}
key={image}
/>
))}
</div>
</div>
</div>
);
};
render(<App />, document.getElementById("root"));
index.css:
body {
margin: 0;
}
.app {
height: 500vh;
}
.sticky {
position: sticky;
top: 0;
height: 100vh;
}
.frame {
z-index: 1;
position: relative;
height: 100%;
width: 100%;
}
.image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
background-repeat: no-repeat;
background-size: cover;
}
.image_0 {
z-index: 0;
background-image: url("./images/0.jpeg");
}
.image_1 {
z-index: 1;
background-image: url("./images/1.jpeg");
}
.image_2 {
z-index: 2;
background-image: url("./images/2.jpeg");
}
.image_3 {
z-index: 3;
background-image: url("./images/3.jpeg");
}
.image_4 {
z-index: 4;
background-image: url("./images/4.jpeg");
}
.image_visible {
opacity: 1;
}
There are plenty of solutions for this but basically you can set in this way.
Wheel event listener turns either positive or negative value so you should create an algorithm if you want to impelement different designs.
import React, { useState } from "react";
export default function App() {
const [bgImage, handleImage] = useState(
"https://media.wired.com/photos/5e9f56f143e5800008514457/1:1/w_1277,h_1277,c_limit/Gear-Feature-Apple_new-iphone-se-white_04152020.jpg"
);
window.addEventListener("wheel", (e) => {
if (e.deltaY > 0) {
handleImage(
"https://media.wired.com/photos/5bcea2642eea7906bba84c67/master/w_2560%2Cc_limit/iphonexr.jpg"
);
} else {
handleImage(
"https://media.wired.com/photos/5e9f56f143e5800008514457/1:1/w_1277,h_1277,c_limit/Gear-Feature-Apple_new-iphone-se-white_04152020.jpg"
);
}
});
return (
<div className="App">
<img
style={{ width: "400px", height: "300px" }}
id="myimage"
src={bgImage}
alt=""
/>
</div>
);
}
And as a result you can use bgImage state in your image src.
This is a codesandbox example https://codesandbox.io/s/pensive-vaughan-cfc63?fontsize=14&hidenavigation=1&theme=dark
You can try useEffect and useRef.
useEffect is sideload functions, and useRef is for real dom referances.
import React, { useRef, useState, useEffect } from 'react';
import logoOrdiW from "../../images/mathis_computer_white.jpg";
import logoOrdiB from "../../images/mathis_computer_black.jpg";
import './BackgroundDiscover.css';
const BackgroundDiscover = () => {
const img = useRef();
const [src, setSrc] = useState(logoOrdiW);
const switchBrackground = () => {
setSrc(logoOrdiB);
}
useEffect(() => {
img.current.onscroll = switchBrackground;
}, []);
return (
<div className="container-discover">
<div className='container-logo-white'>
<img src={src} alt="logo ordinateur mathis blanc" ref={img} />
</div>
</div>
);
};
export default BackgroundDiscover;

react-virtuoso: overscan props does not work

I'm using react-virtuoso library to render a simple virtual list. The code is very straightforward. I pass this overscan props and expect the virtual list to render n items above and below the viewport but it's not working.
The ExpensiveComponents still renders 'loading...' text when I'm scrolling up and down a little. Here is the code:
import { Virtuoso } from "react-virtuoso";
import { useEffect, useState, useRef, PropsWithChildren } from "react";
function ExpensiveComponent({ children }: PropsWithChildren<{}>) {
const [render, setRender] = useState(false);
const mountRef = useRef(false);
useEffect(() => {
mountRef.current = true;
setTimeout(() => {
if (mountRef.current) {
setRender(true);
}
}, 150);
return () => void (mountRef.current = false);
}, []);
return (
<div style={{ height: 150, border: "1px solid pink" }}>
{render ? children : "Loading..."}
</div>
);
}
Usage
function App() {
return (
<Virtuoso
style={{ height: "400px" }}
totalCount={200}
overscan={3} // ----------> this line does not work
itemContent={(index) => {
return <ExpensiveComponent>{index}</ExpensiveComponent>;
}}
/>
);
}
I missed this detail from the docs. Unlike react-window API, the overscan unit is pixel instead of row in virtual list, in my case I need to increase the overscan to 900px and it seems to be working now.
<Virtuoso
style={{ height: "400px" }}
totalCount={200}
overscan={900}
itemContent={(index) => {
return <ExpensiveComponent>{index}</ExpensiveComponent>;
}}
/>

What's wrong with my Navbar menu refusing to fire onClick

I have this Codesandbox with a Hamburger menu that refuse to let onClick work.
This image show the simple menu with the Timeline link
(it's suppose to be text color white but Codesandbox refuses)
Clicking the link does not fire the onClick it's like it's being blocket by another component.
I have tested to remove the Component NavLinkPage that is rendered at the same time and then my Menu works. It's like it's blocking even it's set to be off screen.
I have tried to set e.g. the z-index but with no luck the only think that works is removing the:
<NavLinkPage close={close} />..
The simple Menu is the Component:
<SideMenu close={close} />..
NavLinkPage are controlled by #media (max-width: 1098px).. and will show on large screens only.
here is CollapseMenu.jsx code with NavLinkPage and NavLinkPage :
import React, { useRef, useCallback, useEffect } from 'react';
import styled from 'styled-components';
import { useSpring, animated } from 'react-spring';
import useOnClickOutside from './UseOnClickOutside';
import NavLinkPage from './NavLinkPage';
import SideMenu from './SideMenu';
const CollapseMenu = props => {
const { show, close } = props;
const { open } = useSpring({ open: show ? 0 : 1 });
const reference = useRef();
useOnClickOutside(reference, close, 'burgerMenu');
const escFunction = useCallback(
event => {
// only accept 27 if it's visible
if (event.keyCode === 27 && show === true) {
close();
}
},
[close],
);
useEffect(() => {
document.addEventListener('keydown', escFunction, false);
return () => {
document.removeEventListener('keydown', escFunction, false);
};
}, [escFunction]);
if (show === true) {
return (
<CollapseWrapper
style={{
transform: open
.interpolate({
range: [0, 0.2, 0.3, 1],
output: [0, -20, 0, -200],
})
.interpolate(openValue => `translate3d(0, ${openValue}px, 0`),
}}
>
<NavLinkPage close={close} />
<SideMenu close={close} />
</CollapseWrapper>
);
}
return null;
};
export default CollapseMenu;
const CollapseWrapper = styled(animated.div)`
background: #2d3436;
position: fixed;
left: 0;
right: 0;
width: 200px;
z-index: 100;
`;

Categories

Resources