Posted in

图片碎片化展示-Javascript_AI阅读总结 — 包阅AI

包阅导读总结

1. 关键词:图片碎片化、Javascript、动画效果、背景图片、小块拼接

2. 总结:

– 作者从退游游戏说起,引入图片碎片化展示效果的分享。

– 介绍其原理是通过容器和图片大小生成小块,调整背景图片的大小与位置,添加动画。

– 提及解决白条问题的方法,展示不同的动画效果,最后提到图片加载的注意事项。

3. 主要内容:

– 开篇:作者讲述退游经历,随后引入正题分享图片碎片化展示效果。

– 原理:通过生成小块,利用`background-size`与`background-position`属性合成大图片。

– 实现:

– 布局与样式:设置页面布局和小块样式。

– 生成小块:规定行和列决定小块数量。

– 调整小块背景:设置背景图片的大小、位置及动画延迟。

– 问题解决:解决白条问题,注意`will-change`属性不能滥用并及时重置。

– 更多效果:通过改变延迟方式制造不同效果。

– 结尾:提及图片大量使用和加载时长可能导致效果不佳,需防范,如手动缓存图片。

思维导图:

文章地址:https://mp.weixin.qq.com/s/vWVx_Uzm5CoKBIVTweiprw

文章来源:mp.weixin.qq.com

作者:橙某人

发布时间:2024/9/3 8:01

语言:中文

总字数:2502字

预计阅读时间:11分钟

评分:84分

标签:JavaScript,CSS,前端开发,动画效果,图片特效


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

点击关注公众号,“技术干货”及时达!

写在开头

哈喽吖!各位好!😁

最近,小编从玩了两年多的游戏中退游了😔,本来以为会一直就这么玩下去,和队友们相处很融洽,收获了很多开心快乐的时光😭。可惜,游戏的一波更新……准备要开始收割韭菜了,只能无奈选择弃坑了。

小编属于贫民玩家,靠着硬肝与白嫖也将游戏号整得还不错,这两天把号给卖了💰。玩了两年多,竟然还能赚一点小钱,很开心😛。只是…多少有点舍不得的一起组队的队友们,唉。😔

记录一下,希望未来还有重逢一日吧,也希望各位一切安好!😆

好,回到正题,本文将分享一个图片碎片化展示的效果,具体效果如下,请诸君按需食用。

原理

这种特效早在几年前就已经出现,属于老演员了😪,它最早是经常在轮播图(banner)上应用的,那会追求各种花里胡哨的特效,而现在感觉有点返璞归真了,简洁实用就行。

今天咱们来看看它的具体实现原理是如何的,且看图:

一图胜千言,不知道聪明的你是否看明白了?😉

大概原理是:通过容器/图片大小生成一定数量的小块,然后每个小块背景也使用相同图片,再使用 background-sizebackground-position 属性调整背景图片的大小与位置,使小块又合成一整张大图片,这操作和使用”精灵图”的操作是一样的,最后,我们再给每个小块增加动画效果,就大功告成。

简单朴实😁,你可以根据这个原理自个尝试一下,应该能整出来吧。👻

具体实现

布局与样式:

<!DOCTYPEhtml>
<html>
<head>
<style>
body{
width:100%;
height:100vh;
padding:0;
margin:0;
display:flex;
justify-content:center;
align-items:center;
}
.box{
width:var(--width);
height:var(--height);
display:flex;
/*小块自动换行排列*/
flex-wrap:wrap;
justify-content:center;
}
.small-box{
background-image:url('https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/99b070fcb1de471d9af4f4d5d3f71909~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1120&h=1680&s=2088096&e=png&b=d098d0');
box-sizing:border-box;
background-repeat:no-repeat;
}
</style>
</head>
<body>
<divid="box"class="box"></div>
</body>
</html>

生成无数小块填充:

<script>
document.addEventListener('DOMContentLoaded',()=>{
constbox=document.getElementById('box');
const{width,height}=box.getBoundingClientRect();
//定义多少个小块,由多少行和列决定
constrow=14;
constcol=10;
//计算小块的宽高
constsmallBoxWidth=width/col;
constsmallBoxHeight=height/row;
/**@name创建小块**/
functioncreateSmallBox(){
for(leti=0;i<row;i++){
for(letj=0;j<col;j++){
constsmallBox=document.createElement('div');
smallBox.classList.add('small-box');
smallBox.style.width=smallBoxWidth+'px';
smallBox.style.height=smallBoxHeight+'px';
smallBox.style.border='1pxsolidred';
//插入小块
box.appendChild(smallBox);
}
}
}
createSmallBox();
});
</script>

上面,生成多少个小块是由人为规定行(row)与列(col)来决定。可能有的场景想用小块固定的宽高来决定个数,这也是可以的,只是需要注意处理一下”边界”的情况。😶

调整小块背景图片的大小与位置:

<script>
document.addEventListener('DOMContentLoaded',()=>{
//...
functioncreateSmallBox(){
for(leti=0;i<row;i++){
for(letj=0;j<col;j++){
//...
smallBox.style.border='1pxsolidred';

//设置背景偏移量,让小块的背景显示对应图片的位置,和以前那种精灵图一样
constoffsetX=j*smallBoxWidth*-1;
constoffsetY=i*smallBoxHeight*-1;
smallBox.style.backgroundPosition=`${offsetX}px${offsetY}px`;
smallBox.style.backgroundSize=`${width}px${height}px`;

box.appendChild(smallBox);
}
}
}
createSmallBox();
});
</script>

女神拼接成功,到这里就已经完成一大步了,是不是没什么难度!😋

小块样式整好后,接下来,我们需要来给小块增加动画,让它们动起来,并且是有规律的动起来。

先来整个简单的透明度动画,且看:

<!DOCTYPEhtml>
<html>
<head>
<style>
/*...*/
.small-box{
/*...*/
opacity:0;
animation:smallBoxAnimate2000mslinearforwards;
}
@keyframessmallBoxAnimate{
0%{
opacity:0;
}
40%{
opacity:0;
}
70%{
opacity:1;
}
100%{
opacity:1;
}
}
</style>
</head>
<body>
<script>
document.addEventListener('DOMContentLoaded',()=>{
//...
functioncreateSmallBox(){
for(leti=0;i<row;i++){
for(letj=0;j<col;j++){
//...
//smallBox.style.border='1pxsolidred';

//给每个小块增加不同的延时,让动画不同时间执行
constdelay=i*100;//延迟时间为毫秒(ms),注意不要太小了
smallBox.style.animationDelay=`${delay}ms`;

box.appendChild(smallBox);
}
}
}
createSmallBox();
});
</script>
</body>
</html>

嘿嘿😃,稍微有点意思了吧?

Em…等等,你发现没有?怎么有一些小白条?这可不是小编添加的,小块的边框(border)已经是注释了的。😓

一开始小编以为是常见的”图片底部白边”问题,直接设置一下 display: block 或者 vertical-align : middle 就能解决,结果还不是,折腾了很久都没有搞掉这个小白条。😤

最后,竟然通过设置 will-change 属性能解决这个问题❗我所知道的 will-change 应该是应用在性能优化上,解决动画流畅度问题上的,想不到这里竟然也能用。

❗不对不对,当初以为是 will-change 能直接完美解决白边的问题,但是感觉还是不对,但又确实能解决。。。(部分电脑屏幕)

但其实,应该是 smallBoxWidthsmallBoxHeight 变量不是整数的问题,只要小块的宽度与高度保持一个整数,自然就没有这些白边了❗这是比较靠谱的事实,对于当前的高清屏幕来说。

但是,也是很奇怪,在小编另一台电脑(旧电脑)上即使是保持了整数,也会在横向存在一些小白边,太难受了。。。没办法彻底搞定这个问题。

猜测应该是和屏幕分辨率有关,毕竟那才是根源所在。

2024年07月01日

看来得去深度学习一下💪 will-change 属性的原理过程才行,这里也推荐倔友写得一篇文章:传送门。

解决相邻背景图片白条/白边间隙问题:

<script>
document.addEventListener('DOMContentLoaded',()=>{
//...
functioncreateSmallBox(){
for(leti=0;i<row;i++){
for(letj=0;j<col;j++){
//...

smallBox.style.willChange='transform';
//在动画执行后,需要重置will-change
consttimer=setTimeout(()=>{
smallBox.style.willChange='initial';
clearTimeout(timer);
},2000);

box.appendChild(smallBox);
}
}
}
createSmallBox();
});
</script>

一定要注意 will-change 不可能被滥用,注意重置回来❗

这下女神在动画执行后,也清晰可见了,这是全部小块拼接组成的图片。

在上述代码中,咱们看到,通过 animation-delay 去延迟动画的执行,就能制造一个从上到下的渐变效果。

那么,咱们再改改延迟时间,如:

//constdelay=i*100;
//改成⤵
constdelay=j*100;

效果:

这…好像有那么点意思吧。。。

但是,这渐变…好像还达不到我们开头 gif 的碎片化效果吧?

那么,碎片化安排上:

.small-box{
/*...*/
--rotateX:rotateX(0);
--rotateY:rotateY(0);
transform:var(--rotateX)var(--rotateY)scale(0.8);
}
@keyframessmallBoxAnimate{
0%{
opacity:0;
transform:var(--rotateX)var(--rotateY)scale(0.8);
}
40%{
opacity:0;
transform:var(--rotateX)var(--rotateY)scale(0.8);
}
70%{
opacity:1;
transform:rotateX(0)rotateY(0)scale(0.8);
}
100%{
opacity:1;
transform:rotateX(0)rotateY(0)scale(1);
}
}

其实就是增加小块的样式动画而已,再加点旋转,再加点缩放,都整上,整上。😆

效果:

是不是稍微高级一点?有那味了?😁

看到上面旋转所用的”样式变量”没有?

--rotateX:rotateX(0);
--rotateY:rotateY(0);

不可能无缘无故突然使用,必然是有深意啦。😁

现在效果还不够炫,咱们将样式变量利用起来,让”相邻两个小块旋转相反”:

<script>
document.addEventListener('DOMContentLoaded',()=>{
//...
functioncreateSmallBox(){
for(leti=0;i<row;i++){
for(letj=0;j<col;j++){
//...

//相邻两个小块旋转相反
constcontrary=(i+j)%2===0;
smallBox.style.setProperty('--rotateX',`rotateX(${contrary?-180:0}deg)`);
smallBox.style.setProperty('--rotateY',`rotateY(${contrary?0:-180}deg)`);

box.appendChild(smallBox);
}
}
}
createSmallBox();
});
</script>

效果:

这下对味了。😃

总的来说,我们可以通过”延迟”执行动画与改变”旋转”行为,让小块们呈现不同的动画效果,或者你只要有足够多的设想,你可以给小块添加不同的动画效果,相信也能制造出不错的整体效果。

更多效果

下面列举一些通过”延迟”执行动画产生的效果,可以瞧瞧哈。

「随机:」

constgetRandom=(min,max)=>Math.floor(Math.random()*(max-min+1)+min);
constdelay=getRandom(0,col+row)*100;

「从左上角到右下角:」

constdelay=(i+j)*100;

其他的从”右上角到左下角”或者”左下角到右上角”等等的,只要反向调整一下变量就行了,就靠你自己悟啦,Come On!👻

「从中心向四周扩散:」

constdelay=((Math.abs(col/2-j)+Math.abs(row/2-i)))*100;

「从四周向中心聚齐:」

constdelay=(col/2-Math.abs(col/2-j)+(col/2-Math.abs(row/2-i)))*100;

那么,到这里就差不多了❗

但还有最后一个问题,那就是图片的大量使用与加载时长的情况可能会导致效果展示不佳,这里你最好进行一些防范措施,如:

  • 通过 JS 手动将图片缓存到内存,主要就是创建 Image 对象。

以上等等吧,反正最好就是要等图片完整加载后再进行效果展示。

至此,本篇文章就写完啦,撒花撒花。

希望本文对你有所帮助,如有任何疑问,期待你的留言哦。
老样子,点赞+评论=你会了,收藏=你精通了。