ionic -angular 瀑布流
html
<!-- 瀑布流方式--> <div id="container" [ngClass]="list.length>0?'show':'hide'"> <div class="box" *ngFor="let item of list" (click)="goDetail(item)"> <div class="box_img"> <img src="assets/img/IMG_20190921_174133.jpg" class="im"> <ion-badge slot="start" *ngIf="item.status" class="badge">已标识</ion-badge> <ion-badge slot="start" *ngIf="!item.status" class="badge">未标识</ion-badge> <div style="margin: 4px 2px; text-align:center;font-size: 13px; color: #368ab5;"> <div style="width: 32%;display:inline-block;"><label class="titlecs">品类数</label></div> <div style="width: 32%;display:inline-block;"><label class="titlecs">店家数</label></div> <div style="width: 32%;display:inline-block;"><label class="titlecs">品牌数</label></div> </div> <div style="margin: 4px 2px;padding-bottom: 2px; text-align:center;font-size: 14px; color: #917d5b;"> <label style="display:inline-block; width: 32%;text-align: center; ">{{item.caseNum}}</label> <label style="display:inline-block;width: 32%; text-align: center; ">{{item.shopkeeperNum}}</label> <label style="display:inline-block;width: 32%; text-align: center; ">{{item.brandNum}}</label> </div> </div> </div> </div> <ion-infinite-scroll (ionInfinite)="doInfinite($event)"> <ion-infinite-scroll-content loadingSpinner="bubbles " style="color: black;" [loadingText]="loadText" position="bottom "> </ion-infinite-scroll-content> </ion-infinite-scroll> <!-- 骨架框--> <div> <div id="containerSke" [ngClass]="loading && list.length==0?'show':'hide'"> <div class="box" *ngFor="let i of [160,186,175,170,160,180,165]"> <div class="box_img"> <div style="width: 94%;display: inline-block; margin: 8px;"> <ion-skeleton-text [animated]="true" [style]="'height:'+i+'px;border-radius: 3px;'"></ion-skeleton-text> </div> <div style="margin: 6px 6px;padding-bottom: 2px; text-align:center;font-size: 13px; color: #917d5b;"> <label><ion-skeleton-text [animated]="true" style="width: 100%; height: 16px; margin-bottom: 8px;border-radius: 3px;"></ion-skeleton-text></label> <label><ion-skeleton-text [animated]="true" style="display:block;width: 88%;margin-bottom: 8px;height: 16px;border-radius: 3px;"></ion-skeleton-text></label> </div> </div> </div> </div> </div>
css
// 瀑布流 样式 #container { position: relative; display: inline-block; } #containerSke { position: relative; display: inline-block; } .box { padding: 4px; float: left; margin: 0 auto; } .box_img { width: 177.5px; border: 1px solid #cccccc; box-shadow: 0 0 5px #ccc; // border-radius: 10px; position: relative; } .box_img>img { width: 100%; height: auto; overflow: hidden; // border-radius: 8px 8px 0 0; } ion-infinite-scroll { width: 100%; position: fixed; z-index: 99; bottom: 0; } .titlecs { display: inline-block; // width: 32%; text-align: center; background-color: #b3ddf3; border-radius: 3px; padding: 0px 3px; } .badge { position: absolute; top: 0px; left: 0px; padding: 6px 10px; font-size: 14px; --background: #37a484; --color: white; font-weight: normal; border-radius: 0px; } .hide { visibility: hidden; } .show { visibility: visible; }
ts
export class RecordComponent implements OnInit, AfterViewChecked { list: any = []; loading = false; search: string; pageSize = 2;//时间个数,2表示2天的数据 pageIndex = 0; skip = 0; isEnd = false; loadText = '正在加载...'; timer; constructor( private router: Router, private service: RecordService, private alertControll: AlertController, private el: ElementRef ) { } ngAfterViewChecked(): void { // let parentNode = document.getElementById("container"); // this.getNode(parentNode); } ngOnInit() { this.getRecodrds(null); } //#region 瀑布流 ionViewWillEnter() {
//加载骨架框 let parentNode = document.getElementById("containerSke"); this.getNode(parentNode); } getNode(parentNode) { // let parentNode = document.getElementById("container"); if (parentNode != undefined) { let childNodeArray: any = parentNode.getElementsByClassName("box"); let screenWidth = document.documentElement.clientWidth; let boxImg: any = document.querySelectorAll(".box_img"); let loding = document.querySelector("ion-infinite-scroll"); let childWidth = screenWidth / 2; // console.log(`屏幕的宽` + screenWidth) // console.log(`box的宽` + childWidth) let num = Math.floor(screenWidth / childWidth); //获得一排摆的个数 用Math.floor()转换为整数 parentNode.style.cssText = "width:" + childWidth * num + "px; margin:0 auto; height:auto"; //固定container的宽并设置居中 for (var i = 0; i < boxImg.length; i++) { boxImg[i].style.cssText = "width:" + (childWidth - 10) + "px"; } this.setImagePosition(num, childNodeArray); } } setImagePosition(num, childArray) { var imgHeightArray = [];//定义数组用于存放所有图片的高度 for (var i = 0; i < childArray.length; i++) { //遍历所有图片 if (i < num) { imgHeightArray[i] = childArray[i].offsetHeight; //取得第一排图片的高度 } else { var minHeight = Math.min.apply(null, imgHeightArray); //获取存放图片中高度最小的图片 var minIndex = this.getMinHeight(imgHeightArray, minHeight); //函数获得高度最小的图片的位置 childArray[i].style.position = "absolute"; //绝对定位图片 childArray[i].style.top = minHeight + "px"; //图片距顶部像素 childArray[i].style.left = childArray[minIndex].offsetLeft + "px"; //图片距左的像素 imgHeightArray[minIndex] = imgHeightArray[minIndex] + childArray[i].offsetHeight; //将最低高度的box的高度加上它下方(新一个图片)的box高度 } } } /** * 获取等于minHeight值的元素的数组位置index * @param minHeight * @returns */ getMinHeight(imgHeightArray, minHeight) { for (var i in imgHeightArray) { if (imgHeightArray[i] == minHeight) { //循环所有数组的高度 让它等于最小图片的高度 返回i值 return i; } } } /** * 判断图片元素是否加载完成,完成之后再加载瀑布流模式(解决瀑布流图片重叠的问题) */ isImageLoad() { //所有的图片元素 var imgEls = this.el.nativeElement.querySelectorAll('.im'); // 判断所有的图片元素是否加载完成 if (imgEls.length == this.list.length) { //删除定时器 clearTimeout(this.timer); let parentNode = document.getElementById("container"); this.getNode(parentNode); } else { this.timer = setTimeout(() => { this.isImageLoad() }, 100); } } //这里是借助ionic的上拉加载代替网页的滚动监听实现加载更多 doInfinite(infiniteScroll) { this.loadText = '正在加载...'; this.getRecodrds(infiniteScroll); } //#endregion getRecodrds(infiniteScroll) { this.loading = true; this.skip = this.pageIndex * this.pageSize; this.service.getPictureRecords({ skip: this.skip, size: this.pageSize }) .pipe( finalize(() => { this.loading = false; if (infiniteScroll) { if (this.isEnd) { console.log('到底啦') this.loadText = '到底啦'; } infiniteScroll.target.complete(); } }) ) .subscribe(result => { if (result.length > 0) { var datas: any = []; datas = this.list; datas.push(...result); this.list = datas; this.pageIndex++; this.isEnd = false; this.isImageLoad() } else { this.isEnd = true; } }) } }
效果:
骨架框 结果