react專案中實現元素的拖動和縮放例項

林堯彬發表於2020-04-04

  在react專案中實現此功能可藉助 react-rnd 庫,文件地址:https://github.com/bokuweb/react-rnd#Screenshot 。下面是例項運用:

  

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import assign from 'object-assign'
import classNames from 'classnames'
import _ from 'lodash'
import { Rnd } from 'react-rnd'

import './index.less'

class ScreenShareCapture extends Component {
  static propTypes = {
    style: PropTypes.object,
  }

  static defaultProps = {
    style: {},
  }

  state = {
    x: 0,
    y: 0,
    width: 500,
    height: 281.25,
  }

  componentDidMount() {
  }

  componentWillUnmount() {
  }

  updateRndElemLastSizePos = () => {
    this.rndElemLastSizePos = {
      x: this.state.x,
      y: this.state.y,
      width: this.state.width,
      height: this.state.height,
    }
  }

  calculateRndElemSizePos = (dir, ref, sizeDelta, position) => {
    const sizePos = _.clone(this.rndElemLastSizePos)
    const heightWidthRatio = 0.5625
    sizePos.x = position.x
    sizePos.y = position.y
    sizePos.width = ref.offsetWidth
    sizePos.height = ref.offsetWidth * heightWidthRatio

    this.setState(sizePos)
    return sizePos
  }


  handleDragStart = () => {
    this.updateRndElemLastSizePos()
  }

  handleDrag = (e, data) => {
    this.setState({
      x: data.x,
      y: data.y,
    })
  }

  handleDragStop = (e, data) => {
    this.setState({
      x: data.x,
      y: data.y,
    })
  }

  handleResizeStart = () => {
    this.updateRndElemLastSizePos()
  }

  handleResize = (e, dir, ref, delta, position) => {
    console.log('beibei handleresize', e, dir, ref, delta, position)
    this.calculateRndElemSizePos(dir, ref, delta, position)
  }

  rndElemLastSizePos

  rnd

  render() {
    const wrapStyles = assign({}, this.props.style)
    return (
      <Rnd
        style={wrapStyles}
        bounds=".teacher-layout-component-wrap"
        dragHandleClassName="screen-share-bottom-content-wrap"
        enableResizing={{
          top: false,
          right: false,
          bottom: false,
          left: false,
          topRight: true,
          bottomRight: true,
          bottomLeft: true,
          topLeft: true,
        }}
        position={{
          x: this.state.x,
          y: this.state.y,
        }}
        size={{
          width: this.state.width,
          height: this.state.height,
        }}
        lockAspectRatio={16 / 9}
        maxWidth="100%"
        maxHeight="100%"
        minWidth={400}
        minHeight={225}
        onDragStart={this.handleDragStart}
        onDrag={this.handleDrag}
        onDragStop={this.handleDragStop}
        onResizeStart={this.handleResizeStart}
        onResize={this.handleResize}
        onResizeStop={_.noop}
        ref={(r) => { this.rnd = r }}
      >
        <div className="screen-share-capture-component-wrap">
          <div className="screen-share-main-content-wrap">
            <span className="start-screen-share-button">開始螢幕共享</span>
          </div>
          <div className="screen-share-bottom-content-wrap">
            <div className="screen-share-bottom-left">
              <i
                className="preview-icon"
              />
              <span className="preview-text">預覽</span>
            </div>
            <div className="screen-share-bottom-right">
              <i
                className={classNames({
                  'device-icon': true,
                  'camera-icon': true,
                  active: false,
                })}
              />
              <i
                className={classNames({
                  'device-icon': true,
                  'mic-icon': true,
                  active: false,
                })}
              />
              <i
                className={classNames({
                  'device-icon': true,
                  'speaker-icon': true,
                  active: false,
                })}
              />
              <i
                className={classNames({
                  'device-icon': true,
                  'wifi-icon': true,
                  active: false,
                })}
              />
              {/*<i*/}
                {/*className={classNames({*/}
                  {/*'device-icon': true,*/}
                  {/*'restart-icon': true,*/}
                  {/*active: false,*/}
                {/*})}*/}
              {/*/>*/}
              <i
                className={classNames({
                  'device-icon': true,
                  'exit-icon': true,
                  active: false,
                })}
              />
            </div>
          </div>
        </div>
      </Rnd>
    )
  }
}

export default ScreenShareCapture

  下面是css樣式:

  

.screen-share-capture-component-wrap{
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  position: relative;
  //top: 0;
  //left: 0;
  //width: 100%;
  //height: 100%;
  //display: flex;
  //flex-direction: column;
  //align-items: center;
  //justify-content: center;
  //background-color: red;

  .screen-share-main-content-wrap{
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    border-radius: 2px;
    border: solid 2px #ff4343;
    background-color: #ffffff;
    display: flex;
    justify-content: center;
    align-items: center;


    .start-screen-share-button{
      display: inline-block;
      width: 120px;
      height: 36px;
      line-height: 36px;
      text-align: center;
      border-radius: 2px;
      background-color: #ff4343;
      color: #ffffff;
      font-size: 14px;
      opacity: 0.8;
      cursor: pointer;
    }
  }

  .screen-share-bottom-content-wrap{
    width: 100%;
    height: 36px;
    border-radius: 2px;
    background-color: #5d6674;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    position: absolute;
    bottom: -36px;
    left: 0;

    .screen-share-bottom-left{
      width: 72px;
      height: 32px;
      border-radius: 2px;
      border: solid 1px #ffffff;
      background-color: #5d6674;
      margin: 3px;
      display: flex;
      flex-direction: row;
      justify-content: space-around;
      align-items: center;
      cursor: pointer;

      .preview-icon{
        width: 24px;
        height: 24px;
        outline: none;
        cursor: pointer;
        background: url('~ROOT/shared/assets/image/vn-screen-preview-42-42.png') no-repeat center;
        background-size: 16px 16px;
      }

      .preview-text{
        color: #ffffff;
        font-size: 14px;
      }
    }

    .screen-share-bottom-right{
      display: flex;
      flex-direction: row;
      align-items: center;

      .device-icon {
        width: 24px;
        height: 24px;
        outline: none;
        cursor: pointer;
        margin-right: 11px;

        &:nth-last-child(2){
          margin-right: 38px;
        }

      }

      .camera-icon {
        background: url('~ROOT/shared/assets/image/vn-screen-camera-off-66-66.png') no-repeat center;
        background-size: 22px 22px;
      }

      .mic-icon {
        background: url('~ROOT/shared/assets/image/vn-screen-voice-on-54-72.png') no-repeat center;
        background-size: 18px 24px;
      }

      .speaker-icon {
        background: url('~ROOT/shared/assets/image/vn-screen-speaker-60-66.png') no-repeat center;
        background-size: 20px 22px;
      }

      .wifi-icon {
        background: url('~ROOT/shared/assets/image/vn-screen-wifi-72-57.png') no-repeat center;
        background-size: 24px 19px;
      }

      .restart-icon{
        background: url('~ROOT/shared/assets/image/vn-screen-restart-60-60.png') no-repeat center;
        background-size: 19px 19px;
      }

      .exit-icon{
        background: url('~ROOT/shared/assets/image/vn-screen-exit-60-60.png') no-repeat center;
        background-size: 19px 19px;
      }

    }

  }
}

 

轉載於:https://www.cnblogs.com/chenbeibei520/p/10478549.html

相關文章