You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
4.3 KiB
Vue

1 year ago
<!-- 长宽比例组件 -->
<template>
<view class="tm-ratio--wk d-inline-block">
<view class="tm-ratio" :class="[color,black=='true'||black===true?'bk':'']" :style="style">
<slot name="default" :data="style"></slot>
</view>
</view>
</template>
<script>
/**
*
* 长宽比例组件
* @property {String} ratio = [] 默认4/3比例
* @property {Number | String} width = [] 默认NaN默认会根据父组件自动计算宽高指定宽
* @property {Number | String} height = [] 默认NaN默认会根据父组件自动计算宽高指定高
* @property {String} color = [white] 默认white背景色主题名称
* @property {Boolean} black = [true|false] 默认false暗黑模式
* @example <tm-ratio height="240" ratio="16/9" ><template v-slot="{data}">{{data.width}}</template></tm-ratio>
*
*/
export default {
props: {
// 比例如:16/9,4/3,5/4
ratio: {
type: String,
default: '4/3'
},
width: {
type: Number | String,
default: NaN
},
height: {
type: Number | String,
default: NaN
},
color: {
type: String,
default: "white"
},
black: {
type: String|Boolean,
default: false
},
},
data() {
return {
style: '',
style_obj:{}
};
},
mounted() {
let t = this;
const query = uni.createSelectorQuery().in(this);
query.select('.tm-ratio--wk').boundingClientRect().exec(dsd => {
var ds = dsd[0];
let wsys = uni.getSystemInfoSync();
let maxWidth = wsys.windowWidth - ds.left - ds.right;
if (maxWidth <= 0) maxWidth = ds.width;
query.select('.tm-ratio').boundingClientRect(data => {
let rt = t.ratio;
if (!rt || rt.indexOf('/') == -1 || rt.split('/').length !== 2) {
rt = '4/3'
}
let ro = rt.split('/');
let ws = !isNaN(parseInt(ro[0])) ? parseInt(ro[0]) : 4;
let hs = !isNaN(parseInt(ro[1])) ? parseInt(ro[1]) : 3;
let bl = hs / ws;
if (isNaN(t.width) && isNaN(t.height)) {
t.style ={
width: data.width + 'px',
height: data.width * bl + 'px',
minHeight: data.width + 'px',
minWidth: data.width + 'px'
};
t.style_obj = uni.$tm.objToString({
width: data.width,
height: data.width * bl,
minHeight: data.width ,
minWidth: data.width
});
return;
}
if (!isNaN(t.width) && isNaN(t.height)) {
let width = uni.upx2px(t.width)
t.style = {
width: (width > maxWidth ? maxWidth : width) + 'px',
height: width * bl + 'px',
minHeight: width * bl + 'px',
minWidth: (width > maxWidth ? maxWidth : width) + 'px'
};
t.style_obj = uni.$tm.objToString({
width: (width > maxWidth ? maxWidth : width) ,
height: width * bl,
minHeight: width * bl ,
minWidth: (width > maxWidth ? maxWidth : width)
});
return;
}
if (isNaN(t.width) && !isNaN(t.height)) {
let height = uni.upx2px(t.height)
let xsw = height / bl;
t.style = {
width: (xsw > maxWidth ? maxWidth : xsw) + 'px',
height: height + 'px',
minHeight: height + 'px',
minWidth: (xsw > maxWidth ? maxWidth : xsw) + 'px'
};
t.style_obj = uni.$tm.objToString({
width: (xsw > maxWidth ? maxWidth : xsw) ,
height: height,
minHeight: height ,
minWidth: (xsw > maxWidth ? maxWidth : xsw)
});
return;
}
// 如果同时提供了宽高,那么按比例。以最长边为第一值。
if (!isNaN(t.width) && !isNaN(t.height)) {
// 第一值,默认为宽度。
let xnh = uni.upx2px(t.width);
let isW = true;
if (xnh < uni.upx2px(t.height)) {
xnh = uni.upx2px(t.height);
isW = false;
}
let w = 0;
let h = 0;
if (isW) {
w = xnh;
h = xnh * bl;
} else {
w = xnh / bl;
h = xnh;
}
t.style = {
width: w + 'px',
height: h + 'px',
minHeight: h + 'px',
minWidth: w + 'px'
};
t.style_obj = uni.$tm.objToString({
width: w ,
height: h ,
minHeight: h ,
minWidth: w
});
return;
}
}).exec();
})
}
}
</script>
<style lang="scss" scoped>
</style>