From 28167c45044ddb9ceff22b44e48a7ab496b8839a Mon Sep 17 00:00:00 2001 From: peng <peng.com> Date: 星期三, 25 六月 2025 10:47:25 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev --- uni_modules/zero-loading/components/zero-loading/static/loading-surround.vue | 91 ++ uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue | 140 +++ uni_modules/zero-loading/readme.md | 69 + uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue | 81 + uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue | 132 +++ uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue | 108 ++ pages/tabbar/index/home.vue | 158 +-- uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue | 45 + uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue | 84 ++ pages/video/video-edit.vue | 22 uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue | 67 + uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue | 118 ++ uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue | 96 ++ uni_modules/zero-loading/changelog.md | 51 + uni_modules/zero-loading/components/zero-loading/static/loading-locating.vue | 81 + uni_modules/zero-loading/package.json | 83 + pages/video/video-goods-detail.vue | 14 uni_modules/zero-loading/components/zero-loading/static/loading-equal.vue | 81 + uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue | 78 + uni_modules/zero-loading/components/zero-loading/static/loading-photo.vue | 87 ++ pages/tabbar/video/video.vue | 11 uni_modules/zero-loading/components/zero-loading/static/loading-wobble.vue | 127 +++ uni_modules/zero-loading/components/zero-loading/static/loading-love.vue | 201 ++++ pages/video/video-play.vue | 199 +++- uni_modules/zero-loading/components/zero-loading/zero-loading.vue | 186 ++++ pages/video/home-page.vue | 52 26 files changed, 2,236 insertions(+), 226 deletions(-) diff --git a/pages/tabbar/index/home.vue b/pages/tabbar/index/home.vue index 1c56703..a2cf82d 100644 --- a/pages/tabbar/index/home.vue +++ b/pages/tabbar/index/home.vue @@ -1,11 +1,14 @@ <template> <view class="video-container"> + <!-- 瑙嗛鍔犺浇 --> + <zero-loading v-show="videoLoading" type="circle" color="#0ebd57" text=""></zero-loading> <!-- 瑙嗛鍒楄〃 --> <swiper class="video-swiper" vertical :current="currentIndex" @change="onSwiperChange" + :duration="250" easing-function="linear" > <swiper-item @@ -25,14 +28,16 @@ <image src="/static/video/play.png" style="width: 45px;height: 45px" mode="aspectFit"></image> </view> <video + v-if="index >= currentIndex - videoLiveOffset && index <= currentIndex + videoLiveOffset" :id="'video'+index" :ref="'video'+index" :src="item.videoUrl" - :autoplay="false" + :autoplay="index === currentIndex" :controls="false" :loop="true" :object-fit="item.objectFit" :enable-progress-gesture="false" + :show-center-play-btn="false" class="video-item" @play="onPlay(item.id, index)" @pause="onPause(index)" @@ -40,12 +45,13 @@ @click="togglePlay(index)" @timeupdate="onTimeUpdate($event)" @loadedmetadata="onLoadedMetadata($event)" + @waiting="videoWaiting(index)" ></video> <!-- 鑷畾涔夋帶鍒舵潯 --> <view - @touchstart="handleTouchStart" - @touchmove="handleTouchMove" - @touchend="handleTouchEnd" + @touchstart.stop="handleTouchStart" + @touchmove.stop="handleTouchMove" + @touchend.stop="handleTouchEnd" class="container"> <!-- 杩涘害鏉� - 鏁翠釜鍖哄煙鍙嫋鍔� --> <view class="process-warp" :style="{ opacity: showProcess ? 1 : 0 }"> @@ -300,13 +306,11 @@ startPlayTime: 0 // 杩欎釜瑙嗛浠庝粈涔堟椂鍊欏紑濮嬫挱鏀剧殑 }, currentVideoIsPlaying: true, // 褰撳墠瑙嗛鏄惁姝e湪鎾斁 - isFullScreen: false, - windowHeight: 0, currentIndex: 0, // 褰撳墠鎾斁鐨勮棰戠储寮� + videoLoading: false, // 瑙嗛缂撳啿涓� videoList: [], // 瑙嗛鍒楄〃鏁版嵁 - videoContexts: [], // 瑙嗛涓婁笅鏂囧璞¢泦鍚� videoBufferOffset: 0.1 ,// 瑙嗛棰勫姞杞藉弬鏁� - videoLiveOffset: 5, // 淇濈暀褰撳墠瑙嗛鍓嶅悗鍚勫灏戜釜瑙嗛涓婁笅鏂� + videoLiveOffset: 2, // 淇濈暀褰撳墠瑙嗛鍓嶅悗鍚勫灏戜釜瑙嗛涓婁笅鏂� touchXY: { // 鐩戝惉宸︽粦鍙虫粦 startX: 0, endX: 0, @@ -662,56 +666,6 @@ } }) }, - // 鍒濆鍖栬棰戜笂涓嬫枃 - initVideoContexts() { - const start = Math.max(0, this.currentIndex - this.videoLiveOffset); - const end = Math.min(this.currentIndex + this.videoLiveOffset, this.videoList.length - 1); - let contextsLength = this.videoContexts.length; - if (contextsLength === 0) { - // 绗竴娆″垵濮嬪寲 - for (let i = 0; i < this.videoList.length; i++) { - if (i < start || i > end) { - this.videoContexts.push(null) - } else { - let videoContent = uni.createVideoContext(`video${i}`, this); - videoContent.seek(this.videoBufferOffset); - videoContent.pause(); - this.videoContexts.push(videoContent); - } - } - } else { - for (let i = 0; i < this.videoList.length; i++) { - contextsLength = this.videoContexts.length - if (contextsLength - 1 >= i) { - // 濡傛灉宸茬粡鏄痭ull浜嗗氨涓嶇敤绠★紝鍥犱负瑙嗛鍔犺浇鍙細鍦ㄥ悗闈ush锛屽墠闈㈠凡缁忚缃负null鍒欐棤闇�澶勭悊 - if (this.videoContexts[i] == null) { - continue - } - // 瓒呭嚭鍙鍖栬寖鍥寸殑瑙嗛鐩存帴閲婃斁璧勬簮锛屽苟缃负null - if (i < start || i > end) { - if (this.videoContexts[i]) { - this.videoContexts[i].stop(); - this.videoContexts[i] = null - } - } - } else { - if (i < start || i > end) { - this.videoContexts.push(null); - } else { - let videoContent = uni.createVideoContext(`video${i}`, this); - videoContent.seek(this.videoBufferOffset); - videoContent.pause(); - this.videoContexts.push(videoContent); - } - } - } - } - // 灏嗗綋鍓嶈棰戣缃负鎾斁 - if (this.videoContexts[this.currentIndex]) { - this.videoContexts[this.currentIndex].play() - } - - }, // 鍔犺浇瑙嗛鏁版嵁 async loadVideos() { @@ -730,9 +684,6 @@ ), ]; } - this.$nextTick(() => { - this.initVideoContexts(); - }); this.loading = false; if(res.data.data.length < this.videoQuery.pageSize) { this.videoNoMore = true; @@ -745,6 +696,7 @@ // 婊戝姩鍒囨崲瑙嗛 onSwiperChange(e) { + this.videoLoading = false // 濡傛灉瑙嗛澶勪簬鏆傚仠鐘舵�佸線涓嬪埛瑙嗛锛岄偅涔堥渶瑕佸啀璁$畻涓�娆℃殏鍋滄椂闂� if(!this.currentVideoIsPlaying) { if(this.startPauseTime !== 0) { @@ -756,49 +708,23 @@ this.savePlayRecord() const oldIndex = this.currentIndex; this.currentIndex = e.detail.current; - + const videoContext = uni.createVideoContext(`video${oldIndex}`, this); // 鏆傚仠涓婁竴涓棰� - if (this.videoContexts[oldIndex]) { - this.videoContexts[oldIndex].pause(); - } - + videoContext.pause(); this.startPauseTime = 0; // 璁剧疆褰撳墠鎾斁瑙嗛鐨勬�绘椂闀� this.duration = this.videoList[this.currentIndex].videoDuration; this.formartDuration = this.sliderFormatTime(this.duration); - // 鎾斁褰撳墠瑙嗛 - if (this.videoContexts[this.currentIndex]) { - this.videoContexts[this.currentIndex].play(); - } - this.clearVideoContext() - }, - // 娓呴櫎瓒呭嚭瑙嗛鍙鍖栧尯鍩熺殑瑙嗛涓婁笅鏂� - async clearVideoContext() { - // 瀵硅秴鍑哄彲瑙嗗寲鍖哄煙鐨勮棰戜笂涓嬫枃鍋氶攢姣佸鐞� - const start = Math.max(0, this.currentIndex - this.videoLiveOffset); - const end = Math.min(this.currentIndex + this.videoLiveOffset, this.videoList.length - 1); - for (let i = 0; i < this.videoContexts.length; i++) { - if (i < start || i > end) { - if (this.videoContexts[i]) { - this.videoContexts[i].stop(); - this.videoContexts[i] = null - } - } else { - if (this.videoContexts[i] == null) { - let videoContent = uni.createVideoContext(`video${i}`, this); - videoContent.seek(this.videoBufferOffset); - videoContent.pause(); - this.videoContexts[i] = videoContent; - } - } - } + // 鎾斁褰撳墠瑙嗛 + const videoContext1 = uni.createVideoContext(`video${this.currentIndex}`, this); + videoContext1.play() // 濡傛灉鍓╀綑瑙嗛涓嶈冻锛岃Е鍙戣姹傝幏鍙栨洿澶氳棰� if (this.videoList.length - 1 < this.currentIndex + this.videoLiveOffset) { this.loadVideos() } - }, + }, // 寮�濮嬭Е鎽� handleSwiperStart(e) { @@ -808,12 +734,15 @@ }, // 瑙︽懜涓� handleSwiperMove(e) { - console.log("瑙︽懜涓�", e); this.touchXY.endX = e.touches[0].pageX this.touchXY.endY = e.touches[0].pageY }, // 缁撴潫瑙︽懜 handleSwiperEnd(item) { + // 闃叉婊戝姩婊氬姩鏉′篃瑙﹀彂璺宠浆 + if (this.showProcess) { + return + } const diffX = this.touchXY.endX - this.touchXY.startX const diffY = this.touchXY.endY - this.touchXY.startY @@ -861,18 +790,16 @@ }, // 鍗曞嚮灞忓箷锛氭殏鍋滄垨缁х画鎾斁 togglePlay(index) { - console.log("鍗曞嚮瑙嗛", index, this.videoContexts); + console.log("鍗曞嚮瑙嗛", index); + const videoContext = uni.createVideoContext(`video${index}`, this); if(this.currentVideoIsPlaying) { - this.videoContexts[index].pause(); + videoContext.pause(); } else { - this.videoContexts[index].play(); + videoContext.play(); } }, // 瑙嗛鎾斁浜嬩欢 onPlay(id, index) { - this.getBarRect() - this.progress = 0 - console.log(id, index, "瑙﹀彂鎾斁"); if(index === this.currentIndex) { this.currentVideoIsPlaying = true; if(! this.duration) { @@ -881,9 +808,11 @@ this.formartDuration = this.sliderFormatTime(this.duration); } } else { - this.currentVideoIsPlaying = false; return } + this.getBarRect() + this.progress = 0 + console.log(id, index, "瑙﹀彂鎾斁"); this.playRecord.videoId = id; // 娌″垵濮嬪寲鎵嶈祴鍊硷紝鍥犱负涓�涓棰戦噸澶嶆挱鏀緊nPlay浼氶噸澶嶈Е鍙� if(this.playRecord.startPlayTime === 0) { @@ -893,7 +822,7 @@ const duration = Date.now() - this.startPauseTime this.totalPauseTime += duration } - + this.videoLoading = false }, // 瑙嗛鏆傚仠浜嬩欢 @@ -901,11 +830,8 @@ console.log(index, "瑙﹀彂鏆傚仠"); if(index === this.currentIndex) { this.currentVideoIsPlaying = false; - } else { - this.currentVideoIsPlaying = true; - return + this.startPauseTime = Date.now() } - this.startPauseTime = Date.now() }, // 瑙嗛缁撴潫浜嬩欢 onEnded(index) { @@ -914,6 +840,7 @@ // 璁板綍鎾斁鏃堕暱 onTimeUpdate(e) { + this.videoLoading = false this.playRecord.playAt = e.detail.currentTime; this.currentTime = e.detail.currentTime; @@ -926,7 +853,8 @@ this.startProgress = this.progress; // 璁板綍寮�濮嬫椂鐨勮繘搴� this.startX = e.touches[0].pageX; console.log("璁板綍寮�濮嬫椂鐨勮繘搴�", this.startProgress); - this.videoContexts[this.currentIndex].pause() + const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this); + videoContext.pause() // this.updateProgress(e); }, @@ -934,7 +862,6 @@ handleTouchMove(e) { if (!this.isDragging || !this.barWidth) return; clearTimeout(this.processHidenTimer) - this.videoContexts[this.currentIndex].pause() this.updateProgress(e); }, @@ -942,8 +869,9 @@ handleTouchEnd() { this.isDragging = false; console.log("婊戝姩缁撴潫", this.duration * this.progress); - this.videoContexts[this.currentIndex].seek(this.duration * this.progress / 100) - this.videoContexts[this.currentIndex].play() + const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this); + videoContext.seek(this.duration * this.progress / 100) + videoContext.play() this.processHidenTimer = setTimeout(() => { this.showProcess = false; }, 1000); @@ -959,7 +887,6 @@ // 灏嗗儚绱犺窛绂昏浆鎹负杩涘害澧為噺 const deltaProgress = (deltaX / this.barWidth) * 100; - console.log("杩涘害澧為噺", deltaProgress); // 璁$畻鏂拌繘搴� = 寮�濮嬫椂鐨勮繘搴� + 婊戝姩澧為噺 let newProgress = this.startProgress + deltaProgress; @@ -967,6 +894,13 @@ newProgress = Math.max(0, Math.min(100, newProgress)); this.progress = newProgress; + }, + // 瑙嗛缂撳啿 + videoWaiting(index) { + if (index === this.currentIndex) { + console.log("瑙嗛缂撳啿涓�傘�傘��"); + this.videoLoading = true; + } }, // 鑾峰彇瑙嗛鎬绘椂闀� onLoadedMetadata(e) { @@ -1015,7 +949,7 @@ .video-item { width: 100%; height: 100%; - object-fit: cover; + /* object-fit: cover; */ } .play-icon { position: absolute; diff --git a/pages/tabbar/video/video.vue b/pages/tabbar/video/video.vue index af7dfeb..619c135 100644 --- a/pages/tabbar/video/video.vue +++ b/pages/tabbar/video/video.vue @@ -132,7 +132,7 @@ <view class="goods-price" style="flex: 1;">楼{{ goods.price }}</view> <view @click.stop="() => {}" style="flex: 1;display: flex;justify-content: center;align-items: center;"> <view style="width: 90rpx">鏁伴噺锛�</view> - <uni-number-box v-model="goods.goodsNum" :min="0"/> + <uni-number-box v-model="goods.goodsNum" :min="1"/> </view> </view> </view> @@ -249,7 +249,6 @@ videoFileKey: '', videoDuration: 0, videoFit: 'cover', - goodsId: '', videoContentType: 'video', videoImgs: [], tags: [], @@ -543,10 +542,9 @@ // 閫夋嫨鍟嗗搧 chooseGoods() { if(this.selectedGoodsList.length > 0) { - const selectedGoodsIds = new Set(this.selectedGoodsList.map(i => i.goodsId)); - console.log(selectedGoodsIds, "mimade"); + const selectedGoodsSkuIds = new Set(this.selectedGoodsList.map(i => i.id)); this.goodsList?.forEach(goods => { - this.$set(goods, 'selected', selectedGoodsIds.has(goods.goodsId)); + this.$set(goods, 'selected', selectedGoodsSkuIds.has(goods.id)); }); } this.showGoodsPicker = true; @@ -638,7 +636,7 @@ if (valid && this.canPublish) { this.loading = true; this.formData.fileInfo = this.videoInfo; - this.formData["goodsList"] = this.selectedGoodsList.map(item => {return {goodsId: item.goodsId, goodsNum: item.goodsNum}}); + this.formData["goodsList"] = this.selectedGoodsList.map(item => {return {goodsId: item.goodsId, goodsSkuId: item.id, goodsNum: item.goodsNum}}); publish(this.formData).then(res => { uni.showToast({ title: '瑙嗛宸叉彁浜ゅ鏍竳', @@ -683,7 +681,6 @@ cover: '', videoFit: 'cover', videoDuration: 0, - goodsId: '', videoContentType: 'video', videoImgs: [], tags: [], diff --git a/pages/video/home-page.vue b/pages/video/home-page.vue index 5ce3063..4aebb07 100644 --- a/pages/video/home-page.vue +++ b/pages/video/home-page.vue @@ -24,47 +24,47 @@ <text class="stat-label">鑾疯禐</text> </view> </view> - + <!-- 鍏虫敞鎸夐挳 --> <view class="follow-btn-container" v-if="!userInfo.self"> - <button - class="follow-btn" - :class="{followed: userInfo.hasSub}" + <button + class="follow-btn" + :class="{followed: userInfo.hasSub}" @click="toggleFollow" > {{userInfo.hasSub ? '鍙栨秷鍏虫敞' : '鍏虫敞'}} </button> </view> - + <view class="edit-icon" @click="editInfo" v-if="userInfo.self"> <uni-icons type="compose" size="20" color="#666"></uni-icons>缂栬緫涓婚〉淇℃伅 </view> </view> - + <!-- 浣滃搧/鍠滄鍒囨崲 --> <view class="tab-bar"> - <view - class="tab-item" - :class="{active: currentTab === 'works'}" + <view + class="tab-item" + :class="{active: currentTab === 'works'}" @click="switchTab('works')" > 浣滃搧{{`(${videoTotal})`}} </view> - <view - class="tab-item" - :class="{active: currentTab === 'likes'}" + <view + class="tab-item" + :class="{active: currentTab === 'likes'}" @click="switchTab('likes')" > 鍠滄 </view> </view> - + <!-- 瑙嗛鍒楄〃 --> <scroll-view class="video-list" scroll-y :show-scrollbar="false" @scrolltolower="getPage" v-show="currentTab === 'works' && videoList.length > 0"> <view class="video-container"> <view - class="video-item" - v-for="(item, index) in videoList" + class="video-item" + v-for="(item, index) in videoList" :key="item.id" > <image class="video-cover" @click="playAuthorVideo(index)" :src="item.videoContentType === 'video' ? item.coverUrl : item.imgs[0]" mode="aspectFill"></image> @@ -91,8 +91,8 @@ <scroll-view class="video-list" scroll-y :show-scrollbar="false" @scrolltolower="getPage" v-show="currentTab === 'likes' && collectVideoList.length > 0"> <view class="video-container"> <view - class="video-item" - v-for="(item, index) in collectVideoList" + class="video-item" + v-for="(item, index) in collectVideoList" :key="item.id" @click="playCollectVideo(index)" > @@ -105,10 +105,10 @@ </view> </view> </view> - </view> + </view> </view> </scroll-view> - + <!-- 绌虹姸鎬� --> <view class="empty-state" v-if="videoList.length === 0 && currentTab === 'works'"> <!-- <image src="/static/images/empty.png" mode="aspectFit" class="empty-image"></image> --> @@ -119,13 +119,13 @@ <!-- <image src="/static/images/empty.png" mode="aspectFit" class="empty-image"></image> --> <text class="empty-text">杩樻病鏈夌偣璧炰綔鍝佸摝~</text> </view> - + <!-- 鍒犻櫎瑙嗛鎻愰啋妗� --> <uni-popup ref="delDialog" type="dialog"> <uni-popup-dialog type="error" cancelText="鍙栨秷" confirmText="鍒犻櫎" title="鎻愰啋" :content="`鎮ㄦ鍦ㄥ垹闄わ細${opVideo.title}`" @confirm="deleteVideo" @close="dialogClose"></uni-popup-dialog> </uni-popup> - + <!-- 涓嬫灦瑙嗛鎻愰啋妗� --> <uni-popup ref="downDialog" type="dialog"> <uni-popup-dialog type="error" cancelText="鍙栨秷" confirmText="涓嬫灦" title="鎻愰啋" :content="`鎮ㄦ鍦ㄤ笅鏋讹細${opVideo.title}`" @confirm="downVideo" @@ -383,14 +383,14 @@ url: `/pages/video/home-page-edit?authorId=${this.authorId}&avatar=${this.userInfo.avatar}&motto=${this.userInfo.motto || ''}&nickName=${this.userInfo.nickName}` }); }, - + // 璺宠浆鍒扮矇涓�/鍏虫敞鍒楄〃 navigateToFollow(type) { uni.navigateTo({ url: `/pages/user/follow?type=${type}` }); }, - + // 璺宠浆鍒扮偣璧炲垪琛� navigateToLike() { uni.navigateTo({ @@ -624,15 +624,15 @@ height: 70rpx; line-height: 70rpx; padding: 0 40rpx; - + &::after { border: none; } - + &.followed { background-color: #f5f5f5; color: #666; } } -</style> \ No newline at end of file +</style> diff --git a/pages/video/video-edit.vue b/pages/video/video-edit.vue index 1b51fe7..bfa119a 100644 --- a/pages/video/video-edit.vue +++ b/pages/video/video-edit.vue @@ -132,7 +132,7 @@ <view class="goods-price" style="flex: 1;">楼{{ goods.price }}</view> <view @click.stop="() => {}" style="flex: 1;display: flex;justify-content: center;align-items: center;"> <view style="width: 90rpx">鏁伴噺锛�</view> - <uni-number-box v-model="goods.goodsNum" :min="0"/> + <uni-number-box v-model="goods.goodsNum" :min="1"/> </view> </view> </view> @@ -250,7 +250,6 @@ videoFileKey: '', videoDuration: 0, videoFit: 'cover', - goodsId: '', videoContentType: 'video', videoImgs: [], tags: [], @@ -306,7 +305,7 @@ getVideoDetail(id).then(res => { this.videoInfo.cover = res.data.data.coverUrl this.videoInfo.url = res.data.data.videoUrl - this.formData.videoImgs = res.data.data.imgs + this.formData.videoImgs = res.data.data.videoImgs this.formData.videoContentType = res.data.data.videoContentType this.formData.cover = res.data.data.coverFileKey this.formData.id = res.data.data.id @@ -316,6 +315,9 @@ this.formData.videoDuration = res.data.data.videoDuration this.selectedGoodsList = res.data.data.goodsList this.formData.tags = res.data.data.tags + if (this.formData.videoContentType === 'img') { + this.videoPreviewImgs = res.data.data.imgs + } this.showUploadProgress = false console.log("瑙嗛璇︽儏", this.formData); }) @@ -565,10 +567,9 @@ // 閫夋嫨鍟嗗搧 chooseGoods() { if(this.selectedGoodsList.length > 0) { - const selectedGoodsIds = new Set(this.selectedGoodsList.map(i => i.goodsId)); - console.log(selectedGoodsIds, "mimade"); + const selectedGoodsSkuIds = new Set(this.selectedGoodsList.map(i => i.id)); this.goodsList?.forEach(goods => { - this.$set(goods, 'selected', selectedGoodsIds.has(goods.goodsId)); + this.$set(goods, 'selected', selectedGoodsSkuIds.has(goods.id)); }); } this.showGoodsPicker = true; @@ -660,7 +661,7 @@ if (valid && this.canPublish) { this.loading = true; this.formData.fileInfo = this.videoInfo; - this.formData["goodsList"] = this.selectedGoodsList.map(item => {return {goodsId: item.goodsId, goodsNum: item.goodsNum}}); + this.formData["goodsList"] = this.selectedGoodsList.map(item => {return {goodsId: item.goodsId, goodsSkuId: item.id, goodsNum: item.goodsNum}}); updateVideo(this.formData).then(res => { uni.showToast({ title: '瑙嗛宸叉彁浜ゅ鏍竳', @@ -673,10 +674,10 @@ this.tagInput = ''; this.recommendedTags = []; - // TODO 鍏堣烦棣栭〉,鍚庨潰璺虫垜鐨勮棰戦〉闈� + // 璺虫垜鐨勮棰戦〉闈� setTimeout(() => { - uni.switchTab({ - url: '/pages/tabbar/index/home' + uni.navigateBack({ + delta: 1 }); }, 1500); }) @@ -705,7 +706,6 @@ cover: '', videoFit: 'cover', videoDuration: 0, - goodsId: '', videoContentType: 'video', videoImgs: [], tags: [], diff --git a/pages/video/video-goods-detail.vue b/pages/video/video-goods-detail.vue index 9d06578..a8fc8a1 100644 --- a/pages/video/video-goods-detail.vue +++ b/pages/video/video-goods-detail.vue @@ -29,7 +29,7 @@ <script> import {getGoodsDetail} from "@/api/video.js" - + import { buyBack } from "@/api/trade.js"; import '@/components/uview-components/uview-ui'; export default { computed: { @@ -61,7 +61,17 @@ }, // 鐢熸垚璁㈠崟-鏀粯 toPay() { - + const buyList = this.goodsList.map(goods => { + return { + skuId: goods.id, + num: goods.goodsNum + } + }) + buyBack(buyList).then(res => { + uni.navigateTo({ + url: "/pages/order/fillorder?way=CART" + }) + }) } } } diff --git a/pages/video/video-play.vue b/pages/video/video-play.vue index 4cf61c2..e16b6ac 100644 --- a/pages/video/video-play.vue +++ b/pages/video/video-play.vue @@ -1,32 +1,43 @@ <template> <view class="video-container"> + <!-- 瑙嗛鍔犺浇 --> + <zero-loading v-show="videoLoading" type="circle" color="#0ebd57" text=""></zero-loading> <!-- 瑙嗛鍒楄〃 --> <swiper class="video-swiper" vertical - circular :current="currentIndex" @change="onSwiperChange" + :duration="250" + easing-function="linear" > - <swiper-item v-for="(item, index) in videoList" :key="item.id"> + <swiper-item + v-for="(item, index) in videoList" + :key="item.id" + @touchstart="handleSwiperStart" + @touchmove="handleSwiperMove" + @touchend="handleSwiperEnd(item)" + > <view style="width: 100%;height: 100%;" v-if="item.videoContentType === 'video'"> <!-- 鎾斁鎸夐挳锛堜粎褰撹棰戞殏鍋滄椂鏄剧ず锛� --> <view class="play-icon" @click="togglePlay(index)" - v-if="!currentVideoIsPlaying" + v-show="!currentVideoIsPlaying" > <image src="/static/video/play.png" style="width: 45px;height: 45px" mode="aspectFit"></image> </view> <video + v-if="index >= currentIndex - videoLiveOffset && index <= currentIndex + videoLiveOffset" :id="'video'+index" :ref="'video'+index" :src="item.videoUrl" - :autoplay="currentIndex === index" + :autoplay="index === currentIndex" :controls="false" :loop="true" :object-fit="item.objectFit" :enable-progress-gesture="false" + :show-center-play-btn="false" class="video-item" @play="onPlay(item.id, index)" @pause="onPause(index)" @@ -34,13 +45,13 @@ @click="togglePlay(index)" @timeupdate="onTimeUpdate($event)" @loadedmetadata="onLoadedMetadata($event)" - + @waiting="videoWaiting(index)" ></video> <!-- 鑷畾涔夋帶鍒舵潯 --> <view - @touchstart="handleTouchStart" - @touchmove="handleTouchMove" - @touchend="handleTouchEnd" + @touchstart.stop="handleTouchStart" + @touchmove.stop="handleTouchMove" + @touchend.stop="handleTouchEnd" class="container"> <!-- 杩涘害鏉� - 鏁翠釜鍖哄煙鍙嫋鍔� --> <view class="process-warp" :style="{ opacity: showProcess ? 1 : 0 }"> @@ -291,24 +302,28 @@ startPlayTime: 0 // 杩欎釜瑙嗛浠庝粈涔堟椂鍊欏紑濮嬫挱鏀剧殑 }, currentVideoIsPlaying: true, // 褰撳墠瑙嗛鏄惁姝e湪鎾斁 - isFullScreen: false, - windowHeight: 0, currentIndex: 0, // 褰撳墠鎾斁鐨勮棰戠储寮� - videoList: [ - - ], // 瑙嗛鍒楄〃鏁版嵁 - videoContexts: [], // 瑙嗛涓婁笅鏂囧璞¢泦鍚� + videoLoading: false, // 瑙嗛缂撳啿涓� + videoList: [], // 瑙嗛鍒楄〃鏁版嵁 + videoBufferOffset: 0.1 ,// 瑙嗛棰勫姞杞藉弬鏁� + videoLiveOffset: 2, // 淇濈暀褰撳墠瑙嗛鍓嶅悗鍚勫灏戜釜瑙嗛涓婁笅鏂� + touchXY: { // 鐩戝惉宸︽粦鍙虫粦 + startX: 0, + endX: 0, + startY: 0, + endY: 0 + }, loading: false, // 鏄惁姝e湪鍔犺浇 videoQuery: { pageNumber: 1, - pageSize: 6, + pageSize: 10, authorId: '', videoFrom: '' } } }, onShow() { - this.loadVideos() + // this.loadVideos() // 濡傛灉瑙嗛鎸変笅鏆傚仠鍚庡垏鎹㈤〉闈㈠啀鍥炲埌椤甸潰鏃讹紝鍙畻鏆傚仠鏃堕棿锛堝洜涓烘殏鍋滄椂闂村拰绂诲紑椤甸潰鏃堕棿鏄噸澶嶇殑锛屽彧绠椾竴涓級 if(this.startHidenTime !== 0 && this.currentVideoIsPlaying) { const duration = Date.now() - this.startHidenTime @@ -321,24 +336,28 @@ onUnload() { uni.removeStorageSync("playInfo"); }, + onReady() { + + }, onLoad(option) { const playInfo = uni.getStorageSync("playInfo", playInfo); if(playInfo) { + this.currentIndex = playInfo.playIndex; this.videoList = playInfo.videoList; console.log("鎷垮埌鏁版嵁浜�",playInfo); this.videoQuery.pageNumber = playInfo.pageNumber; this.videoNoMore = playInfo.nomore; this.videoQuery.authorId = option.authorId; this.videoQuery.videoFrom = option.videoFrom; - this.currentIndex = playInfo.playIndex; + this.currentVideoIsPlaying = true; + this.$nextTick(() => { + const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this); + videoContext.play() + }) } else { this.videoQuery.videoFrom = 'recommend'; this.loadVideos(); } - }, - onReady() { - // 鍒濆鍖栬棰戜笂涓嬫枃 - this.initVideoContexts(); }, onShareAppMessage(e) { const userInfo = storage.getUserInfo(); @@ -623,13 +642,6 @@ } }) }, - // 鍒濆鍖栬棰戜笂涓嬫枃 - initVideoContexts() { - this.videoContexts = this.videoList.map((_, index) => { - let videoContent = uni.createVideoContext(`video${index}`, this); - return videoContent; - }); - }, // 鍔犺浇瑙嗛鏁版嵁 async loadVideos() { @@ -647,9 +659,6 @@ ), ]; } - this.$nextTick(() => { - this.initVideoContexts(); - }); this.loading = false; if(res.data.data.length < this.videoQuery.pageSize) { this.videoNoMore = true; @@ -661,29 +670,75 @@ // 婊戝姩鍒囨崲瑙嗛 onSwiperChange(e) { - // 濡傛灉瑙嗛澶勪簬鏆傚仠鐘舵�佸線涓嬪埛瑙嗛锛岄偅涔堥渶瑕佸啀璁$畻涓�娆℃殏鍋滄椂闂� - if(!this.currentVideoIsPlaying) { - if(this.startPauseTime !== 0) { - const duration = Date.now() - this.startPauseTime - this.totalPauseTime += duration - } - } - // 淇濆瓨涓婁竴涓棰戠殑鎾斁璁板綍 - this.savePlayRecord() - const oldIndex = this.currentIndex; - this.currentIndex = e.detail.current; - - // 鏆傚仠涓婁竴涓棰� - if (this.videoContexts[oldIndex]) { - this.videoContexts[oldIndex].pause(); + this.videoLoading = false + // 濡傛灉瑙嗛澶勪簬鏆傚仠鐘舵�佸線涓嬪埛瑙嗛锛岄偅涔堥渶瑕佸啀璁$畻涓�娆℃殏鍋滄椂闂� + if(!this.currentVideoIsPlaying) { + if(this.startPauseTime !== 0) { + const duration = Date.now() - this.startPauseTime + this.totalPauseTime += duration + } + } + // 淇濆瓨涓婁竴涓棰戠殑鎾斁璁板綍 + this.savePlayRecord() + const oldIndex = this.currentIndex; + this.currentIndex = e.detail.current; + const videoContext = uni.createVideoContext(`video${oldIndex}`, this); + // 鏆傚仠涓婁竴涓棰� + videoContext.pause(); + this.startPauseTime = 0; + + // 璁剧疆褰撳墠鎾斁瑙嗛鐨勬�绘椂闀� + this.duration = this.videoList[this.currentIndex].videoDuration; + this.formartDuration = this.sliderFormatTime(this.duration); + + // 鎾斁褰撳墠瑙嗛 + const videoContext1 = uni.createVideoContext(`video${this.currentIndex}`, this); + videoContext1.play() + // 濡傛灉鍓╀綑瑙嗛涓嶈冻锛岃Е鍙戣姹傝幏鍙栨洿澶氳棰� + if (this.videoList.length - 1 < this.currentIndex + this.videoLiveOffset) { + this.loadVideos() + } + }, + + // 寮�濮嬭Е鎽� + handleSwiperStart(e) { + this.touchXY.startX = e.touches[0].pageX + this.touchXY.startY = e.touches[0].pageY + }, + // 瑙︽懜涓� + handleSwiperMove(e) { + this.touchXY.endX = e.touches[0].pageX + this.touchXY.endY = e.touches[0].pageY + }, + // 缁撴潫瑙︽懜 + handleSwiperEnd(item) { + // 闃叉婊戝姩婊氬姩鏉′篃瑙﹀彂璺宠浆 + if (this.showProcess) { + return } - this.startPauseTime = 0; - // 鎾斁褰撳墠瑙嗛 - if (this.videoContexts[this.currentIndex]) { - this.videoContexts[this.currentIndex].play(); + const diffX = this.touchXY.endX - this.touchXY.startX + const diffY = this.touchXY.endY - this.touchXY.startY + + // 鍒ゆ柇鏄惁鏄í鍚戞粦鍔紙X杞村彉鍖栧ぇ浜嶻杞村彉鍖栵級 + if (Math.abs(diffX) > Math.abs(diffY)) { + if (diffX > 0) { + console.log('鍙虫粦') + if (item.goodsList && item.goodsList.length > 0) { + this.jumpToPay(item.id) + } + } else { + console.log('宸︽粦') + } + } + // 閲嶇疆鍧愭爣 + this.touchXY = { + startX: 0, + endX: 0, + startY: 0, + endY: 0 } - }, + }, // 鑾峰彇杩涘害鏉$殑浣嶇疆鍜屽昂瀵� getBarRect() { @@ -703,7 +758,8 @@ this.startProgress = this.progress; // 璁板綍寮�濮嬫椂鐨勮繘搴� this.startX = e.touches[0].pageX; console.log("璁板綍寮�濮嬫椂鐨勮繘搴�", this.startProgress); - this.videoContexts[this.currentIndex].pause() + const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this); + videoContext.pause() // this.updateProgress(e); }, @@ -711,7 +767,6 @@ handleTouchMove(e) { if (!this.isDragging || !this.barWidth) return; clearTimeout(this.processHidenTimer) - this.videoContexts[this.currentIndex].pause() this.updateProgress(e); }, @@ -719,11 +774,12 @@ handleTouchEnd() { this.isDragging = false; console.log("婊戝姩缁撴潫", this.duration * this.progress); - this.videoContexts[this.currentIndex].seek(this.duration * this.progress / 100) - this.videoContexts[this.currentIndex].play() + const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this); + videoContext.seek(this.duration * this.progress / 100) + videoContext.play() this.processHidenTimer = setTimeout(() => { - this.showProcess = false; - }, 1000); + this.showProcess = false; + }, 1000); }, // 鏇存柊杩涘害 @@ -736,7 +792,6 @@ // 灏嗗儚绱犺窛绂昏浆鎹负杩涘害澧為噺 const deltaProgress = (deltaX / this.barWidth) * 100; - console.log("杩涘害澧為噺", deltaProgress); // 璁$畻鏂拌繘搴� = 寮�濮嬫椂鐨勮繘搴� + 婊戝姩澧為噺 let newProgress = this.startProgress + deltaProgress; @@ -770,16 +825,16 @@ }, // 鍗曞嚮灞忓箷锛氭殏鍋滄垨缁х画鎾斁 togglePlay(index) { + console.log("鍗曞嚮瑙嗛", index); + const videoContext = uni.createVideoContext(`video${index}`, this); if(this.currentVideoIsPlaying) { - this.videoContexts[index].pause(); + videoContext.pause(); } else { - this.videoContexts[index].play(); + videoContext.play(); } }, // 瑙嗛鎾斁浜嬩欢 onPlay(id, index) { - this.getBarRect() - this.progress = 0 if(index === this.currentIndex) { this.currentVideoIsPlaying = true; if(! this.duration) { @@ -788,9 +843,11 @@ this.formartDuration = this.sliderFormatTime(this.duration); } } else { - this.currentVideoIsPlaying = false; return } + this.getBarRect() + this.progress = 0 + console.log(id, index, "瑙﹀彂鎾斁"); this.playRecord.videoId = id; // 娌″垵濮嬪寲鎵嶈祴鍊硷紝鍥犱负涓�涓棰戦噸澶嶆挱鏀緊nPlay浼氶噸澶嶈Е鍙� if(this.playRecord.startPlayTime === 0) { @@ -800,6 +857,7 @@ const duration = Date.now() - this.startPauseTime this.totalPauseTime += duration } + this.videoLoading = false }, // 瑙嗛鏆傚仠浜嬩欢 @@ -807,11 +865,8 @@ console.log(index, "瑙﹀彂鏆傚仠"); if(index === this.currentIndex) { this.currentVideoIsPlaying = false; - } else { - this.currentVideoIsPlaying = true; - return + this.startPauseTime = Date.now() } - this.startPauseTime = Date.now() }, // 瑙嗛缁撴潫浜嬩欢 @@ -821,9 +876,17 @@ // 璁板綍鎾斁鏃堕暱 onTimeUpdate(e) { + this.videoLoading = false this.playRecord.playAt = e.detail.currentTime this.currentTime = e.detail.currentTime; this.progress = (e.detail.currentTime / this.duration) * 100 + }, + // 瑙嗛缂撳啿 + videoWaiting(index) { + if (index === this.currentIndex) { + console.log("瑙嗛缂撳啿涓�傘�傘��"); + this.videoLoading = true; + } }, // 鑾峰彇瑙嗛鎬绘椂闀� onLoadedMetadata(e) { @@ -872,7 +935,7 @@ .video-item { width: 100%; height: 100%; - object-fit: cover; + /* object-fit: cover; */ } .play-icon { position: absolute; diff --git a/uni_modules/zero-loading/changelog.md b/uni_modules/zero-loading/changelog.md new file mode 100644 index 0000000..af6947d --- /dev/null +++ b/uni_modules/zero-loading/changelog.md @@ -0,0 +1,51 @@ +## 1.4.2锛�2025-04-03锛� +## 澧炲姞涓や釜鍔ㄧ敾 +| locating | 瀹氫綅 (鑷畾涔夐鑹�) | +| photo | 鐓х墖 (鑷畾涔夐鑹�) | +## 1.4.1锛�2024-07-02锛� +### 1. 澧炲姞鍔ㄧ敾equal(绛夎竟), wobble(鎽囨憜) +### 2. 鍘熸潵鐨則riangle(涓夎)鏀逛负surround(鐜粫) +### 3. 鏂板鍙嚜瀹氫箟棰滆壊椤� +## 1.4.0锛�2024-06-28锛� + +## 澧炲姞 loading 鍔犺浇鏂囧瓧鎻愰啋閰嶇疆椤�,榛樿 false + +## 1.3.2锛�2023-10-31锛� + +淇敼閬僵榛樿閫忔槑搴︿负 0.1 + +## 1.3.1锛�2023-10-31锛� + +## 鏂板鏀寔,鑷畾涔夊姩鐢婚鑹�(浠呴儴鍒嗗姩鐢绘敮鎸�) + +## 鏂板鍔ㄧ敾-annulus(鍦嗙幆) + +## 1.3.0锛�2023-08-11锛� + +鏀寔 vue3 浣跨敤, 澧炲姞鍔ㄧ敾绫诲瀷 radar(闆疯揪) + +## 1.2.2锛�2023-06-12锛� + +澧炲姞 maskOpacity, maskMini, maskDark 鑷畾涔夊弬鏁�, 鎻愪緵鏇翠赴瀵岀殑鑷畾涔夐伄缃╁眰鑳藉姏 + +## 1.2.1锛�2022-09-09锛� + +澧炲姞榻胯疆鍔ㄧ敾 type=gear + +## 1.2.0锛�2022-05-27锛� + +1. 澧炲姞鍔犺浇绫诲瀷-鍓戞皵锛坰word锛夛紝鍘熷瓙锛坅tom锛� +2. 榛樿绫诲瀷鏀逛负 atom +3. 閬僵閫忔槑搴﹁皟鏁� + +## 1.1.1锛�2022-04-02锛� + +鏇存柊浣跨敤璇存槑 + +## 1.1.0锛�2022-02-23锛� + +澧炲姞 type="love" 鐨勫績褰㈠姞杞藉姩鐢� + +## 1.0.0锛�2022-01-28锛� + +棣栨鍙戝竷 diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue new file mode 100644 index 0000000..260301f --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue @@ -0,0 +1,45 @@ +<template> + <view class="animations"> + <view class="loader" :style="{ '--color': color }"></view> + </view> +</template> + +<script> +export default { + name: "loading-annulus", + props: { + color: { + type: String, + default: "#0396FF", + }, + }, + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +.loader { + width: 60px; + height: 60px; +} + +.loader::before { + content: ""; + box-sizing: border-box; + position: absolute; + width: 60px; + height: 60px; + border-radius: 50%; + border-top: 2px solid var(--color); + border-right: 2px solid transparent; + animation: spinner 1s linear infinite; +} + +@keyframes spinner { + to { + transform: rotate(360deg); + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue new file mode 100644 index 0000000..3b3b75e --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue @@ -0,0 +1,108 @@ +<template> + <view class="animations"> + <view class="box" :style="{ '--color': color }"> + <view class="atom"></view> + <view class="atom"></view> + <view class="atom"></view> + <view class="dot"></view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-atom", + props: { + color: { + type: String, + default: "#0396FF", + }, + }, + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +.box { + position: relative; + width: 120rpx; + height: 120rpx; +} +.dot { + position: absolute; + width: 10px; + height: 10px; + border-radius: 50%; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background: var(--color); + animation: dotbreath 2s linear infinite; +} +.atom { + position: absolute; + width: 100%; + height: 100%; + border-radius: 50%; + border-left-width: 6rpx; + border-top-width: 6rpx; + border-left-color: var(--color); + border-left-style: solid; + border-top-style: solid; + border-top-color: transparent; +} +.atom:nth-of-type(1) { + left: 0%; + top: 0%; + animation: atom1 1s linear infinite; +} +.atom:nth-of-type(2) { + right: 0%; + top: 0%; + animation: atom2 1s linear infinite; +} +.atom:nth-of-type(3) { + right: 0%; + bottom: 0%; + animation: atom3 1s linear infinite; +} +@keyframes dotbreath { + 0% { + opacity: 1; + } + + 50% { + opacity: 0.5; + } + 100% { + opacity: 1; + } +} +@keyframes atom1 { + 0% { + transform: rotateZ(120deg) rotateX(66deg) rotateZ(0deg); + } + 100% { + transform: rotateZ(120deg) rotateX(66deg) rotateZ(360deg); + } +} +@keyframes atom2 { + 0% { + transform: rotateZ(240deg) rotateX(66deg) rotateZ(0deg); + } + 100% { + transform: rotateZ(240deg) rotateX(66deg) rotateZ(360deg); + } +} + +@keyframes atom3 { + 0% { + transform: rotateZ(360deg) rotateX(66deg) rotateZ(0deg); + } + 100% { + transform: rotateZ(360deg) rotateX(66deg) rotateZ(360deg); + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue new file mode 100644 index 0000000..860d23d --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue @@ -0,0 +1,84 @@ +<template> + <view class="animations"> + <view class="box"> + <view class="dot dot1"></view> + <view class="dot dot2"></view> + <view class="dot dot3"></view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-bounce", + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +.box { + width: 100rpx; + height: 50rpx; + position: relative; +} +.dot { + width: 14rpx; + height: 14rpx; + background: #007aff; + border-radius: 50%; + position: absolute; + top: calc(50% - 5rpx); +} + +.dot1 { + background: #1fa2ff; + left: 0rpx; + -webkit-animation: bounce 0.5s cubic-bezier(0.77, 0.47, 0.64, 0.28) alternate + infinite; + animation: bounce 0.5s cubic-bezier(0.77, 0.47, 0.64, 0.28) alternate infinite; +} + +.dot2 { + background: #12d8fa; + left: 40rpx; + -webkit-animation: bounce 0.5s 0.2s cubic-bezier(0.77, 0.47, 0.64, 0.28) + alternate infinite; + animation: bounce 0.5s 0.2s cubic-bezier(0.77, 0.47, 0.64, 0.28) alternate + infinite; +} + +.dot3 { + background: #29ffc6; + left: 80rpx; + -webkit-animation: bounce 0.5s 0.4s cubic-bezier(0.77, 0.47, 0.64, 0.28) + alternate infinite; + animation: bounce 0.5s 0.4s cubic-bezier(0.77, 0.47, 0.64, 0.28) alternate + infinite; +} + +@-webkit-keyframes bounce { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + -webkit-transform: translateY(-20rpx); + transform: translateY(-20rpx); + } +} + +@keyframes bounce { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + -webkit-transform: translateY(-20rpx); + transform: translateY(-20rpx); + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue new file mode 100644 index 0000000..958bb14 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue @@ -0,0 +1,96 @@ +<template> + <view class="animations"> + <view class="loader" :style="{ '--color': color }"></view> + </view> +</template> + +<script> +export default { + name: "loading-circle", + props: { + color: { + type: String, + default: "#0396FF", + }, + }, + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +// .container { +// position: absolute; +// top: 50%; +// left: 50%; +// transform: translate(-50%, -50%); +// } +.loader { + display: block; + width: 120rpx; + height: 120rpx; + border-radius: 50%; + border: 3rpx solid transparent; + border-top-color: var(--color); + -webkit-animation: spin 2s linear infinite; + animation: spin 2s linear infinite; + position: relative; +} + +.loader::before { + content: ""; + position: absolute; + top: 8rpx; + left: 8rpx; + right: 8rpx; + bottom: 8rpx; + border-radius: 50%; + border: 3rpx solid transparent; + border-top-color: var(--color); + -webkit-animation: spin 3s linear infinite; + animation: spin 3s linear infinite; +} + +.loader::after { + content: ""; + position: absolute; + top: 16rpx; + left: 16rpx; + right: 16rpx; + bottom: 16rpx; + border-radius: 50%; + border: 3rpx solid transparent; + border-top-color: var(--color); + -webkit-animation: spin 1.5s linear infinite; + animation: spin 1.5s linear infinite; +} + +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-equal.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-equal.vue new file mode 100644 index 0000000..b68b86c --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-equal.vue @@ -0,0 +1,81 @@ +<template> + <view class="animations"> + <view class="loader" :style="{ '--color': color }"></view> + </view> +</template> + +<script> +export default { + name: "loading-equal", + props: { + color: { + type: String, + default: "#ff1919", + }, + }, + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +.loader { + width: 50px; + aspect-ratio: 1.154; + position: relative; + background: conic-gradient( + from 120deg at 50% 64%, + #0000, + var(--color) 1deg 120deg, + #0000 121deg + ); + animation: spin 1.5s infinite cubic-bezier(0.3, 1, 0, 1); +} + +.loader:before, +.loader:after { + content: ""; + position: absolute; + inset: 0; + background: inherit; + transform-origin: 50% 66%; + animation: separate 1.5s infinite; +} + +.loader:after { + --s: -1; +} + +@keyframes spin { + 0%, + 30% { + transform: rotate(0); + } + + 70% { + transform: rotate(120deg); + } + + 70.01%, + 100% { + transform: rotate(360deg); + } +} + +@keyframes separate { + 0% { + transform: rotate(calc(var(--s, 1) * 120deg)) translate(0); + } + + 30%, + 70% { + transform: rotate(calc(var(--s, 1) * 120deg)) + translate(calc(var(--s, 1) * -5px), 10px); + } + + 100% { + transform: rotate(calc(var(--s, 1) * 120deg)) translate(0); + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue new file mode 100644 index 0000000..f7a18d1 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue @@ -0,0 +1,78 @@ +<template> + <view class="animations"> + <view class="box"> + <view class="eye"></view> + <view class="eye"></view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-eyes", + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +.box { + width: 110rpx; + display: flex; + justify-content: space-between; + align-items: center; +} + +.eye { + width: 50rpx; + height: 50rpx; + background: linear-gradient(135deg, #1fa2ff, #12d8fa); + border-radius: 50%; + position: relative; +} + +.eye:after { + background-color: #ffffff; + width: 18rpx; + height: 18rpx; + border-radius: 50%; + left: 20rpx; + top: 24rpx; + position: absolute; + content: ""; + -webkit-animation: eyeball 1s linear infinite alternate; + -moz-animation: eyeball 1s linear infinite alternate; + animation: eyeball 1s linear infinite alternate; +} + +@-webkit-keyframes eyeball { + 0% { + left: 30rpx; + } + + 100% { + left: 2rpx; + } +} + +@-moz-keyframes eyeball { + 0% { + left: 30rpx; + } + + 100% { + left: 2rpx; + } +} + +@keyframes eyeball { + 0% { + left: 30rpx; + } + + 100% { + left: 2rpx; + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue new file mode 100644 index 0000000..19ce873 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue @@ -0,0 +1,118 @@ +<template> + <view class="animations"> + <view class="box"> + <view class="gear1"> + <view class="inner inner1"> </view> + <view class="inner inner2"> </view> + <view class="inner inner3"> </view> + </view> + <view class="gear2"> + <view class="inner inner1"> </view> + <view class="inner inner2"> </view> + <view class="inner inner3"> </view> + </view> + <view class="gear3"> + <view class="inner inner1"> </view> + <view class="inner inner2"> </view> + <view class="inner inner3"> </view> + </view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-gear", + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +$size: 80rpx; +$bgc: red; + +.box { + width: 200rpx; + height: 200rpx; + position: relative; +} + +@mixin gear($size: $size, $bgc: $bgc) { + width: $size; + height: $size; + .inner { + position: absolute; + width: $size; + height: $size; + top: 0; + left: 0; + background: $bgc; + border-radius: 6rpx; + mask: radial-gradient(transparent 40%, #fff 60%); + } + + .inner2 { + transform: rotate(120deg); + } + + .inner3 { + transform: rotate(240deg); + } + + // &:after { + // position: absolute; + // content: ''; + // background: #fff; + // width: $size / 1.8; + // height: $size / 1.8; + // border-radius: 100%; + // top: 50%; + // left: 50%; + // transform: translate(-50%, -50%); + // } +} + +.gear1 { + @include gear(60rpx, #0396ff); + position: absolute; + top: 35rpx; + left: 35rpx; + animation: rotate 5s infinite linear; +} + +.gear2 { + @include gear(50rpx, #dd524d); + position: absolute; + top: 50rpx; + left: 110rpx; + animation: rotateR 5s infinite linear; +} +.gear3 { + @include gear(50rpx, #f0ad4e); + position: absolute; + top: 110rpx; + left: 50rpx; + animation: rotateR 5s infinite linear; +} + +@keyframes rotate { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} +@keyframes rotateR { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(-360deg); + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-locating.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-locating.vue new file mode 100644 index 0000000..7e140ec --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-locating.vue @@ -0,0 +1,81 @@ +<template> + <view class="animations"> + <view class="loader" :style="{ '--color': color }"></view> + </view> + </template> + + <script> + export default { + name: "loading-locating", + props: { + color: { + type: String, + default: "#0396FF", + }, + }, + data() { + return {}; + }, + }; + </script> + + <style lang="scss" scoped> + + .loader { + width: 96rpx; + height: 96rpx; + display: block; + margin: 40rpx auto; + box-sizing: border-box; + position: relative; + } + + .loader::after { + content: ''; + width: 96rpx; + height: 96rpx; + left: 0; + bottom: 0; + position: absolute; + border-radius: 50% 50% 0; + border: 30rpx solid var(--color); + transform: rotate(45deg) translate(0, 0); + box-sizing: border-box; + animation: animMarker 0.4s ease-in-out infinite alternate; + } + + .loader::before { + content: ''; + box-sizing: border-box; + position: absolute; + left: 0; + right: 0; + margin: auto; + top: 150%; + width: 48rpx; + height: 8rpx; + border-radius: 50%; + background: rgba(0, 0, 0, 0.2); + animation: animShadow 0.4s ease-in-out infinite alternate; + } + + @keyframes animMarker { + 0% { + transform: rotate(45deg) translate(10rpx, 10rpx); + } + + 100% { + transform: rotate(45deg) translate(-10rpx, -10rpx); + } + } + + @keyframes animShadow { + 0% { + transform: scale(0.5); + } + + 100% { + transform: scale(1); + } + } +</style> \ No newline at end of file diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-love.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-love.vue new file mode 100644 index 0000000..9b5e6cd --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-love.vue @@ -0,0 +1,201 @@ +<template> + <view class="animations"> + <view class="box"> + <view class="item"></view> + <view class="item"></view> + <view class="item"></view> + <view class="item"></view> + <view class="item"></view> + <view class="item"></view> + <view class="item"></view> + <view class="item"></view> + <view class="item"></view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-love", + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +.box { + display: flex; + justify-content: center; + align-items: center; + flex-flow: row nowrap; + height: 160rpx; +} + +.item { + background: linear-gradient(to bottom, #f00000, #e73827); + width: 16rpx; + height: 16rpx; + border-radius: 20rpx; + margin-right: 10rpx; +} + +.item:nth-child(1) { + animation: love1 4s infinite; +} + +.item:nth-child(2) { + animation: love2 4s infinite; + animation-delay: 0.15s; +} + +.item:nth-child(3) { + animation: love3 4s infinite; + animation-delay: 0.3s; +} + +.item:nth-child(4) { + animation: love4 4s infinite; + animation-delay: 0.45s; +} + +.item:nth-child(5) { + animation: love5 4s infinite; + animation-delay: 0.6s; +} + +.item:nth-child(6) { + animation: love4 4s infinite; + animation-delay: 0.75s; +} + +.item:nth-child(7) { + animation: love3 4s infinite; + animation-delay: 0.9s; +} + +.item:nth-child(8) { + animation: love2 4s infinite; + animation-delay: 1.05s; +} + +.item:nth-child(9) { + animation: love1 4s infinite; + animation-delay: 1.2s; +} + +@keyframes love1 { + 30%, + 50% { + height: 50rpx; + transform: translateY(-20rpx); + } + + 75%, + 100% { + height: 20rpx; + transform: translateY(0); + } +} + +@keyframes love2 { + 30%, + 50% { + height: 90rpx; + transform: translateY(-25rpx); + } + + 75%, + 100% { + height: 20rpx; + transform: translateY(0); + } +} + +@keyframes love3 { + 30%, + 50% { + height: 120rpx; + transform: translateY(-20rpx); + } + + 75%, + 100% { + height: 20rpx; + transform: translateY(0); + } +} + +@keyframes love4 { + 30%, + 50% { + height: 130rpx; + transform: translateY(-10rpx); + } + + 75%, + 100% { + height: 20rpx; + transform: translateY(0); + } +} + +@keyframes love5 { + 30%, + 50% { + height: 130rpx; + transform: translateY(10rpx); + } + + 75%, + 100% { + height: 20rpx; + transform: translateY(0); + } +} + +// .item:nth-child(1) { +// height: 50rpx; +// transform: translateY(-20rpx); +// } + +// .item:nth-child(2) { +// height: 90rpx; +// transform: translateY(-25rpx); +// } + +// .item:nth-child(3) { +// height: 120rpx; +// transform: translateY(-20rpx); +// } + +// .item:nth-child(4) { +// height: 130rpx; +// transform: translateY(-10rpx); +// } + +// .item:nth-child(5) { +// height: 130rpx; +// transform: translateY(10rpx); +// } + +// .item:nth-child(6) { +// height: 130rpx; +// transform: translateY(-10rpx); +// } + +// .item:nth-child(7) { +// height: 120rpx; +// transform: translateY(-20rpx); +// } + +// .item:nth-child(8) { +// height: 90rpx; +// transform: translateY(-25rpx); +// } + +// .item:nth-child(9) { +// height: 50rpx; +// transform: translateY(-20rpx); +// } +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-photo.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-photo.vue new file mode 100644 index 0000000..3c9b383 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-photo.vue @@ -0,0 +1,87 @@ +<template> + <view class="animations"> + <view class="loader" :style="{ '--color': color }"></view> + </view> +</template> + +<script> +export default { + name: "loading-photo", + props: { + color: { + type: String, + default: "#0396FF", + }, + }, + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> + +.loader { + width: 128rpx; + height: 128rpx; + position: relative; + background: #f4f4f4; + border-radius: 8rpx; + overflow: hidden; +} + +.loader:before { + content: ""; + position: absolute; + left: 0; + bottom: 0; + width: 80rpx; + height: 80rpx; + transform: rotate(45deg) translate(30%, 40%); + background: var(--color); + box-shadow: 64rpx -68rpx 0 10rpx var(--color); + animation: slide 2s infinite ease-in-out alternate; +} + +.loader:after { + content: ""; + position: absolute; + left: 20rpx; + top: 20rpx; + width: 28rpx; + height: 28rpx; + border-radius: 50%; + background: var(--color); + transform: rotate(0deg); + transform-origin: 70rpx 290rpx; + animation: rotate 2s infinite ease-in-out; +} + +@keyframes slide { + 0% , 100% { + bottom: -70rpx + } + + 25% , 75% { + bottom: -4rpx + } + + 20% , 80% { + bottom: 4rpx + } +} + +@keyframes rotate { + 0% { + transform: rotate(-15deg) + } + + 25% , 75% { + transform: rotate(0deg) + } + + 100% { + transform: rotate(25deg) + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue new file mode 100644 index 0000000..9c32c7e --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue @@ -0,0 +1,67 @@ +<template> + <view class="animations"> + <view class="box" :style="{ '--color': color }"> + <view class="pulse-bubble pulse-bubble-1"></view> + <view class="pulse-bubble pulse-bubble-2"></view> + <view class="pulse-bubble pulse-bubble-3"></view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-pulse", + props: { + color: { + type: String, + default: "#0396FF", + }, + }, + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +.box { + width: 100rpx; + display: flex; + justify-content: space-between; + align-items: center; +} + +.pulse-bubble { + width: 16rpx; + height: 16rpx; + border-radius: 50%; + background: var(--color); +} + +.pulse-bubble-1 { + // background: #1fa2ff; + animation: pulse 0.4s ease 0s infinite alternate; +} + +.pulse-bubble-2 { + // background: #12d8fa; + animation: pulse 0.4s ease 0.2s infinite alternate; +} + +.pulse-bubble-3 { + // background: #29ffc6; + animation: pulse 0.4s ease 0.4s infinite alternate; +} + +@keyframes pulse { + from { + opacity: 1; + transform: scale(1); + } + + to { + opacity: 0.25; + transform: scale(0.75); + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue new file mode 100644 index 0000000..ebafa85 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue @@ -0,0 +1,132 @@ +<template> + <view class="animations"> + <view class="radar"> + <view class="dot dot-1"></view> + <view class="dot dot-2"></view> + <view class="dot dot-3"></view> + <view class="cover"></view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-radar", + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +$size: 180rpx; +$dotSize: 4rpx; +$maincolor: #2da3f6; + +.radar { + position: relative; + z-index: 1; + height: $size; + width: $size; + background: -webkit-repeating-radial-gradient( + rgba(45, 163, 246, 0) 0%, + rgba(45, 163, 246, 0) 23%, + rgba(45, 163, 246, 0.7) 24%, + rgba(45, 163, 246, 0) 25% + ); + margin: 0 auto; + border-radius: 50%; + border: 2rpx solid rgba(45, 163, 246, 0.7); + overflow: hidden; +} + +.radar::after { + content: ""; + position: absolute; + top: 50%; + left: 50%; + width: $dotSize; + height: $dotSize; + background: $maincolor; + margin-left: -1rpx; + margin-top: -1rpx; + border-radius: 1rpx; +} + +.dot { + position: absolute; + width: $dotSize; + height: $dotSize; + background: $maincolor; + opacity: 0; + border-radius: 50%; + animation: breath 3s linear infinite; + box-shadow: 0 0 2rpx 2rpx rgba(45, 163, 246, 0.5); +} + +.dot-1 { + top: 50rpx; + left: 30rpx; + animation-delay: 1s; +} + +.dot-2 { + top: 60rpx; + right: 20rpx; + animation-delay: 0.2s; +} + +.dot-3 { + top: 140rpx; + right: 100rpx; + animation-delay: 2.3s; +} + +.cover { + transform-origin: bottom right; + border-right: 1rpx solid $maincolor; + background: linear-gradient( + 45deg, + rgba(255, 255, 255, 0) 45%, + $maincolor 100% + ); + width: 50%; + height: 50%; + position: absolute; + top: 0; + left: 0; + animation: rotation 3s linear infinite; +} + +@keyframes rotation { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +@keyframes breath { + 0% { + opacity: 0; + } + + 10% { + opacity: 1; + } + + 20% { + opacity: 1; + } + + 40% { + opacity: 0; + } + + 100% { + opacity: 0; + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue new file mode 100644 index 0000000..ed079d8 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue @@ -0,0 +1,140 @@ +<template> + <view class="animations"> + <view class="box"> + <view class="sun"></view> + <view class="orbit orbit1"> + <view class="planetX planet1"></view> + </view> + <view class="orbit orbit2"> + <view class="planetX planet2"></view> + </view> + <view class="orbit orbit3"> + <view class="planetX planet3"></view> + </view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-sun", + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +.box { + width: 210rpx; + height: 210rpx; + position: relative; +} +.sun { + background: radial-gradient(#ff0, #f90); + height: 50rpx; + width: 50rpx; + border-radius: 50%; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; +} + +.planetX { + position: absolute; + z-index: 100; + border-radius: 50%; +} + +.planet1 { + left: 20rpx; + height: 13rpx; + width: 13rpx; + background-color: #fed313; +} + +.planet2 { + left: 23rpx; + height: 20rpx; + width: 20rpx; + background: linear-gradient(#00ff00, #09f, #09f); + -webkit-animation: rotation 1s infinite linear; + animation: rotation 1s infinite linear; +} + +.planet3 { + left: 49rpx; + height: 17rpx; + width: 17rpx; + background: radial-gradient(#ff9900, #ff4400); +} + +.orbit { + background: transparent; + border-radius: 50%; + border: 1rpx solid #cccccc; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; +} + +.orbit1 { + height: 100rpx; + width: 100rpx; + -webkit-animation: rotation 2s infinite linear; + -moz-animation: rotation 2s infinite linear; + animation: rotation 2s infinite linear; +} + +.orbit2 { + height: 150rpx; + width: 150rpx; + -webkit-animation: rotation 3s infinite linear; + -moz-animation: rotation 3s infinite linear; + animation: rotation 3s infinite linear; +} + +.orbit3 { + height: 200rpx; + width: 200rpx; + -moz-animation: rotation 6s infinite linear; + -webkit-animation: rotation 6s infinite linear; + animation: rotation 6s infinite linear; +} + +@-webkit-keyframes rotation { + from { + -webkit-transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(359deg); + } +} + +@keyframes rotation { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(359deg); + } +} + +@-moz-keyframes rotation { + from { + -moz-transform: rotate(0deg); + } + + to { + -moz-transform: rotate(359deg); + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-surround.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-surround.vue new file mode 100644 index 0000000..0e47a11 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-surround.vue @@ -0,0 +1,91 @@ +<template> + <view class="animations"> + <view class="box"> + <view class="loader"> + <view class="loader__ball"></view> + <view class="loader__ball"></view> + <view class="loader__ball"></view> + </view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-triangle", + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +$dotColor: linear-gradient(135deg, #1fa2ff, #12d8fa, #29ffc6); +$dotSize: 30rpx; +$duration: 2s; +.animations { + width: 160rpx; + height: 160rpx; + position: relative; +} +.box { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} +.loader { + animation: rotate $duration linear infinite normal; + position: relative; + transform-origin: 50% 50%; + + &__ball { + height: $dotSize; + width: $dotSize; + left: -$dotSize * 0.5; + position: absolute; + top: -$dotSize * 0.5; + transform-origin: 50% 50%; + + &:nth-of-type(2) { + transform: rotate(120deg); + } + + &:nth-of-type(3) { + transform: rotate(240deg); + } + + &::after { + animation: move $duration * 0.5 ease-in-out infinite alternate; + background: $dotColor; + border-radius: 50%; + content: ""; + display: inline-block; + height: 100%; + width: 100%; + transform-origin: 50% 50%; + } + } +} + +@keyframes rotate { + from { + transform: rotate(0); + } + + to { + transform: rotate(360deg); + } +} + +@keyframes move { + 0%, + 15% { + transform: translateY(0); + } + + 100% { + transform: translateY(-150%); + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue new file mode 100644 index 0000000..8efb848 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue @@ -0,0 +1,81 @@ +<template> + <view class="animations"> + <view class="box" :style="{ '--color': color }"> + <view class="sword"></view> + <view class="sword"></view> + <view class="sword"></view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-sword", + props: { + color: { + type: String, + default: "#ED213A", + }, + }, + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +.box { + position: relative; + width: 120rpx; + height: 120rpx; +} +.sword { + position: absolute; + width: 100%; + height: 100%; + border-radius: 50%; +} +.sword:nth-of-type(1) { + left: 0%; + top: 0%; + border-bottom: 8rpx solid var(--color); + animation: sword1 0.8s linear infinite; +} +.sword:nth-of-type(2) { + right: 0%; + top: 0%; + border-right: 8rpx solid var(--color); + animation: sword2 0.8s linear infinite; +} +.sword:nth-of-type(3) { + right: 0%; + bottom: 0%; + border-top: 8rpx solid var(--color); + animation: sword3 0.8s linear infinite; +} +@keyframes sword1 { + 0% { + transform: rotateX(35deg) rotateY(-45deg) rotateZ(0deg); + } + 100% { + transform: rotateX(35deg) rotateY(-45deg) rotateZ(360deg); + } +} +@keyframes sword2 { + 0% { + transform: rotateX(50deg) rotateY(10deg) rotateZ(0deg); + } + 100% { + transform: rotateX(50deg) rotateY(10deg) rotateZ(360deg); + } +} + +@keyframes sword3 { + 0% { + transform: rotateX(35deg) rotateY(55deg) rotateZ(0deg); + } + 100% { + transform: rotateX(35deg) rotateY(55deg) rotateZ(360deg); + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-wobble.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-wobble.vue new file mode 100644 index 0000000..d8f6283 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-wobble.vue @@ -0,0 +1,127 @@ +<template> + <view class="animations"> + <view class="three-body" :style="{ '--color': color }"> + <view class="three-body__dot"></view> + <view class="three-body__dot"></view> + <view class="three-body__dot"></view> + </view> + </view> +</template> + +<script> +export default { + name: "loading-wobble", + props: { + color: { + type: String, + default: "#0396FF", + }, + }, + data() { + return {}; + }, +}; +</script> + +<style lang="scss" scoped> +$size: 100rpx; +$speed: 1s; +.three-body { + position: relative; + display: inline-block; + height: $size; + width: $size; + animation: spin78236 calc($speed * 2.5) infinite linear; +} + +.three-body__dot { + position: absolute; + height: 100%; + width: 27%; +} + +.three-body__dot:after { + content: ""; + position: absolute; + height: 0%; + width: 100%; + padding-bottom: 100%; + background-color: var(--color); + border-radius: 50%; +} + +.three-body__dot:nth-child(1) { + bottom: 5%; + left: 0; + transform: rotate(60deg); + transform-origin: 50% 85%; +} + +.three-body__dot:nth-child(1)::after { + bottom: 0; + left: 0; + animation: wobble1 $speed infinite ease-in-out; + animation-delay: calc($speed * -0.3); +} + +.three-body__dot:nth-child(2) { + bottom: 5%; + right: 0; + transform: rotate(-60deg); + transform-origin: 50% 85%; +} + +.three-body__dot:nth-child(2)::after { + bottom: 0; + left: 0; + animation: wobble1 $speed infinite calc($speed * -0.15) ease-in-out; +} + +.three-body__dot:nth-child(3) { + bottom: -5%; + left: 0; + transform: translateX(116.666%); +} + +.three-body__dot:nth-child(3)::after { + top: 0; + left: 0; + animation: wobble2 $speed infinite ease-in-out; +} + +@keyframes spin78236 { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +@keyframes wobble1 { + 0%, + 100% { + transform: translateY(0%) scale(1); + opacity: 1; + } + + 50% { + transform: translateY(-66%) scale(0.65); + opacity: 0.8; + } +} + +@keyframes wobble2 { + 0%, + 100% { + transform: translateY(0%) scale(1); + opacity: 1; + } + + 50% { + transform: translateY(66%) scale(0.65); + opacity: 0.8; + } +} +</style> diff --git a/uni_modules/zero-loading/components/zero-loading/zero-loading.vue b/uni_modules/zero-loading/components/zero-loading/zero-loading.vue new file mode 100644 index 0000000..62db5eb --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/zero-loading.vue @@ -0,0 +1,186 @@ +<template> + <!-- --> + <view + :style="{ position: position, 'z-index': zIndex, '--opacity': maskOpacity }" + class="container" + :class="[ + mask ? 'mask' : '', + maskMini ? 'mask-mini' : '', + (mask || maskMini) && maskDark ? 'mask-dark' : '', + ]" + @click.prevent="handleClick" + > + <view> + <view class="main"> + <loading0 v-if="type == 'circle'" :color="color"></loading0> + <loading1 v-if="type == 'pulse'" :color="color"></loading1> + <loading2 v-if="type == 'bounce'"></loading2> + <loading3 v-if="type == 'eyes'"></loading3> + <loading4 v-if="type == 'surround'"></loading4> + <loading5 v-if="type == 'sun'"></loading5> + <loading6 v-if="type == 'love'"></loading6> + <loading7 v-if="type == 'sword'" :color="color"></loading7> + <loading8 v-if="type == 'atom'" :color="color"></loading8> + <loading9 v-if="type == 'gear'"></loading9> + <loading10 v-if="type == 'radar'"></loading10> + <loading11 v-if="type == 'annulus'" :color="color"></loading11> + <loading12 v-if="type == 'wobble'" :color="color"></loading12> + <loading13 v-if="type == 'equal'" :color="color"></loading13> + <loading14 v-if="type == 'photo'" :color="color"></loading14> + <loading15 v-if="type == 'locating'" :color="color"></loading15> + </view> + <view + class="tips" + v-if="showText" + :style="{ color: textColor, fontSize: textSize, marginTop: textGap }" + >{{ text }}</view + > + </view> + </view> +</template> + +<script> +import loading0 from "./static/loading-circle.vue"; +import loading1 from "./static/loading-pulse.vue"; +import loading2 from "./static/loading-bounce.vue"; +import loading3 from "./static/loading-eyes.vue"; +import loading4 from "./static/loading-surround.vue"; +import loading5 from "./static/loading-sun.vue"; +import loading6 from "./static/loading-love.vue"; +import loading7 from "./static/loading-sword.vue"; +import loading8 from "./static/loading-atom.vue"; +import loading9 from "./static/loading-gear.vue"; +import loading10 from "./static/loading-radar.vue"; +import loading11 from "./static/loading-annulus.vue"; +import loading12 from "./static/loading-wobble.vue"; +import loading13 from "./static/loading-equal.vue"; +import loading14 from "./static/loading-photo.vue"; +import loading15 from "./static/loading-locating.vue"; + +export default { + name: "zero-loading", + components: { + loading0, + loading1, + loading2, + loading3, + loading4, + loading5, + loading6, + loading7, + loading8, + loading9, + loading10, + loading11, + loading12, + loading13, + loading14, + loading15, + }, + props: { + type: { + type: String, + default: "atom", + }, + position: { + type: String, + default: "fixed", + }, + zIndex: { + type: Number, + default: 9, + }, + mask: { + type: Boolean, + default: false, + }, + maskOpacity: { + type: Number, + default: 0.1, + }, + maskMini: { + type: Boolean, + default: false, + }, + maskDark: { + type: Boolean, + default: true, + }, + color: { + type: String, + default: "#0396FF", + }, + showText: { + type: Boolean, + default: false, + }, + text: { + type: String, + default: "鍔犺浇涓�...", + }, + textSize: { + type: String, + default: "28rpx", + }, + textColor: { + type: String, + default: "#333333", + }, + textGap: { + type: String, + default: "40rpx", + }, + }, + data() { + return {}; + }, + methods: { + handleClick() { + this.$emit("click"); + }, + }, +}; +</script> + +<style lang="scss" scoped> +.container { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + display: flex; + align-items: center; + justify-content: center; +} +.tips { + // margin-top: 40rpx; + text-align: center; +} + +.mask { + z-index: 999 !important; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + height: 100vh; + width: 100vw; + background: rgba(255, 255, 255, var(--opacity)); + transform: translate(0, 0); +} + +.mask-mini { + height: 300rpx; + width: 300rpx; + border-radius: 20rpx; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.mask-dark { + background: rgba(7, 17, 27, var(--opacity)); +} +</style> diff --git a/uni_modules/zero-loading/package.json b/uni_modules/zero-loading/package.json new file mode 100644 index 0000000..17f7d3e --- /dev/null +++ b/uni_modules/zero-loading/package.json @@ -0,0 +1,83 @@ +{ + "id": "zero-loading", + "displayName": "zero-loading(鍔犺浇鍔ㄧ敾)", + "version": "1.4.2", + "description": "绾痗ss鍔犺浇鍔ㄧ敾, 涓�涓爣绛惧厓绱犲嵆鍙疄鐜扮偒閰风殑鍏ㄥ睆loading鏁堟灉,鏀寔vue2,vue3", + "keywords": [ + "loading", + "鍔犺浇鍔ㄧ敾", + "css鍔ㄧ敾", + "鍔犺浇" +], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "鏃�", + "data": "鎻掍欢涓嶉噰闆嗕换浣曟暟鎹�", + "permissions": "鏃�" + }, + "npmurl": "", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "n" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-vue": "u", + "app-nvue": "u", + "app-harmony": "u", + "app-uvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "寰俊娴忚鍣�(Android)": "y", + "QQ娴忚鍣�(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "u", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "灏忕▼搴�": { + "寰俊": "y", + "闃块噷": "u", + "鐧惧害": "u", + "瀛楄妭璺冲姩": "u", + "QQ": "u" + }, + "蹇簲鐢�": { + "鍗庝负": "u", + "鑱旂洘": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/zero-loading/readme.md b/uni_modules/zero-loading/readme.md new file mode 100644 index 0000000..2f14f69 --- /dev/null +++ b/uni_modules/zero-loading/readme.md @@ -0,0 +1,69 @@ +# zero-loading + +> 浠呮祴璇曚簬 vue2, vue3, 寰俊灏忕▼搴�. 鍏朵粬骞冲彴鑷娴嬭瘯 + +## 浣跨敤鏂规硶 + +瀵煎叆 `uni_modules` 鍚庣洿鎺ヤ娇鐢ㄥ嵆鍙� + +鎻愪緵澶氱鍔犺浇鍔ㄧ敾绫诲瀷,浼犲叆 type 鏀瑰彉 loading 鏍峰紡锛屼笉浼犻粯璁� circle + +### 鍏ㄥ睆浣跨敤 + +```html +<zero-loading v-if="loading"></zero-loading> +``` + +### 灞�閮ㄤ娇鐢� + +**鐖跺厓绱犵殑 `position` 璁板緱鏀逛负 `relative` 涓嶇劧鍙兘褰卞搷鏁堟灉** + +```html +<zero-loading type="pulse" position="absolute"></zero-loading> +``` + +## 鍙傛暟璇存槑 + +| 鍙傛暟 | 绫诲瀷 | 榛樿鍊� | 鎻忚堪 | +| ----------- | -------- | --------- | ---------------------------------------------- | +| type | String | atom | 鏍峰紡 | +| position | String | fixed | 瀹氫綅鏂瑰紡 | +| zIndex | Number | 9 | | +| mask | Boolean | false | 鏄惁闇�瑕侀伄缃� (榛樿涓哄叏灞忛伄缃�,鑳屾櫙鑹查粯璁や负榛戣壊) | +| maskOpacity | Number | 0.1 | 閬僵閫忔槑搴� | +| maskMini | Boolean | false | 浼犲叆 true 鏃�,浣跨敤灏忛伄缃� | +| maskDark | Boolean | true | 浼犲叆 false 鏃�,閬僵鑳屾櫙鑹蹭负鐧借壊 | +| color | String | #0396FF | 鑷畾涔夐鑹�,浠呴儴鍒嗘敮鎸� | +| showText | showText | false | 鏄惁鏄剧ず鏂囧瓧 | +| text | String | 鍔犺浇涓�... | 鏂囨湰鍐呭 | +| textSize | String | 28rpx | 鏂囧瓧澶у皬 | +| textColor | String | #333333 | 鏂囧瓧棰滆壊 | +| textGap | String | 40rpx | 鏂囧瓧涓� loading 鍔ㄧ敾鐨勯棿璺� | + +### type 鍙�夊�硷細 + +| type 鍊� | 鎻忚堪 | +| -------- | ----------------- | +| locating | 瀹氫綅 (鑷畾涔夐鑹�) | +| photo | 鐓х墖 (鑷畾涔夐鑹�) | +| equal | 绛夎竟 (鑷畾涔夐鑹�) | +| wobble | 鎽囨憜 (鑷畾涔夐鑹�) | +| annulus | 鍦嗙幆 (鑷畾涔夐鑹�) | +| sword | 鍓戞皵 (鑷畾涔夐鑹�) | +| atom | 鍘熷瓙 (鑷畾涔夐鑹�) | +| pulse | 鑴夊啿 (鑷畾涔夐鑹�) | +| circle | 鍦嗗湀 (鑷畾涔夐鑹�) | +| eyes | 鐪肩潧 | +| surround | 鐜粫 | +| bounce | 寮硅烦 | +| radar | 闆疯揪 | +| gear | 榻胯疆 | +| love | 鐖卞績 | +| sun | 澶槼 | + +鎻掍欢棰勮: + + +> 灏忕▼搴忔悳绱�: 闆舵妧鏈� + +> 棰勮鐨勫皬绋嬪簭涓嶄竴瀹氳兘鍙婃椂鏇存柊褰撳墠鎻掍欢 -- Gitblit v1.8.0