mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-06-01 23:16:51 +00:00
切换主题预览方案调整
This commit is contained in:
@@ -2,9 +2,11 @@ import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
/**
|
||||
* 可拖拽组件
|
||||
* @param {children} 渲染的子元素
|
||||
* @param {stick} 是否要吸附
|
||||
* @returns
|
||||
*/
|
||||
export const Draggable = props => {
|
||||
const { children, stick } = props
|
||||
export const Draggable = ({ children, stick }) => {
|
||||
const draggableRef = useRef(null)
|
||||
const rafRef = useRef(null)
|
||||
const [moving, setMoving] = useState(false)
|
||||
@@ -13,75 +15,70 @@ export const Draggable = props => {
|
||||
useEffect(() => {
|
||||
const draggableElements = document.getElementsByClassName('draggable')
|
||||
|
||||
// 标准化鼠标事件对象
|
||||
function e(event) {
|
||||
// 定义事件对象标准化函数
|
||||
if (!event) {
|
||||
// 兼容IE浏览器
|
||||
event = window.event
|
||||
event.target = event.srcElement
|
||||
event.layerX = event.offsetX
|
||||
event.layerY = event.offsetY
|
||||
}
|
||||
// 移动端
|
||||
if (event.type === 'touchstart' || event.type === 'touchmove') {
|
||||
event.clientX = event.touches[0].clientX
|
||||
event.clientY = event.touches[0].clientY
|
||||
}
|
||||
|
||||
event.mx = event.pageX || event.clientX + document.body.scrollLeft
|
||||
// 计算鼠标指针的x轴距离
|
||||
event.my = event.pageY || event.clientY + document.body.scrollTop
|
||||
// 计算鼠标指针的y轴距离
|
||||
|
||||
return event // 返回标准化的事件对象
|
||||
return event
|
||||
}
|
||||
|
||||
// 定义鼠标事件处理函数
|
||||
// document.pointerdown = start
|
||||
document.onmousedown = start
|
||||
document.ontouchstart = start
|
||||
|
||||
function start(event) {
|
||||
// 按下鼠标时,初始化处理
|
||||
if (!draggableElements) return
|
||||
event = e(event) // 获取标准事件对象
|
||||
event = e(event)
|
||||
|
||||
for (const drag of draggableElements) {
|
||||
// 判断鼠标点击的区域是否是拖拽框内
|
||||
if (inDragBox(event, drag)) {
|
||||
currentObj = drag.firstElementChild
|
||||
}
|
||||
}
|
||||
if (currentObj) {
|
||||
if (event.type === 'touchstart') {
|
||||
event.preventDefault() // 阻止默认的滚动行为
|
||||
document.documentElement.style.overflow = 'hidden' // 防止页面一起滚动
|
||||
event.preventDefault()
|
||||
document.documentElement.style.overflow = 'hidden'
|
||||
}
|
||||
|
||||
setMoving(true)
|
||||
offsetX = event.mx - currentObj.offsetLeft
|
||||
offsetY = event.my - currentObj.offsetTop
|
||||
|
||||
document.onmousemove = move // 注册鼠标移动事件处理函数
|
||||
document.onmousemove = move
|
||||
document.ontouchmove = move
|
||||
document.onmouseup = stop // 注册松开鼠标事件处理函数
|
||||
document.onmouseup = stop
|
||||
document.ontouchend = stop
|
||||
}
|
||||
}
|
||||
|
||||
function move(event) {
|
||||
// 鼠标移动处理函数
|
||||
event = e(event)
|
||||
rafRef.current = requestAnimationFrame(() => updatePosition(event))
|
||||
}
|
||||
|
||||
const stop = event => {
|
||||
event = e(event)
|
||||
document.documentElement.style.overflow = 'auto' // 恢复默认的滚动行为
|
||||
document.documentElement.style.overflow = 'auto'
|
||||
cancelAnimationFrame(rafRef.current)
|
||||
setMoving(false)
|
||||
currentObj = document.ontouchmove = document.ontouchend = document.onmousemove = document.onmouseup = null
|
||||
if (stick) {
|
||||
checkInWindow() // 吸附逻辑
|
||||
}
|
||||
currentObj =
|
||||
document.ontouchmove =
|
||||
document.ontouchend =
|
||||
document.onmousemove =
|
||||
document.onmouseup =
|
||||
null
|
||||
}
|
||||
|
||||
const updatePosition = event => {
|
||||
@@ -90,51 +87,41 @@ export const Draggable = props => {
|
||||
const top = event.my - offsetY
|
||||
currentObj.style.left = left + 'px'
|
||||
currentObj.style.top = top + 'px'
|
||||
checkInWindow()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标是否在可拖拽区域内
|
||||
* @param {*} event
|
||||
* @returns
|
||||
*/
|
||||
function inDragBox(event, drag) {
|
||||
const { clientX, clientY } = event // 鼠标位置
|
||||
const { offsetHeight, offsetWidth, offsetTop, offsetLeft } = drag.firstElementChild // 窗口位置
|
||||
const horizontal = clientX > offsetLeft && clientX < offsetLeft + offsetWidth
|
||||
const { clientX, clientY } = event
|
||||
const { offsetHeight, offsetWidth, offsetTop, offsetLeft } =
|
||||
drag.firstElementChild
|
||||
const horizontal =
|
||||
clientX > offsetLeft && clientX < offsetLeft + offsetWidth
|
||||
const vertical = clientY > offsetTop && clientY < offsetTop + offsetHeight
|
||||
|
||||
if (horizontal && vertical) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return horizontal && vertical
|
||||
}
|
||||
|
||||
/**
|
||||
* 若超出窗口则吸附。
|
||||
*/
|
||||
function checkInWindow() {
|
||||
// 检查是否悬浮在窗口内
|
||||
for (const drag of draggableElements) {
|
||||
// 判断鼠标点击的区域是否是拖拽框内
|
||||
const { offsetHeight, offsetWidth, offsetTop, offsetLeft } = drag.firstElementChild
|
||||
const { offsetHeight, offsetWidth, offsetTop, offsetLeft } =
|
||||
drag.firstElementChild
|
||||
const { clientHeight, clientWidth } = document.documentElement
|
||||
if (offsetTop < 0) {
|
||||
drag.firstElementChild.style.top = 0
|
||||
drag.firstElementChild.style.top = '0px'
|
||||
}
|
||||
if (offsetTop > clientHeight - offsetHeight) {
|
||||
drag.firstElementChild.style.top = clientHeight - offsetHeight + 'px'
|
||||
}
|
||||
if (offsetLeft < 0) {
|
||||
drag.firstElementChild.style.left = 0
|
||||
drag.firstElementChild.style.left = '0px'
|
||||
}
|
||||
if (offsetLeft > clientWidth - offsetWidth) {
|
||||
drag.firstElementChild.style.left = clientWidth - offsetWidth + 'px'
|
||||
}
|
||||
if (stick === 'left') {
|
||||
drag.firstElementChild.style.left = 0 + 'px'
|
||||
drag.firstElementChild.style.left = '0px'
|
||||
} else if (stick === 'right') {
|
||||
drag.firstElementChild.style.left = clientWidth - offsetWidth + 'px'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,15 +129,15 @@ export const Draggable = props => {
|
||||
window.addEventListener('resize', checkInWindow)
|
||||
|
||||
return () => {
|
||||
return () => {
|
||||
window.removeEventListener('resize', checkInWindow)
|
||||
cancelAnimationFrame(rafRef.current)
|
||||
}
|
||||
window.removeEventListener('resize', checkInWindow)
|
||||
cancelAnimationFrame(rafRef.current)
|
||||
}
|
||||
}, [])
|
||||
}, [stick])
|
||||
|
||||
return (
|
||||
<div className={`draggable ${moving ? 'cursor-grabbing' : 'cursor-grab'} select-none`} ref={draggableRef}>
|
||||
<div
|
||||
className={`draggable ${moving ? 'cursor-grabbing' : 'cursor-grab'} select-none`}
|
||||
ref={draggableRef}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user