1. 礼物特效
This commit is contained in:
@@ -18,6 +18,75 @@ export const MOBILE_LAYOUTS = [
|
||||
{ value: 'landscape', label: '横屏展示', desc: '手机端强制左右分栏' },
|
||||
]
|
||||
|
||||
/** 后台 9×9 快速选点边长 */
|
||||
export const HERO_FOCUS_GRID = 9
|
||||
|
||||
/** 旧版命名焦点 → 百分比(兼容已保存配置) */
|
||||
const LEGACY_HERO_FOCUS = {
|
||||
'top-left': [0, 0],
|
||||
top: [50, 0],
|
||||
'top-right': [100, 0],
|
||||
left: [0, 50],
|
||||
center: [50, 50],
|
||||
right: [100, 50],
|
||||
'bottom-left': [0, 100],
|
||||
bottom: [50, 100],
|
||||
'bottom-right': [100, 100],
|
||||
}
|
||||
|
||||
export function clampHeroFocus(n, fallback = 50) {
|
||||
const v = Number(n)
|
||||
if (!Number.isFinite(v)) return fallback
|
||||
return Math.min(100, Math.max(0, Math.round(v * 10) / 10))
|
||||
}
|
||||
|
||||
/** 生成 9×9 网格点 {x,y,key} */
|
||||
export function heroFocusGridPoints(size = HERO_FOCUS_GRID) {
|
||||
const n = Math.max(2, size | 0)
|
||||
const pts = []
|
||||
for (let row = 0; row < n; row += 1) {
|
||||
for (let col = 0; col < n; col += 1) {
|
||||
const x = (col / (n - 1)) * 100
|
||||
const y = (row / (n - 1)) * 100
|
||||
pts.push({
|
||||
key: `${row}-${col}`,
|
||||
x: clampHeroFocus(x),
|
||||
y: clampHeroFocus(y),
|
||||
})
|
||||
}
|
||||
}
|
||||
return pts
|
||||
}
|
||||
|
||||
/**
|
||||
* object-position CSS
|
||||
* - heroFocusCss(cfg) 读 cfg.heroFocusX/Y
|
||||
* - heroFocusCss(x, y) 直接传百分比
|
||||
* - heroFocusCss('center') 兼容旧字符串
|
||||
*/
|
||||
export function heroFocusCss(a, b) {
|
||||
if (a && typeof a === 'object') {
|
||||
return `${clampHeroFocus(a.heroFocusX, 50)}% ${clampHeroFocus(a.heroFocusY, 50)}%`
|
||||
}
|
||||
if (typeof a === 'string' && LEGACY_HERO_FOCUS[a]) {
|
||||
const [x, y] = LEGACY_HERO_FOCUS[a]
|
||||
return `${x}% ${y}%`
|
||||
}
|
||||
return `${clampHeroFocus(a, 50)}% ${clampHeroFocus(b, 50)}%`
|
||||
}
|
||||
|
||||
export function resolveHeroFocusXY(loaded = {}) {
|
||||
const hasXY = Number.isFinite(Number(loaded.heroFocusX)) && Number.isFinite(Number(loaded.heroFocusY))
|
||||
if (hasXY) {
|
||||
return {
|
||||
heroFocusX: clampHeroFocus(loaded.heroFocusX),
|
||||
heroFocusY: clampHeroFocus(loaded.heroFocusY),
|
||||
}
|
||||
}
|
||||
const legacy = LEGACY_HERO_FOCUS[loaded.heroFocus] || LEGACY_HERO_FOCUS.center
|
||||
return { heroFocusX: legacy[0], heroFocusY: legacy[1] }
|
||||
}
|
||||
|
||||
/** 解析为 1 | 2 | 3,无法识别返回 0 */
|
||||
export function resolvePosterSide(input) {
|
||||
if (input === 1 || input === '1') return 1
|
||||
@@ -47,6 +116,9 @@ function baseFields(side) {
|
||||
mobileLayout: 'auto',
|
||||
enabled: true,
|
||||
heroImg: '',
|
||||
/** 主图焦点百分比 0–100(object-position) */
|
||||
heroFocusX: 50,
|
||||
heroFocusY: 50,
|
||||
/** 二维码中心图;空则显示圆圈大囍 */
|
||||
qrCenterImg: '',
|
||||
title: '婚礼邀请函',
|
||||
@@ -269,6 +341,7 @@ export function normalizePosterConfig(raw, side = 1) {
|
||||
pageTitle: loaded.pageTitle || base.pageTitle || '',
|
||||
pageDescription: loaded.pageDescription || base.pageDescription || '',
|
||||
qrCenterImg: loaded.qrCenterImg || '',
|
||||
...resolveHeroFocusXY(loaded),
|
||||
verticalSlogan: loaded.verticalSlogan || base.verticalSlogan,
|
||||
subSlogan1: loaded.subSlogan1 || base.subSlogan1,
|
||||
subSlogan2: loaded.subSlogan2 || base.subSlogan2,
|
||||
|
||||
Reference in New Issue
Block a user