I. Project Description
- Using a framework
uniapp
, need to be compatible with wechatSmall program
,H5
- Implement functional album
The waterfall flow
andMulti-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 parameters
Css style dynamic binding
Click 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
- 1. Set the parameters
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