我正在尝试用react来实现HTML视频。因此,如果视口的宽度小于750像素,我想将视频源更改为较小的分辨率/较小的文件(因为数据传输量较高等)。
因此,在完美的HTML世界中,您可以构建以下代码:
<video controls>
<source src="video-small.mp4" type="video/mp4" media="all and (max-width: 750px)">
<source src="video.mp4" type="video/mp4">
</video>
由于media
不是(或没有更多)specified in the source tag if it's inside of a video ta g,因此我不能再使用它了。由于Chrome显示的是第一个来源,即移动视频。无论是台式机还是手机。
第二个解决方案是将一个容器包装起来并将display: none;
设置为不可见的视频:
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import LazyLoad from 'react-lazyload'
const MobileVideo = styled.div`
width: 100%;
height: 100%;
object-fit: cover;
display: none;
${({theme}) => theme.media.mobile`
display: block;
`}
`
const DesktopVideo = styled.div`
width: 100%;
height: 100%;
object-fit: cover;
display: block;
${({theme}) => theme.media.mobile`
display: none;
`}
`
const VideoComponent = ({
srcWebm,
srcMp4,
mobileSrcWebm,
mobileSrcMp4,
poster,
className,
forwardedRef,
...rest
}) => (
<React.Fragment>
<MobileVideo>
<video
playsInline
poster={poster.url}
className={className}
ref={forwardedRef}
{...rest}
>
{mobileSrcWebm.url !== '' && (
<source src={mobileSrcWebm.url} type="video/webm" />
)}
{mobileSrcMp4.url !== '' && (
<source src={mobileSrcMp4.url} type="video/mp4" />
)}
</video>
</MobileVideo>
<DesktopVideo>
<video
playsInline
poster={poster.url}
className={className}
ref={forwardedRef}
{...rest}
>
{srcWebm.url !== '' && <source src={srcWebm.url} type="video/webm" />}
{srcMp4.url !== '' && <source src={srcMp4.url} type="video/mp4" />}
</video>
</DesktopVideo>
</React.Fragment>
)
在这种情况下,将显示正确的视频,但两个视频均已下载(在Chrome中)。隐藏并不会阻止浏览器下载。急!
第三种解决方案是使用第二种解决方案,并从DOM中删除了不可见的组件:
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import LazyLoad from 'react-lazyload'
import {sizes} from '../../lib/ThemeProvider/media'
const MobileVideo = styled.div`
width: 100%;
height: 100%;
object-fit: cover;
display: none;
${({ theme }) => theme.media.mobile`
display: block;
`}
`
const DesktopVideo = styled.div`
width: 100%;
height: 100%;
object-fit: cover;
display: block;
${({ theme }) => theme.media.mobile`
display: none;
`}
`
class VideoComponent extends React.Component {
state = {
showMobileSrc: true
}
componentDidMount() {
this.resize()
window.addEventListener('resize', this.resize)
}
componentWillUnmount() {
window.removeEventListener('resize', this.resize)
}
resize = () => {
if (window.innerWidth >= sizes.mobile) {
this.setState({ showMobileSrc: false })
} else {
this.setState({ showMobileSrc: true })
}
}
render() {
const { srcWebm,
srcMp4,
mobileSrcWebm,
mobileSrcMp4,
poster,
className,
forwardedRef,
...rest
} = this.props
const {showMobileSrc} = this.state
return (
<React.Fragment>
{showMobileSrc && <MobileVideo>
<video
playsInline
poster={poster.url}
className={className}
ref={forwardedRef}
{...rest}
>
{mobileSrcWebm.url !== '' && (
<source src={mobileSrcWebm.url} type="video/webm" />
)}
{mobileSrcMp4.url !== '' && (
<source src={mobileSrcMp4.url} type="video/mp4" />
)}
</video>
</MobileVideo>}
{!showMobileSrc && <DesktopVideo>
<video
playsInline
poster={poster.url}
className={className}
ref={forwardedRef}
{...rest}
>
{srcWebm.url !== '' && <source src={srcWebm.url} type="video/webm" />}
{srcMp4.url !== '' && <source src={srcMp4.url} type="video/mp4" />}
</video>
</DesktopVideo>}
</React.Fragment>
)
}
}
但是chrome仍在下载两个视频。 HTML似乎是正确的。不知道铬在那做什么。
首先,我真的不明白为什么他们从视频标签内的源标签中删除了媒体属性。这并不是始终如一地实现的。
无论如何:如何在定义的视口宽度下更改源并防止下载两个视频?
答案 0 :(得分:1)
简单的JavaScript解决方案(不是特定于ReactJS的,但是请参见this component以获取纯ReactJS解决方案)
if (matchMedia) {
var mq = window.matchMedia("(min-width: 600px)");
mq.addListener(WidthChange);
}
function WidthChange(mq) {
if (mq.matches) {
// set source to desktop
} else {
// set source to mobile
}
}