React Spring animation slowing down - javascript

I have a react-spring simple rotation animation with adjustable speed. But once I sett the speed to full (setting duration to 10ms) and returning it to lower even 1 second, it wouldn't animate properly and rather gets lagging.
Here is the animation preview
https://3l3kb.csb.app/
And here is the sandbox https://codesandbox.io/s/spring-anim-test-forked-6wno4
And here is the code
export default function App() {
const [reverse, setReverse] = useState(false);
const [speed, setSpeed] = useState(50);
const rotation = useSpring({
from: { transform: "rotate(0deg)" },
to: { transform: "rotate(360deg)" },
loop: true,
reset: true,
config: { duration: 10 + (100 - speed) * 10 }
});
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
{/* <animated.div>
<animated.h1>{num.get().toFixed(2)}</animated.h1>
</animated.div> */}
<div
style={{
width: "300px",
height: "300px",
position: "relative",
margin: "auto"
}}
>
<animated.div
style={{
...{
...rotation,
marginLeft: "auto",
position: "absolute",
color: "purple",
fontSize: "130px"
}
}}
>
T
</animated.div>
</div>
<input
type="range"
value={speed}
onChange={(e) => setSpeed(e.target.value)}
style={{
marginTop: "100px",
width: "500px"
}}
/>
</div>
);
}

Related

How to keep wrapper remain centered when zooming?

I'm trying to zoom in using the input slider, and I want when content overflows the scrollbar to appear and also position the content to stay centered.
import { useState } from "react";
export default function App() {
const [scale, setScale] = useState(0.3);
const updateScale = (e) => {
setScale(parseFloat(e.target.value));
};
return (
<div style={{
background:"#DE5833",
width:"100%",
height:"100vh"
}}>
<div
style={{
position: "absolute",
zIndex: 50
}}
>
<input
type="range"
min="0.1"
max="1.5"
step="0.01"
value={scale}
onChange={updateScale}
/>
</div>
<div style={{
background:"#DE5833",
width:"100%",
height:"100%",
display:"flex",
justifyContent:"center",
alignItems : "center",
transform: `scale(${scale})`,
}}>
<div
style={{
width: 600,
height: 600,
background:"#2563EB"
}}
>
</div>
</div>
</div>
);
}
This is the example of what behaviour I want to achieve
https://res.cloudinary.com/dv8aesvfs/video/upload/v1630150060/screen-capture_dernvs.mkv
I can center the content , but i can't sroll to the top or to the left like this :
https://res.cloudinary.com/dv8aesvfs/video/upload/v1630150115/screen-capture_1_aas9k8.mkv
you can try it here : codesandbox

Having a Fullscreen preview image onHover property in Mapbox GL to cover entire map

Currently I have a ReactMapboxGL component with markers. These markers have a onMouseEnter function that brings up a fullscreen popup to my screen, but that not what I want. Currently I'm trying to replicate this design with my Markers (http://www.francoisrisoud.com/projects), where if you hover over a dot it gives a fullscreen preview image and only if that is clicked on, it'll go to that particular page.
Currently this is my code:
export default function Map({ posts }) {
const [viewport, setViewport] = useState({
latitude: 36.592206968562685,
longitude: 3.332469343750031,
width: "100%",
height: "100vh",
zoom: 1.3,
scrollZoom: "false",
});
const [selectedProperty, setSelectedProperty] = useState(null);
const [isPopupShown, setIsPopupShown] = useState(false);
return (
<>
<div className="root">
{!isPopupShown && (
<div className="map">
<ReactMapGL
scrollZoom="false"
{...viewport}
mapboxApiAccessToken="//myAPIkey"
mapStyle="mapbox://styles/jay5053/cks5xkaa892cp17o5hyxcuu0z"
onViewportChange={(viewport) => {
setViewport(viewport);
}}
>
{posts &&
posts.map((maps) => (
<Marker
key={maps.id}
latitude={maps.Latitude}
longitude={maps.Longitude}
>
<button
className="marker-btn"
onMouseEnter={() => {
setSelectedProperty(maps);
setViewport({
latitude: 36.592206968562685,
longitude: 3.332469343750031,
width: "0vw",
height: "0vh",
zoom: 1.3
});
setIsPopupShown(true);
}}
>
<img src="placeholder.svg" />
</button>
</Marker>
))}
</ReactMapGL>
</div>
)}
{selectedProperty && isPopupShown && (
<div className="full-popup">
// todo: Have the fullscreen as a hover to close it?
</div>
)}
</div>
</>
);
}
I've added a sandbox for reference if anyone wants to test it out: https://codesandbox.io/s/full-popup-mapbox-stackoverflow-forked-myu0i
You could use the HTMLOverlay
<HTMLOverlay
redraw={(props) => {
return (
<div
style={{
backgroundColor: "rgba(255, 0, 0, 0.5)",
width: isPopupShown ? props.width : 0,
height: isPopupShown ? props.height : 0,
transition: "all .2s ease-in-out",
transform: "scale(1.1)",
overflow: "hidden",
alignItems: "center",
justifyContent: "center"
}}
>
<h1>Text</h1>
</div>
);
}}
/>
Forked your sandbox to create a working example: https://codesandbox.io/s/full-popup-mapbox-stackoverflow-forked-srfvp?file=/src/App.js

Having a different image shown on each Marker hover on a Map

Currently I am using ReactMapGL as my Map component. Here I'm using its HTMLOverlay feature to bring a full screen popup whenever I hover above a marker. I have currently set different image data for all my markers, but when I hover over the marker I only get the 1 same image for all of them. How do I get the marker to show its respective image?
I've added a codesandbox for better reference:
https://codesandbox.io/s/full-popup-mapbox-stackoverflow-forked-p8934?file=/src/App.js:1540-1551
Here's my code:
<ReactMapGL
{...viewport}
mapboxApiAccessToken={YOURMAPBOXTOKEN}
mapStyle="mapbox://styles/mapbox/dark-v9"
onViewportChange={(viewport) => {
setViewport(viewport);
}}
>
{posts &&
posts.map((item) => (
<HTMLOverlay
redraw={(props) => {
{
/* todo: grow animation from center */
}
return (
<div
style={{
backgroundColor: "rgba(255, 0, 0, 0.5)",
width: isPopupShown ? props.width : 0,
height: isPopupShown ? props.height : 0,
transition: "all .2s ease-in-out",
transform: "scale(1.1)",
overflow: "hidden",
alignItems: "center",
justifyContent: "center"
}}
>
{/* todo: text/content position */}
<img src={item.backgroundImage} alt="bg" />
</div>
);
}}
/>
))}
{posts &&
posts.map((item) => (
<Marker
key={item.id}
latitude={item.latitude}
longitude={item.longitude}
>
<button className="marker-btn">
<img
style={{
width: 48,
height: 48
}}
onMouseEnter={() => {
setSelectedProperty(item);
setIsPopupShown(true);
}}
onMouseOut={() => {
setSelectedProperty(null);
setIsPopupShown(false);
}}
alt="Marker"
/>
</button>
</Marker>
))}
</ReactMapGL>
You'd have to selectively render the HTMLOverlap for whatever pin is currently hovered over.
{selectedProperty && (
<HTMLOverlay
redraw={(props) => {
{
/* todo: grow animation from center */
}
return (
<div
style={{
width: isPopupShown ? props.width : 0,
height: isPopupShown ? props.height : 0,
transition: "all .2s ease-in-out",
transform: "scale(1.1)",
overflow: "hidden",
alignItems: "center",
justifyContent: "center",
backgroundImage: `url(${selectedProperty.backgroundImage})`,
backgroundSize: "cover",
backgroundRepeat: "no-repeat"
}}
>
{/* some text */}
</div>
);
}}
/>
)}
Here's a sandbox with working example.

justifyContent with createStyles in TypeScript

I have a toolbar where I am using 2 icons that appear on the left end. Currently, I am using this styling method:
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
display: 'flex',
},
appBar: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
},
drawer: {
width: drawerWidth,
flexShrink: 0,
},
drawerPaper: {
width: drawerWidth,
},
panelheaderRight: {
marginRight: 0,
right: 0,
},
toolbar: theme.mixins.toolbar,
content: {
flexGrow: 1,
// justifyContent: spaceBetween,
backgroundColor: theme.palette.background.default,
padding: theme.spacing(3),
},
}),
);
I want the icons to appear on the right end. If I add a separate css file with this, it works:
.toolbar-class{
justify-content:space-between;
}
but I want to use it inside the createStyles. There's no 'space-between' option in createStyles. This is how a portion of my component looks like:
<AppBar position="fixed" className={classes.appBar}>
<Toolbar className="toolbar-class">
<Typography variant="h6" noWrap>
Al
</Typography>
<div className="panelheaderRight">
<NotificationsIcon />
{/* <ExitToAppIcon onClick={() =>
<ExitToAppIcon onClick={logout}></ExitToAppIcon>
</div>
</Toolbar>
</AppBar>
Is there any way I can move the icons to the left using createStylesand without adding a separate css file?
Some notice points:
Change justify-content to justifyContent, and value as string.
No need to use createStyels for makeStyles
const useStyles = makeStyles((theme: Theme) => ({
toolBar: {
justifyContent: 'space-between'
},
...
...
<Toolbar className={classes.toolBar}>

react-virtualized - calling public methods on Grid

I'd like to access the public method recomputeGridSize on one of the Grids that I'm rendering. I've created the ref but when I try call the method it appears that the method is not available.
See below where the ref is defined in the final Grid:
render() {
const { structure, columnHeaderIndex, variables } = this.props;
const {
sidebarWidth,
headerHeight,
headerRowCount,
height,
gridHeight,
gridWidth
} = variables;
const rowCount = structure.length;
const columnCount = columnHeaderIndex.length;
if (structure.length === 0 || columnCount.length === 0) return null;
console.log(this.bodyGrid);
return (
<div>
<ScrollSync>
{({
clientHeight,
clientWidth,
onScroll,
scrollHeight,
scrollLeft,
scrollTop,
scrollWidth
}) => {
return (
<div>
<div
className="LeftSideGridContainer"
style={{
position: 'absolute',
top: 0,
left: 0,
backgroundColor: 'black',
borderBottom: '1px solid black',
color: 'white'
}}
>
<Grid
cellRenderer={this.renderLeftHeaderCell}
className="header-grid"
width={sidebarWidth + 1}
columnWidth={sidebarWidth + 1}
height={headerHeight}
rowHeight={headerHeight}
rowCount={1}
columnCount={1}
/>
</div>
<div
className="LeftSideGridContainer"
style={{
position: 'absolute',
top: headerHeight,
left: 0,
borderTop: '1px solid black',
backgroundColor: 'white',
color: 'black'
}}
>
<Grid
cellRenderer={this.renderLeftSideCell}
columnWidth={sidebarWidth + 1}
columnCount={1}
className="left-side-grid"
height={height}
rowHeight={gridHeight}
rowCount={rowCount}
scrollTop={scrollTop}
width={sidebarWidth + 1}
/>
</div>
<div className="grid-column">
<AutoSizer disableHeight>
{({ width }) =>
<div>
<div
style={{
height: headerHeight,
width: width - scrollbarsize(),
overflow: 'hidden'
}}
>
<Grid
className="header-grid"
cellRenderer={this.cellRenderer}
cellRangeRenderer={this.renderHeaderCells}
columnWidth={gridWidth}
columnCount={columnCount}
height={headerHeight}
rowHeight={headerHeight / headerRowCount}
rowCount={headerRowCount}
scrollLeft={scrollLeft}
width={width - scrollbarsize()}
/>
</div>
<div
style={{
height: height,
width: width,
borderLeft: '1px solid black',
borderTop: '1px solid black'
}}
>
<Grid
className="calendar-body"
cellRenderer={this.cellRenderer}
cellRangeRenderer={this.cellRangeRenderer}
columnWidth={gridWidth}
columnCount={columnCount}
height={height}
rowHeight={gridHeight}
rowCount={rowCount}
width={width}
onScroll={onScroll}
ref={ref => {
this.bodyGrid = ref;
}}
/>
</div>
</div>}
</AutoSizer>
</div>
</div>
);
}}
</ScrollSync>
</div>
);
}
And you can see that if I console.log(this.bodyGrid) that none of the public methods defined in the documentation are available:
Am I doing something wrong here?
I don't think the screenshot shows what you think it shows. The Grid API methods should be within a __proto__ proprety further down:
Without seeing your full code it's not really possible to tell what's going on, but Grid definitely defines a method recomputeGridSize. The CellMeasurer component, for example, works by calling this method.

Categories