Vue3 + TS 百叶窗效果组件封装

OK,兄弟们!

今日忙里偷闲,我们来封装一个百叶窗效果组件,这个也是非常简单啊,我们简单写一下。

效果图

百叶窗

代码

index.vue

html 复制代码
<script setup lang="ts">
import Persiennes from "@/components/PersiennesView.vue";
// 导入图片
const webImgs = Object.keys(import.meta.glob("@/assets/images/web/*.jpg"), { eager: true }));
</script>

<template>
  <Persiennes :list="webImgs" />
</template>

PersiennesView.vue

html 复制代码
<script lang="ts" setup>
const props = defineProps<{ list: string[] }>();
const options = reactive({
  containerWidth: 1050, // 窗口宽度
  leaf: [192 * 3, 108 * 3], // 叶片尺寸 宽 高
});
const open = reactive({
  inx: -1, // 开叶
  show: false, // 叶开合
});
const leafLeft = (inx: number) => {
  // 开
  if (open.show) {
    // 剩余合叶宽度
    let gap = (options.containerWidth - options.leaf[0]) / (props.list.length - 1);
    // 开叶右侧的每叶 left + 一开叶宽度
    if (inx > open.inx) return gap * (inx - 1) + options.leaf[0];
    else return gap * inx;
  }
  // 合
  else return (options.containerWidth / props.list.length) * inx;
};
const mouseEnter = (inx: number) => {
  open.inx = inx;
  open.show = true;
};
const mouseLeave = () => (open.show = false);
</script>

<template>
  <div class="persiennes">
    <div class="persiennes-container">
      <div
        class="persiennes-leaf"
        v-for="(leaf, inx) in list"
        :key="inx"
        :style="{ left: `${leafLeft(inx)}px` }"
        @mouseenter="mouseEnter(inx)"
        @mouseleave="mouseLeave"
      >
        <img class="leaf" :src="leaf" alt="" />
        <div class="index">{{ inx + 1 }}</div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.persiennes {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: linear-gradient(
    to bottom right,
    #ffc09c,
    #fef0cd,
    #acfdee,
    #ecbcbc,
    #a6a0c0,
    #7098bb
  );
  .persiennes-container {
    position: relative;
    width: v-bind("options.containerWidth + 20 + 'px'");
    height: v-bind("options.leaf[1] + 20 + 'px'");
    margin: 200px auto;
    border: 10px dotted white;
    border-radius: 8px;
    box-shadow: 0 0 60px rgba($color: orangered, $alpha: 0.5);
    background-color: #fff;
    overflow: hidden;
    .persiennes-leaf {
      position: absolute;
      height: v-bind("options.leaf[1] + 'px'");
      border-radius: 4px;
      overflow: hidden;
      transition: 0.3s ease-in-out;
      .leaf {
        height: 100%;
      }
      .index {
        position: absolute;
        top: 10px;
        left: 10px;
        width: 36px;
        height: 36px;
        color: #fff;
        font-size: 24px;
        font-weight: 600;
        line-height: 28px;
        text-align: center;
        border: 4px solid #fff;
        border-radius: 50%;
      }
    }
  }
}
</style>
相关推荐
Highcharts.js27 分钟前
智能数据分析组件Orbit 正式发布与快速上手体验教程
前端·人工智能·信息可视化·数据分析系统·highcharts·orbit·智能可视化
螺丝钉tina1 小时前
[Playwright ][16]Playwright + TypeScript API 自动化测试实战:API测试
前端·javascript·typescript
小天源2 小时前
智叟云集系统 · 架构与职责分层
服务器·前端·数据库
Highcharts.js3 小时前
React 中原生支持使用 JSX 组件配置自定义表格 Highcharts Grid
前端·javascript·react.js·前端框架·jsx·highcharts·自定义表格
薛定谔的猫-菜鸟程序员4 小时前
Electron开发超详细教程(从入门到放弃)
前端·javascript·electron
最强小杰4 小时前
DeepSeek V4 Flash + Codex CLI 接入教程:原生 Responses API 适配,从配置到跑通收藏这篇就够了(2026)
java·前端·python·ai
静水leo5 小时前
使用 Whistle 拦截接口并模拟后端响应
前端
掘金者阿豪5 小时前
SQL Server数据迁移完成后,凌晨的数据库告警该怎么查?
前端·后端
小郎君6585 小时前
Vue 多标签页的加载态设计:为什么我没有用 Suspense 实现 PageLoading
vue.js·算法
JudithHuang5 小时前
React 嵌套路由与布局
前端·react.js·arcgis·react·react router