提交 0ceb3bc6 编写于 作者: Q qiang

feat: App、H5 端 image 组件支持 heightFix 属性

上级 a5f5ddaa
...@@ -2,17 +2,25 @@ ...@@ -2,17 +2,25 @@
<uni-image v-on="$listeners"> <uni-image v-on="$listeners">
<div <div
ref="content" ref="content"
:style="modeStyle" :style="style"
/> />
<img :src="realImagePath"> <img :src="contentPath">
<v-uni-resize-sensor <v-uni-resize-sensor
v-if="mode === 'widthFix'" v-if="mode === 'widthFix' || mode === 'heightFix'"
ref="sensor" ref="sensor"
@resize="_resize" @resize="_fixSize()"
/> />
</uni-image> </uni-image>
</template> </template>
<script> <script>
function fixNumber (number) {
// fix: 解决 Chrome 浏览器上某些情况下导致 1px 缝隙的问题
if (typeof navigator && navigator.vendor === 'Google Inc.' && number > 10) {
number = Math.round(number / 2) * 2
}
return number
}
export default { export default {
name: 'Image', name: 'Image',
props: { props: {
...@@ -34,17 +42,15 @@ export default { ...@@ -34,17 +42,15 @@ export default {
return { return {
originalWidth: 0, originalWidth: 0,
originalHeight: 0, originalHeight: 0,
availHeight: '' originalStyle: { width: '', height: '' },
contentPath: ''
} }
}, },
computed: { computed: {
ratio () { ratio () {
return this.originalWidth && this.originalHeight ? this.originalWidth / this.originalHeight : 0 return this.originalWidth && this.originalHeight ? this.originalWidth / this.originalHeight : 0
}, },
realImagePath () { style () {
return this.$getRealPath(this.src)
},
modeStyle () {
let size = 'auto' let size = 'auto'
let position = '' let position = ''
const repeat = 'no-repeat' const repeat = 'no-repeat'
...@@ -59,6 +65,7 @@ export default { ...@@ -59,6 +65,7 @@ export default {
position = 'center center' position = 'center center'
break break
case 'widthFix': case 'widthFix':
case 'heightFix':
size = '100% 100%' size = '100% 100%'
break break
case 'top': case 'top':
...@@ -94,117 +101,140 @@ export default { ...@@ -94,117 +101,140 @@ export default {
break break
} }
return `background-position:${position};background-size:${size};background-repeat:${repeat};` return {
'background-image': this.contentPath ? `url("${this.contentPath}")` : 'none',
'background-position': position,
'background-size': size,
'background-repeat': repeat
}
} }
}, },
watch: { watch: {
src (newValue, oldValue) { src (newValue, oldValue) {
this._setContentImage()
this._loadImage() this._loadImage()
}, },
mode (newValue, oldValue) { mode (newValue, oldValue) {
if (oldValue === 'widthFix') { if (oldValue === 'widthFix' || oldValue === 'heightFix') {
this.$el.style.height = this.availHeight this._resetSize()
} }
if (newValue === 'widthFix' && this.ratio) { if (newValue === 'widthFix' || newValue === 'heightFix') {
this._fixSize() this._fixSize()
} }
} }
}, },
mounted () { mounted () {
this.availHeight = this.$el.style.height || '' this.originalStyle.width = this.$el.style.width || ''
this._setContentImage() this.originalStyle.height = this.$el.style.height || ''
if (!this.realImagePath) {
return
}
this._loadImage() this._loadImage()
}, },
beforeDestroy () {
this._clearImage()
},
methods: { methods: {
_resize () {
if (this.mode === 'widthFix') {
this._fixSize()
}
},
_fixSize () { _fixSize () {
const elWidth = this._getWidth() if (this.ratio) {
if (elWidth) { const $el = this.$el
let height = elWidth / this.ratio const rect = $el.getBoundingClientRect()
// fix: 解决 Chrome 浏览器上某些情况下导致 1px 缝隙的问题 if (this.mode === 'widthFix') {
if (typeof navigator && navigator.vendor === 'Google Inc.' && height > 10) { const width = rect.width
height = Math.round(height / 2) * 2 if (width) {
$el.style.height = fixNumber(width / this.ratio) + 'px'
}
} else if (this.mode === 'heightFix') {
const height = rect.height
if (height) {
$el.style.width = fixNumber(height / this.ratio) + 'px'
}
} }
this.$el.style.height = height + 'px'
} }
}, },
_setContentImage () { _resetSize () {
this.$refs.content.style.backgroundImage = this.src ? `url("${this.realImagePath}")` : 'none' this.$el.style.width = this.originalStyle.width
this.$el.style.height = this.originalStyle.height
},
_resetData () {
this.originalWidth = 0
this.originalHeight = 0
this.contentPath = ''
}, },
_loadImage () { _loadImage () {
const _self = this const realImagePath = this.$getRealPath(this.src)
const img = new Image() if (realImagePath) {
img.onload = function ($event) { const img = this._img = this._img || new Image()
_self.originalWidth = this.width img.onload = $event => {
_self.originalHeight = this.height this._img = null
this.originalWidth = img.width
this.originalHeight = img.height
if (_self.mode === 'widthFix') { this._fixSize()
_self._fixSize()
}
_self.$trigger('load', $event, { this.contentPath = realImagePath
width: this.width,
height: this.height this.$trigger('load', $event, {
}) width: img.width,
} height: img.height
img.onerror = function ($event) { })
_self.$trigger('error', $event, { }
errMsg: `GET ${_self.src} 404 (Not Found)` img.onerror = $event => {
}) this._img = null
this._resetData()
// 与微信小程序保持一致,保留之前样式
// this._resetSize()
this.$trigger('error', $event, {
errMsg: `GET ${this.src} 404 (Not Found)`
})
}
img.src = realImagePath
} else {
this._clearImage()
// 与微信小程序保持一致,保留之前样式
// this._resetData()
this._resetSize()
} }
img.src = this.realImagePath
}, },
_getWidth () { _clearImage () {
const computedStyle = window.getComputedStyle(this.$el) const img = this._img
const borderWidth = (parseFloat(computedStyle.borderLeftWidth, 10) || 0) + (parseFloat(computedStyle.borderRightWidth, if (img) {
10) || 0) img.onload = null
const paddingWidth = (parseFloat(computedStyle.paddingLeft, 10) || 0) + (parseFloat(computedStyle.paddingRight, 10) || img.onerror = null
0) this._img = null
return this.$el.offsetWidth - borderWidth - paddingWidth }
} }
} }
} }
</script> </script>
<style> <style>
uni-image { uni-image {
width: 320px; width: 320px;
height: 240px; height: 240px;
display: inline-block; display: inline-block;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
} }
uni-image[hidden] { uni-image[hidden] {
display: none; display: none;
} }
uni-image>div { uni-image > div {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
uni-image>img { uni-image > img {
-webkit-touch-callout: none; -webkit-touch-callout: none;
-webkit-user-select: none; -webkit-user-select: none;
-moz-user-select: none; -moz-user-select: none;
display: block; display: block;
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
opacity: 0; opacity: 0;
} }
uni-image>.uni-image-will-change { uni-image > .uni-image-will-change {
will-change: transform; will-change: transform;
} }
</style> </style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册