[英]React.js - Change image based on door puzzle answer
我在React.js制作了這個小游戲:
演示: https: //door-game.netlify.com/ App.js文件: https : //github.com/Blazej6/Door-game/blob/master/src/App.js
我想在中心按鈕中渲染一個與所選框架相匹配的圖片。 3 Vue渲染vue,3反應 - 反應等。
我如何制定邏輯呢?
做了一些實驗性的approches,比如在app和圓形組件中放置一個顏色類錨,但它似乎根本沒有讀取當前狀態,至少不是從當前角度,也試圖在一個鏈接中使用反應路由器和包圍圓組件,但是無論出於何種原因,這真的搞砸了CSS
真的沒有人能勝任這項任務嗎?
對於像這樣的簡單應用程序,還沒有必要集成redux / mobx。 我推薦的是在React中非常常見的東西,那就是提升你的狀態 。
我們可以通過三個步驟完成此任務:
愚蠢的Circleone
, Circletwo
, Circlethree
組件。 他們只需要知道當前角度是什么,以便渲染
應該告訴ClawCircle
要渲染的圖像(或其他空白)
App
需要保持所有這些信息的狀態(因此我們已經將狀態從CircleX
“提升”到其父級App
)。
我們假設信息是通過prop currentAngle
提供給我們的,而不是將currentAngle
保持在狀態中。 當一個圓圈被點擊時,我們只會告訴誰創建了我們被點擊的圓圈,因為他們會傳給我們一個名為onClick
的道具。
由於我們現在不需要跟蹤我們的狀態,我們可以使組件無狀態並將其轉換為功能組件。
例如, CircleOne
可能看起來更像是這樣:
const CircleOne = ({ currentAngle, onClick }) => (
<div
className="App-logo small-logo"
alt="logo"
style={{ transform: `rotateZ(${currentAngle}deg)` }}
onClick={onClick}
>
<div className="little-circle one react">
{/* ... rest of your divs */}
</div>
);
接下來,讓我們改變ClawCircle
,我們將給它一個可選的imageClass
prop,可能是claw-react
, claw-vue
等,或者它可能只是一個空字符串(相應地更新css以渲染圖像!)。 所以render
方法可能會變成這樣:
render() {
const circleStyle = { transform: `rotateZ(${this.props.currentAngle}deg)` };
return (
<div
className={`App-logo claw-circle ${this.props.imageClass}`}
alt="logo"
style={circleStyle}
onClick={this.rotateCircle.bind(this)}
/>
);
}
順便說一下,綁定調用可以在構造函數中完成而不是渲染方法,這樣我們就不必在每次重新渲染組件時重新綁定。
constructor(props) {
super(props);
// constructor code
this.rotateCircle = this.rotateCircle.bind(this);
}
// later: onClick={this.rotateCircle}
這是一個更復雜的步驟,因為我們現在必須將繁重的工作委托給App
而不是個人Circle
。
所以App
需要知道每個圓圈的角度,並處理每個圓圈點擊時發生的事情。 此外,當角度改變時,我們想檢查它們中的所有三個是否相等。 如果它們相等,我們需要告訴ClawCircle
要渲染的圖像。
總而言之,它可能看起來像這樣:
編輯:我應該嘗試運行此代碼,然后在此處動態編寫。 這是完整版(經過測試!)只需確保你的CSS中有claw-react
claw-vue
和claw-angular
規則
import React, { Component } from 'react';
import './App.css';
import { CSSTransitionGroup } from 'react-transition-group';
class HalfCircle extends Component {
render() {
return (
<div className="App-logo half-circle" alt="logo">
</div>
);
}
}
const Circleone = ({ currentAngle, onClick }) => (
<div
className="App-logo small-logo"
alt="logo"
style={{ transform: `rotateZ(${currentAngle}deg` }}
onClick={onClick}
>
<div className="little-circle one react"></div>
<div className="little-circle two angular"></div>
<div className="little-circle three vue"></div>
</div>
);
const Circletwo = ({ currentAngle, onClick }) => (
<div
className="App-logo big-logo"
alt="logo"
style={{ transform: `rotateZ(${currentAngle}deg` }}
onClick={onClick}
>
<div className="little-circle un react"></div>
<div className="little-circle dos angular"></div>
<div className="little-circle tres vue"></div>
</div>
);
const Circlethree = ({ currentAngle, onClick }) => (
<div
className="App-logo biggest-logo"
alt="logo"
style={{ transform: `rotateZ(${currentAngle}deg` }}
onClick={onClick}
>
<div className="little-circle ein react"></div>
<div className="little-circle zwei angular"></div>
<div className="little-circle drei vue"></div>
</div>
);
class ClawCircle extends Component {
constructor(props){
super(props)
this.state = {
currentAngle: 45,
anglePerClick: 360,
}
}
rotateCircle() {
const { currentAngle, anglePerClick } = this.state;
this.setState({
currentAngle: currentAngle + anglePerClick
})
}
render() {
const circleStyle = {
transform: `rotateZ(${this.state.currentAngle}deg)`
}
return (
<div
className={`App-logo claw-circle ${this.props.imageName}`}
alt="logo"
style={circleStyle}
onClick={this.rotateCircle.bind(this)}
/>
);
}
}
const getNameForAngle = (one, two, three) => {
if (one === two && one === three) {
switch(one) {
case 120:
return 'claw-react';
case 240:
return 'claw-vue';
case 360:
return 'claw-angular';
default:
return '';
}
}
return '';
};
class App extends Component {
constructor(props) {
super(props);
this.state = {
oneAngle: 120,
twoAngle: 120,
threeAngle: 120,
};
this.handleOneClick = this.handleOneClick.bind(this);
this.handleTwoClick = this.handleTwoClick.bind(this);
this.handleThreeClick = this.handleThreeClick.bind(this);
}
handleClick(circle) {
const nextAngle = this.state[circle] + 120;
this.setState ({
[circle]: nextAngle
});
}
handleOneClick() {
this.handleClick('oneAngle');
}
handleTwoClick() {
this.handleClick('twoAngle');
}
handleThreeClick() {
this.handleClick('threeAngle');
}
render() {
const { oneAngle, twoAngle, threeAngle } = this.state;
const imageName = getNameForAngle(oneAngle, twoAngle, threeAngle);
return (
<div className="App">
<header className="App-header">
<Circleone
currentAngle={oneAngle}
onClick={this.handleOneClick}
/>
<Circletwo
currentAngle={twoAngle}
onClick={this.handleTwoClick}
/>
<Circlethree
currentAngle={threeAngle}
onClick={this.handleThreeClick}
/>
<ClawCircle imageName={imageName} />
<HalfCircle/>
</header>
</div>
);
}
}
export default App;
好吧,似乎組件封裝在這里真的不喜歡這個有趣的王者,無論如何我得到的應用程序使用純js,所有冰雹全局變量!
如果有人需要它,這是codepen: https ://codepen.io/Raitar/pen/OOWRzb
當然JS代碼:
var angle=0;
var angle2=0;
var angle3=0;
count = 0;
count2 = 0;
count3 = 0;
document.getElementById("small-logo").addEventListener("click", rotateCircle)
document.getElementById("big-logo").addEventListener("click", rotateCircle2)
document.getElementById("biggest-logo").addEventListener("click", rotateCircle3)
function rotateCircle(){
angle+=120;
this.style.webkitTransform="rotate("+angle+"deg)";
count += 1;
if (count > 2) {
count = 0;
}
}
function rotateCircle2(){
angle2+=120;
this.style.webkitTransform="rotate("+angle2+"deg)";
count2 += 1;
if (count2 > 2) {
count2 = 0;
}
}
function rotateCircle3(){
angle3+=120;
this.style.webkitTransform="rotate("+angle3+"deg)";
count3 += 1;
if (count3 > 2) {
count3 = 0;
}
}
angular = "background-image:
url(https://raw.githubusercontent.com/Blazej6/Door-
game/master/src/img/angular.png);"
react = "background-image:
url(https://raw.githubusercontent.com/Blazej6/Door-
game/master/src/img/react.png);"
vue = "background-image: url(https://raw.githubusercontent.com/Blazej6/Door-
game/master/src/img/vue.png);"
document.getElementById("claw-circle").addEventListener("click",
changeCenter)
var x = document.getElementById("claw-circle")
function changeCenter() {
if (count == 0 && count2 == 0 && count3 == 0) {
x.style.cssText = angular;
} else if(count == 1 && count2 == 1 && count3 == 1) {
x.style.cssText = react;
} else if(count == 2 && count2 == 2 && count3 == 2) {
x.style.cssText = vue;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.