From f26f29d84e0a68831a6af14dab3eec5500496d2e Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期三, 28 五月 2025 16:48:52 +0800 Subject: [PATCH] 初始化项目 --- uview-ui/components/u-image/u-image.vue | 267 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 267 insertions(+), 0 deletions(-) diff --git a/uview-ui/components/u-image/u-image.vue b/uview-ui/components/u-image/u-image.vue new file mode 100644 index 0000000..c729c3c --- /dev/null +++ b/uview-ui/components/u-image/u-image.vue @@ -0,0 +1,267 @@ +<template> + <view class="u-image" @tap="onClick" :style="[wrapStyle, backgroundStyle]"> + <image + v-if="!isError" + :src="src" + :mode="mode" + @error="onErrorHandler" + @load="onLoadHandler" + :lazy-load="lazyLoad" + class="u-image__image" + :show-menu-by-longpress="showMenuByLongpress" + :style="{ + borderRadius: shape == 'circle' ? '50%' : $u.addUnit(borderRadius) + }" + ></image> + <view + v-if="showLoading && loading" + class="u-image__loading" + :style="{ + borderRadius: shape == 'circle' ? '50%' : $u.addUnit(borderRadius), + backgroundColor: this.bgColor + }" + > + <slot v-if="$slots.loading" name="loading" /> + <u-icon v-else :name="loadingIcon" :width="width" :height="height"></u-icon> + </view> + <view + v-if="showError && isError && !loading" + class="u-image__error" + :style="{ + borderRadius: shape == 'circle' ? '50%' : $u.addUnit(borderRadius) + }" + > + <slot v-if="$slots.error" name="error" /> + <u-icon v-else :name="errorIcon" :width="width" :height="height"></u-icon> + </view> + </view> +</template> + +<script> +/** + * Image 鍥剧墖 + * @description 姝ょ粍浠朵负uni-app鐨刬mage缁勪欢鐨勫姞寮虹増锛屽湪缁ф壙浜嗗師鏈夊姛鑳藉锛岃繕鏀寔娣″叆鍔ㄧ敾銆佸姞杞戒腑銆佸姞杞藉け璐ユ彁绀恒�佸渾瑙掑�煎拰褰㈢姸绛夈�� + * @tutorial https://uviewui.com/components/image.html + * @property {String} src 鍥剧墖鍦板潃 + * @property {String} mode 瑁佸壀妯″紡锛岃瀹樼綉璇存槑 + * @property {String | Number} width 瀹藉害锛屽崟浣嶄换鎰忥紝濡傛灉涓烘暟鍊硷紝鍒欎负rpx鍗曚綅锛堥粯璁�100%锛� + * @property {String | Number} height 楂樺害锛屽崟浣嶄换鎰忥紝濡傛灉涓烘暟鍊硷紝鍒欎负rpx鍗曚綅锛堥粯璁� auto锛� + * @property {String} shape 鍥剧墖褰㈢姸锛宑ircle-鍦嗗舰锛宻quare-鏂瑰舰锛堥粯璁quare锛� + * @property {String | Number} border-radius 鍦嗚鍊硷紝鍗曚綅浠绘剰锛屽鏋滀负鏁板�硷紝鍒欎负rpx鍗曚綅锛堥粯璁� 0锛� + * @property {Boolean} lazy-load 鏄惁鎳掑姞杞斤紝浠呭井淇″皬绋嬪簭銆丄pp銆佺櫨搴﹀皬绋嬪簭銆佸瓧鑺傝烦鍔ㄥ皬绋嬪簭鏈夋晥锛堥粯璁� true锛� + * @property {Boolean} show-menu-by-longpress 鏄惁寮�鍚暱鎸夊浘鐗囨樉绀鸿瘑鍒皬绋嬪簭鐮佽彍鍗曪紝浠呭井淇″皬绋嬪簭鏈夋晥锛堥粯璁� false锛� + * @property {String} loading-icon 鍔犺浇涓殑鍥炬爣锛屾垨鑰呭皬鍥剧墖锛堥粯璁� photo锛� + * @property {String} error-icon 鍔犺浇澶辫触鐨勫浘鏍囷紝鎴栬�呭皬鍥剧墖锛堥粯璁� error-circle锛� + * @property {Boolean} show-loading 鏄惁鏄剧ず鍔犺浇涓殑鍥炬爣鎴栬�呰嚜瀹氫箟鐨剆lot锛堥粯璁� true锛� + * @property {Boolean} show-error 鏄惁鏄剧ず鍔犺浇閿欒鐨勫浘鏍囨垨鑰呰嚜瀹氫箟鐨剆lot锛堥粯璁� true锛� + * @property {Boolean} fade 鏄惁闇�瑕佹贰鍏ユ晥鏋滐紙榛樿 true锛� + * @property {String Number} width 浼犲叆鍥剧墖璺緞鏃跺浘鐗囩殑瀹藉害 + * @property {String Number} height 浼犲叆鍥剧墖璺緞鏃跺浘鐗囩殑楂樺害 + * @property {Boolean} webp 鍙敮鎸佺綉缁滆祫婧愶紝鍙寰俊灏忕▼搴忔湁鏁堬紙榛樿 false锛� + * @property {String | Number} duration 鎼厤fade鍙傛暟鐨勮繃娓℃椂闂达紝鍗曚綅ms锛堥粯璁� 500锛� + * @event {Function} click 鐐瑰嚮鍥剧墖鏃惰Е鍙� + * @event {Function} error 鍥剧墖鍔犺浇澶辫触鏃惰Е鍙� + * @event {Function} load 鍥剧墖鍔犺浇鎴愬姛鏃惰Е鍙� + * @example <u-image width="100%" height="300rpx" :src="src"></u-image> + */ +export default { + name: 'u-image', + props: { + // 鍥剧墖鍦板潃 + src: { + type: String, + default: '' + }, + // 瑁佸壀妯″紡 + mode: { + type: String, + default: 'aspectFill' + }, + // 瀹藉害锛屽崟浣嶄换鎰� + width: { + type: [String, Number], + default: '100%' + }, + // 楂樺害锛屽崟浣嶄换鎰� + height: { + type: [String, Number], + default: 'auto' + }, + // 鍥剧墖褰㈢姸锛宑ircle-鍦嗗舰锛宻quare-鏂瑰舰 + shape: { + type: String, + default: 'square' + }, + // 鍦嗚锛屽崟浣嶄换鎰� + borderRadius: { + type: [String, Number], + default: 0 + }, + // 鏄惁鎳掑姞杞斤紝寰俊灏忕▼搴忋�丄pp銆佺櫨搴﹀皬绋嬪簭銆佸瓧鑺傝烦鍔ㄥ皬绋嬪簭 + lazyLoad: { + type: Boolean, + default: true + }, + // 寮�鍚暱鎸夊浘鐗囨樉绀鸿瘑鍒井淇″皬绋嬪簭鐮佽彍鍗� + showMenuByLongpress: { + type: Boolean, + default: true + }, + // 鍔犺浇涓殑鍥炬爣锛屾垨鑰呭皬鍥剧墖 + loadingIcon: { + type: String, + default: 'photo' + }, + // 鍔犺浇澶辫触鐨勫浘鏍囷紝鎴栬�呭皬鍥剧墖 + errorIcon: { + type: String, + default: 'error-circle' + }, + // 鏄惁鏄剧ず鍔犺浇涓殑鍥炬爣鎴栬�呰嚜瀹氫箟鐨剆lot + showLoading: { + type: Boolean, + default: true + }, + // 鏄惁鏄剧ず鍔犺浇閿欒鐨勫浘鏍囨垨鑰呰嚜瀹氫箟鐨剆lot + showError: { + type: Boolean, + default: true + }, + // 鏄惁闇�瑕佹贰鍏ユ晥鏋� + fade: { + type: Boolean, + default: true + }, + // 鍙敮鎸佺綉缁滆祫婧愶紝鍙寰俊灏忕▼搴忔湁鏁� + webp: { + type: Boolean, + default: false + }, + // 杩囨浮鏃堕棿锛屽崟浣峬s + duration: { + type: [String, Number], + default: 500 + }, + // 鑳屾櫙棰滆壊锛岀敤浜庢繁鑹查〉闈㈠姞杞藉浘鐗囨椂锛屼负浜嗗拰鑳屾櫙鑹茶瀺鍚� + bgColor: { + type: String, + default: '#f3f4f6' + } + }, + data() { + return { + // 鍥剧墖鏄惁鍔犺浇閿欒锛屽鏋滄槸锛屽垯鏄剧ず閿欒鍗犱綅鍥� + isError: false, + // 鍒濆鍖栫粍浠舵椂锛岄粯璁や负鍔犺浇涓姸鎬� + loading: true, + // 涓嶉�忔槑搴︼紝涓轰簡瀹炵幇娣″叆娣″嚭鐨勬晥鏋� + opacity: 1, + // 杩囨浮鏃堕棿锛屽洜涓簆rops鐨勫�兼棤娉曚慨鏀癸紝鏁呴渶瑕佷竴涓腑闂村�� + durationTime: this.duration, + // 鍥剧墖鍔犺浇瀹屾垚鏃讹紝鍘绘帀鑳屾櫙棰滆壊锛屽洜涓哄鏋滄槸png鍥剧墖锛屽氨浼氭樉绀虹伆鑹茬殑鑳屾櫙 + backgroundStyle: {} + }; + }, + watch: { + src: { + immediate: true, + handler (n) { + if(!n) { + // 濡傛灉浼犲叆null鎴栬��''锛屾垨鑰協alse锛屾垨鑰卽ndefined锛屾爣璁颁负閿欒鐘舵�� + this.isError = true; + this.loading = false; + } else { + this.isError = false; + } + } + } + }, + computed: { + wrapStyle() { + let style = {}; + // 閫氳繃璋冪敤addUnit()鏂规硶锛屽鏋滄湁鍗曚綅锛屽鐧惧垎姣旓紝px鍗曚綅绛夛紝鐩存帴杩斿洖锛屽鏋滄槸绾补鐨勬暟鍊硷紝鍒欏姞涓妑px鍗曚綅 + style.width = this.$u.addUnit(this.width); + style.height = this.$u.addUnit(this.height); + // 濡傛灉鏄厤缃簡鍦嗗舰锛岃缃�50%鐨勫渾瑙掞紝鍚﹀垯鎸夌収榛樿鐨勯厤缃�� + style.borderRadius = this.shape == 'circle' ? '50%' : this.$u.addUnit(this.borderRadius); + // 濡傛灉璁剧疆鍦嗚锛屽繀椤昏鏈塰idden锛屽惁鍒欏彲鑳藉渾瑙掓棤鏁� + style.overflow = this.borderRadius > 0 ? 'hidden' : 'visible'; + if (this.fade) { + style.opacity = this.opacity; + style.transition = `opacity ${Number(this.durationTime) / 1000}s ease-in-out`; + } + return style; + } + }, + methods: { + // 鐐瑰嚮鍥剧墖 + onClick() { + this.$emit('click'); + }, + // 鍥剧墖鍔犺浇澶辫触 + onErrorHandler(err) { + this.loading = false; + this.isError = true; + this.$emit('error', err); + }, + // 鍥剧墖鍔犺浇瀹屾垚锛屾爣璁發oading缁撴潫 + onLoadHandler() { + this.loading = false; + this.isError = false; + this.$emit('load'); + // 濡傛灉涓嶉渶瑕佸姩鐢绘晥鏋滐紝灏变笉鎵ц涓嬫柟浠g爜锛屽悓鏃剁Щ闄ゅ姞杞芥椂鐨勮儗鏅鑹� + // 鍚﹀垯鏃犻渶fade鏁堟灉鏃讹紝png鍥剧墖渚濈劧鑳界湅鍒颁笅鏂圭殑鑳屾櫙鑹� + if (!this.fade) return this.removeBgColor(); + // 鍘熸潵opacity涓�1(涓嶉�忔槑锛屾槸涓轰簡鏄剧ず鍗犱綅鍥�)锛屾敼鎴�0(閫忔槑锛屾剰鍛崇潃璇ュ厓绱犳樉绀虹殑鏄儗鏅鑹诧紝榛樿鐨勭伆鑹�)锛屽啀鏀规垚1锛屾槸涓轰簡鑾峰緱杩囨浮鏁堟灉 + this.opacity = 0; + // 杩欓噷璁剧疆涓�0锛屾槸涓轰簡鍥剧墖灞曠ず鍒拌儗鏅叏閫忔槑杩欎釜杩囩▼鏃堕棿涓�0锛屽欢鏃朵箣鍚庡欢鏃朵箣鍚庨噸鏂拌缃负duration锛屾槸涓轰簡鑾峰緱鑳屾櫙閫忔槑(鐏拌壊) + // 鍒板浘鐗囧睍绀虹殑杩囩▼涓殑娣″叆鏁堟灉 + this.durationTime = 0; + // 寤舵椂50ms锛屽惁鍒欏湪娴忚鍣℉5锛岃繃娓℃晥鏋滄棤鏁� + setTimeout(() => { + this.durationTime = this.duration; + this.opacity = 1; + setTimeout(() => { + this.removeBgColor(); + }, this.durationTime); + }, 50); + }, + // 绉婚櫎鍥剧墖鐨勮儗鏅壊 + removeBgColor() { + // 娣″叆鍔ㄧ敾杩囨浮瀹屾垚鍚庯紝灏嗚儗鏅缃负閫忔槑鑹诧紝鍚﹀垯png鍥剧墖浼氱湅鍒扮伆鑹茬殑鑳屾櫙 + this.backgroundStyle = { + backgroundColor: 'transparent' + }; + } + } +}; +</script> + +<style scoped lang="scss"> +@import '../../libs/css/style.components.scss'; + +.u-image { + position: relative; + transition: opacity 0.5s ease-in-out; + + &__image { + width: 100%; + height: 100%; + } + + &__loading, + &__error { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + @include vue-flex; + align-items: center; + justify-content: center; + background-color: $u-bg-color; + color: $u-tips-color; + font-size: 46rpx; + } +} +</style> -- Gitblit v1.9.3