rc-virtual-keyboard
Version:
310 lines (295 loc) • 10.4 kB
JavaScript
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;