feat(card): 实现卡片预览区域自适应缩放功能
- 添加预览区高度动态计算逻辑,确保按钮始终可见 - 实现超大卡片等比缩放功能,避免超出屏幕范围 - 添加卡片真实高度测量和缩放比例计算 - 优化页面布局结构,设置固定操作按钮区域 - 调整样式防止内容溢出和滚动条显示
This commit is contained in:
+57
-9
@@ -7,9 +7,15 @@
|
|||||||
<text class="card-nav-title">酒局卡片</text>
|
<text class="card-nav-title">酒局卡片</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 大卡片预览 -->
|
<!-- 大卡片预览:超高时自动等比缩放,保证按钮始终可见 -->
|
||||||
<view class="card-preview-area">
|
<view class="card-preview-area" :style="{ height: previewH + 'px' }">
|
||||||
<DrinkCard v-if="record" :record="record" />
|
<view
|
||||||
|
v-if="record"
|
||||||
|
class="card-scale-wrap"
|
||||||
|
:style="previewScale < 1 ? { transform: 'scale(' + previewScale + ')', width: '620rpx' } : {}"
|
||||||
|
>
|
||||||
|
<DrinkCard :record="record" />
|
||||||
|
</view>
|
||||||
<view v-else class="card-empty">暂无记录</view>
|
<view v-else class="card-empty">暂无记录</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -50,7 +56,11 @@ export default {
|
|||||||
record: null,
|
record: null,
|
||||||
saving: false,
|
saving: false,
|
||||||
saved: false,
|
saved: false,
|
||||||
posterPath: '' // 预生成的海报图片路径
|
posterPath: '', // 预生成的海报图片路径
|
||||||
|
// 预览区自适应缩放
|
||||||
|
previewScale: 1,
|
||||||
|
previewH: 400,
|
||||||
|
cardNaturalH: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async onLoad(options) {
|
async onLoad(options) {
|
||||||
@@ -76,12 +86,45 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this.record) this.record = this.loadLocalRecord(options.recordId) || this.fallback()
|
if (!this.record) this.record = this.loadLocalRecord(options.recordId) || this.fallback()
|
||||||
|
this.$nextTick(() => this.fitPreview())
|
||||||
},
|
},
|
||||||
onReady() {
|
onReady() {
|
||||||
// 页面渲染完成后预生成海报,供分享使用
|
// 页面渲染完成后预生成海报,供分享使用
|
||||||
this.preGeneratePoster()
|
this.preGeneratePoster()
|
||||||
|
// 图片加载完成后卡片高度会变化,延迟再适配一次
|
||||||
|
setTimeout(() => this.fitPreview(), 1500)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// ===== 预览区自适应:卡片超高时等比缩放,按钮始终完整可见 =====
|
||||||
|
fitPreview() {
|
||||||
|
const sys = uni.getSystemInfoSync()
|
||||||
|
// 头部导航与底部按钮区的实测高度
|
||||||
|
const query = uni.createSelectorQuery().in(this)
|
||||||
|
query.select('.card-nav').boundingClientRect()
|
||||||
|
query.select('.card-actions').boundingClientRect()
|
||||||
|
query.exec(res => {
|
||||||
|
const navH = (res && res[0] && res[0].height) || 88
|
||||||
|
const actH = (res && res[1] && res[1].height) || 320
|
||||||
|
this.previewH = Math.max(200, sys.windowHeight - navH - actH)
|
||||||
|
this.measureCard()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
measureCard() {
|
||||||
|
uni.createSelectorQuery().in(this)
|
||||||
|
.select('.card-root').boundingClientRect()
|
||||||
|
.exec(res => {
|
||||||
|
const h = res && res[0] && res[0].height
|
||||||
|
if (!h || h <= 0) {
|
||||||
|
// 卡片尚未渲染完成,稍后重试
|
||||||
|
setTimeout(() => this.measureCard(), 150)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// scale 后测量值已被缩放,还原真实高度
|
||||||
|
const natural = this.previewScale < 1 ? h / this.previewScale : h
|
||||||
|
this.cardNaturalH = natural
|
||||||
|
this.previewScale = natural > this.previewH ? Math.max(0.5, this.previewH / natural) : 1
|
||||||
|
})
|
||||||
|
},
|
||||||
loadLocalRecord(id) {
|
loadLocalRecord(id) {
|
||||||
if (!id) return null
|
if (!id) return null
|
||||||
try {
|
try {
|
||||||
@@ -757,7 +800,8 @@ export default {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 100vh;
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
background: $bg-base;
|
background: $bg-base;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -792,14 +836,17 @@ export default {
|
|||||||
color: $text-primary;
|
color: $text-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 大卡片预览区 */
|
/* 大卡片预览区:高度由 JS 按剩余可用空间动态设定,卡片超高时缩放 */
|
||||||
.card-preview-area {
|
.card-preview-area {
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: $sp-lg;
|
padding: 0 $sp-lg;
|
||||||
min-height: 0;
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-scale-wrap {
|
||||||
|
transform-origin: center center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-empty {
|
.card-empty {
|
||||||
@@ -809,6 +856,7 @@ export default {
|
|||||||
|
|
||||||
/* 操作按钮 */
|
/* 操作按钮 */
|
||||||
.card-actions {
|
.card-actions {
|
||||||
|
flex-shrink: 0;
|
||||||
padding: $sp-lg;
|
padding: $sp-lg;
|
||||||
padding-bottom: calc($sp-lg + env(safe-area-inset-bottom));
|
padding-bottom: calc($sp-lg + env(safe-area-inset-bottom));
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user