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就可以了

相关推荐
SamChan9010 分钟前
在Web应用中集成PDF多语言翻译功能:PDFTranslator API实战指南
前端·python·ai·pdf·yapi·机器翻译
kyriewen24 分钟前
AI Agent 9秒删光了生产数据库——我给自己的项目做了5个紧急检查
前端·ai编程·claude
IT_陈寒36 分钟前
JavaScript的this又双叒叕让我怀疑人生了
前端·人工智能·后端
陈随易1 小时前
MCP协议第5次更新,从打电话到微信聊天的巨大变革
前端·后端·程序员
omnijk1 小时前
前端工程化
前端
做前端的娜娜子1 小时前
前端必看!我把一段"能跑不敢动"的报表代码用 AI 重构成了组件(附完整 Prompt)
前端·ai编程
hunterandroid2 小时前
[鸿蒙从零到一] ArkUI 动画与转场实战:状态驱动、组件过渡与页面衔接
前端
何时梦醒2 小时前
React + TypeScript + Vite 实战:从零构建 Color Picker 应用
前端·javascript·架构
谁在黄金彼岸2 小时前
Nuxt.js 详解(一):Vue 开发者为什么要关注 Nuxt
前端