UNPKG

rc-virtual-keyboard

Version:
310 lines (295 loc) 10.4 kB
import React, { useEffect, useRef } from 'react'; import { useDebounceFn, useEventListener, useUpdateEffect } from 'ahooks'; import { FixedBottomPosition, FixedLeftPosition, FixedRightPosition, FixedTopPosition, FloatPosition } from "../keys"; import "./style.css"; /** * * * * @param param0 * @returns * * @description */ var DragBlock = function DragBlock(_ref) { var init = _ref.init, resizeOverRight = _ref.resizeOverRight, _ref$autoKeepRightDel = _ref.autoKeepRightDelay, autoKeepRightDelay = _ref$autoKeepRightDel === void 0 ? 3000 : _ref$autoKeepRightDel, _ref$autoKeepRight = _ref.autoKeepRight, autoKeepRight = _ref$autoKeepRight === void 0 ? true : _ref$autoKeepRight, _ref$delay = _ref.delay, delay = _ref$delay === void 0 ? 280 : _ref$delay, _ref$zIndex = _ref.zIndex, zIndex = _ref$zIndex === void 0 ? 9999 : _ref$zIndex, children = _ref.children, style = _ref.style, _ref$positionMode = _ref.positionMode, positionMode = _ref$positionMode === void 0 ? FloatPosition.code : _ref$positionMode, onClick = _ref.onClick; /** 是否允许移动 */ var allowMove = useRef(false); /** 开始位置 */ var start = useRef({ clientX: 0, clientY: 0 }); /** touch 事件开始位置 */ var startTouch = useRef({ clientX: 0, clientY: 0 }); /** block */ var blockRef = useRef(null); /** 点击时间记录 */ var clickTimer = useRef(0); /** block 是否隐藏 */ var isHidden = useRef(true); /** @type {*} * 自动靠右 */ var keepRight = useDebounceFn(function () { if (blockRef.current && autoKeepRight) { isHidden.current = true; blockRef.current.style.left = window.innerWidth - blockRef.current.offsetWidth / 2 + 'px'; setTimeout(function () { if (blockRef.current) { blockRef.current.style.transition = 'none'; } }, 400); } }, { wait: autoKeepRightDelay }); /** @type {*} * 点击展示块 */ var showBlock = useDebounceFn(function () { if (blockRef.current) { isHidden.current = false; blockRef.current.style.left = "calc(100% - ".concat(blockRef.current.offsetWidth, "px)"); // blockRef.current.style.transition = "all 0.3s"; keepRight.run(); } }, { wait: autoKeepRightDelay, leading: true }); /** * 点击事件 * */ var onClickFn = function onClickFn() { if (Date.now() - clickTimer.current < delay) { if (isHidden.current && autoKeepRight && blockRef.current) { blockRef.current.style.transition = 'all 0.3s'; showBlock.run(); } else { !allowMove.current && onClick && onClick(); } } }; /** 初始位置 */ useEffect(function () { if (blockRef.current) { if (init) { var _init$width; blockRef.current.style.top = "calc(100% - ".concat(init.height, ")"); // blockRef.current.style.left = `calc(100% - ${init.width})`; blockRef.current.style.left = parseFloat((_init$width = init === null || init === void 0 ? void 0 : init.width) !== null && _init$width !== void 0 ? _init$width : '0') > window.innerWidth ? '0px' : "calc(100vw - ".concat(init === null || init === void 0 ? void 0 : init.width, ")"); } else { blockRef.current.style.top = "calc(50% - ".concat(blockRef.current.offsetHeight / 2, "px)"); blockRef.current.style.left = "calc(100% - ".concat(blockRef.current.offsetWidth / 2, "px)"); } } }, []); /** 层级 */ useEffect(function () { if (blockRef.current) { blockRef.current.style.zIndex = zIndex.toString(); } }, [zIndex]); useEffect(function () { var _init$width2; if (blockRef.current) { switch (positionMode) { case FixedBottomPosition.code: blockRef.current.style.left = '0px'; blockRef.current.style.top = "calc(100vh - ".concat(init === null || init === void 0 ? void 0 : init.height, ")"); break; case FixedTopPosition.code: case FixedLeftPosition.code: blockRef.current.style.left = '0px'; blockRef.current.style.top = '0px'; break; case FixedRightPosition.code: blockRef.current.style.left = parseFloat((_init$width2 = init === null || init === void 0 ? void 0 : init.width) !== null && _init$width2 !== void 0 ? _init$width2 : '0') > window.innerWidth ? '0px' : "calc(100vw - ".concat(init === null || init === void 0 ? void 0 : init.width, ")"); blockRef.current.style.top = '0px'; break; } } }, [positionMode]); /** 监听自动靠右 */ useUpdateEffect(function () { if (blockRef.current) { blockRef.current.style.transition = 'all 0.3s'; if (autoKeepRight) { keepRight.run(); } else { showBlock.run(); } } }, [autoKeepRight]); /** 鼠标按下 */ var onMouseDown = function onMouseDown(e) { allowMove.current = true; showBlock.cancel(); keepRight.cancel(); if (blockRef.current) { // 记录初始位置 var offsetLeft = blockRef.current.offsetLeft; var offsetTop = blockRef.current.offsetTop; var clientX = e.clientX - offsetLeft; var clientY = e.clientY - offsetTop; start.current = { clientX: clientX, clientY: clientY }; clickTimer.current = Date.now(); } }; /** 鼠标移动 */ useEventListener('mousemove', function (e) { if (allowMove.current) { var x = e.clientX - start.current.clientX; var y = e.clientY - start.current.clientY; if (blockRef.current) { var _blockRef$current; blockRef.current.style.transition = 'none'; if (x <= window.innerWidth - (blockRef === null || blockRef === void 0 || (_blockRef$current = blockRef.current) === null || _blockRef$current === void 0 ? void 0 : _blockRef$current.offsetWidth)) { isHidden.current = false; } if (x < window.innerWidth - blockRef.current.offsetWidth / (isHidden.current ? 2 : 1) && x > 0) { blockRef.current.style.left = x + 'px'; } if (y < window.innerHeight - blockRef.current.offsetHeight / (isHidden.current ? 2 : 1) && y > 0) { blockRef.current.style.top = y + 'px'; } } } }, { target: window }); /** 鼠标抬起 */ useEventListener('mouseup', function () { allowMove.current = false; if (blockRef.current) { blockRef.current.style.transition = 'all 0.3s'; start.current = { clientX: 0, clientY: 0 }; keepRight.run(); } }, { target: window }); /** 窗口改变 */ useEventListener('resize', function () { if (blockRef.current) { if (resizeOverRight) { if (blockRef.current.offsetLeft >= 0) { blockRef.current.style.left = window.innerWidth - blockRef.current.offsetWidth / (isHidden.current ? 2 : 1) + 'px'; } if (blockRef.current.offsetTop >= 0) { blockRef.current.style.top = window.innerHeight / 2 - blockRef.current.offsetHeight / (isHidden.current ? 2 : 1) + 'px'; } } else { switch (positionMode) { case FixedBottomPosition.code: blockRef.current.style.left = '0px'; blockRef.current.style.top = "calc(100vh - ".concat(init === null || init === void 0 ? void 0 : init.height, ")"); break; case FixedTopPosition.code: case FixedLeftPosition.code: blockRef.current.style.left = '0px'; blockRef.current.style.top = '0px'; break; case FixedRightPosition.code: blockRef.current.style.left = "calc(100vw - ".concat(init === null || init === void 0 ? void 0 : init.width, ")"); blockRef.current.style.top = '0px'; break; } } } }, { target: window }); /** 移动端点击 */ var onTouchStart = function onTouchStart(e) { var _e$preventDefault; allowMove.current = true; showBlock.cancel(); keepRight.cancel(); e === null || e === void 0 || (_e$preventDefault = e.preventDefault) === null || _e$preventDefault === void 0 || _e$preventDefault.call(e); var element = e.targetTouches[0]; // 防止页面跟随滚动 document.body.style.overflow = 'hidden'; if (blockRef.current) { var offsetLeft = blockRef.current.offsetLeft; var offsetTop = blockRef.current.offsetTop; var clientX = element.clientX - offsetLeft; var clientY = element.clientY - offsetTop; startTouch.current = { clientX: clientX, clientY: clientY }; } }; /** 移动端点击结束 */ var onTouchEnd = function onTouchEnd() { if (blockRef.current) { allowMove.current = false; blockRef.current.style.transition = 'all 0.3s'; // 防止页面跟随滚动 document.body.style.overflow = 'unset'; startTouch.current = { clientX: 0, clientY: 0 }; keepRight.run(); } }; /** 移动端移动 */ useEventListener('touchmove', function (e) { if (blockRef.current && allowMove.current) { var _blockRef$current2; blockRef.current.style.transition = 'none'; // 根据初始点击位置 client 计算移动距离 var element = e.targetTouches[0]; var x = element.clientX - startTouch.current.clientX; var y = element.clientY - startTouch.current.clientY; if (x <= window.innerWidth - (blockRef === null || blockRef === void 0 || (_blockRef$current2 = blockRef.current) === null || _blockRef$current2 === void 0 ? void 0 : _blockRef$current2.offsetWidth)) { isHidden.current = false; } if (x < window.innerWidth - blockRef.current.offsetWidth / (isHidden.current ? 2 : 1) && x > 0) { blockRef.current.style.left = x + 'px'; } if (y < window.innerHeight - blockRef.current.offsetHeight / (isHidden.current ? 2 : 1) && y > 0) { blockRef.current.style.top = y + 'px'; } } }, { target: blockRef }); return /*#__PURE__*/React.createElement("div", { style: style, className: "virtual-drag-block", ref: blockRef, onClick: onClickFn, onMouseDown: onMouseDown, onTouchStart: onTouchStart, onTouchEnd: onTouchEnd }, children); }; export default DragBlock;