图片等比例缩放

最近遇到一个需求, 要求项目中的轮播图随着屏幕大小,等比例缩放。实现思路是使用自定义指令去修改图片的宽度和高度。在细节处理上我们给图面设置了最大的宽高1350*450 按3:1的比例显示。图片无法覆盖到的区域使用背景色填充。

代码片段

图片的宽高徐亚修改,轮播图的容器高度也需要修改。否则高度小于450的时候图片会变形。我这是使用的页面较多, 所以在APP.vue页面去获取高度并传递给子页面进行修改, 使用provide和inject来实现

app.vue文件

  provide(){ 、
    return {
      bannerHeight: ()=> ({
        height:this.swiperHeight
      })
    }
  },
  data(){
    return {
      swiperHeight:450
    }
  },
  mounted(){
    const that = this
     window.addEventListener('resize', function() {
        that.setHeight();
      }, false);
  },
  methods:{
    setHeight(){
      const  width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
      this.swiperHeight = width >= 1350 ? 450: ((width - 140) / 1350) * 450
    }
  },
  destroyed(){
    const that = this
     window.removeEventListener('resize', function() {
        that.setHeight();
      }, false);
  }

使用页面html部分

 <el-carousel :height="`${actHeight}px`">
        <el-carousel-item v-imgScale v-for="(item, index) in swiperList" :key="index" :style="{ backgroundColor: `#${item.bgColor}` }">
          <img :src="item.imageUrl" alt="" @click="skipNews(item)">
        </el-carousel-item>
      </el-carousel>

js部分

// 引入 自定义组件
import { imgScale } from '@/utils/directives'

export default {

  inject:['bannerHeight'],
  directives: {
    imgScale
  },
  computed: {
    actHeight() {
      return this.bannerHeight().height;
    },
  },
  }

自定义指令

/**
 * @params cover | 修饰符,缩放类型:cover表示缩放至铺满父元素并居中,contain表示图片缩放至能在父元素看到图片所有内容并居中
 * @params stop | 修饰符,默认是false,有stop: true修饰符代表不处理图片
 * @params options :{    
 *  imgWidth : Number | 图片的宽度width,单位px    
 *  imgHeight :Number | 图片的高度height,单位px   
 *  panelWidth :Number | 图片容器的宽度,单位px    
 *  panelHeight :Number | 图片容器的高度,单位px      
 *  scale :Boolean | 默认是true ,是否缩放    
 *  resizeType :String |  缩放类型:contain | cover
 *  unit: String | 宽高的单位,默认‘px’ 
 * }
 */
 export const imgScale = {
    inserted(el, binding, vnode) {
        let isJson = (obj) => {
            return typeof obj === 'object' && Object.prototype.toString.call(obj) == "[object Object]"
        }
        let imgScale = (options) => {
            let defaults = {
                imgWidth: el.width|| 1350,
                imgHeight: el.height || 450,
                panelWidth: el?.parentNode?.offsetWidth,
                panelHeight: el?.parentNode?.offsetHeight ,
                scale: !binding?.modifiers?.stop,
                resizeType: binding?.modifiers?.contain ? "contain" : "cover",
                unit: 'px'
            }
            options = isJson(options) ? options : {}
            options = Object.assign({}, defaults, options || {})
            if (options.scale) {
                if (options.imgWidth > 0 && options.imgHeight > 0) {
                    // el.parentNode.style.width = options.panelWidth + options.unit
                    // el.parentNode.style.maxHeight = options.panelHeight + options.unit
                    switch (options.resizeType) {
                        case "cover":
                            // 默认 cover 方式,处理后的宽或高超过容器的宽高,用margin负值使之上下或左右居中
                            // 如果图片比容器扁
                            if (options.imgWidth / options.imgHeight >= options.panelWidth / options.panelHeight) {
                                let toWidth = options.imgWidth * (options.panelHeight / options.imgHeight)
                                el.style.width = toWidth > 1350?1350:toWidth + options.unit
                                el.style.height = options.panelHeight> 450?450:options.panelHeight + options.unit//等比缩放,保持清晰度
                            }
                            // 如果图片比容器瘦
                            else {
                                let toHeight = options.imgHeight * (options.panelWidth / options.imgWidth)
                                el.style.width = options.panelWidth > 1350?1350:options.panelWidth + options.unit
                                el.style.height = toHeight > 450?450:toHeight + options.unit//等比缩放,保持清晰度
                            }
                            break
                        case "contain":
                            // contain方式,处理后的宽或高不足容器的宽高,用margin正值使之上下或左右居中
                            if (options.imgWidth / options.imgHeight >= options.panelWidth / options.panelHeight) {
                                let toHeight = (options.imgHeight * (options.panelWidth / options.imgWidth))
                                el.style.width = options.panelWidth > 1350?1350:options.panelWidth + options.unit
                                el.style.height = toHeight > 450?450:toHeight + options.unit
                            } else {
                                let toWidth = options.imgWidth * (options.panelHeight / options.imgHeight)
                                el.style.width = toWidth > 1350?1350:toWidth + options.unit
                                el.style.height = options.panelHeight> 450?450:options.panelHeight + options.unit
                            }
                            break
                    }
                }
            }
        }
        //已经加载过了
        if (el.complete && el.width > 0) {
            imgScale(binding.value)
            return
        }
        //没加载过则监听load事件
        el.addEventListener("load", () => {
            imgScale(binding.value)
        }, false)
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值