如何在Quasar框架中实现可点击图片的全屏展示功能
纯Quasar实现图片画廊的全屏预览功能
Quasar没有单独的overlay组件,但可以通过QDialog实现全屏图片预览的效果,同时用QBtn配合Quasar的布局类添加右下角的查看按钮。以下是修改后的完整代码:
<template> <div class="service-block q-pa-lg text-center column no-wrap flex-center block-wrapper" id="RecentWork"> <h2 class="text-h2 text-weight-bolder text-dark q-mb-xs">RECENT WORK</h2> <h6 class="text-h6 text-weight-light text-dark q-my-none" style="max-width: 800px;">We are a one stop shop for all your home remodeling needs. Check out some of our recent jobs below!</h6> </div> <q-tabs v-model="tab" outside-arrows mobile-arrows inline-label active-color="primary" indicator-color="primary" class="text-grey-7" > <q-tab name="decks" label="DECKS" class="q-pa-md q-ma-md menu-item" active-class="active-menu-item"></q-tab> <q-tab name="interior" label="INTERIOR REMODELING" class="q-pa-md q-ma-md menu-item" active-class="active-menu-item"></q-tab> <q-tab name="exterior" label="EXTERIOR REMODELING" class="q-pa-md q-ma-md menu-item" active-class="active-menu-item"></q-tab> <q-tab name="new" label="NEW CONSTRUCTION" class="q-pa-md q-ma-md menu-item" active-class="active-menu-item"></q-tab> </q-tabs> <q-tab-panels v-model="tab" animated> <q-tab-panel name="decks"> <div class="row q-pa-md block-wrapper text-center q-col-gutter-md" style="margin-bottom:100px;"> <div v-for="item in imagesArray[0]['decks']" :key="item.id" class="col-sm-4 col-xs-12"> <!-- 相对定位容器,用于放置按钮 --> <div class="relative"> <q-img :src="item.link" :ratio="16/9" class="rounded-borders"/> <!-- 右下角的查看按钮 --> <q-btn icon="zoom_in" size="sm" round color="white" text-color="black" class="absolute bottom-2 right-2 bg-opacity-80" @click="openPreview(item.link)" /> </div> </div> </div> </q-tab-panel> <q-tab-panel name="interior"> <div class="row q-pa-md block-wrapper text-center q-col-gutter-md" style="margin-bottom:100px;"> <div v-for="item in imagesArray[0]['interior']" :key="item.id" class="col-sm-4 col-xs-12"> <div class="relative"> <q-img :src="item.link" :ratio="16/9" class="rounded-borders"/> <q-btn icon="zoom_in" size="sm" round color="white" text-color="black" class="absolute bottom-2 right-2 bg-opacity-80" @click="openPreview(item.link)" /> </div> </div> </div> </q-tab-panel> <q-tab-panel name="exterior"> <div class="row q-pa-md block-wrapper text-center q-col-gutter-md" style="margin-bottom:100px;"> <div v-for="item in imagesArray[0]['exterior']" :key="item.id" class="col-sm-4 col-xs-12"> <div class="relative"> <q-img :src="item.link" :ratio="16/9" class="rounded-borders"/> <q-btn icon="zoom_in" size="sm" round color="white" text-color="black" class="absolute bottom-2 right-2 bg-opacity-80" @click="openPreview(item.link)" /> </div> </div> </div> </q-tab-panel> <q-tab-panel name="new"> <div class="row q-pa-md block-wrapper text-center q-col-gutter-md" style="margin-bottom:100px;"> <div v-for="item in imagesArray[0]['newConstruction']" :key="item.id" class="col-sm-4 col-xs-12"> <div class="relative"> <q-img :src="item.link" :ratio="16/9" class="rounded-borders"/> <q-btn icon="zoom_in" size="sm" round color="white" text-color="black" class="absolute bottom-2 right-2 bg-opacity-80" @click="openPreview(item.link)" /> </div> </div> </div> </q-tab-panel> </q-tab-panels> <!-- 全屏预览弹窗 --> <q-dialog v-model="showPreviewDialog" fullscreen content-class="bg-black" > <q-img :src="previewImgUrl" class="full-width full-height" fit="contain" /> <!-- 关闭按钮 --> <q-btn icon="close" size="lg" round color="white" text-color="black" class="absolute top-4 right-4" @click="showPreviewDialog = false" /> </q-dialog> </template> <script setup> import { ref } from 'vue' const imagesArray = [{ decks:[{ id: 1, link: new URL('../assets/imgs/recentwork/decks/615.jpg', import.meta.url).href}, { id: 2, link: new URL('../assets/imgs/recentwork/decks/619.jpg', import.meta.url).href}, { id: 3, link: new URL('../assets/imgs/recentwork/decks/627.jpg', import.meta.url).href}, { id: 4, link: new URL('../assets/imgs/recentwork/decks/655.jpg', import.meta.url).href}, { id: 5, link: new URL('../assets/imgs/recentwork/decks/659.jpg', import.meta.url).href}, { id: 6, link: new URL('../assets/imgs/recentwork/decks/666.jpg', import.meta.url).href}, { id: 7, link: new URL('../assets/imgs/recentwork/decks/668.jpg', import.meta.url).href}, { id: 8, link: new URL('../assets/imgs/recentwork/decks/677.jpg', import.meta.url).href}, { id: 9, link: new URL('../assets/imgs/recentwork/decks/678.jpg', import.meta.url).href}], interior:[{ id: 1, link: new URL('../assets/imgs/recentwork/interior/2633.jpg', import.meta.url).href}, { id: 2, link: new URL('../assets/imgs/recentwork/interior/989.jpg', import.meta.url).href}, { id: 3, link: new URL('../assets/imgs/recentwork/interior/1015.jpg', import.meta.url).href}, { id: 4, link: new URL('../assets/imgs/recentwork/interior/2671.jpg', import.meta.url).href}, { id: 5, link: new URL('../assets/imgs/recentwork/interior/1020.jpg', import.meta.url).href}, { id: 6, link: new URL('../assets/imgs/recentwork/interior/2123.jpg', import.meta.url).href}, { id: 7, link: new URL('../assets/imgs/recentwork/interior/2634.jpg', import.meta.url).href}, { id: 8, link: new URL('../assets/imgs/recentwork/interior/1406.jpg', import.meta.url).href}, { id: 9, link: new URL('../assets/imgs/recentwork/interior/2041.jpeg', import.meta.url).href}], exterior: [{ id: 1, link: new URL('../assets/imgs/recentwork/exterior/642.jpg', import.meta.url).href}, { id: 2, link: new URL('../assets/imgs/recentwork/exterior/651.jpg', import.meta.url).href}, { id: 3, link: new URL('../assets/imgs/recentwork/exterior/652.jpg', import.meta.url).href}, { id: 4, link: new URL('../assets/imgs/recentwork/exterior/672.jpg', import.meta.url).href}, { id: 5, link: new URL('../assets/imgs/recentwork/exterior/711.jpg', import.meta.url).href}, { id: 6, link: new URL('../assets/imgs/recentwork/exterior/722.jpg', import.meta.url).href}, { id: 7, link: new URL('../assets/imgs/recentwork/exterior/732.jpg', import.meta.url).href}, { id: 8, link: new URL('../assets/imgs/recentwork/exterior/748.jpg', import.meta.url).href}, { id: 9, link: new URL('../assets/imgs/recentwork/exterior/762.jpg', import.meta.url).href}], newConstruction: [{ id: 1, link: new URL('../assets/imgs/recentwork/construction/618.jpg', import.meta.url).href}, { id: 2, link: new URL('../assets/imgs/recentwork/construction/626.jpg', import.meta.url).href}, { id: 3, link: new URL('../assets/imgs/recentwork/construction/630.jpg', import.meta.url).href}, { id: 4, link: new URL('../assets/imgs/recentwork/construction/657.jpg', import.meta.url).href}, { id: 5, link: new URL('../assets/imgs/recentwork/construction/710.jpg', import.meta.url).href}, { id: 6, link: new URL('../assets/imgs/recentwork/construction/716.jpg', import.meta.url).href}, { id: 7, link: new URL('../assets/imgs/recentwork/construction/758.jpg', import.meta.url).href}, { id: 8, link: new URL('../assets/imgs/recentwork/construction/799.jpg', import.meta.url).href}, { id: 9, link: new URL('../assets/imgs/recentwork/construction/850.jpg', import.meta.url).href}] }] const slide = ref(1) const tab = ref('decks') // 新增预览相关变量 const showPreviewDialog = ref(false) const previewImgUrl = ref('') // 打开预览弹窗的方法 const openPreview = (url) => { previewImgUrl.value = url showPreviewDialog.value = true } </script> <style lang="scss" scoped> .block-wrapper{ max-width: 1024px; margin-left: auto; margin-right: auto; } .active-menu-item{ background-color: $background-accent; color: $primary !important; } .menu-item{ letter-spacing: .15rem; font-weight:500; border-radius: 7px; color:$dark } </style>
关键改动说明
- 图片容器与按钮布局:给每个
q-img外层添加relative类的容器,用Quasar的absolute、bottom-2、right-2类把按钮固定在图片右下角,bg-opacity-80让按钮半透明不遮挡图片内容。 - 全屏预览弹窗:使用
q-dialog并设置fullscreen属性,内部的q-img用full-width和full-height配合fit="contain"实现图片自适应全屏且保持比例。 - 交互逻辑:新增响应式变量控制弹窗显示状态和当前预览的图片链接,点击按钮时更新变量打开弹窗,点击关闭按钮或弹窗外部可关闭预览。
内容的提问来源于stack exchange,提问作者Qiuzman
相关产品推荐
相关产品推荐

