>  기사  >  웹 프론트엔드  >  반응으로 슬라이딩을 구현하는 방법

반응으로 슬라이딩을 구현하는 방법

藏色散人
藏色散人원래의
2022-12-30 11:09:002209검색

React에서 슬라이딩을 구현하는 방법: 1. onTouchStart 이벤트에서 터치를 찾고 식별자에 따라 새로운 터치의 발생을 기록합니다. 2. onTouchMove 이벤트의 식별자에 따라 터치가 통과한 각 지점의 좌표를 기록합니다. 3. onTouchEnd 이벤트에서 종료 터치 이벤트를 찾은 후 종료 터치 이벤트가 교차하는 지점을 기준으로 수행할 제스처를 계산합니다.

반응으로 슬라이딩을 구현하는 방법

이 튜토리얼의 운영 환경: Windows 10 시스템, 반응 버전 18.0.0, Dell G3 컴퓨터.

반응에서 슬라이딩을 구현하는 방법은 무엇입니까?

react는 좌우 슬라이딩 효과를 구현합니다

React에서 슬라이딩 제스처 구현

반응으로 슬라이딩을 구현하는 방법

최근 모바일 단말기에서 React의 슬라이딩 페이지 넘김 기능에 대해 조금 다루었습니다.

검색을 시작했는데 적합한 라이브러리를 찾을 수 없었습니다. 제가 찾은 유일한 라이브러리는 첫눈에 프론트엔드 세계에 400~500개의 별이 있다는 것을 알았습니다. === 제가 원하는 기능이 아닌 것 같았습니다. 잊어버리세요. 그냥 직접 작성해 보세요.

원리를 살펴보면 기본적으로 onTouchStart, onTouchMove 및 onTouchEnd의 세 가지 이벤트와 함께 작동하여 슬라이딩 지점을 기록한 다음 제스처를 계산합니다.

분명히 멀티 터치의 경우 각 터치 포인트의 경로를 찾아야 하므로 다음 단계가 있습니다.

  • onTouchStart 이벤트에서 터치를 찾고 식별자에 따라 새로운 터치 발생을 기록합니다.

  • onTouchMove 이벤트에서 식별자를 기반으로 터치가 통과한 각 지점의 좌표를 기록합니다.

  • onTouchEnd 이벤트에서 엔딩 터치 이벤트를 찾은 후, 엔딩 터치 이벤트가 교차하는 지점에서 수행할 제스처를 계산합니다.

저는 그냥 위아래로 슬라이딩하는 기능만 원해서 싱글터치 상황에만 집중합니다.

다음으로 코드 작성을 준비합니다. 아뇨, 먼저 어떻게 캡슐화할지 생각해야 합니다. 스스로 묻고 답해보세요.

싱글턴 패턴을 사용하고 싶습니다.

사용하기 너무 번거로운가요? 먼저 인스턴스화해야 하나요?

그럼 정적 클래스를 사용하시겠습니까?

이미 js가 있다면 어떤 정적 클래스가 더 필요한가요? 사전만 출력하면 끝입니다.

그럼 자위를 시작해 볼까요.

데이터 부분

const touchData = { touching: false, trace: [] };
// 单点触摸,所以只要当前在触摸中,就可以把划过的点记录到trace中了
function* idGenerator() {
  let start = 0;
  while (true) {
    yield start;
    start += 1;
  }
}
//这个生成器用来生成不同事件回调的id,这样我们可以注册不同的回调,然后在不需要的时候删掉。
const callbacks = {
  onSlideUpPage: { generator: idGenerator(), callbacks: {} },
  onSlideDownPage: { generator: idGenerator(), callbacks: {} }
};
//存储向上、下换页的回调函数

녹화 터치 부분

여기의 이벤트는 네이티브 이벤트가 아닌 리액트의 합성 이벤트를 처리합니다.

function onTouchStart(evt) {
  if (evt.touches.length !== 1) {
    touchData.touching = false;
    touchData.trace = [];
    return;
  }
  touchData.touching = true;
  touchData.trace = [{ x: evt.touches[0].screenX, y: evt.touches[0].screenY }];
}
//在onTouchStart事件,如果是多点触摸直接清空所有数据。如果是单点触摸,记录第一个点,并设置状态
function onTouchMove(evt) {
  if (!touchData.touching) return;
  touchData.trace.push({
    x: evt.touches[0].screenX,
    y: evt.touches[0].screenY
  });
}
//如果在单点触摸过程中,持续记录触摸的位置。
function onTouchEnd() {
  if (!touchData.touching) return;
  let trace = touchData.trace;
  touchData.touching = false;
  touchData.trace = [];
  handleTouch(trace);  //判断touch类型并调用适当回调
}
//在触摸结束事件,中调用handleTouch函数来处理手势判断逻辑并执行回调

handleTouch 기능

function handleTouch(trace) {
  let start = trace[0];
  let end = trace[trace.length - 1];
  if (end.y - start.y > 200) {
    Object.keys(callbacks.onSlideUpPage.callbacks).map(key =>
      callbacks.onSlideUpPage.callbacks[key]()
    ); 
    // 向上翻页
  } else if (start.y - end.y > 200) {
    Object.keys(callbacks.onSlideDownPage.callbacks).map(key =>
      callbacks.onSlideDownPage.callbacks[key]()
    );
    // 向下翻页
  }
}

여기서는 페이지 업, 다운 두 가지 이벤트만 판단합니다. 이벤트에 도달하면 해당 이벤트에 등록된 모든 콜백이 호출됩니다. 콜백이 여러 개인 경우 필요에 따라 콜백의 실행 순서를 조정할 수 있습니다. 여기에는 순서가 있어서는 안 됩니다.

인터페이스 부분

function addSlideUpPage(f) {
  let key = callbacks.onSlideUpPage.generator.next().value;
  callbacks.onSlideUpPage.callbacks[key] = f;
  return key;
}
//注册向上滑动回调并返回回调id
function addSlideDownPage(f) {
  let key = callbacks.onSlideDownPage.generator.next().value;
  callbacks.onSlideDownPage.callbacks[key] = f;
  return key;
}
//注册向下滑动回调并返回回调id
function removeSlideUpPage(key) {
  delete callbacks.onSlideUpPage.callbacks[key];
}
//使用回调id删除向上滑动回调
function removeSlideDownPage(key) {
  delete callbacks.onSlideDownPage.callbacks[key];
}
//使用回调id删除向下滑动回调
export default {
  onTouchEnd,
  onTouchMove,
  onTouchStart,
  addSlideDownPage,
  addSlideUpPage,
  removeSlideDownPage,
  removeSlideUpPage
};
//输出所有接口函数

별로 할 말이 없고 너무 단순하고 투박합니다. 다음으로, React에서 사용해 보겠습니다!

next.js에서

을 사용하여 next.js+create-next-app을 사용합니다. 페이지 디렉터리의 _app.js 파일에 모든 터치 이벤트를 바인딩합니다.

//pages/_app.js
import App, { Container } from "next/app";
import React from "react";
import withReduxStore from "../redux/with-redux-store";
import { Provider } from "react-redux";
import touch from "../components/touch";

class MyApp extends App {
  render() {
    const { Component, pageProps, reduxStore } = this.props;
    return (
      <Container>
        <Provider store={reduxStore}>
          <div
            onTouchEnd={touch.onTouchEnd}
            onTouchStart={touch.onTouchStart}
            onTouchMove={touch.onTouchMove}
          >
            <Component {...pageProps} />
          </div> 
{
// 将所有导出的touch事件绑定在最外层的div上
// 这样就可以全局注册事件了
}
        </Provider>
      </Container>
    );
  }
}

export default withReduxStore(MyApp);

다음에는 어떻게 사용하는지 살펴보겠습니다.

import React, {useEffect} from "react";
import touch from "../touch";

const Example = () => {
  useEffect(() => {
    let key = touch.addSlideDownPage(() => {
      console.log("try to slideDownPage!!")
    });
    return () => {
      touch.removeSlideDownPage(key)
      // 用完别忘了删除事件
    };
  }, []);
  return (
    <div>This is an example!!</div>
  );
};

네이티브 리액트에서 사용됨

이 프로젝트는 create-react-app을 사용하여 생성되었습니다

//src/App.js
import React from &#39;react&#39;;
import logo from &#39;./logo.svg&#39;;
import &#39;./App.css&#39;;
import touch from "./components/touch";

function App() {
  return (
    <div className="App"
      onTouchEnd={touch.onTouchEnd}
      onTouchStart={touch.onTouchStart}
      onTouchMove={touch.onTouchMove}
    >
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

결론

누군가가 코드를 정말 유심히 보면 A가 있을 수 있습니다. 질문.react의 합성 이벤트를 사용하는 것 외에도 touch.js의 콘텐츠는 반응과 관련이 없습니다.

그렇습니다. 반응과는 아무런 관련이 없습니다. 설명은 이러한 데이터가 React의 상태 또는 Redux의 상태를 통해 전달될 필요가 없다는 것입니다. 첫째, 성능 측면에서 redux 또는 React의 상태를 업데이트하면 React의 재렌더링이 트리거되며, 둘째, 이러한 인터페이스가 필요하지 않기를 바랍니다. 전역적으로 사용할 수 있으므로 반응 메커니즘을 사용하지 않았습니다. 실제로 이는 React가 제어되지 않는 구성 요소를 호출하는 것과 같습니다.

마지막으로 첨부된 것은 완전한 touch.js

//touch.js
const touchData = { touching: false, trace: [] };

function* idGenerator() {
  let start = 0;
  while (true) {
    yield start;
    start += 1;
  }
}

const callbacks = {
  onSlideUpPage: { generator: idGenerator(), callbacks: {} },
  onSlideDownPage: { generator: idGenerator(), callbacks: {} }
};

function onTouchStart(evt) {
  if (evt.touches.length !== 1) {
    touchData.touching = false;
    touchData.trace = [];
    return;
  }
  touchData.touching = true;
  touchData.trace = [{ x: evt.touches[0].screenX, y: evt.touches[0].screenY }];
}
function onTouchMove(evt) {
  if (!touchData.touching) return;
  touchData.trace.push({
    x: evt.touches[0].screenX,
    y: evt.touches[0].screenY
  });
}
function onTouchEnd() {
  if (!touchData.touching) return;
  let trace = touchData.trace;
  touchData.touching = false;
  touchData.trace = [];
  handleTouch(trace);
}
function handleTouch(trace) {
  let start = trace[0];
  let end = trace[trace.length - 1];
  if (end.y - start.y > 200) {
    Object.keys(callbacks.onSlideUpPage.callbacks).map(key =>
      callbacks.onSlideUpPage.callbacks[key]()
    );
  } else if (start.y - end.y > 200) {
    Object.keys(callbacks.onSlideDownPage.callbacks).map(key =>
      callbacks.onSlideDownPage.callbacks[key]()
    );
  }
}
function addSlideUpPage(f) {
  let key = callbacks.onSlideUpPage.generator.next().value;
  callbacks.onSlideUpPage.callbacks[key] = f;
  return key;
}
function addSlideDownPage(f) {
  let key = callbacks.onSlideDownPage.generator.next().value;
  callbacks.onSlideDownPage.callbacks[key] = f;
  return key;
}
function removeSlideUpPage(key) {
  delete callbacks.onSlideUpPage.callbacks[key];
}
function removeSlideDownPage(key) {
  delete callbacks.onSlideDownPage.callbacks[key];
}
export default {
  onTouchEnd,
  onTouchMove,
  onTouchStart,
  addSlideDownPage,
  addSlideUpPage,
  removeSlideDownPage,
  removeSlideUpPage
};

권장 학습: "react 비디오 튜토리얼"

위 내용은 반응으로 슬라이딩을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.