时间:2021-02-28 14:48:23 | 栏目:AngularJS | 点击:次
前言
最近一段时间由于项目需要接触到了ionic3,发现真是一个利器啊!ionic项目提供了一套丰富的图标库,在ionic3中也进行了升级。
公司的一个项目中由于要用到一个瀑布流的特效,找了半天竟然没有找到相关的资源,没有办法,只能迎着头皮上了~
话不多说,先上图
相信看过图片的同学都明白什么意思了吧。对,就是瀑布流!
但是今天我们的瀑布流可不是一般的瀑布流。让我们接着看:
自动排版
我们的要求是做那种随机凌乱的感觉,所以我们需要做一种机制,来将图片选择最优的一种排列方式来展示到页面上,也就是保证图片与相邻图片的比例是最合适的然后在实现排列.
angular4
相信这个效果如果在平常的jq插件中似乎也不难实现,确实,网上也能搜到一些jq的插件。但是我们的技术栈是angular4呀~
在ng中我们的DOM操作基本都是放在指令中的,相信用过angularjs1.x的同学并不陌生了吧~,在angular4中也是一样。
好了,让我们贴代码~
创建指令
我们假设你已经在你的ionic中建立好了相关的组件,并且已经拥有的图片数据,如果没有相关基础的同学建议大家先去看看ionic3 与 angular4的入门。
这是我的一个组件html的页面,也许眼尖的同学已经发现了我们的指令 [imagr-sort]="item",对的,我们的指令是需要你当前的图片的angular数据的。
创建一个指令ts
ionic g directive image-sort
执行建立我们的指令。
创建完了我们的自定义指令就是这个样子,空空如也啊~
编写我们的逻辑
1.1接收并且注入一些东西:
看图!
既然我们在模板中有输入([[imagr-sort]="item"]);
那么我们也当然应该在指令中接收到输入的数据;如截图中红色箭头所示,我将输入的数据保存了起来->sourceArr;
然后我们在angular4中如果要获取到dom宿主的一些属性了,元素了等等就要用到ElementRef,Renderer2是angular4中的一个类似渲染器的东西吧,这个具体的我还没有搞懂,大家可以多看看这块的资料,我主要是在这个指令中用于更改Dom的一些结构。
关于我们的imgLength ,我待会再说
1.2实际点!图片是从异步加载过来的!
我们首先思考这样一个问题:
我们的指令是在angular数据渲染的时候就开始执行的,这个是基本大家都懂。
but!我们的图片可都是异步加载的呢~,所以自然而然我们要有一个图片加载的过程:
嗯,相信各位早就想到了---->image.onload
,不错,是它~
也是时候说下之前的imgLength了,这个变量来记录记载完成的图片的数量,用来辨别是否当前图片都已经加载完毕了,为我们后续的动作做依据。
image.onerror
,这个相信大家也看明白了吧,这个是图片加载失败的一个函数,我在里面做的操作是将加载失败的图片从原始的DOM中,angular的数据剔除。
这里面就用到了我们angular的渲染器this.render2();
相关功能方法大家可以去源码里面看一下,基本上所有常用的Dom操作都有实现。
for循环呢是因为我们的图片数据是多条的,所以我们要等待每一张图片都顺利的加载完成。
ps:注意在onerror与onload的函数中使用this要在imgOnlod中使用变量引用let _self = this;
图片加载完成开始我们的改造工程
1.3将我们的适口按照网格划分
imageStartStort()!
上图
大家看1图红圈内,我是自己划分出五个横向网格标准,便于我们待会将图片比例做对比。
1.4将我们的图片定义网格占用
我们创建了一个数组allImageArr=[];用于保存当前处理过的所有图片的数据。
还记的我们之前获得的angular的数据吧,我们通过循环它来将图片划分网格占用。
我们的循环中都做了些什么?
1.图片的宽高,并且求出每一张图片的比例。
2.将获得的图片比列与我们自己定义的网格比例进行区间划分。
3.按照我们划分的网格来计算出占有网格的图片的新的宽度,所占网格数储存并且记录保存到我们的自定义的allImageArr中,并且在原有的angular数据中添加gridding数字那个记录相应的网格数。
执行this.pictureColumnSort
方法;
我们的图片已经划分完成了,接下来,我们来激情的一刻~
1.5图片排列,跟据网格派选最合适的邻居~
pictureColumnSort()!
上图
这一个过程其实也没啥好说的,主要就是循环,查看每个图片的网格数,将最合适的进行相邻排序(执行下一步:goExchange函数),最后匹配不上的单独做一个5分网格战术出来.
格式可以是多种:
3+2,1+4,1+1+3,1+3+1,2+3.。。。。。
怎么高兴怎么来~
没啥好说的就是循环筛选,大家看看图就好。
1.6无序变有序,除了交换应该没有更好的选择了吧
goExchange()! 上图
看看1.5中的代码,我们呢是在每次匹配到了合适的图片之后执行这个函数,因为我们需要把匹配到的图片换位置啊!
这个函数中接收到的repeatI与repeatA就是1.5中的双重循环的索引,这个索引决定了我们换图片的位置。
代码所示的原理就是将匹配到的图片换到我们当前图片的后面,将原来后面的图片补到换过来图片的位置,有点绕可能是我的比哦打能力不好,哈哈。
没啥好说的这个函数,就是换位置。
1.7取长补短,完工!
setHeight()!上图
再次循环(代码应该还有不少改进的地步,循环用的不少~);
这个地步已经我们呢的布局页面完成了,但是我们的图片的尺寸实际上是不规则的,不忍直视,
所以我们在这个函数中将差异抹平,取长补短。
实际上我们的图片肯定会有一点拉伸,所以我们也是取了平衡的一个中间点,来进行适当的拉伸。
这个函数肯定其实还可以做一些适当的限制来精细化图片的尺寸调整。至此我们也算是写完了整个指令逻辑。
完工! ioinc serve
至于中间的调用的过程有一点我要说明:
setTimeout(() => { _self.setHeight(angularImageList, ele); });
整个调用我也是晚班无奈的情况下才使用的,如果不加整个调用在setHeight函数中设置的angular,数据会莫名其妙的出现图片位置更换错误,至今误解,如果大佬们能看到整个有好的解决方法也分享一下。
总结