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>

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

相关推荐
Luke Ewin4 小时前
ASR数据集采集系统 | ASR方言数据集采集系统 | ASR方言数据集采集系统 | 语音识别数据集采集系统
vue·springboot·语音识别·asr·asr数据集采集·asr方言数据集采集
沙振宇13 小时前
【Web】使用Vue3+PlayCanvas开发3D游戏(一)3D 立方体交互式游戏
游戏·3d·vue·vue3·playcanvas
鱼是一只鱼啊13 小时前
实战 | uni-app (Vue2) HBuilderX 项目改造为 CLI 项目,实现多客户多平台命令行自动化发布
微信小程序·vue·claude·vue-cli·.net8·自动化发布
南_山无梅落14 天前
从传统Web到API驱动:使用Django REST Framework重构智能合同审查系统
重构·django·vue·drf
PD我是你的真爱粉15 天前
API 请求封装(Axios + 拦截器 + 错误处理)
前端框架·vue
biyezuopinvip17 天前
基于Spring Boot的投资理财系统设计与实现(毕业论文)
java·spring boot·vue·毕业设计·论文·毕业论文·投资理财系统设计与实现
biyezuopinvip17 天前
基于Spring Boot的投资理财系统设计与实现(任务书)
java·spring boot·vue·毕业设计·论文·任务书·投资理财系统设计与实现
huohuopro17 天前
Vue3 Webview 转 Android 虚拟导航栏遮挡问题记录
android·vue
码界筑梦坊18 天前
332-基于XGBoost与SHAP的可穿戴设备亚健康风险识别系统
python·数据分析·flask·vue·毕业设计