vue2 精细级别判断图片页面

逻辑:listdata 获取 他的宽度 来减去当前一行可以容纳多少 image-item 然后在通过剩余的值去平均分给 image-item 剩余的值

javascript 复制代码
<template>
  <div class="Celebimagecharacter">
    <Row>
      <Col :span="12">
        <div class="basic-info-card-title" style="margin-top: 6px">
          已匹配源人物
          <span style="margin-left: 6px; color: rgb(153, 153, 153); font-size: 12px">{{ 0 }}</span>
        </div>
      </Col>
      <Col :span="12" style="text-align: right; padding-right: 32px">
        <Button type="primary" @click="openCelebimagecharacterDlog">全部</Button>
      </Col>
    </Row>
    <Row>
      <Col :span="24">
        <div ref="listdata" class="listdata">
          <div
            class="image-item"
            v-for="(item, index) in [1,2,3,4,5,5,5,4,5,5,5,5,5,5,5,5,5,5]"
            :key="index"
            :style="itemStyle"
          >
            <img
              :src="defaultImage"
              class="image-content"
              alt="人物图片"
              @error="handleImgError"
            />
          </div>
        </div>
      </Col>
    </Row>
    <!-- <CelebimagecharacterDlog
          ref="CelebimagecharacterDlog"
          :is-edited="editModal.relation"
          :base-ps-id="openTagBasePsId"
          :baseOpType="baseOpType"
          :create-source-ps-id="basePs.createSourcePsId"
          @showSourcePsDetail="showSourcePsDetail"
          @update-source-ps-list-total="handleSourcePsListUpdateTotal"
        ></CelebimagecharacterDlog> -->
    <!-- <CelebimagecharacterDlog ref="CelebimagecharacterDlog"></CelebimagecharacterDlog> -->
  </div>
</template>
<script>
import CelebimagecharacterDlog from './pop-up/CelebimagecharacterDlog.vue';
export default {
  components: {
    CelebimagecharacterDlog,
  },
  props: {
    basePsId: {
      type: String,
      default: '',
    },
    isEdited: {
      type: Boolean,
      default: false,
    },
    baseOpType: {
      type: String,
      default: 'NONE',
    },
    createSourcePsId: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      drawerVisible: false,
      sourcePsList: [],
      defaultImage: require('../../../../images/add.png'),
      // 调整:默认尺寸与最小尺寸保持一致
      itemWidth: 160,
      resizeTimer: null,
    };
  },
  computed: {
    itemStyle() {
      return {
        width: `${this.itemWidth}px`,
        // 保持1:1.5的宽高比(160x240)
        height: `${Math.floor(this.itemWidth * 1.5)}px`,
        // 调整CSS层防护与JS计算逻辑一致
        maxWidth: '200px',
        maxHeight: '300px',
        minWidth: '160px',  // 修改为160,确保最小尺寸
        minHeight: '240px', // 修改为240,确保最小尺寸
      };
    },
  },
  methods: {
    getSourceCodes() {},
    openCelebimagecharacterDlog() {
      this.$refs.CelebimagecharacterDlog.openDrawer();
    },
    handleImgError(e) {
      // 图片加载失败时降级显示,避免裂图
      e.target.style.objectFit = 'contain';
      e.target.style.padding = '20px';
      e.target.style.opacity = '0.5';
    },
    
    // 调整:动态计算item宽度,以160为基准
    calculateItemWidth() {
      const container = this.$refs.listdata;
      if (!container) return;
      
      const containerWidth = container.clientWidth;
      const gap = 12;
      const targetWidth = 160; // 目标宽度
      const safetyMargin = 4;  // 减少安全余量,避免过度压缩
      
      // 计算一行可容纳多少个160px的项
      const estimatedCount = Math.floor((containerWidth + gap) / (targetWidth + gap));
      const itemsPerRow = Math.max(1, estimatedCount);
      
      // 平均分配宽度,但确保不小于160
      const totalGapWidth = (itemsPerRow - 1) * gap;
      const availableWidth = containerWidth - totalGapWidth - safetyMargin;
      const calculatedWidth = Math.floor(availableWidth / itemsPerRow);
      
      // 应用边界限制:最小160,最大200
      this.itemWidth = Math.max(160, Math.min(200, calculatedWidth));
    },
    
    // 新增:防抖处理的resize监听
    handleResize() {
      clearTimeout(this.resizeTimer);
      // 调整:延长防抖时间,减少计算频率
      this.resizeTimer = setTimeout(() => {
        this.calculateItemWidth();
      }, 300);
    },
  },
  mounted() {
    this.getSourceCodes();
    // 新增:初始化时计算宽度
    this.$nextTick(() => {
      this.calculateItemWidth();
    });
    // 新增:监听窗口变化
    window.addEventListener('resize', this.handleResize);
  },
  beforeDestroy() {
    // 新增:清理事件监听
    window.removeEventListener('resize', this.handleResize);
    clearTimeout(this.resizeTimer);
  },
};
</script>
<style lang="less" scoped>
.listdata {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding: 8px 0;
}

.image-item {
  border-radius: 4px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  transition: all 0.3s ease;
  cursor: pointer;
  background-color: #f5f5f5;
  flex-shrink: 0;
  
  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    transform: translateY(-2px);
  }
}

.image-content {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
</style>

要稍微减少一点点 留一点点备用空间

相关推荐
呱牛do it2 天前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 5)
java·vue
无心使然云中漫步2 天前
Openlayers调用ArcGis地图服务之一 —— 地图切片(/tile)
前端·arcgis·vue·数据可视化
Python私教2 天前
我在开发 ShadcnVueAdmin 时发现了一个 Claude Code 超级插件
vue
无心使然云中漫步3 天前
Openlayers调用ArcGis地图服务之三 —— 要素查询(/query)
前端·arcgis·vue·数据可视化
呱牛do it3 天前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 3)
java·vue
呱牛do it3 天前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 4)
java·vue
无心使然云中漫步4 天前
Openlayers调用ArcGis地图服务之二 —— 动态地图(/export)
前端·arcgis·vue·数据可视化
神探小白牙4 天前
3D饼图,带背景图和自定义图例(threejs)
开发语言·前端·javascript·3d·vue
是吗乔治4 天前
vuetify实现excel表格粘贴效果
前端·vue.js·vue·excel
空中海4 天前
第五章:Pinia 状态管理
vue