aiceps-mobile/src/components/scaleBox/index.vue

135 lines
3.1 KiB
Vue

<template>
<div
ref="ScaleBox"
v-dragbox
class="ScaleBox"
:style="{
width: boxWidth + 'px',
height: boxHeight + 'px'
}"
>
<slot v-if="inited" />
</div>
</template>
<script>
import { createDebounce } from '@/utils'
export default {
name: 'ScaleBox',
props: {
/**
* 使用父元素的宽高计算缩放比例
*/
useParentSize: {
type: Boolean,
default: () => {
return false
}
},
width: {
type: Number,
default: () => {
return 0
}
},
height: {
type: Number,
default: () => {
return 0
}
},
// width/height
screenRatio: {
type: Array,
default: () => {
return []
}
}
},
emits: ['inited'],
data() {
return {
boxHeight: 0,
boxWidth: 0,
inited: false
}
},
mounted() {
this.setScale()
window.addEventListener('resize', createDebounce(this.setScale, 300))
},
methods: {
getRatio() {
const ratioValue = this.useParentSize ? this.$el.parentElement.clientWidth / this.$el.parentElement.clientHeight : window.innerWidth / window.innerHeight
let result = 0
let minDiff = Infinity
for (const ratio of this.screenRatio) {
if (Math.abs(ratio - ratioValue) < minDiff) {
result = ratio
minDiff = Math.abs(ratio - ratioValue)
}
}
return result
},
setScale() {
// 获取到缩放比例,设置它
let { width, height } = this
const ratio = this.getRatio()
if (ratio && width && !height) {
height = width / ratio
}
if (ratio && !width && height) {
width = ratio * height
}
this.boxHeight = height
this.boxWidth = width
const wh = (this.useParentSize ? this.$el.parentElement.clientHeight : window.innerHeight) / height
const ww = (this.useParentSize ? this.$el.parentElement.clientWidth : window.innerWidth) / width
const scale = ww < wh ? ww : wh
if (this.$refs.ScaleBox) {
this.$refs.ScaleBox.style.setProperty('--scale', scale)
}
this.$nextTick(() => {
let clientHeight = this.$el.clientHeight
let clientWidth = this.$el.clientWidth
const timer = setInterval(() => {
if (this.$el.clientHeight && this.$el.clientWidth) {
if (this.$el.clientHeight === clientHeight && this.$el.clientWidth === clientWidth) {
if (!this.inited) {
this.$nextTick(() => {
this.$emit('inited')
})
}
this.inited = true
clearInterval(timer)
} else {
clientHeight = this.$el.clientHeight
clientWidth = this.$el.clientWidth
}
}
}, 1000)
})
}
}
}
</script>
<style lang="scss" scoped>
#ScaleBox {
--scale: 1;
}
.ScaleBox {
position: absolute;
transform: scale(var(--scale)) translate(-50%, -50%);
transform-origin: 0 0;
left: 50%;
top: 50%;
transition: 0.3s;
z-index: 999;
// background: rgba(255, 0, 0, 0.3);
}
</style>