如何无需额外div实现图片从右下到左上的渐显CSS/JS动画?
问题描述
我是CSS初学者,想要实现一张图片从右下角开始渐显至左上角的动画。尝试直接在img元素上实现失败后,我使用了一个与背景同色的div覆盖在图片上方完成效果,现请教无需额外div的专业实现方法,纯CSS或JS方案均可。
原实现代码:
.personal-photo { padding: 4rem; z-index: -10; } .photo-effect { position: absolute; padding: 42%; top: 91px; left: 91px; background-image: linear-gradient(120deg, #fff 0%, #fff 50%, transparent 50%); background-size: 300%; animation: photoEffect 2s infinite; z-index: 10; } @keyframes photoEffect { 100% { background-position: 100%; } }
<div class="container"> <img src="https://placekitten.com/200/300" class="personal-photo" alt=""> <div class="photo-effect"></div> </div>
无需额外div的实现方案
方案一:CSS Mask 属性(推荐)
用CSS Mask可以直接在img元素上做遮罩动画,不用额外元素,效果精准。核心是用渐变遮罩从完全覆盖图片(隐藏状态)过渡到完全透明(显示状态),动画方向对应右下角到左上角。
代码示例:
.container { position: relative; padding: 4rem; } .personal-photo { width: 200px; height: 300px; animation: revealFromCorner 2s forwards; /* 初始遮罩完全盖住图片 */ mask: linear-gradient(120deg, black 50%, transparent 50%); mask-size: 300%; mask-position: 100% 100%; /* 遮罩初始定位在右下角 */ /* 兼容webkit内核浏览器 */ -webkit-mask: linear-gradient(120deg, black 50%, transparent 50%); -webkit-mask-size: 300%; -webkit-mask-position: 100% 100%; } @keyframes revealFromCorner { to { mask-position: 0% 0%; /* 遮罩移到左上角,完全显示图片 */ -webkit-mask-position: 0% 0%; } }
<div class="container"> <img src="https://placekitten.com/200/300" class="personal-photo" alt="猫咪图片"> </div>
- 黑色遮罩区域会显示图片,透明区域隐藏图片
- 动画通过改变
mask-position,让遮罩从右下角滑到左上角,实现渐显 - 加
-webkit-前缀适配Chrome、Safari等浏览器
方案二:父容器伪元素替代额外div
如果要兼容不支持mask的旧浏览器,可以用图片父容器的伪元素来做,同样不用额外div标签。
代码示例:
.container { position: relative; padding: 4rem; display: inline-block; /* 让容器贴合图片尺寸 */ } .container::after { content: ''; position: absolute; top: 4rem; /* 对应容器的padding值 */ left: 4rem; width: 100%; height: 100%; background: linear-gradient(120deg, #fff 50%, transparent 50%); background-size: 300%; background-position: 100% 100%; animation: coverEffect 2s forwards; } .personal-photo { width: 200px; height: 300px; } @keyframes coverEffect { to { background-position: 0% 0%; opacity: 0; /* 动画结束后隐藏伪元素 */ } }
<div class="container"> <img src="https://placekitten.com/200/300" class="personal-photo" alt="猫咪图片"> </div>
- 用容器的
::after伪元素代替原来的额外div,定位在图片上方 - 动画移动渐变背景,让白色覆盖区域从右下角移到左上角,最后隐藏伪元素
方案三:JavaScript 像素级控制(可选)
如果需要更精细的自定义效果,可以用JS通过Canvas逐像素控制透明度,不过性能比CSS方案稍差,适合复杂交互场景。
代码示例:
.container { padding: 4rem; } .personal-photo { width: 200px; height: 300px; position: relative; }
<div class="container"> <img src="https://placekitten.com/200/300" class="personal-photo" id="photo" alt="猫咪图片"> </div> <script> const img = document.getElementById('photo'); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); let progress = 0; const duration = 2000; // 动画时长2秒 const startTime = Date.now(); function animate() { const elapsed = Date.now() - startTime; progress = Math.min(elapsed / duration, 1); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const data = imageData.data; // 遍历每个像素,根据进度控制透明度 for (let y = 0; y < canvas.height; y++) { for (let x = 0; x < canvas.width; x++) { const index = (y * canvas.width + x) * 4; // 计算当前像素到右下角的距离比例 const distanceRatio = Math.sqrt( Math.pow((canvas.width - x)/canvas.width, 2) + Math.pow((canvas.height - y)/canvas.height, 2) ) / Math.sqrt(2); // 进度达标就显示该像素 data[index + 3] = distanceRatio <= progress ? 255 : 0; } } ctx.putImageData(imageData, 0, 0); img.src = canvas.toDataURL(); if (progress < 1) requestAnimationFrame(animate); } img.onload = animate; </script>
- 通过Canvas绘制图片,逐像素设置透明度,实现从右下角到左上角的渐显
- 适合需要自定义渐变曲线或复杂交互的场景,但性能开销比CSS大
内容的提问来源于stack exchange,提问作者Marya
相关产品推荐
相关产品推荐

