【发布时间】:2022-01-01 16:21:30
【问题描述】:
我正在使用 React 制作一个名为 Random Quote Machine 的项目。并尝试在 React 组件中的状态更新时进行一些动画转换。但我不希望动画过渡影响所有内容。
在进入问题之前,这是我的代码:
CSS 代码:
@import url('https://fonts.googleapis.com/css2?family=Bitter:ital,wght@0,200;0,400;0,600;0,700;1,400&display=swap');
// Font Variable
$main-fonts: 'Bitter', serif;
// Color variable
$default-color: #d1d1d1;
$white-color: #ffffff;
$black-color: #000000;
// Animation Fade-In transition
@mixin animation($time){
animation: fadeIn $time;
-webkit-animation: fadeIn $time;
-moz-animation: fadeIn $time;
-o-animation: fadeIn $time;
-ms-animation: fadeIn $time;
}
// Start of evert keyframes //
@keyframes fadeIn {
0% {opacity:0;}
100% {opacity:1;}
}
@-moz-keyframes fadeIn {
0% {opacity:0;}
100% {opacity:1;}
}
@-webkit-keyframes fadeIn {
0% {opacity:0;}
100% {opacity:1;}
}
@-o-keyframes fadeIn {
0% {opacity:0;}
100% {opacity:1;}
}
// End of keyframes //
// Classes to add to React when state updated for it's element performed the animation
.animation-transition {
@include animation(2.5s);
}
// HTML LAYOUT //
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
color: $white-color;
font-family: $main-fonts;
font-weight: 700;
line-height: 1.6;
}
.wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
.quote-box {
background: $white-color;
display: table;
width: 500px;
padding: 2rem 3rem;
border-radius: 5px;
z-index: 1;
.quote {
color: $black-color;
padding: 0rem 1.6rem;
.quote-text {
font-size: 1.3rem;
}
.quote-icon {
width: 35px;
margin-bottom: -8px;
margin-right: 10px;
}
}
.quote-author {
color: $black-color;
text-align: right;
padding: 1.5rem 0rem;
font-weight: 400;
}
.buttons {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 0.45rem;
& > * {
background-color: $black-color;
color: $white-color;
height: 38px;
border-radius: 3px;
font-weight: 400;
padding: 0.5rem 1rem;
cursor: pointer;
}
.tweet-quote-button {
text-decoration: none;
font-size: 0.9rem;
}
.new-quote-button {
font-size: 0.85rem;
}
.tweet-quote-button:hover, .new-quote-button:hover {
opacity: 0.8;
}
}
}
.footer {
text-align: center;
font-weight: 600;
font-size: 0.8rem;
margin-top: 1rem;
span a {
color: $white-color;
text-decoration: none;
}
}
反应代码:
// START OF App Parent Component //
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
quote: "",
author: "",
color: "",
fade: false
}
this.getData = this.getData.bind(this);
this.handleClick = this.handleClick.bind(this);
this.animationStart = this.animationStart.bind(this);
}
/* RANDOMLY GET VALUE FROM QUOTE OBJECT and color arrays to store as state value */
getData() {
const n = Math.floor(Math.random() * 21);
const q = QUOTE[n]['quote'];
const a = QUOTE[n]['author'];
const c = colors[n];
this.setState({
quote: q,
author: a,
color: c
});
}
/* TRIGGERED WHEN USER CLICK BUTTON TO SET STATE TRUE OR FALSE OF TRANSITION ANIMATION */
animationStart() {
this.setState({
fade: true
})
setTimeout(() => {
console.log("false called");
this.setState({
fade: false
})
}, 2400);
}
/* TRIGGER WHEN USER CLICK NEW QUOTE BUTTON, GET NEW VALUE FOR STATE TO RENDERED */
handleClick() {
this.getData();
this.animationStart();
}
/* THIS WILL HANDLE STATE TO PASS TO CHILD IN VERY FIRST RENDER */
componentDidMount() {
this.getData();
this.animationStart();
}
render() {
return (
<div>
<QuoteBox quote={this.state.quote} author={this.state.author} color={this.state.color} fade={this.state.fade} handleClick={this.handleClick}/>
</div>
)
}
}
// END OF PARENT COMPONENT //
// START OF QUOTE BOX CHILD COMPONENT //
class QuoteBox extends React.Component {
constructor(props) {
super(props)
}
render() {
{/* GET QUOTE-LEFT ICON FROM CODEPEN ASSETS*/}
const iconQuote = <svg class="quote-icon" viewBox="0 0 512 512" title="quote-left">
<path d="M464 256h-80v-64c0-35.3 28.7-64 64-64h8c13.3 0 24-10.7 24-24V56c0-13.3-10.7-24-24-24h-8c-88.4 0-160 71.6-160 160v240c0 26.5 21.5 48 48 48h128c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48zm-288 0H96v-64c0-35.3 28.7-64 64-64h8c13.3 0 24-10.7 24-24V56c0-13.3-10.7-24-24-24h-8C71.6 32 0 103.6 0 192v240c0 26.5 21.5 48 48 48h128c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48z" />
</svg>
{/* CHANGE THE BACKGROUND OF HTML BODY AFTER RENDER*/}
{/*document.body.style.backgroundColor = this.props.color;
if (this.props.fade) {
document.body.classList.add('animation-transition');
} else {
document.body.classList.remove('animation-transition');
}*/}
return (
<div style={{'backgroundColor': this.props.color}} className={`wrapper ${this.props.fade ? 'animation-transition' : ''}`}>
{/* START OF QUOTE BOX WRAPPER */}
<div id="quote-box" className="quote-box">
{/* QUOTE TEXT, ALWAYS UPDATE FROM PROPS PASSED BY PARENT'S STATE */}
<div className="quote">
<span style={{'color': this.props.color, 'fill': this.props.color}} id="text" className={`quote-text ${this.props.fade ? 'animation-transition' : ''}`}>{iconQuote} {this.props.quote}</span>
</div>
{/* AUTHOR TEXT, ALWAYS UPDATE FROM PROPS PASSED BY PARENT'S STATE */}
<div style={{'color': this.props.color}} id="author" className={`quote-author ${this.props.fade ? 'animation-transition' : ''}`}>
<span>- {this.props.author}</span>
</div>
{/* BUTTON WRAPPER */}
<div className="buttons">
{/* TWITTER BUTTON, UPDATE BACKGROUND FROM PROPS */}
<a style={{'backgroundColor': this.props.color}} id="tweet-quote" class="tweet-quote-button" href="twitter.com/intent/tweet" target="_blank">
tweet <FontAwesomeIcon icon={['fab', 'twitter']} />
</a>
{/* NEW QUOTE BUTTON, UPDATE BACKGROUND FROM PROPS */}
<button style={{'backgroundColor': this.props.color}} id="new-quote" className="new-quote-button" onClick={this.props.handleClick} onAnimationEnd={this.props.animationEnd}>new quote</button>
</div>
</div>
{/* END OF QUOTE BOX WRAPPER */}
{/* START OF FOOTER */}
<div className="footer">
<span>created by <a href="https://codepen.io/thekevinkun" target="_blank">Kevinkun</a></span>
</div>
{/* END OF FOOTER */}
</div>
)
}
}
// END OF CHILD COMPONENT //
ReactDOM.render(<App />, document.getElementById('root'));
希望大家可以访问codepen以获得更好的理解:My Projects
项目说明:每当用户点击新报价按钮时,它会在显示新报价以及新的文本颜色和背景颜色之前进行淡入淡出转换。
问题是:正如您在我的 codepen 中看到的那样,我不希望包裹所有内容的 白框 跟随动画过渡。
这是我要实现的例子:freeCodeCamp Random Quote Machine
您可以看到,在 freeCodeCamp 示例中,白框没有进行转换。
我知道这听起来很简单,但我被困住了。我希望你们理解并写一个解决方案。谢谢。
【问题讨论】:
标签: html css reactjs animation css-transitions