背景
众所周知,Android
中存在点九图,即将一张图片分为9块,四角固定,其他区域进行横向、纵向拉伸从而满足自适应大小的背景功能。
但是在前端Web
工程中如何实现这种功能呢?
这篇文章简化该问题:实现上下两部分固定百分比,中间自由拉伸。
已有技术
1.使用border-image
实现点九图 border-image
主要考虑兼容性问题
使用技术思考
-
如何让背景图动态根据内容伸缩(纯
CSS
)内容使用文档流书写,背景
div
使用绝对定位获取到父元素大小<!-- lang = vue --> <div class="vendor-outbox"><!-- position: relative --> <div class="flc fl-a-c" style="position: relative;"> <div class="vendor-list-box fl fl-w fl-j-c"> <template v-for="(item, index) in vendors"> <img v-if="item" class="vendor-item" @click="openLink(item)" :src="item.imgSrc" /> <div v-else class="vendor-item"></div> </template> </div> </div> <CustomBackgroundImage></CustomBackgroundImage> </div>
该代码为商户列表,使用flex布局一行两个,进行自动延伸
-
如何让图片仅展示一部分(纯
CSS
)使用
overflow:hidden + transfrom: translateY()
进行隐藏<!-- lang = vue --> <div class="custombackground-t"> <img :src="imgSrc" style="width: 100%;transform:translateY(50%)" /> </div>
.custombackground-t { overflow: hidden; position: absolute; top: 0; left: 0; right: 0; transform: translateY(-50%); }
-
如何让
div
获取到剩余部分大小在当前这个问题中,父元素的高度是不确定的,上部分的高度为图片高度的固定百分比,下部分的高度为图片的固定百分比,中间使用剩下的高度(暂未想到纯
CSS
的方式,目前使用JS
实现)先获取到图片实际宽高,然后动态进行计算
实际使用代码
<template>
<div class="ab-full" style="z-index: -1" ref="imgRef"> <!-- 该部分注意必须覆盖在实际内容之下 -->
<!-- 下面是中间模块 -->
<div
class="custombackground-c"
:style="{ top: `${imgRealHeight * topPercent / 100}px`, bottom: `${imgRealHeight * bottomPercent / 100}px` }"
>
<img
:src="imgSrc"
style="width: 100%;"
:style="{ transform: `translateY(-50%) scaleY(${centerScale})` }"
/>
</div>
<!-- 下面是top模块 -->
<div class="custombackground-t" :style="{ transform: `translateY(${topPercent - 100}%)` }">
<img
:src="imgSrc"
style="width: 100%;"
:style="{ transform: `translateY(${100 - topPercent}%)` }"
/>
</div>
<!-- 下面是bottom模块 -->
<div
class="custombackground-b"
:style="{ transform: `translateY(${100 - bottomPercent}%)` }"
>
<img
:src="imgSrc"
style="width: 100%;"
:style="{ transform: `translateY(${bottomPercent - 100}%)` }"
/>
</div>
</div>
</template>
<script>
export default {
name: 'CustomBackgroundImage',
props: {
imgSrc: { // 实际背景图url
type: String,
required: true
},
topPercent: { // 头部占图片的百分比
type: Number,
default: 50
},
bottomPercent: { // 底部占图片的百分比
type: Number,
default: 10
}
},
data() {
return {
width: 0, // 图片的实际宽度
height: 0, // 图片的实际高度
}
},
watch: {
imgSrc: { // 当图片url改变时,实时重新拉取图片的实际宽高
immediate: true,
handler(val) {
if (val) {
const i = new Image()
i.onload = (e) => {
this.width = i.width
this.height = i.height
i.onload = null
}
i.src = val
} else {
this.width = 0
this.height = 0
}
}
},
},
computed: {
imgRealHeight() { // 根据实际占用宽度,计算出实际占用高度(保持图片的长宽比不变)
const val = this.width && this.$refs.imgRef ? this.height * this.$refs.imgRef.clientWidth / this.width : 0
return val
},
centerScale() { // 计算出中间部分的缩放比率
if (!this.$refs.imgRef) {
this.centerScale = 1
} else {
const allPercent = (this.topPercent + this.bottomPercent) / 100
this.centerScale = (this.$refs.imgRef.clientHeight - this.imgRealHeight * allPercent) / (this.imgRealHeight * (1 - allPercent))
}
}
},
}
</script>
<style>
.custombackground-t {
overflow: hidden;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.custombackground-b {
overflow: hidden;
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
.custombackground-c {
overflow: hidden;
position: absolute;
left: 0;
right: 0;
}
</style>
初步想法,欢迎讨论,实现高兼容性下的背景缩放功能