【react+ts】react+ts实现双滑块移动效果,包含交叉和碰撞

import React, { Component } from "react";
import "./block.scss";

interface Props {}
interface state {
  left1: number;
  left2: number;
  maxWidth: number;
}

class BlockDrog extends Component<Props, state> {
  slideButton1: any = React.createRef();
  slideButton2: any = React.createRef();
  slideBar: any = React.createRef();

  x1: number = 0;
  x2: number = 0;
  disX1: number = 10;
  disX2: number = 200;
  // 进度条
  scaleArr: Array<number> = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
  constructor(props: Props) {
    super(props);
    this.state = {
      left1: 10,
      left2: 200,
      maxWidth: this.slideBar.offsetWidth ? this.slideBar.offsetWidth : 770,
    };
  }

  componentDidMount() {
    this.x1 = this.slideButton1.offsetLeft;
    this.x2 = this.slideButton2.offsetLeft;
  }

  FnDown1(e: any) {
    // 获取当前点击元素的起始点
    this.disX1 = e.clientX - this.slideButton1.offsetLeft;
    // 事件绑定和阻止默认事件
    document.onmousemove = this.FnMove1.bind(this);
    document.onmouseup = this.FnUp.bind(this);
    e.preventDefault && e.preventDefault();
  }
  FnMove1(e: MouseEvent) {
    // 移动的距离
    this.x1 = e.clientX - this.disX1;
    // 边界判断
    if (this.x1 < 0) {
      this.x1 = 0;
    }
    if (this.x1 > this.state.maxWidth) {
      this.x1 = this.state.maxWidth;
    }
    // 交叉形式的 判断
    if (
      this.x1 >= 0 &&
      this.x1 <= this.state.maxWidth
    ) {
      // 碰撞形式的判断
    /* if (
      this.x1 >= 0 &&
      this.x1 <= this.state.maxWidth - this.slideButton1.offsetWidth
    ) { */
      this.setState({
        left1: this.x1,
      });

      // 碰撞形式的判断
      // if (
      //   this.x1 + this.slideButton1.offsetWidth >= this.x2 &&
      //   this.x1 + this.slideButton1.offsetWidth <= this.state.maxWidth
      // ) {
      //   this.setState({
      //     left1: this.x1,
      //     left2: this.x1 + this.slideButton1.offsetWidth,
      //   });
      //   this.x2 = this.x1 + this.slideButton1.offsetWidth;
      // }
    }
  }
  FnDown2(e: any) {
    this.disX2 = e.clientX - this.slideButton2.offsetLeft;
    document.onmousemove = this.FnMove2.bind(this);
    document.onmouseup = this.FnUp.bind(this);
    e.preventDefault && e.preventDefault();
  }
  FnMove2(e: MouseEvent) {
    this.x2 = e.clientX - this.disX2;
    if (this.x2 < 0) {
      this.x2 = 0;
    }
    if (this.x2 > this.state.maxWidth) {
      this.x2 = this.state.maxWidth;
    }
    // 交叉形式的 判断
    if (
      this.x2 >= 0 &&
      this.x2 <= this.state.maxWidth
    ) {
      // 碰撞形式的判断
    /* if (
      this.x2 >= this.slideButton1.offsetWidth &&
      this.x2 <= this.state.maxWidth
    ) { */
      this.setState({
        left2: this.x2,
      });

      // 碰撞形式的判断
      // if (
      //   this.x2 - this.slideButton2.offsetWidth <= this.x1 &&
      //   this.x2 - this.slideButton2.offsetWidth >= 0
      // ) {
      //   this.setState({
      //     left1: this.x2 - this.slideButton2.offsetWidth,
      //     left2: this.x2,
      //   });
      //   this.x1 = this.x2 - this.slideButton2.offsetWidth;
      // }
    }
  }
  FnUp() {
    document.onmousemove = null;
  }

  render() {
    return (
      <div className="block-drog">
        <div className="block">
          <h2 className="block-title">双滑块</h2>
          <div className="slider">
            <div className="scale">
              {this.scaleArr.map((item, index) => (
                <div
                  key={index}
                  style={{
                    left: item + "%",
                  }}
                >
                  {item}
                </div>
              ))}
            </div>
            <div
              className="slider-bar"
              ref={(div: HTMLDivElement) => {
                this.slideBar = div;
              }}
              style={{
                width:
                  Math.floor(
                    Math.abs(this.state.left2 * 100 - this.state.left1 * 100) /
                      this.state.maxWidth
                  ) + "%",
                // left: Math.floor(Math.min(this.state.left2 , this.state.left1)),
              }}
            >
              <div
                className="slider-button-left"
                style={{
                  width:
                    this.state.left1 < this.state.left2
                      ? this.state.left1
                      : this.state.left2,
                }}
              >
                <div
                  className="slider-button"
                  ref={(div: HTMLDivElement) => {
                    this.slideButton1 = div;
                  }}
                  onMouseDown={this.FnDown1.bind(this)}
                  style={{ left: this.state.left1 }}
                >
                  {Math.floor((this.state.left1 / this.state.maxWidth) * 100)}
                </div>
              </div>
              <div
                className="slider-button-right"
                style={{
                  width:
                    this.state.left2 > this.state.left1
                      ? this.state.left2
                      : this.state.left1,
                }}
              >
                <div
                  className="slider-button"
                  ref={(div: HTMLDivElement) => {
                    this.slideButton2 = div;
                  }}
                  onMouseDown={this.FnDown2.bind(this)}
                  style={{ left: this.state.left2 }}
                >
                  {Math.floor((this.state.left2 / this.state.maxWidth) * 100)}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default BlockDrog;

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁星召唤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值