Javascript基础之写一个好玩的点击效果

1,853 阅读3分钟

基础准备工

写一个div,让它跟随鼠标移动而移动

const point = document.querySelector('#point') as HTMLDivElement;
const mouseMove = (e: MouseEvent)=>{
    const { clientX, clientY } = e
    point.style.left = clientX - point.offsetWidth / 2 + 'px'
    point.style.top = clientY - point.offsetHeight / 2 + 'px'
}
window.addEventListener('mousemove', mouseMove)
<body>
    <div id="point"></div>
</body>
body {
    background-image: url(../assets/image/indexBackgroundImage.jpeg);
    background-repeat: no-repeat;
    background-size: cover;
    background-position: center;

    #point {
        width: 16px;
        height: 16px;
        border-radius: 100%;
        border: 3px solid #fff;
        position: fixed;
        left: 10px;
        top: 10px;
        box-shadow: #fff 0px 0px 8px;
        user-select: none;
    }
}

image.png

大概就是这样的一个样式

添加点击效果

给window添加一个点击事件,并创建一个烟花

const onClick = (e: MouseEvent) => {
    const { clientX, clientY } = e

    const mouse = new Vector2(clientX, clientY)

    const div = createDiv(mouse)
    document.body.appendChild(div)

}

createDiv方法

const createDiv = (v: Vector2) => {
    const div: HTMLDivElement = document.createElement('div');
    // 添加一个类名,在style.less中写上公共样式
    div.classList.add('fieworks')
    // 颜色随机
    div.style.background = randomColor()
    // 位置为鼠标所在位置
    div.style.left = v.x + 'px'
    div.style.top = v.y + 'px'
    return div
}

randomColor方法用来获取随机颜色

const r = Math.floor(Math.random() * 255);
const g = Math.floor(Math.random() * 255);
const b = Math.floor(Math.random() * 255);
return `rgb(${r},${g},${b})`

计算烟花消失的位置

烟花向下做抛物线运动,起点为鼠标点击的位置,结束点要通过计算,算出相应的位置,首先写一个随机数,介于两个数值之间返回一个随机数

export function getRandomArbitrary(min: number, max: number): number {
    return Math.random() * (max - min) + min;
}

结束坐标基于鼠标坐标,向外扩散

const end = mouse.clone()
.setX(mouse.x + getRandomArbitrary(-width, width))
.setY(mouse.y + getRandomArbitrary(-height, height))

动画

加入动画之前,先把点位创建出来,数量随机

for (let i = 0; i < getRandomArbitrary(100, 1000); i++) {
    const end = mouse.clone()
        .setX(mouse.x + getRandomArbitrary(-width, width))
        .setY(mouse.y + getRandomArbitrary(-height, height))
    const div = createDiv(mouse)
    document.body.appendChild(div)
    changeFireworks(div, mouse, end,getRandomArbitrary(1, 2))
}

定义一个changeFireworks方法,接受四个参数,移动的元素,起点坐标,终点坐标,执行时间,在方法内调用new TWEEN方法

/**
 * 
 * @param element   移动的元素
 * @param s         起点坐标
 * @param e         终点坐标
 * @param time      执行时间
 */
const changeFireworks = (element: any, s: Vector2, e: Vector2, time = 1) => {
    new TWEEN.Tween(s)
        .to(e, time * 1000)
        .start()
        // .easing(TWEEN.Easing.Linear.None)
        .easing(TWEEN.Easing.Back.InOut) // 运动动画方式
        .onUpdate((v: any) => { // 更新时的回调
            const { x, y } = v
            element.style.left = x + 'px'
            element.style.top = y + 'px'
        })
        .onComplete(() => { // 结束的回调
            element.parentNode.removeChild(element)
        })
}

更新动画

定义一个自调用函数,在该函数内调用TWEEN && TWEEN.update(),并且时候循环动画requestAnimationFrame来继续调用animate方法,比传统的setInterval性能提升不止一点点,感兴趣的同学可以研究研究

(function animate() {
    requestAnimationFrame(animate);
    TWEEN && TWEEN.update()
})()

window.requestAnimationFrame()  告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

tween中easing方法可以传入不同的运动效果,tween内置了许多运动模式

image.png

效果

2023-05-25 16.03.50.gif

2023-05-25 16.15.54.gif

源码

源码地址

历史文章

# Javascript基础之鼠标拖拉拽

# three.js 打造游戏小场景(拾取武器、领取任务、刷怪)

# threejs 打造 world.ipanda.com 同款3D首页

# three.js——物理引擎

# three.js——镜头跟踪

# threejs 笔记 03 —— 轨道控制器