<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
.erase-container {
position: relative;
display: inline-block;
font-size: 48px;
font-weight: bold;
}
.erase-text {
background: linear-gradient(to right,
#000 0%,
#000 50%,
transparent 50%,
transparent 100%);
background-size: 200% 100%;
background-position: 100% 0;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
transition: background-position 2s ease-in-out;
}
.erase-text.active {
background-position: 0 0;
}
button {
margin-top: 20px;
padding: 10px 20px;
font-size: 16px;
}
</style>
</head>
<body>
<div class="erase-container">
<div class="erase-text" id="eraseText">Hello World!</div>
</div>
<br>
<button onclick="startErase()">开始擦除</button>
<button onclick="resetErase()">重置</button>
<script>
function startErase() {
const text = document.getElementById('eraseText');
text.classList.add('active');
}
function resetErase() {
const text = document.getElementById('eraseText');
text.classList.remove('active');
}
// 自动开始
setTimeout(startErase, 500);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
canvas {
border: 1px solid #ddd;
}
.controls {
margin-top: 20px;
}
button {
padding: 10px 20px;
font-size: 16px;
margin-right: 10px;
}
input[type="range"] {
width: 300px;
}
</style>
</head>
<body>
<canvas id="eraseCanvas" width="600" height="150"></canvas>
<div class="controls">
<button onclick="startAnimation()">开始动画</button>
<button onclick="resetCanvas()">重置</button>
<button onclick="eraseRandom()">随机擦除</button>
<br><br>
<label>擦除进度: <span id="progress">0%</span></label>
<input type="range" id="eraseSlider" min="0" max="100" value="0" oninput="manualErase(this.value)">
</div>
<script>
const canvas = document.getElementById('eraseCanvas');
const ctx = canvas.getContext('2d');
const text = "Canvas文字擦除效果";
let isAnimating = false;
let animationId = null;
// 初始化绘制文字
function drawText() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.font = "bold 60px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = "#333";
ctx.fillText(text, canvas.width / 2, canvas.height / 2);
}
// 擦除指定百分比
function erase(percentage) {
drawText();
// 创建擦除区域
const eraseWidth = (canvas.width * percentage) / 100;
// 使用合成模式擦除
ctx.globalCompositeOperation = 'destination-out';
// 绘制擦除矩形(从左到右)
ctx.fillRect(
canvas.width / 2 - ctx.measureText(text).width / 2,
canvas.height / 2 - 30,
eraseWidth,
60
);
// 恢复合成模式
ctx.globalCompositeOperation = 'source-over';
// 更新进度显示
document.getElementById('progress').textContent = percentage + '%';
}
// 开始动画擦除
function startAnimation() {
if (isAnimating) return;
isAnimating = true;
let progress = 0;
function animate() {
if (progress >= 100) {
isAnimating = false;
cancelAnimationFrame(animationId);
return;
}
progress += 0.5;
erase(progress);
document.getElementById('eraseSlider').value = progress;
animationId = requestAnimationFrame(animate);
}
animate();
}
// 手动控制擦除
function manualErase(value) {
if (isAnimating) {
cancelAnimationFrame(animationId);
isAnimating = false;
}
erase(value);
}
// 随机擦除效果
function eraseRandom() {
drawText();
// 创建多个随机位置的擦除圆圈
ctx.globalCompositeOperation = 'destination-out';
for (let i = 0; i < 50; i++) {
const x = Math.random() * canvas.width;
const y = Math.random() * canvas.height;
const radius = Math.random() * 20 + 5;
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fill();
}
ctx.globalCompositeOperation = 'source-over';
}
// 重置画布
function resetCanvas() {
if (isAnimating) {
cancelAnimationFrame(animationId);
isAnimating = false;
}
document.getElementById('eraseSlider').value = 0;
drawText();
document.getElementById('progress').textContent = '0%';
}
// 初始化
drawText();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
.svg-container {
width: 600px;
height: 150px;
border: 1px solid #ddd;
}
.erase-btn {
padding: 10px 20px;
font-size: 16px;
margin-top: 20px;
}
</style>
</head>
<body>
<svg class="svg-container" id="eraseSvg">
<defs>
<!-- 创建遮罩 -->
<mask id="textMask">
<!-- 白色区域显示文字 -->
<rect id="maskRect" x="0" y="0" width="100%" height="100%" fill="white"/>
<!-- 黑色矩形用于擦除 -->
<rect id="eraseRect" x="0" y="0" width="0" height="100%" fill="black">
<animate
id="eraseAnim"
attributeName="width"
from="0%"
to="100%"
dur="2s"
fill="freeze"
begin="indefinite"
/>
</rect>
</mask>
</defs>
<!-- 应用遮罩的文字 -->
<text x="50%" y="50%"
text-anchor="middle"
dominant-baseline="middle"
font-size="60"
font-weight="bold"
mask="url(#textMask)">
SVG擦除效果
</text>
</svg>
<br>
<button class="erase-btn" onclick="startSVGErase()">开始擦除</button>
<button class="erase-btn" onclick="reverseSVGErase()">反向擦除</button>
<button class="erase-btn" onclick="resetSVGErase()">重置</button>
<script>
const eraseAnim = document.getElementById('eraseAnim');
const eraseRect = document.getElementById('eraseRect');
const maskRect = document.getElementById('maskRect');
function startSVGErase() {
// 设置从0%到100%的动画
eraseAnim.setAttribute('from', '0%');
eraseAnim.setAttribute('to', '100%');
eraseAnim.beginElement();
}
function reverseSVGErase() {
// 设置从100%到0%的动画(恢复)
eraseAnim.setAttribute('from', '100%');
eraseAnim.setAttribute('to', '0%');
eraseAnim.beginElement();
}
function resetSVGErase() {
// 立即重置到初始状态
eraseRect.setAttribute('width', '0');
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
.particle-container {
position: relative;
width: 600px;
height: 150px;
overflow: hidden;
}
.text {
position: absolute;
font-size: 60px;
font-weight: bold;
color: #333;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
z-index: 1;
}
.particles {
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
}
.particle {
position: absolute;
background: white;
border-radius: 50%;
pointer-events: none;
}
button {
padding: 10px 20px;
font-size: 16px;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="particle-container">
<div class="text" id="particleText">粒子擦除效果</div>
<div class="particles" id="particles"></div>
</div>
<br>
<button onclick="startParticleErase()">开始粒子擦除</button>
<button onclick="resetParticles()">重置</button>
<script>
const textElement = document.getElementById('particleText');
const particlesContainer = document.getElementById('particles');
let particles = [];
function createParticles() {
// 清除现有粒子
resetParticles();
const textRect = textElement.getBoundingClientRect();
const containerRect = particlesContainer.getBoundingClientRect();
// 创建网格粒子
const particleSize = 6;
const spacing = 4;
for (let x = 0; x < textRect.width; x += spacing) {
for (let y = 0; y < textRect.height; y += spacing) {
// 检查点是否在文字区域内
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1;
canvas.height = 1;
// 临时绘制文字
ctx.font = getComputedStyle(textElement).font;
ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText(textElement.textContent, -x, -y);
// 检查像素是否不透明
const pixel = ctx.getImageData(0, 0, 1, 1).data;
if (pixel[3] > 128) { // 如果像素不透明
createParticle(
textRect.left - containerRect.left + x,
textRect.top - containerRect.top + y,
particleSize
);
}
}
}
}
function createParticle(x, y, size) {
const particle = document.createElement('div');
particle.className = 'particle';
particle.style.width = size + 'px';
particle.style.height = size + 'px';
particle.style.left = x + 'px';
particle.style.top = y + 'px';
particle.style.opacity = '1';
particle.style.boxShadow = '0 0 2px rgba(0,0,0,0.3)';
particlesContainer.appendChild(particle);
particles.push(particle);
return particle;
}
function startParticleErase() {
// 先创建粒子
createParticles();
// 为每个粒子添加动画
particles.forEach((particle, index) => {
// 随机延迟
const delay = Math.random() * 1000;
setTimeout(() => {
// 随机方向和距离
const angle = Math.random() * Math.PI * 2;
const distance = 50 + Math.random() * 100;
const duration = 1000 + Math.random() * 1000;
// 飞走动画
particle.style.transition = `all ${duration}ms ease-out`;
particle.style.transform = `translate(
${Math.cos(angle) * distance}px,
${Math.sin(angle) * distance}px
)`;
particle.style.opacity = '0';
// 动画结束后移除
setTimeout(() => {
if (particle.parentNode) {
particle.parentNode.removeChild(particle);
}
}, duration);
}, delay);
});
// 文字淡出
textElement.style.transition = 'opacity 1.5s ease-out';
textElement.style.opacity = '0';
}
function resetParticles() {
// 移除所有粒子
particles.forEach(particle => {
if (particle.parentNode) {
particle.parentNode.removeChild(particle);
}
});
particles = [];
// 重置文字
textElement.style.opacity = '1';
textElement.style.transition = 'none';
}
</script>
</body>
</html>
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| CSS渐变 | 简单、性能好、代码少 | 效果较简单 | 基础擦除效果 |
| Canvas | 灵活、可定制性强 | 代码较复杂 | 需要精确控制或特效 |
| SVG | 矢量不失真、动画流畅 | 兼容性稍差 | 需要高质量显示 |
| 粒子 | 视觉效果炫酷 | 性能开销大 | 特殊展示效果 |
建议:
可以根据具体需求选择合适的方法!