I’m trying to build a section like in the screen capture below (it’s the intro block of our current website). For the movement of the individual images, I’m using translate(X, Y)
.
Screen capture:
https://drive.google.com/file/d/1S1WKFlw5Q9k6QtTBYJwEfoI1kgTY4mT-/view?usp=sharing
I managed to re-create it with Frontity/React, but I the animation seems way less smooth than what we did on our current site. I noticed that the component completely re-renders when applying the new CSS values. Isn’t that more heavy than it should be?
Can I change something, so only the transformation will be applied, instead of a complete re-rendering? Or is this something that is caused by the core of React?
This is my code for the images:
import React, { useEffect, useState } from "react";
import { connect, styled, css } from "frontity";
import FeaturedMedia from "./featured-media";
const FeaturedProjectImages = ({ state, actions, imgs, imagesKeys, item }) => {
useEffect(() => {
actions.source.fetch(`/media/${imgs}`);
}, []);
const img = state.source.get(`/media/${imgs}`);
// setting up an array with multipliers
const imageProperties = {
'back_parallax_layer': {
'multiplier': 0.025,
'size': '110%',
},
'middle_parallax_layer': {
'multiplier': 0.05,
'size': '110%',
},
'front_parallax_layer': {
'multiplier': 0.075,
'size': '110%',
},
'static_layer': {
'multiplier': 0.0025,
'size': '75%',
},
'top_static_layer': {
'multiplier': 0.1,
'size': '80%',
},
};
const { mouseMove } = actions.theme;
return (img.isReady ? (
<FeaturedProjectImagesWrapper onMouseMove={(event) => { mouseMove({ event: event }) }} onMouseLeave={resetMove} className="mouseMoveTarget">
{
imagesKeys.map(key => {
return (
<FeaturedMedia
id={item.acf.intro_block_images[key].id}
css={css`
position: absolute;
height: ${imageProperties[key].size};
width: ${imageProperties[key].size};
transform: translate(${state.theme.introBlockPosition.x * imageProperties[key].multiplier}px, ${state.theme.introBlockPosition.y * imageProperties[key].multiplier}px);
will-change: transform;
transition: .05s ease-in-out;
transition-property: all;
transition-property: transform;
margin-top: auto;
margin-bottom: auto;
margin-left: auto;
margin-right: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
`}
/>
)
})
}
</FeaturedProjectImagesWrapper>
) : null);
}
export default connect(FeaturedProjectImages);
const FeaturedProjectImagesWrapper = styled.div`
width: 100%;
height: 100%;
`;
And this is my action in the index.js
:
const marsTheme = {
...
state: {
theme: {
...
introBlockPosition: {
x: 0,
y: 0,
wait: false
},
},
},
/**
* Actions are functions that modify the state or deal with other parts of
* Frontity like libraries.
*/
actions: {
theme: {
...
mouseMove: ({ state }) => ({ event }) => {
event.preventDefault();
event.stopPropagation();
if (state.theme.introBlockPosition.wait == false) {
const mouseMoveTarget = document.querySelector('.mouseMoveTarget');
state.theme.introBlockPosition.x = (mouseMoveTarget.offsetWidth / 2 + (event.clientX - mouseMoveTarget.offsetWidth));
state.theme.introBlockPosition.y = (mouseMoveTarget.offsetHeight / 2 + (event.clientY - mouseMoveTarget.offsetHeight));
state.theme.introBlockPosition.wait = true;
// setting a timeout to throttle the animation somewhat
setTimeout(function () {
state.theme.introBlockPosition.wait = false;
// console.log('waiting no more');
}, 25);
}
}
},
},
};