vue组件封装——固定宽高比的容器(2种方法:纯CSS实现 + JS实现)

简介: vue组件封装——固定宽高比的容器(2种方法:纯CSS实现 + JS实现)

什么是固定宽高比容器?

定义:

无论浏览器窗口或页面元素如何变化,容器的宽度和高度永远保持固定的比例,如16:9。

应用场景:

如大屏自适应,内部元素对容器宽高比依赖很高的复杂模块布局等。

纯CSS实现固定宽高比的容器

原理

  • padding-top的值为百分比时,最终padding-top的计算值 = 百分比 * 当前元素宽度的计算值,从而通过padding-top将容器撑开。
  • 为容器添加样式 box-sizing: border-box; 则容器的高度 = padding-top的计算值,从而实现容器高度根据容器的宽度按百分比自适应变化。
  • 使用“子绝父相”,让容器中的内容完全覆盖容器。

cssRatioContainer.vue

<template>
  <div class="box" :style="ratioStyle">
    <div class="content" :style="contentStyle">
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    ratio: {
      type: Number,
      default: 1,
    },
    overflow: {
      type: String,
      default: "auto",
    },
    overflowX: {
      type: String,
    },
    overflowY: {
      type: String,
    },
  },
  computed: {
    ratioStyle() {
      let ratio = (1 / this.ratio) * 100;
      if (ratio == null || Number.isNaN(ratio)) {
        ratio = 100;
      }
      if (typeof ratio !== "string" || !ratio.endsWith("%")) {
        ratio = ratio + "%";
      }
      return `padding-top: ${ratio};`;
    },

    contentStyle() {
      const styles = [];
      if (this.overflow) {
        styles.push("overflow:" + this.overflow);
      }
      if (this.overflowX) {
        styles.push("overflow-x:" + this.overflowX);
      }
      if (this.overflowY) {
        styles.push("overflow-y:" + this.overflowY);
      }
      return styles.join(";");
    },
  },
};
</script>

<style scoped>
.box {
  position: relative;
  box-sizing: border-box;
}
.content {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
</style>

JS实现固定宽高比的容器

原理

  • 通过js获取容器的宽度计算值后,按宽高比计算出容器的高度,并赋值给容器。

jsRatioContainer.vue

<template>
  <div id="jsRatioContainerBox" class="box" :style="contentStyle">
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    ratio: {
      type: Number,
      default: 1,
    },
    overflow: {
      type: String,
      default: "auto",
    },
    overflowX: {
      type: String,
    },
    overflowY: {
      type: String,
    },
  },
  data() {
    return {
      myHeight: "",
    };
  },
  computed: {
    contentStyle() {
      const styles = [];
      if (this.myHeight) {
        styles.push("height:" + this.myHeight);
      }
      if (this.overflow) {
        styles.push("overflow:" + this.overflow);
      }
      if (this.overflowX) {
        styles.push("overflow-x:" + this.overflowX);
      }
      if (this.overflowY) {
        styles.push("overflow-y:" + this.overflowY);
      }
      return styles.join(";");
    },
  },
  mounted() {
    this.setHeight();
    window.addEventListener("resize", () => {
      this.setHeight();
    });
  },
  watch: {
    ratio() {
      this.setHeight();
    },
  },
  methods: {
    // 根据宽高比和当前宽度,设置最终的高度
    setHeight() {
      this.$nextTick(() => {
        let myDom = document.getElementById("jsRatioContainerBox");
        let width = window.getComputedStyle(myDom)["width"];
        this.myHeight =
          Number(width.replace("px", "")) * (1 / this.ratio) + "px";
      });
    },
  },
};
</script>

<style scoped>
.box {
  width: 100%;
}
</style>

使用范例

<template>
  <div class="father">
    <h2>CSS实现固定宽高比的容器</h2>
    <CssRatioContainer
      ref="CssRatioContainer"
      id="CssRatioContainer"
      :ratio="ratioWidth / ratioHeight"
    >
      <div class="itemBox" v-for="item in 100" :key="item">段落{{ item }}</div>
    </CssRatioContainer>
    <p>容器的宽度为:{{ mySize.width }}</p>
    <p>容器的高度为:{{ mySize.height }}</p>
    <label>容器的宽高比:</label>
    <input
      class="inputStyle"
      type="number"
      v-model="ratioWidth"
      @input="getSize"
    />
    <input
      class="inputStyle"
      type="number"
      v-model="ratioHeight"
      @input="getSize"
    />
    <h2>JS实现固定宽高比的容器</h2>
    <JsRatioContainer :ratio="ratioWidth / ratioHeight">
      <div class="itemBox" v-for="item in 100" :key="item">段落{{ item }}</div>
    </JsRatioContainer>
  </div>
</template>
<script>
import CssRatioContainer from "./cssRatioContainer.vue";
import JsRatioContainer from "./jsRatioContainer.vue";
export default {
  components: { CssRatioContainer, JsRatioContainer },
  mounted() {
    this.getSize();
    window.addEventListener("resize", () => {
      this.getSize();
    });
  },
  methods: {
    getSize() {
      this.$nextTick(() => {
        let myDom = document.getElementById("CssRatioContainer");
        let myComputedStyle = window.getComputedStyle(myDom);
        this.$set(this.mySize, "height", myComputedStyle.height);
        this.$set(this.mySize, "width", myComputedStyle.width);
      });
    },
  },

  data() {
    return {
      mySize: {},
      ratioWidth: 6,
      ratioHeight: 1,
    };
  },
};
</script>
<style scoped>
.father {
  max-width: 1200px;
  margin: 20px;
}
.itemBox {
  background: red;
  border: 1px solid yellow;
}
.inputStyle {
  width: 60px;
  text-align: center;
}
</style>

目录
相关文章
|
1天前
|
JavaScript
网页CAD(JS Vue 预览dwg)如何二次开发常用的CAD编辑功能
```markdown # CAD网页编程概览 - 使用mxcad库,实现CAD操作如删除、复制、镜像、移动和旋转。 - `erase()`方法删除实体,`clone()`配合`transformBy()`用于复制和编辑。 - `mirror()`和`transformBy(setMirror)`执行镜像操作,基于参考线。 - `move()`和`transformBy(setToTranslation)`实现移动功能。 - `rotate()`和`transformBy(setToRotation)`进行旋转,支持角度输入。 ```
网页CAD(JS Vue 预览dwg)如何二次开发常用的CAD编辑功能
|
1天前
|
前端开发 JavaScript
文本,wangEditor5展示HTML无样式,wangEditor5如何看源码,Ctrl + U看CSS文件,代码高亮,Prism.js可以实现,解决方法,参考网页源代码的写法
文本,wangEditor5展示HTML无样式,wangEditor5如何看源码,Ctrl + U看CSS文件,代码高亮,Prism.js可以实现,解决方法,参考网页源代码的写法
|
1天前
|
JSON JavaScript 数据格式
vue 绘制波形图 wavesurfer.js (音频/视频) 【实用教程】
vue 绘制波形图 wavesurfer.js (音频/视频) 【实用教程】
16 3
|
1天前
|
JavaScript
js 数组移除指定元素【函数封装】(含对象数组移除指定元素)
js 数组移除指定元素【函数封装】(含对象数组移除指定元素)
2 0
|
2天前
|
JavaScript
Eslint.js文件Vue中没有,如何修改配置
Eslint.js文件Vue中没有,如何修改配置
|
前端开发 容器 Web App开发
用纯 CSS 创作一个在容器中反弹的小球
效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。 https://codepen.io/comehope/pen/jKVbyE 可交互视频教程 此视频是可以交互的,你可以随时暂停视频,编辑视频中的代码。
798 0
|
8天前
|
安全 JavaScript
旋转木马轮播图 html+css+js
旋转木马轮播图 html+css+js
|
8天前
|
移动开发 前端开发 JavaScript
HTML5+CSS3+JavaScript网页实战
HTML5+CSS3+JavaScript网页实战
|
13天前
|
前端开发
HTML+CSS练习小项目——百叶窗
HTML+CSS练习小项目——百叶窗
|
11天前
|
XML 前端开发 JavaScript
HTML、CSS、JavaScript有什么区别
HTML、CSS、JavaScript有什么区别