当组件安装并设置为使用事件侦听器跟随鼠标时,我通过在 useEffect 挂钩中动态附加 div 元素来创建自定义光标。但是,正在渲染两个 div — 一个正确跟随鼠标,而另一个则停留在视口的左上角。
import { useRef, useEffect, useState } from "react"
function Pcanvas({width, height, pixelSize}){
const [canvasColor, setCanvasColor] = useState("#dcdcdc")
const [pencilSize, setPencilSize] = useState(pixelSize)
const canvasRef = useRef(null)
var mousePressed = false
function mouseCursor(){
const cursor = document.createElement("div")
cursor.className = 'cursor'
cursor.style.backgroundColor = 'black'
cursor.style.width = pencilSize + 'px'
cursor.style.height = pencilSize + 'px'
cursor.style.position = 'absolute';
cursor.style.display = 'block';
cursor.style.zIndex = 999;
cursor.style.pointerEvents = 'none';
document.body.appendChild(cursor)
console.log(cursor.getBoundingClientRect().y)
}
function handleMouseMov(event){
const cursor = document.getElementsByClassName('cursor')[0]
console.log(cursor.getBoundingClientRect().y)
if(cursor){
cursor.style.top = event.clientY-(pencilSize/2) + 'px'
cursor.style.left = event.clientX-(pencilSize/2) + 'px'
}
}
function handleMouseLeave(event){
const cursor = document.getElementsByClassName('cursor')[0]
if(cursor){
cursor.style.display = 'none'
}
}
function handleMouseEnter(event){
const cursor = document.getElementsByClassName('cursor')[0]
if(cursor){
cursor.style.display = 'block'
}
}
useEffect(() => {
const canvas = canvasRef.current
mouseCursor()
document.body.addEventListener('mouseenter', handleMouseEnter)
document.body.addEventListener('mousemove', handleMouseMov)
document.body.addEventListener('mouseleave', handleMouseLeave)
return(() => {
document.body.removeEventListener('mouseenter', handleMouseEnter)
document.body.removeEventListener('mousemove', handleMouseMov)
document.body.removeEventListener('mouseleave', handleMouseLeave)
})
}, [pencilSize])
return(
<></>
)
}
export default Pcanvas
使用 React 时,您应该避免
createElement
,尤其是 getElementsByClassName
。
让组件自行渲染
div
,然后在需要时使用 useRef
更改任何样式。
const { useRef, useEffect, useState } = React;
function Pcanvas({ width, height, pixelSize = 15 }){
const cursor = useRef(null)
const [pencilSize, setPencilSize] = useState(pixelSize)
const handleMouseEnter = (event) => cursor.current.style.display = 'block';
const handleMouseLeave = (event) => cursor.current.style.display = 'none';
const handleMouseMov = (event) => {
cursor.current.style.top = event.clientY-(pencilSize/2) + 'px'
cursor.current.style.left = event.clientX-(pencilSize/2) + 'px'
}
useEffect(() => {
document.body.addEventListener('mouseenter', handleMouseEnter);
document.body.addEventListener('mousemove', handleMouseMov);
document.body.addEventListener('mouseleave', handleMouseLeave);
return(() => {
document.body.removeEventListener('mouseenter', handleMouseEnter);
document.body.removeEventListener('mousemove', handleMouseMov);
document.body.removeEventListener('mouseleave', handleMouseLeave);
})
}, [pencilSize])
return (
<div
ref={cursor}
className={'cursor'}
style={{ width: pencilSize, height: pencilSize, display: 'none' }}
/>
);
}
ReactDOM.render(<Pcanvas />, document.getElementById("react"));
html, body, #react { height: 100%; }
.cursor {
background: black;
position: absolute;
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>