I am trying to make a hot air balloon styled button that floats (translates over x and y space). Currently I am using CSS variable to set animation properties but I can only do this once or else I get an error saying
"TypeError: Cannot assign to read only property '--animation-time' of object '#'"
How do I work around this to be able to set new random properties for where the animation starts, ends, and how long it lasts?
Currently I have this:
class HotAir extends React.Component{
constructor(props){
super(props);
this.state = {
link: props.link,
cls: props.cls,
img: props.img,
text: props.text,
}
}
render(){
var cssProperties = {};
cssProperties['--animation-time'] = Math.random()*10 + 's';
console.log(cssProperties);
return(
<div className="balloon" style={cssProperties} onAnimationEnd={()=> cssProperties['--animation-time'] = '60s'}>
<Link to={this.state.link}><button className="balloonbutt">
<img src={this.state.img} alt=""></img>
<div className="balloontext">{this.state.text}</div></button>
</Link>
</div>
);
}
}
and this is my relevant css
.balloon{
--animation-time: 60s;
--x-float-start: 10vw;
--y-float-start: 10vh;
--x-float-end: 20vw;
--y-float-end: 20vh;
position: relative;
text-align: center;
color: white;
animation: float var(--animation-time) linear;
}
@keyframes float{
0%{
left: var(--x-float-start);
top: var(--y-float-start);
}
100%{
left: var(--x-float-end);
top: var(--y-float-end);
}
}
I have modified your code in more Reacty way. You were using a var object and mutating the data which is not how React expects things to be done. I have updated my code and hopefully your linting tool won't complain after the changes.
Changes:
cssProperties to state so react will be aware of that property.this.setState({ ...this.state, cssProperties: { '--animation-time': '60' } });
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
interface AppProps {}
interface AppState {
name: string;
cssProperties;
}
class App extends Component<AppProps, AppState> {
constructor(props) {
super(props);
this.state = {
name: 'React',
cssProperties: {
'--animation-time': Math.random() * 10 + 's',
'--x-float-start': Math.trunc(Math.random() * 200) - 10 + 'px',
'--y-float-start': Math.trunc(Math.random() * 200) - 10 + 'px',
'--x-float-end': Math.trunc(Math.random() * 200) - 10 + 'px',
'--y-float-end': Math.trunc(Math.random() * 200) - 10 + 'px'
}
};
}
render() {
console.log(this.state.cssProperties);
return (
<div
className="balloon"
style={this.state.cssProperties}
onAnimationIteration={() => {
console.log(this.state.cssProperties);
this.setState({
...this.state,
cssProperties: {
...this.state.cssProperties,
'--x-float-start': this.state.cssProperties['--x-float-end'],
'--y-float-start': this.state.cssProperties['--y-float-end'],
'--x-float-end': Math.trunc(Math.random() * 200) - 10 + 'px',
'--y-float-end': Math.trunc(Math.random() * 200) - 10 + 'px'
}
});
}}
>
<Hello name={this.state.name} />
<p>Start editing to see some magic happen :)</p>
</div>
);
}
}
render(<App />, document.getElementById('root'));
Update
Since you need an infinite animation, your CSS should have that option.
animation: float var(--animation-time) linear infinite;