簡體   English   中英

React.js - 根據門拼圖答案更改圖像

[英]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中非常常見的東西,那就是提升你的狀態

我們可以通過三個步驟完成此任務:

  1. 愚蠢的CircleoneCircletwoCirclethree組件。 他們只需要知道當前角度是什么,以便渲染

  2. 應該告訴ClawCircle要渲染的圖像(或其他空白)

  3. App需要保持所有這些信息的狀態(因此我們已經將狀態從CircleX “提升”到其父級App )。

第1步

我們假設信息是通過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>
);

第2步

接下來,讓我們改變ClawCircle ,我們將給它一個可選的imageClass prop,可能是claw-reactclaw-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}

第3步

這是一個更復雜的步驟,因為我們現在必須將繁重的工作委托給App而不是個人Circle

所以App需要知道每個圓圈的角度,並處理每個圓圈點擊時發生的事情。 此外,當角度改變時,我們想檢查它們中的所有三個是否相等。 如果它們相等,我們需要告訴ClawCircle要渲染的圖像。

總而言之,它可能看起來像這樣:

編輯:我應該嘗試運行此代碼,然后在此處動態編寫。 這是完整版(經過測試!)只需確保你的CSS中有claw-react claw-vueclaw-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM