I. Project Description

  • Using a frameworkuniapp, need to be compatible with wechatSmall program,H5
  • Implement functional albumThe waterfall flowandMulti-select - all select function

Effect:

Implementation approach

1. Function description: pass an array, loop to get the height of the picture, according to the original array split into two arrays, put in two columns, 1. Calculate the cumulative height of a single column and compare the height values to achieve the layout of waterfall flow, 1. Since it takes some time to get the height of the image, block the for loop process with async await, 1. Each to obtain the height of a picture assigned to render to the page, the realization of loading a picture on the first render up, to achieve the lazy loading effect of the picture

Code implementation

1. Package waterFall page component

  • HTML:
Word-wrap: break-word! Important; "> < span style="height: 490px; overflow: hidden;" Scroll -y="true" class="scroll -y "@scrolltolower="loadMoreImages" > // The content body <view class="main"> // the left half of the album <div class="view" Left"> <div class="content" v-for="(item, index) in firstList" :key="index"> <div class="img-content"> <image v-if="item.small_img" :src="item.small_img" class="image" mode="widthFix" :data-index="index" data-type="1"/> <div v-if="select" :class="['select-ele',{ selected: selectList.includes(item) },]" @click="selected(item)" > <div class="checkbox iconfont"></div> </div> </div> </div> <div class="view Right"> <div class="content" v-for="(item, index) in secondList" :key="index" > <div class="img-content"> <image v-if="item.small_img" :src="item.small_img" class="image" mode="widthFix" :data-index="index" data-type="2" /> <div v-if="select" :class="['select-ele',{ selected: selectList.includes(item) },]" @click="selected(item)" > <div class="checkbox iconfont"></div> </div> </div> </div> </div> <div class="footer" v-if="select"> <div class="all-check" @click="selectAll"> <div:class="['checkbox iconfont',{ selected: </div> <span> </span> <div >< div class=" fun-btn "@click="cancel"> </div> <div class=" fun-btn" </div> </div> </view> </scroll view>Copy the code
  • 2. Multi-selection/all-selection implementation idea
    • 1. Set the parametersCss style dynamic bindingClick on each item in the album
    • 1. Call@click="selected(item)"Method to get click album data
    • 2. Call@click="selectAll"Method to obtain all data of the album
  • Js:
<script> import { myPhotos } from "@/api/api"; export default { props: { select: { type: Boolean, default: false, }, }, data() { return { showImg: false, dataList: [], // firstList: [], // secondList: [], // Second column windowWidth: 0, // Page view width windowHeight: ImgMargin: 0, // imgWidth: 0, // Image width: px pageSize: 8, scrollHeight: "0", last: false, Page: 1, like: true, I: 0, photoParams: {type: 4, // 1 buy 2 click 3 like 4,}, selectList: [],}; }, mounted() {this.getGoodThingList () = this.getGoodThingList (); }, created() {// Create () {this.init(); this.initScrollHeight(); }, // Get all image data by calculating computed: {allSelected: {get() {return this.selectlist. length >= this.datalist. }, set(val) { if (val) { console.log(val); this.selectList = [...this.dataList]; } else { this.selectList = []; }}},}, the methods: {/ / access to multiple data selected (item) {const index. = this selectList. FindIndex ((I) = > i.i d = = = item. Id); if (index >= 0) { this.selectList.splice(index, 1); this.selectList = [...this.selectList]; } else { this.selectList.push(item); } }, selectAll() { this.allSelected = ! this.allSelected; }, cancel() { this.selectList = []; this.$emit("parentBtnSelect", false); this.$emit("cancel"); }, confirm() { if (! This.selectlist.length) {uni.showtoast ({title: "please select picture ", icon: "none"}); return; } console.log(this.selectList, "this.selectList"); this.$emit("confirm", this.selectList); this.selectList = []; this.$emit("parentBtnSelect", false); }, init() { this.dataList = []; this.firstList = []; this.secondList = []; this.last = false; this.imgMargin = 0; // Image margins: unit: px this.pageSize = 8; this.page = 1; this.i = 0; // debugger }, initScrollHeight() { let _self = this; uni.getSystemInfo({ success: function(res) { _self.scrollHeight = res.windowHeight + "px" / 2; }}); }, GetGoodthingList () {myPhotos(this.photoparams).then((res) => {if (res.data.code == 1) {if (res.data.code == 1) (res.data.result.pics == null) {return uni.showtoast ({title: "sorry not to find relevant information ", icon:" None ",}); } this.photoParams.page++; uni.hideLoading(); this.last = res.data.success || false; This.datalist = [... this.datalist,...res.data.result.pics,]; this.setDataList(res.data.result.pics,"small_img"); }}); }, // calculate the size of the image async setDataList(arr = data, attributeName, otherHeight = 100, minHeight = 10, MaxHeight = 1000) {var arr1 = [], arr2 = [], imgMargin = 0, // Var getSystemInfo = await wx.getSystemInfo() for (let I = 0; i < arr.length; i++) { try { let heightData = await uni.getImageInfo({src: "https:" + arr[i][attributeName], }); let ImgHeight = heightData.length == 1? minHeight: heightData[1].height; ImgWidth = heightData.length == 1? // If the length is 1, the image is wrong. minHeight: heightData[1].width; // If the length is 1, the image is wrong, let height = ImgHeight; if (height < minHeight) height = minHeight; if (height > maxHeight) height = maxHeight; if (height1 <= height2) { height1 += height; this.firstList.push(arr[i]); } else { height2 += height; this.secondList.push(arr[i]); } // console.log('arr2',height1,height2,arr1,arr2); } catch (err) { console.log("getImageInfo-err", err); }}, loadMoreImages: function() {if (! This.last) {uni. ShowLoading ({title: "loading...") }); this.getGoodthingList(); } else { this.getGoodthingList(); } uni.hideLoading(); ,}}}; </script>Copy the code
  • CSS
<style scoped lang="scss"> .page { width: 100%; } .main { width: 100%; .view { width: 50%; display: inline-block ! important; position: relative; vertical-align: top; padding: 5rpx; box-sizing: border-box; .content { border-radius: 4px; margin-bottom: 6rpx; box-sizing: border-box; .img-content { position: relative; .image { width: 100%; height: 100%; border-top-right-radius: 4px; border-top-left-radius: 4px; box-sizing: border-box; display: block; } } } .select-ele { position: absolute; left: 0; top: 0; width: 100%; height: 100%; &. Selected {background-color: rgba(255, 255, 255, 0.3); .checkbox { display: flex; align-items: center; justify-content: center; background-color: #2147f1; border-color: #2147f1; &::before { content: "\e62d"; font-size: 20rpx; color: #fff; } } } .checkbox { position: absolute; right: 18rpx; top: 18rpx; width: 36rpx; height: 36rpx; border-radius: 4rpx; border: 2rpx solid #ffffff; } } } .footer { position: fixed; left: 0; bottom: 0; display: flex; align-items: center; justify-content: flex-end; width: 100%; height: 100rpx; background-color: #fff; z-index: 22; .all-check { position: absolute; left: 30rpx; display: flex; align-items: center; font-size: 26rpx; font-weight: 400; color: #666666; line-height: 39rpx; .checkbox { width: 36rpx; height: 36rpx; margin-right: 14rpx; border-radius: 4rpx; border: 2rpx solid #bababa; &.selected { display: flex; align-items: center; justify-content: center; background-color: #2147f1; border-color: #2147f1; &::before { content: "\e62d"; font-size: 20rpx; color: #fff; } } } } .func-btn { width: 220rpx; height: 70rpx; margin-right: 30rpx; font-size: 30rpx; font-weight: 500; color: #666666; line-height: 70rpx; text-align: center; background: #ececec; border-radius: 35rpx; &.confirm { color: #fff; background: #dd4e4e; } } } } </style>Copy the code