旋转正方形的逻辑

时间:2018-12-27 20:20:04

标签: javascript reactjs animation rotation anime.js

以下代码正在使用React。

我有一个位于45度的正方形,其中有四个元素。在单击每个元素时,我希望正方形旋转相关角度,以便单击的元素位于顶部。 (在图像中,当前选择了3。)

请参阅代码中的注释。我希望它能解释我的逻辑。

enter image description here

这是组件代码:

class CentreCtrls extends React.Component {
  constructor(props) {
    super(props);
        this.state = {
            aboutUs: {
                activeCtrl: 0
            }
        }
  }

   // animate the square to rotate the relevant degrees 
   // so that the clicked element is at the top.
   // this logic is flawed and not working correctly
  componentDidUpdate() {
    const activeHeading = this.state.aboutUs.activeCtrl;
    const { centreCtrl } = this.refs;
    const style = centreCtrl.style;
    const currentDeg = parseInt(style.transform.slice(7, -4), 10);
    const position = this.getPosition(activeHeading, 0);
    const degRotation = position * 90;
    console.log('pos:', position, 'deg:', currentDeg, '-', degRotation);
    anime({
      targets: this.refs.centreCtrl,
      rotate: `-${currentDeg + degRotation}deg`,
      duration: 150,
      easing: 'linear',
    });
  }

  onClickHandler = e => 
        const ele = e.target;
    const i = ele.parentNode.getAttribute('data-i');
    this.setState({
      aboutUs: {
        activeCtrl: parseInt(i, 10),
      },
    });
  };


   // the purpose of this function is to find the current value
   // to be assigned to the 'data-i' property on element, this 'data-i'
   // is read in the above 'componentDidUpdate' function to animate
   // the square the relevant degrees so that the clicked square is at
   // top (where the purple 3 is in the image).
  getPosition = (i, activeHeading) => {
    const total = 3; // start: 0, ttl: 4
    let correctSeq = i;
    if (i === activeHeading) {
      correctSeq = 0;
     // if i == 2, then for our rotation purpose, its at position 3 in DOM
     // because of the way, DOM renders elements from left to right within
     // square
    } else if (i === 2) {
      correctSeq = 3;
    } else if (i === 3) {
      correctSeq = 2;
    }
    let pos = total - activeHeading + (correctSeq + 0);
    if (pos > 3) {
      pos = pos - 3;
    }
    return pos;
  };

  render() {
    const { data } = this.props;
    const activeHeading = this.state.aboutUs.activeCtrl;
    return (
      // using the react v15 style ref
      <div
        className="centreCtrl"
        ref="centreCtrl"
        style={{ transform: 'rotate(45deg)' }}
      >
        {data.map((entry, i) => {
          const j = this.getPosition(i, activeHeading);
          return (
            <div
              className="ctrl"
              key={i}
              data-i={j}
              id={`${entry.narrative.heading}`}
              onClick={this.onClickHandler}
            >
              <div
                className="textContainer"
                id={entry.narrative.heading}
                ref={`textRef${i}`}
              >
                {j}
              </div>
            </div>
          );
        })}
      </div>
    );
  }
}

编辑:如何使旋转逻辑正常工作。更重要的是,我正在寻找输入该平方的最佳旋转计算逻辑的输入。看起来比我估计的容易得多。

1 个答案:

答案 0 :(得分:1)

假设您想顺时针旋转,这样的操作可能会有所帮助:

import React from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
import { Container, Square, Block, Top, Bottom } from './components';

const rotateRight = items => {
  const last = items.pop();
  items.unshift(last);
};

class App extends React.Component {
  state = {
    items: ["a", "b", "c", "d"],
    rotation: 0,
  };

  handleClick = i => {
    let start = i;
    let count = 0;
    let items = [...this.state.items];
    const end = items.length - 1;

    while (start <= end) {
      rotateRight(items);
      start += 1;
      count += 1;
    }

    this.setState(state => ({
      rotation: ((count * 90) % 360),
    }));
  };

  render() {
    const { items, rotation } = this.state;

    return (
      <Container>
        <Square rotation={rotation}>
          <Top>
            <Block onClick={() => this.handleClick(0)}>
              {items[0]}
            </Block>
            <Block onClick={() => this.handleClick(1)}>
              {items[1]}
            </Block>
          </Top>
          <Bottom>
            <Block onClick={() => this.handleClick(2)}>{
              items[2]}
            </Block>
            <Block onClick={() => this.handleClick(3)}>
              {items[3]}
            </Block>
          </Bottom>
        </Square>
      </Container>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

StackBlitz链接here