将魔法光标效果的jQuery代码重构为Angular代码
如何在Angular中复刻魔法光标效果
原jQuery实现代码
JavaScript
$(document).ready(function(){ var coordinateX=0; var coordinateY=0; var bottomCursor=document.querySelector('.circle-cursor-bottom'); var topCursor=document.querySelector('.circle-cursor-top'); function displayCursor(e){ document.addEventListener('mousemove',e=>{ coordinateX=e.clientX; coordinateY=e.clientY }); function animCursor(){ topCursor.style.transform=`translate(${coordinateX}px, ${coordinateY}px)`; bottomCursor.style.transform=`translate(${coordinateX}px, ${coordinateY}px)`; requestAnimationFrame(animCursor) }; requestAnimationFrame(animCursor) }; displayCursor(); });
CSS
.circle-cursor { position:fixed; pointer-events:none; width:1.4376rem; height:1.4376rem; margin:-0.630rem 0 0 -0.630px; top:0; left:0; border-radius:50%; } .circle-cursor-inner { width:100%; height:100%; border-radius:50%; display:block; } .circle-cursor-top { background-color:#22d4b5; transition:transform 0.06s cubic-bezier(.12,.12,.25,.92),opacity 1s ease; z-index:9999; } .circle-cursor-bottom { background:#6edddf; transition:transform 0.26s cubic-bezier(.12,.12,.25,.92),opacity 1s ease; z-index:9998; }
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="custom-cursor-holder"> <div class="circle-cursor circle-cursor-top"> <span class="circle-cursor-inner"></span> </div> <div class="circle-cursor circle-cursor-bottom"></div> </div>
我的Angular尝试代码
模板代码
<div class="custom-cursor-holder"> <div #top class="circle-cursor circle-cursor-top"> <span class="circle-cursor-inner"></span> </div> <div #bottom class="circle-cursor circle-cursor-bottom"></div> </div>
组件代码
export class AppComponent{ coordinateX = 0; coordinateY = 0; @ViewChild('top') top!: ElementRef; @ViewChild('bottom') bottom!: ElementRef; constructor(private renderer: Renderer2) { } @HostListener('mouseover', ['$event']) onOver(event: MouseEvent): void { this.coordinateX = event.clientX; this.coordinateY = event.clientY; this.renderer.setStyle(this.top.nativeElement, 'transform', 'translate('+ this.coordinateX +'px, '+ this.coordinateY +'px)'); } }
最佳Angular实现方案
组件代码优化
import { Component, ElementRef, ViewChild, HostListener, OnInit, OnDestroy } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit, OnDestroy { coordinateX = 0; coordinateY = 0; animationId?: number; @ViewChild('top') top!: ElementRef<HTMLDivElement>; @ViewChild('bottom') bottom!: ElementRef<HTMLDivElement>; ngOnInit(): void { this.startCursorAnimation(); } ngOnDestroy(): void { if (this.animationId) { cancelAnimationFrame(this.animationId); } } @HostListener('document:mousemove', ['$event']) onMouseMove(event: MouseEvent): void { this.coordinateX = event.clientX; this.coordinateY = event.clientY; } private startCursorAnimation(): void { const animCursor = () => { this.top.nativeElement.style.transform = `translate(${this.coordinateX}px, ${this.coordinateY}px)`; this.bottom.nativeElement.style.transform = `translate(${this.coordinateX}px, ${this.coordinateY}px)`; this.animationId = requestAnimationFrame(animCursor); }; animCursor(); } }
模板代码(保持不变)
<div class="custom-cursor-holder"> <div #top class="circle-cursor circle-cursor-top"> <span class="circle-cursor-inner"></span> </div> <div #bottom class="circle-cursor circle-cursor-bottom"></div> </div>
CSS代码(直接复用原代码)
将原jQuery实现中的CSS代码复制到组件的app.component.css文件中即可。
关键改进点
- 改用
document:mousemove监听全局鼠标移动,确保光标在整个页面范围内响应 - 沿用
requestAnimationFrame实现和原jQuery一致的流畅动画效果 - 实现
OnDestroy接口,组件销毁时清除动画帧,避免内存泄漏 - 同时更新顶部和底部光标的位置,修复原尝试代码只处理顶部光标的问题
- 为
ElementRef添加类型标注,提升代码健壮性
内容的提问来源于stack exchange,提问作者Ranjith Varatharajan
相关产品推荐
相关产品推荐

