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

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

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