# FloatButton/QuickMenu 悬浮按钮/快捷菜单

- 来源：[E10 UI 组件库](https://www.e-cology.com.cn/ui/float-button/freepass)
- 平台：PC
- 维护者：屈正巍
- Issue：http://gitlab.ecology10.cn/FRONTEND/weapp-ui/-/issues?state=all&search=[FloatButton]

## 代码演示

### 基础用法

挂载到全局的document上

```jsx
import { Component, ReactText, CSSProperties } from 'react';
import { FloatButton, Checkbox, Select, SingleType, SelectValueType, SelectOptionData, Input, Icon } from '@weapp/ui';
const rtl = window.weappUtils?.needRTL?.()
const { InputNumber } = Input

const options1 = [
  { id: 'px', content: 'px', },
  { id: '%', content: '%', },
]

const options2 = [
  { id: 'trigger', content: '四周展开', },
  { id: 'popover', content: '列表卡片', },
  { id: 'dialog', content: '下方滑出', },
]

const options3 = [
  { id: '', content: '自适应' },
  { id: 'top', content: '上', },
  { id: 'bottom', content: '下', },
  { id: 'left', content: '左', },
  { id: 'right', content: '右' },
]
const options4 = [
  { id: 'tooltip', content: '文字提示', },
  { id: 'popover', content: '气泡卡片', },
]

class QuickMenuDemo extends Component<any> {

  state = {
    disableDrag: false,
    right: 100,
    bottom: 100,
    useCustomRender: false,
    sidebarCollapse: false,
    sidebarCollapseDragLimit: false,
    closeAnimation: false,
    countsComplete: false,
    size: 50,
    width: void 0,
    height: void 0,
    borderRadiusType: '%',
    borderRadius: 50,
    renderCount: 15,
    counts: 100,
    menuType: 'trigger',
    inputValue: '',
    popoverPlacement: '',
    popoverType: 'tooltip',
  }

  onClick = () => console.log('onClick')
  onMenuVisibleChange = (visible?: boolean) => console.log('onMenuVisibleChange', visible)
  onQuickIconClick = () => console.info('onQuickIconClick-外部自定义渲染点击事件')
  renderQuickIcon = () => {
    return (
      <div id={'demo-test-customIcon'}>
        <Icon style={{ width: 30, height: 30, border: ' 1px solid pink' }} name={'Icon-Robot2'} onClick={this.onQuickIconClick} />
      </div>
    )
    // return <Icon style={{ width: 30, height: 30, border: ' 1px solid pink' }} name={'Icon-Robot2'} onClick={this.onQuickIconClick} />
  }

  // 是否禁止拖拽
  handleChangeDisableDrag = (value: any) => this.setState({ disableDrag: value })
  // 按钮位置
  handleChangeRight = (value: ReactText) => this.setState({ right: value })
  handleChangeBottom = (value: ReactText) => this.setState({ bottom: value })
  // 是否用自定义渲染
  handleChangeUseCustomRender = (value: any) => this.setState({ useCustomRender: value })
  // 是否侧边收起
  handleChangeSidebarCollapse = (value: any) => this.setState({ sidebarCollapse: value })
  // 是否开启侧边收起拖拽限制
  handleChangeSidebarCollapseDragLimit = (value: any) => this.setState({ sidebarCollapseDragLimit: value })
  // 按钮大小
  handleInputNumber = (value: ReactText) => this.setState({ size: value })
  // 按钮宽高
  handleInputNumber2 = (value: ReactText) => this.setState({ width: value })
  handleInputNumber3 = (value: ReactText) => this.setState({ height: value })
  // 按钮圆角
  handleSelect = (value: SingleType<SelectValueType>, option: SelectOptionData) => this.setState({ borderRadiusType: value })
  handleInputNumber4 = (value: ReactText) => this.setState({ borderRadius: value })
  // 计数数量
  handleInputNumber6 = (value: ReactText) => this.setState({ counts: value })
  // 计数按钮是否完整展示
  handleCountsComplete = (value: any) => this.setState({ countsComplete: value })
  // 子菜单数量
  handleInputNumber5 = (value: ReactText) => this.setState({ renderCount: value })
  // 子菜单类型
  handleSelect1 = (value: SingleType<SelectValueType>, option: SelectOptionData) => this.setState({ menuType: value })
  // 禁止子菜单动画
  handleChangeCloseAnimation = (value: any) => this.setState({ closeAnimation: value })
  // 提示文字
  handleInput = (value: ReactText) => this.setState({ inputValue: value })
  handleSelect2 = (value: SingleType<SelectValueType>, option: SelectOptionData) => this.setState({ popoverPlacement: value })
  handleSelect3 = (value: SingleType<SelectValueType>, option: SelectOptionData) => this.setState({ popoverType: value })

  // buttons
  click1 = () => alert('点击了第一个')
  click2 = () => alert('点击了第二个')
  click3 = () => alert('点击了第三个')
  click4 = () => alert('点击了第四个')
  click5 = () => alert('点击了第五个')
  getButtons = () => {
    const buttonsStyle: CSSProperties = rtl ? { transform: 'scaleX(-1)' } : {}
    const buttons = [
      [(<span style={buttonsStyle} onClick={this.click1}><Icon name={'Icon-Right-fold-up'} /></span>), '新建流程', '#FF666A'],
      [(<span style={buttonsStyle} onClick={this.click2} ><Icon name={'Icon-Speechless'} /></span>), '图标按钮', '#ffcd52'],
      [(<span style={buttonsStyle} onClick={this.click3}><Icon name={'Icon-@My-new-feedback'} /></span>), '一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接', '#40D8AD'],
      [(<span style={buttonsStyle} onClick={this.click4}><Icon name={'Icon-gateway'} /></span>), '一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮', '#24CEF6'],
      [(<span style={buttonsStyle} onClick={this.click5}><Icon name={'Icon-gateway'} /></span>), '第五个按钮', '#666666'],
      [(<span style={buttonsStyle} onClick={this.click1}><Icon name={'Icon-Right-fold-up'} /></span>), '新建流程', '#FF666A'],
      [(<span style={buttonsStyle} onClick={this.click2} ><Icon name={'Icon-Speechless'} /></span>), '图标按钮', '#ffcd52'],
      [(<span style={buttonsStyle} onClick={this.click3}><Icon name={'Icon-@My-new-feedback'} /></span>), '一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接', '#40D8AD'],
      [(<span style={buttonsStyle} onClick={this.click4}><Icon name={'Icon-gateway'} /></span>), '一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮', '#24CEF6'],
      [(<span style={buttonsStyle} onClick={this.click5}><Icon name={'Icon-gateway'} /></span>), '第五个按钮', '#666666'],
      [(<span style={buttonsStyle} onClick={this.click1}><Icon name={'Icon-Right-fold-up'} /></span>), '新建流程', '#FF666A'],
      [(<span style={buttonsStyle} onClick={this.click2} ><Icon name={'Icon-Speechless'} /></span>), '图标按钮', '#ffcd52'],
      [(<span style={buttonsStyle} onClick={this.click3}><Icon name={'Icon-@My-new-feedback'} /></span>), '一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接', '#40D8AD'],
      [(<span style={buttonsStyle} onClick={this.click4}><Icon name={'Icon-gateway'} /></span>), '一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮', '#24CEF6'],
      [(<span style={buttonsStyle} onClick={this.click5}><Icon name={'Icon-gateway'} /></span>), '第五个按钮', '#666666'],
      [(<span style={buttonsStyle} onClick={this.click1}><Icon name={'Icon-Right-fold-up'} /></span>), '新建流程', '#FF666A'],
      [(<span style={buttonsStyle} onClick={this.click2} ><Icon name={'Icon-Speechless'} /></span>), '图标按钮', '#ffcd52'],
      [(<span style={buttonsStyle} onClick={this.click3}><Icon name={'Icon-@My-new-feedback'} /></span>), '一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接', '#40D8AD'],
      [(<span style={buttonsStyle} onClick={this.click4}><Icon name={'Icon-gateway'} /></span>), '一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮', '#24CEF6'],
      [(<span style={buttonsStyle} onClick={this.click5}><Icon name={'Icon-gateway'} /></span>), '第五个按钮', '#666666'],
      [(<span style={buttonsStyle} onClick={this.click1}><Icon name={'Icon-Right-fold-up'} /></span>), '新建流程', '#FF666A'],
      [(<span style={buttonsStyle} onClick={this.click2} ><Icon name={'Icon-Speechless'} /></span>), '图标按钮', '#ffcd52'],
      [(<span style={buttonsStyle} onClick={this.click3}><Icon name={'Icon-@My-new-feedback'} /></span>), '一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接一个链接', '#40D8AD'],
      [(<span style={buttonsStyle} onClick={this.click4}><Icon name={'Icon-gateway'} /></span>), '一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮一个按钮', '#24CEF6'],
      [(<span style={buttonsStyle} onClick={this.click5}><Icon name={'Icon-gateway'} /></span>), '第五个按钮', '#666666'],
    ]
    return buttons
  }

  render() {
    const { disableDrag, right, bottom, sidebarCollapse, sidebarCollapseDragLimit, closeAnimation, countsComplete, size, width, height, popoverPlacement, inputValue, popoverType, borderRadius, renderCount, menuType, borderRadiusType, counts, useCustomRender } = this.state
    const notPopover = (menuType !== 'popover')
    const buttons = this.getButtons()
    return (
      <div>
        <div style={{ height: 50, display: 'flex', alignItems: 'center' }}>
          <span>禁止拖拽:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={disableDrag}
            onChange={this.handleChangeDisableDrag} />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>距离右侧:</span>
          <InputNumber
            style={{ width: 50, marginLeft: 10 }}
            value={right}
            onChange={this.handleChangeRight}
            min={0}
          />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>距离底部:</span>
          <InputNumber
            style={{ width: 50, marginLeft: 10 }}
            value={bottom}
            onChange={this.handleChangeBottom}
            min={0}
          />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>自定义渲染:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={useCustomRender}
            onChange={this.handleChangeUseCustomRender} />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>侧边收起:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={sidebarCollapse}
            onChange={this.handleChangeSidebarCollapse} />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>侧边收起拖拽限制:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={sidebarCollapseDragLimit}
            onChange={this.handleChangeSidebarCollapseDragLimit} />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>侧边收起拖拽限制:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={sidebarCollapseDragLimit}
            onChange={this.handleChangeSidebarCollapseDragLimit} />
        </div>
        <div style={{ height: 50, display: 'flex', alignItems: 'center' }}>
          <span>按钮大小:</span>
          <InputNumber
            style={{ width: 50, marginLeft: 10 }}
            value={size}
            onChange={this.handleInputNumber}
            max={9999}
            min={20}
          />
          <span>（注意当宽/高设置值后会替代按钮大小的值） </span>
        </div>
        <div style={{ height: 50, display: 'flex', alignItems: 'center' }}>
          <span>按钮宽度:</span>
          <InputNumber
            style={{ width: 50, marginLeft: 10 }}
            value={width}
            onChange={this.handleInputNumber2}
            max={9999}
            min={20}
          />
        </div>
        <div style={{ height: 50, display: 'flex', alignItems: 'center' }}>
          <span>按钮高度:</span>
          <InputNumber
            style={{ width: 50, marginLeft: 10 }}
            value={height}
            onChange={this.handleInputNumber3}
            max={9999}
            min={20}
          />
        </div>
        <div style={{ height: 50, display: 'flex', alignItems: 'center' }}>
          <span>按钮圆角:</span>
          <div style={{ display: 'inline-flex' }}>
            <Select
              style={{ marginLeft: 10, marginRight: 5 }}
              data={options1}
              value={borderRadiusType}
              onSelect={this.handleSelect}
              placeholder={'类型'}
            />
          </div>
          <div style={{ display: 'inline-flex' }}>
            <InputNumber
              style={{ width: 50 }}
              value={borderRadius}
              onChange={this.handleInputNumber4}
              max={borderRadiusType === '%' ? 50 : void 0}
              min={0}
            />
          </div>
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>计数按钮数量:</span>
          <InputNumber
            style={{ width: 50, marginLeft: 10 }}
            value={counts}
            onChange={this.handleInputNumber6}
            min={0}
          />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>计数按钮数量:</span>
          <InputNumber
            style={{ width: 50, marginLeft: 10 }}
            value={counts}
            onChange={this.handleInputNumber6}
            min={0}
          />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>计数按钮完整展示:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={countsComplete}
            onChange={this.handleCountsComplete} />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>子菜单数量</span>
          <InputNumber
            style={{ width: 50, marginLeft: 10 }}
            value={renderCount}
            onChange={this.handleInputNumber5}
            max={50}
            min={0}
          />
          <span>（注意demo最多25个） </span>
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>子菜单类型:</span>
          <Select
            style={{ marginLeft: 10 }}
            data={options2}
            value={menuType}
            onSelect={this.handleSelect1}
          />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>禁止子菜单动画:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={closeAnimation}
            onChange={this.handleChangeCloseAnimation} />
        </div>
        {notPopover && <>
          <h4>鼠标悬浮的弹窗只有在菜单类型为四周展开时才会生效，否则会有交互逻辑上的冲突，下列配置为鼠标悬浮弹窗配置</h4>
          <div style={{ height: 50, display: 'flex', alignItems: 'center' }}>
            <span>弹窗内容:</span>
            <Input
              style={{ width: 250, marginLeft: 10 }}
              value={inputValue}
              onChange={this.handleInput}
            />
          </div>
          <div style={{ height: 50, display: 'flex', alignItems: 'center' }}>
            <span>弹窗位置:</span>
            <Select
              style={{ width: 100, marginLeft: 10 }}
              data={options3}
              value={popoverPlacement}
              onSelect={this.handleSelect2}
            />
          </div>
          <div style={{ height: 50, display: 'flex', alignItems: 'center' }}>
            <span>弹层类型:</span>
            <Select
              style={{ width: 100, marginLeft: 10 }}
              data={options4}
              value={popoverType}
              onSelect={this.handleSelect3}
            />
          </div>
        </>}
        <FloatButton
          disableDrag={disableDrag}
          sidebarCollapse={sidebarCollapse}
          sidebarCollapseDragLimit={sidebarCollapseDragLimit}
          className={"my-float-button-demo"}
          menuClassName={"menu-class-demo"}
          size={Number(size)}
          width={Number(width)}
          height={Number(height)}
          borderRadius={Number(borderRadius)}
          borderRadiusType={borderRadiusType as any}
          closeAnimation={closeAnimation}
          countsComplete={countsComplete}
          popoverText={inputValue}
          popoverPlacement={popoverPlacement}
          popoverType={popoverType as any}
          counts={Number(counts)}
          right={!isNaN(Number(right)) ? Number(right) : void 0}
          bottom={!isNaN(Number(bottom)) ? Number(bottom) : void 0}
          // 一些菜单配置项
          menuType={menuType as any}
          buttons={buttons.slice(0, this.state.renderCount)}
          popoverId={'my-popover-id-demo'}
          popoverClassName={'my-popover-class-demo'}
          menuTriggerClassName={'my-menu-trigger-class-demo'}
          menuTriggerPlacementButtonClassName='my-menu-trigger-placement-button-class-demo'
          // moreMenuTitle={'自定义更多'}
          // moreMenuElement={(<Icon name={'Icon-Right-fold-up'} />)}
          onClick={this.onClick}
          onMenuVisibleChange={this.onMenuVisibleChange}
          quickIcon={useCustomRender ? this.renderQuickIcon() : void 0}
        />
      </div>
    );
  }
}

export default QuickMenuDemo;
```

### 挂载到指定容器

挂载到组件库demo上的id为'demoNode'的容器上

```jsx
import { Component } from 'react';
import { FloatButton, Checkbox } from '@weapp/ui';

class QuickMenuDemo extends Component<any> {

  state = {
    relativeToContainer: true,
    restrictToContainer: false,
  }

  onClick = () => console.log('onClick')
  getContainer = () => document.getElementById('demoNode') as any
  renderQuickIcon = () => <div style={{ color: '#ffffff' }}>可拖</div>
  renderQuickIcon2 = () => <div style={{ color: '#ffffff' }}>不可拖</div>

  // 是否根据容器定位
  handleChangeRelativeToContainer = (value: any) => this.setState({ relativeToContainer: value })
  // 是否只在定位元素上拖拽
  handleChangeRestrictToContainer = (value: any) => this.setState({ restrictToContainer: value })

  render() {
    const { relativeToContainer, restrictToContainer } = this.state
    return (
      <div id={'demoNode'} style={{ border: '1px solid pink', position: 'relative' }}>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>根据容器定位:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={relativeToContainer}
            onChange={this.handleChangeRelativeToContainer}
          />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>只在定位元素上拖拽:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={restrictToContainer}
            onChange={this.handleChangeRestrictToContainer}
          />
          <span>（注意只在开启根据容器定位时才会生效）</span>
        </div>
        <div style={{ width: '100%', height: 300, border: '1px solid #5d9cec', position: 'relative' }}>
          <FloatButton
            getContainer={this.getContainer}
            relativeToContainer={relativeToContainer}
            restrictToContainer={restrictToContainer}
            disableDrag={false}
            top={0}
            left={0}
            onClick={this.onClick}
            quickIcon={this.renderQuickIcon()}
          />
          <FloatButton
            getContainer={this.getContainer}
            relativeToContainer={relativeToContainer}
            restrictToContainer={restrictToContainer}
            disableDrag={true}
            top={0}
            right={0}
            onClick={this.onClick}
            quickIcon={this.renderQuickIcon2()}
          />
        </div>
      </div>
    );
  }
}

export default QuickMenuDemo;
```

### 挂载到父容器

挂载到组件库demo上的id为'parentNode'的直接父容器上

```jsx
import { Component } from 'react';
import { FloatButton, Checkbox } from '@weapp/ui';

class QuickMenuDemo extends Component<any> {

  state = {
    relativeToContainer: true,
    restrictToContainer: false,
  }

  onClick = () => console.log('onClick')
  getContainer = () => document.getElementById('parentNode') as any
  renderQuickIcon = () => <div style={{ color: '#ffffff' }}>可拖</div>
  renderQuickIcon2 = () => <div style={{ color: '#ffffff' }}>不可拖</div>

  // 是否根据容器定位
  handleChangeRelativeToContainer = (value: any) => this.setState({ relativeToContainer: value })
  // 是否只在定位容器上拖拽
  handleChangeRestrictToContainer = (value: any) => this.setState({ restrictToContainer: value })

  render() {
    const { relativeToContainer, restrictToContainer } = this.state
    return (
      <div style={{ border: '1px solid pink', position: 'relative' }}>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>根据容器定位:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={relativeToContainer}
            onChange={this.handleChangeRelativeToContainer}
          />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>只在定位元素上拖拽:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={restrictToContainer}
            onChange={this.handleChangeRestrictToContainer}
          />
          <span>（注意只在开启根据容器定位时才会生效）</span>
        </div>
        <div id={'parentNode'} style={{ width: '100%', height: 300, border: '1px solid #5d9cec', position: 'relative' }}>
          <FloatButton
            getContainer={this.getContainer}
            relativeToContainer={relativeToContainer}
            restrictToContainer={restrictToContainer}
            disableDrag={false}
            top={0}
            left={0}
            onClick={this.onClick}
            quickIcon={this.renderQuickIcon()}
          />
          <FloatButton
            getContainer={this.getContainer}
            relativeToContainer={relativeToContainer}
            restrictToContainer={restrictToContainer}
            disableDrag={true}
            top={0}
            right={0}
            onClick={this.onClick}
            quickIcon={this.renderQuickIcon2()}
          />
        </div>
      </div>
    );
  }
}

export default QuickMenuDemo;
```

### 容器异步生成

组件会实施监控容器的变化以及生成

```jsx
import { Component } from 'react';
import { FloatButton, Checkbox, Button } from '@weapp/ui';

class QuickMenuDemo extends Component<any> {

  state = {
    relativeToContainer: true,
    restrictToContainer: false,
    showAsyncDom: false
  }

  onClick = () => console.log('onClick')
  getContainer = () => document.getElementById('asyncNode') as any
  renderQuickIcon = () => <div style={{ color: '#ffffff', fontSize: 10 }}>异步可拖</div>
  renderQuickIcon2 = () => <div style={{ color: '#ffffff', fontSize: 10 }}>异步不可拖</div>

  // 是否根据容器定位
  handleChangeRelativeToContainer = (value: any) => this.setState({ relativeToContainer: value })
  // 是否只在定位元素上拖拽
  handleChangeRestrictToContainer = (value: any) => this.setState({ restrictToContainer: value })
  // 点击生成模拟生成异步dom
  onButtonClick = () => this.setState({ showAsyncDom: true })

  render() {
    const { relativeToContainer, restrictToContainer, showAsyncDom } = this.state
    return (
      <div style={{ border: '1px solid pink', position: 'relative' }}>
        {showAsyncDom && (
          <div id={'asyncNode'} style={{ width: '100%', height: 300, border: '1px solid black' }}></div>
        )}
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>根据容器定位:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={relativeToContainer}
            onChange={this.handleChangeRelativeToContainer}
          />
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>只在定位元素上拖拽:</span>
          <Checkbox
            style={{ marginLeft: 10 }}
            value={restrictToContainer}
            onChange={this.handleChangeRestrictToContainer}
          />
          <span>（注意只在开启根据容器定位时才会生效）</span>
        </div>
        <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
          <span>点击生成模拟生成异步dom:</span>
          <Button
            style={{ marginLeft: 10 }}
            onClick={this.onButtonClick}
          >
            生成异步dom
          </Button>
        </div>
        <div style={{ width: '100%', height: 300, border: '1px solid #5d9cec', position: 'relative' }}>
          <FloatButton
            getContainer={this.getContainer}
            relativeToContainer={relativeToContainer}
            restrictToContainer={restrictToContainer}
            disableDrag={false}
            bottom={0}
            left={0}
            onClick={this.onClick}
            quickIcon={this.renderQuickIcon()}
          />
          <FloatButton
            getContainer={this.getContainer}
            relativeToContainer={relativeToContainer}
            restrictToContainer={restrictToContainer}
            disableDrag={true}
            bottom={0}
            right={0}
            onClick={this.onClick}
            quickIcon={this.renderQuickIcon2()}
          />
        </div>
      </div>
    );
  }
}

export default QuickMenuDemo;
```

## API

### 注意：

```typescript
1.更多配置项请查看m-quick-menu的demo
2.打开方式分别对应 四周展开 列表卡片 下方滑出（type QuickMenuMenuType = 'trigger' | 'popover' | 'dialog'）
```

### 参数说明如下：

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
| --- | --- | --- | --- | --- |
| menuClassName | 菜单样式类 | string | 否 |  |
| buttons | 按钮属性配置 | (ReactNode, text:string, color:string)[][] | 否 |  |
| quickIcon | 自定义渲染图标 | ReactNode | 否 |  |
| onClick | 悬浮菜单点击事件 | function | 否 |  |
| onDragStart | 悬浮菜单拖拽开始 | (e: React.MouseEvent, data: any) => void | 否 |  |
| onDragging | 悬浮菜单拖拽中 | (e: React.MouseEvent, data: any) => void | 否 |  |
| onDragEnd | 悬浮菜单拖拽结束 | (e: React.MouseEvent, data: any) => void | 否 |  |
| startClassName(废弃，此后使用buttonClassName) | 点击按钮样式类 | string | 否 |  |
| buttonClassName | 点击按钮样式类 | string | 否 |  |
| staticClassName | 非拖拽按钮样式类 | string | 否 |  |
| dragClassName | 拖拽按钮样式类 | string | 否 |  |
| getContainer | 按钮渲染指定节点(默认为body) | () => HTMLElement | 否 |  |
| disableDrag | 禁用按钮拖拽 | boolean | 否 |  |
| size | 按钮大小 | number | 否 | 44 |
| defaultPosition | 拖拽按钮初始位置(此api废弃，改为right、bottom、left、top来定位) | ControlPosition | 否 |  |
| borderRadius | borderRadius的数值 | number | 否 | 50 |
| borderRadiusType | borderRadius的类型 | 'px'\|'%' | 否 | % |
| popoverText | 弹层内容(此项有值才会展示) | string | 否 |  |
| popoverType | 弹层类型 | PopoverType | 否 |  |
| popoverPlacement | 弹层位置 | PopupPlacement | 否 |  |
| popoverProps | 弹层props | PopoverProps | 否 |  |
| popoverId | 弹层id | string | 否 |  |
| popoverClassName | 弹层className | string | 否 |  |
| menuTriggerProps | 四周展开模式的triggerProps | TriggerProps | 否 |  |
| menuTriggerClassName | 四周展开模式的trigger的类名 | string | 否 |  |
| menuTriggerPlacementButtonClassName | 四周展开模式的占位按钮的类名 | string | 否 |  |
| menuType | 菜单打开方式 | QuickMenuMenuType | 否 | 'trigger' |
| menuPopoverType | 移动端菜单模式的popoverType | PopoverType | 否 | 'popover' |
| menuPopoverProps | 移动端菜单模式的popover的props | PopoverProps | 否 |  |
| menuPopoverId | 移动端菜单模式的popover的id | string | 否 |  |
| menuPopoverClassName | 移动端菜单模式的popover的className | string | 否 |  |
| right | 绝对定位右侧边距 | number | 否 |  |
| bottom | 绝对定位底部边距 | number | 否 |  |
| left | 绝对定位左侧边距 | number | 否 |  |
| top | 绝对定位顶部边距 | number | 否 |  |
| closeAnimation | 是否关闭动画(安卓手机默认开启) | boolean | 否 |  |
| countsComplete | 右上角计数按钮是否完整展示 | boolean | 否 |  |
| countsZeroHide | 右上角计数按钮为0时是否隐藏 | boolean | 否 |  |
| clickStopPropagation | 点击时是否阻止冒泡(当开启自定义渲染quickIcon时默认开启) | boolean | 否 |  |
| useQuickIconClick | 是否触发自定义渲染的icon内部的点击事件 | boolean | 否 |  |
| sidebarCollapse | 是否开启侧边收起 | boolean | 否 |  |
| sidebarCollapseDragLimit | 侧边收起拖拽限制 | boolean | 否 |  |
| relativeToContainer | 是否相对于容器定位(需要在getContainer中传入有效节点) | boolean | 否 |  |
| restrictToContainer | 拖拽是否限制在容器内(需要开启相对容器定位) | boolean | 否 |  |
