diff --git a/config/index.js b/config/index.js index 4cea31b99..700873477 100644 --- a/config/index.js +++ b/config/index.js @@ -57,7 +57,10 @@ const config = { sourceRoot: 'src', outputRoot: DIST_PATH, sass: { - resource: path.resolve(__dirname, '..', 'src/style/imports.scss'), + resource: + process.env.TARO_ENV === 'weapp' + ? ['src/style/imports.scss', 'src/style/weapp-mixins.scss'] + : ['src/style/imports.scss', 'src/style/h5-mixins.scss'], projectDirectory: path.resolve(__dirname, '..') }, diff --git a/src/pages/home/wgts/film/index.jsx b/src/pages/home/wgts/film/index.jsx index 0e9266986..4b91c0d5b 100644 --- a/src/pages/home/wgts/film/index.jsx +++ b/src/pages/home/wgts/film/index.jsx @@ -2,91 +2,39 @@ * Copyright © ShopeX (http://www.shopex.cn). All rights reserved. * See LICENSE file for license details. */ -import React, { useState, useEffect, useMemo } from 'react' -import Taro, { getCurrentInstance } from '@tarojs/taro' +import React, { useMemo } from 'react' import { View, Video, Text } from '@tarojs/components' import { classNames, styleNames, linkPage } from '@/utils' import { getGlobalBaseStyle } from '../helper' import './index.scss' -const $instance = getCurrentInstance() +// proportion 与比例 class 的映射:0=16:9, 1=9:16, 2=4:3, 3=3:4, 4=1:1 +const RATIO_CLASS_MAP = ['16-9', '9-16', '4-3', '3-4', '1-1'] function WgtFilm(props) { const { info } = props - const [screenWidth, setScreenWidth] = useState(null) // 从 params 中获取配置和数据,兼容两种数据结构 - // 1. 新结构:info.params.config, info.params.data, info.params.base - // 2. 旧结构:info.config, info.data, info.base const params = info?.params || info || {} const base = params.base || {} const config = params.config || {} const data = params.data || [] - useEffect(() => { - const res = Taro.getSystemInfoSync() - setScreenWidth(res.screenWidth) - }, []) - // 获取外层样式(包含 outerMargin 和背景配置) const outerStyle = useMemo(() => { return getGlobalBaseStyle(base.outerMargin) }, [base]) - // 计算视频尺寸 - const videoSize = useMemo(() => { - if (!screenWidth) { - return { width: '100%', height: 'auto', objectFit: 'contain' } - } + // 根据 base.proportion / config.ratio 得到比例 class,用 aspect-ratio mixin 渲染 + const videoWrapClass = useMemo(() => { + if (config.ratio === 'square') return 'wgt-film__video-wrap--1-1' + if (config.ratio === 'rectangle') return 'wgt-film__video-wrap--16-9' + const proportion = base.proportion ?? 0 + const key = RATIO_CLASS_MAP[proportion] || RATIO_CLASS_MAP[0] + return `wgt-film__video-wrap--${key}` + }, [base.proportion, config.ratio]) - // 计算实际可用宽度(减去边距) - const padding = config.padded || base.padded ? 32 : 0 // 16px * 2 - const availableWidth = screenWidth - padding - - const aspectRatios = [16 / 9, 9 / 16, 4 / 3, 3 / 4, 1 / 1] - const { proportion = 0 } = base - let ratio = aspectRatios[proportion] - - let w = '100%', - h - let objectFit = 'contain' - const defaultHeight = Math.round(availableWidth / ratio) - - if (config.width && config.height) { - ratio = config.width / config.height - if (ratio <= 10 / 16) { - h = defaultHeight - } else { - objectFit = 'cover' - h = Math.round(availableWidth / ratio) - } - } else { - h = defaultHeight - } - - if (config.ratio === 'square') { - // 1:1 - objectFit = 'cover' - h = availableWidth - } else if (config.ratio === 'rectangle') { - // 16:9 - h = defaultHeight - } - - return { - width: w, - height: `${h}px`, - objectFit - } - }, [ - screenWidth, - base.proportion, - base.padded, - config.width, - config.height, - config.ratio, - config.padded - ]) + const objectFit = config.ratio === 'square' ? 'cover' : 'contain' const handleClickItem = linkPage @@ -109,20 +57,16 @@ function WgtFilm(props) { )} - - ) diff --git a/src/pages/home/wgts/film/index.scss b/src/pages/home/wgts/film/index.scss index eb7010434..642cdfcb8 100644 --- a/src/pages/home/wgts/film/index.scss +++ b/src/pages/home/wgts/film/index.scss @@ -2,12 +2,41 @@ * Copyright © ShopeX (http://www.shopex.cn). All rights reserved. * See LICENSE file for license details. */ - .wgt-film { - .flim-video { - height: 100%; - display: block; - width: 100%; - // background-color: #000; +.wgt-film { + .wgt-film__video-wrap { + width: 100%; + overflow: hidden; + + &--16-9 { + @include aspect-ratio(16, 9); + } + &--9-16 { + @include aspect-ratio(9, 16); + } + &--4-3 { + @include aspect-ratio(4, 3); + } + &--3-4 { + @include aspect-ratio(3, 4); + } + &--1-1 { + @include aspect-ratio(1, 1); } } - \ No newline at end of file + + .wgt-film__video-inner { + // 作为 aspect-ratio 容器的直接子元素,由 mixin 设为 absolute 填满 + video, + .flim-video { + width: 100%; + height: 100%; + display: block; + } + } + + .flim-video { + height: 100%; + display: block; + width: 100%; + } +} diff --git a/src/pages/home/wgts/imghot-zone.js b/src/pages/home/wgts/imghot-zone.js index f4477b2b1..6c65b8c06 100644 --- a/src/pages/home/wgts/imghot-zone.js +++ b/src/pages/home/wgts/imghot-zone.js @@ -36,14 +36,14 @@ function WgtImgHotZone(props) { } // 高度优先级:config.imgHeight > animation模式下的imgHeight > auto - if (config.imgHeight) { - style.height = Taro.pxTransform(config.imgHeight) - } else if (isVertical) { - style.height = Taro.pxTransform(imgHeight) - } else { - style.height = 'auto' - } - + // if (config.imgHeight) { + // style.height = Taro.pxTransform(config.imgHeight) + // } else if (isVertical) { + // style.height = Taro.pxTransform(imgHeight) + // } else { + // style.height = 'auto' + // } + style.height = 'auto' return style }, [outerStyle, config.imgWidth, config.imgHeight, isVertical, imgHeight]) diff --git a/src/pages/home/wgts/imghot-zone/index.jsx b/src/pages/home/wgts/imghot-zone/index.jsx index 0f4026903..25eacf2db 100644 --- a/src/pages/home/wgts/imghot-zone/index.jsx +++ b/src/pages/home/wgts/imghot-zone/index.jsx @@ -49,15 +49,15 @@ function WgtImgHotZone(props) { } // 纵向布局时,优先使用 base.imgHeight - if (isVertical && base.imgHeight) { - style.height = Taro.pxTransform(base.imgHeight) - } else if (config.imgHeight) { - // 横向布局时,使用 config.imgHeight - style.height = Taro.pxTransform(config.imgHeight) - } else { - style.height = 'auto' - } - + // if (isVertical && base.imgHeight) { + // style.height = Taro.pxTransform(base.imgHeight) + // } else if (config.imgHeight) { + // // 横向布局时,使用 config.imgHeight + // style.height = Taro.pxTransform(config.imgHeight) + // } else { + // style.height = 'auto' + // } + style.height = 'auto' return style }, [config.imgWidth, config.imgHeight, isVertical, base.imgHeight]) diff --git a/src/style/h5-mixins.scss b/src/style/h5-mixins.scss new file mode 100644 index 000000000..982da1b5e --- /dev/null +++ b/src/style/h5-mixins.scss @@ -0,0 +1,27 @@ +@mixin aspect-ratio($width: 1, $height: 1, $useFallback: true) { + // 计算 padding-top 降级比例 + $ratio: $width / $height; + $padding: percentage($height / $width); + // 降级方案:使用 padding-top 模拟宽高比 + @if $useFallback { + @supports not (aspect-ratio: #{$width}/#{$height}) { + position: relative; + padding-top: $padding; + width: 100%; + flex-grow: 0; + // 使用 > 选择器确保仅匹配直接子元素 + > * { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + } + } + + @supports (aspect-ratio: #{$width}/#{$height}) { + // 现代浏览器标准语法 + aspect-ratio: #{$width}/#{$height}; + } +} diff --git a/src/style/weapp-mixins.scss b/src/style/weapp-mixins.scss new file mode 100644 index 000000000..f660df3d5 --- /dev/null +++ b/src/style/weapp-mixins.scss @@ -0,0 +1,19 @@ +@mixin aspect-ratio($width: 1, $height: 1, $useFallback: true) { + // 计算 padding-top 降级比例 + $ratio: $width / $height; + $padding: percentage($height / $width); + // 降级方案:使用 padding-top 模拟宽高比 + + position: relative; + padding-top: $padding; + width: 100%; + flex-grow: 0; + // 使用 > 选择器确保仅匹配直接子元素 + > view { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } +}