Я пытаюсь реализовать видео в 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
не (или не более) не указано в теге источника, если оно находится внутри видео, то 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). Скрытие не препятствует загрузке браузера. SAD!
Третье решение заключалось в использовании второго решения и удалении невидимого компонента из 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 кажется правильным. Понятия не имею, что там делает хром ...
Сначала я действительно не понимаю, почему они удалили атрибут media из тега source внутри тега video. Это не всегда реализовано.
В любом случае: как я могу изменить источник на определенной ширине области просмотра и предотвратить загрузку обоих видео?