react封装横向滚动组件

在浏览器中封装横向滚动组件确实不是很必要,但是产品说过用户不一定知道shfit+鼠标滚轮就是横向滚动

而普通的监听没有原生的滚动丝滑,借鉴曾经看过的抖音上渡一老师的思路封装了一个横向滚动的组件

ts 复制代码
import React from 'react';
import { ConstructorParamsBase, PageInstance } from '@/abstractClass/PageInstance';

interface State {
  width: number,
  height: number,
}

export class XScrollInstance extends PageInstance<State> {
  vScrollRef = React.createRef<HTMLDivElement>();

  constructor({ forceUpdate, state }: ConstructorParamsBase<State>) {
    super();

    this.setForceUpdate(forceUpdate);
    this.setState({
      height: 0,
      width: 0,
      ...state,
    });
  }

  scrollLeft(scrollNumber: number) {
    this.vScrollRef.current.scrollTop -= scrollNumber;
    this.forceUpdate();
  }

  scrollRight(scrollNumber: number) {
    this.vScrollRef.current.scrollTop += scrollNumber;
    this.forceUpdate();
  }
}
ts 复制代码
import React, { FC, MutableRefObject, useRef } from 'react';
import {
  useCreation, useSize, useUnmount, useUpdate,
} from 'ahooks';
import { css, cx } from '@emotion/css';
import styles from './XScroll.css';
import { XScrollInstance } from './XScrollInstance';

interface Props {
  children: React.ReactNode;
  instanceRef?: MutableRefObject<XScrollInstance>,
  containerClassName?: string
}

export const XScroll: FC<Props> = ({ children, instanceRef, containerClassName }) => {
  const forceUpdate = useUpdate();
  const xScrollRef = useRef();
  const size = useSize(xScrollRef);

  const pageInstance = useCreation(() => {
    const instance = new XScrollInstance({ forceUpdate, state: {} });
    if (instanceRef) {
      instanceRef.current = instance;
    }
    return instance;
  }, []);

  pageInstance.setState({
    width: size?.width || 0,
    height: size?.height || 0,
  });

  useUnmount(() => {
    if (instanceRef) {
      instanceRef.current = null;
    }
  });

  return (
    <div
      ref={xScrollRef}
      className={cx(css`width: 100%;height: 100%;`, containerClassName)}
    >
      <div
        ref={pageInstance.vScrollRef}
        className={cx(styles.vScroll, css`
          position: relative;
          width: calc(${size?.height} * 1px);
          height: calc(${size?.width} * 1px);
          overflow: auto;
          scroll-behavior: smooth;
          transform-origin: 0 0;
          transform: translateY(calc(${size?.height} * 1px)) rotate(-90deg);
        `)}
      >
        <div
          className={cx(css`
            height: calc(${size?.height} * 1px);
            position: absolute;
            left: 100%;
            transform-origin: 0 0;
            transform: rotate(90deg);
            padding-top: 1px;
          `)}
        >
          {children}
        </div>
      </div>
    </div>
  );
};
css 复制代码
.vScroll::-webkit-scrollbar {
    width: 0;
}

用法只需用组件包裹过长dom就可以了

相关推荐
destinying4 分钟前
当部分请求失败时,前端如何保证用户体验不崩溃?
前端·javascript·程序员
幼儿园技术家9 分钟前
Diff算法的简单介绍
前端
陈随易10 分钟前
为VSCode扩展开发量身打造的UI库 - vscode-elements
前端·后端·程序员
叁金Coder13 分钟前
业务系统跳转Nacos免登录方案实践
前端·javascript·nginx·nacos
蓝倾14 分钟前
京东商品销量数据如何获取?API接口调用操作详解
前端·api·fastapi
stoneship14 分钟前
满帮微前端
前端
GKDf1sh15 分钟前
【前端安全】聊聊 HTML 闭合优先级和浏览器解析顺序
前端·安全·html
前端老鹰16 分钟前
HTML <dialog> 元素:原生弹窗解决方案,无需再写复杂遮罩
前端·html
CodeTransfer22 分钟前
今天给大家带来的是一个简单的小球抛物线动画效果
前端·javascript
宁静_致远31 分钟前
使用 React 实现高效的接口轮询与高实时性通信:性能优化与最佳实践
前端·javascript·面试