泳道+flex布局)

<script setup>
import {computed, ref} from "vue";

const images = ref([
  {
    type: '环境传感器',
    name: '环境传感器',
    modelName: 'env_data',
    dateLabel: '环境数据',
    data: [
      {fieldName: 'temperature', fieldLabel: '温度', unit: '℃'},
      {fieldName: 'humidity', fieldLabel: '湿度', unit: '%'},
      {fieldName: 'co2', fieldLabel: '二氧化碳', unit: 'ppm'},
      {fieldName: 'pm25', fieldLabel: 'PM2.5', unit: 'μg/m3'},
      {fieldName: 'pm10', fieldLabel: 'PM10', unit: 'μg/m3'},
      {fieldName: 'no2', fieldLabel: 'NO2', unit: 'μg/m3'},
      {fieldName: 'so2', fieldLabel: 'SO2', unit: 'μg/m3'},
      {fieldName: 'o3', fieldLabel: 'O3', unit: 'μg/m3'},
    ]
  },
  {
    type: '水表',
    name: '水表',
    modelName: 'water_data',
    dateLabel: '水表数据',
    data: [
      {fieldName: 'water_flow', fieldLabel: '水流量', unit: 'L/min'},
      {fieldName: 'water_level', fieldLabel: '水位', unit: 'cm'},
    ]
  },
  {
    type: '电表',
    name: '电表',
    modelName: 'electricity_data',
    dateLabel: '电表数据',
    data: [
      {fieldName: 'electricity_flow', fieldLabel: '电流流量', unit: 'A'},
      {fieldName: 'voltage', fieldLabel: '电压', unit: 'V'},
    ]
  },
  {
    type: '水表',
    name: '水表',
    modelName: 'water_data',
    dateLabel: '水表数据',
    data: [
      {fieldName: 'water_flow', fieldLabel: '水流量', unit: 'L/min'},
      {fieldName: 'water_level', fieldLabel: '水位', unit: 'cm'},
    ]
  }
])
const laneCount = ref(2) // 指定泳道的数量

// 计算属性:计算每个模块分布到各个泳道,一列表示一条泳道
const lanes = computed(() => {
  const lanes = new Array(laneCount.value).fill().map(() => [])

  images.value.forEach((image, index) => {
    const laneIndex = index % laneCount.value
    lanes[laneIndex].push(image)
  })

  return lanes
})

// 计算属性:泳道的宽度
const laneWidth = computed(() => {
  return 100 / laneCount.value
})
</script>

<template>
  <div class="waterfall-container">
    <!-- 创建每个泳道,lanes 数组中的每个元素都代表一个泳道 -->
    <div
      v-for="(lane, index) in lanes"
      :key="index" class="lane"
      :style="{ width: laneWidth + '%' }">
      <!-- 创建每个瀑布流项,flowItem 模块的内容和高度 -->
      <el-card
        v-for="(flowItem, flowIndex) in lane"
                :key="flowIndex" class="item"
                :style="{ height: flowItem.height + 'px' }">
        <template #header>
          <div class="card-header">
            <span> 传感器类型:{{ flowItem.type }}</span>
            <span> 传感器设备:{{ flowItem.name }}</span>
            <span> 数据表:{{ flowItem.modelName }}</span>
            <span> 数据别名:{{ flowItem.dateLabel }}</span>
          </div>
        </template>
        <div class="main">
          <div v-for="item in flowItem.data" :key="item" class="content">
            <span>key值:{{item.fieldName}}</span>
            <span>数据表字段:{{item.fieldLabel}}</span>
            <span>单位:{{item.unit}}</span>
          </div>
        </div>
      </el-card>
    </div>
  </div>
</template>

<style scoped lang="scss">
.waterfall-container {
  display: flex;
  flex-wrap: wrap;
}

.lane {
  display: flex;
  flex-direction: column;
}

.item {
  margin: 6px;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  transition: transform 0.3s ease, box-shadow 0.3s ease;

  &:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
  }
}

.card-header {
  background-color: #f4f7fa;
  padding: 10px 15px;
  font-size: 14px;
  font-weight: bold;
}

.card-header span {
  display: block;
  margin-bottom: 5px;
  color: #333;
}
.main {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.content {
  border: 1px solid #b5efed;
  border-radius: 8px;
  padding: 6px;
  width: calc(33.3% - 4px);
  display: flex;
  flex-direction: column;
  background-color: #f9f9f9;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: background-color 0.3s ease, box-shadow 0.3s ease;

  &:hover {
    background-color: #f0f8ff;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }
}

.content span {
  display: flex;
  margin-bottom: 8px;
  color: #666;
  line-height: 1.5;
}

.content span:first-child {
  font-weight: bold;
  color: #333;
}

.content span:last-child {
  color: #1a73e8;
}

</style>

2. v-masonry
2.1 什么是v-masonry
Vue-Masonry 是一个用于 Vue.js 的瀑布流布局插件,它基于 Masonry 布局库,可以帮助你创建灵活的、瀑布流风格的网格布局。这种布局常用于展示不同高度的项目,使它们以整齐的方式排列在网页上。

2.2 v-masonry主要特点和用法
易于使用:Vue-Masonry 提供了简单的 Vue 组件,只需将项目包装在 标签内,就可以轻松地实现瀑布流布局。

自适应布局:Vue-Masonry 自动处理项目的高度不一致,确保它们在网格中以最佳方式排列。

可定制性:你可以通过设置属性来自定义布局,例如指定列数、列之间的间距、项目之间的间距等。

动态添加项目:你可以在 Vue 组件中动态添加或移除项目,Vue-Masonry 会自动重新排列项目,而无需手动干预。

响应式设计:Vue-Masonry 可以适应不同屏幕尺寸,从而在移动设备和桌面设备上都具有良好的显示效果。

支持过渡动画:你可以通过 Vue 的过渡动画系统为项目添加过渡效果,使项目的添加和移除更加平滑。
2.3 安装及使用
                 

npm install vue-masonry --save
 

yarn add vue-masonry

      导入

// 在你的组件中导入 Vue Masonry
import VueMasonry from 'vue-masonry';

// 注册 Vue Masonry 插件
Vue.use(VueMasonry);

使用

<template>
  <div v-masonry class="container" :options="masonryOptions">
    <div
        v-masonry-tile
        v-for="(item, index) in items"
        :key="index"
        :style="{
          width: `${100 / imagePerRow}%`
        }"
    >
        <!-- 你的元素内容 -->
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        // 你的项目数据
      ],
      imagePerRow: 3, // 设置每行显示的图片数量,可以根据需要更改
      masonryOptions: {
        // 可以在此添加其他配置选项
      },
    };
  }
}
</script>


参考文献

vue-masonry#readme

参考文章链接:https://blog.youkuaiyun.com/qq_51137480/article/details/133858816

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值