mirror of
https://github.com/zen-browser/www.git
synced 2025-07-07 17:05:32 +02:00
Merge pull request #644 from j14i/j14i/video-refactoring
Re-encode video files for less gpu usage
This commit is contained in:
commit
199d83f25c
28 changed files with 49 additions and 52 deletions
BIN
public/media/compact-mode/poster.webp
Normal file
BIN
public/media/compact-mode/poster.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
BIN
public/media/compact-mode/video.mp4
Normal file
BIN
public/media/compact-mode/video.mp4
Normal file
Binary file not shown.
BIN
public/media/compact-mode/video.webm
Normal file
BIN
public/media/compact-mode/video.webm
Normal file
Binary file not shown.
BIN
public/media/glance/poster.webp
Normal file
BIN
public/media/glance/poster.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 97 KiB |
BIN
public/media/glance/video.mp4
Normal file
BIN
public/media/glance/video.mp4
Normal file
Binary file not shown.
BIN
public/media/glance/video.webm
Normal file
BIN
public/media/glance/video.webm
Normal file
Binary file not shown.
BIN
public/media/hero-video/poster.webp
Normal file
BIN
public/media/hero-video/poster.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 132 KiB |
BIN
public/media/hero-video/video.mp4
Normal file
BIN
public/media/hero-video/video.mp4
Normal file
Binary file not shown.
BIN
public/media/hero-video/video.webm
Normal file
BIN
public/media/hero-video/video.webm
Normal file
Binary file not shown.
BIN
public/media/split-views/poster.webp
Normal file
BIN
public/media/split-views/poster.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
BIN
public/media/split-views/video.mp4
Normal file
BIN
public/media/split-views/video.mp4
Normal file
Binary file not shown.
BIN
public/media/split-views/video.webm
Normal file
BIN
public/media/split-views/video.webm
Normal file
Binary file not shown.
BIN
public/media/whats-new/poster.webp
Normal file
BIN
public/media/whats-new/poster.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
public/media/whats-new/video.mp4
Normal file
BIN
public/media/whats-new/video.mp4
Normal file
Binary file not shown.
BIN
public/media/whats-new/video.webm
Normal file
BIN
public/media/whats-new/video.webm
Normal file
Binary file not shown.
BIN
public/media/workspaces/poster.webp
Normal file
BIN
public/media/workspaces/poster.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
BIN
public/media/workspaces/video.mp4
Normal file
BIN
public/media/workspaces/video.mp4
Normal file
Binary file not shown.
BIN
public/media/workspaces/video.webm
Normal file
BIN
public/media/workspaces/video.webm
Normal file
Binary file not shown.
|
@ -1,14 +1,9 @@
|
||||||
---
|
---
|
||||||
import { motion } from 'motion/react'
|
import { motion } from 'motion/react'
|
||||||
import { getTitleAnimation } from '~/animations'
|
import { getTitleAnimation } from '~/animations'
|
||||||
import Description from '~/components/Description.astro'
|
|
||||||
|
|
||||||
import CompactModeVideo from '~/assets/CompactMode.webm'
|
|
||||||
import GlanceVideo from '~/assets/Glance.webm'
|
|
||||||
import SplitViewsVideo from '~/assets/SplitViews.webm'
|
|
||||||
import WorkspacesVideo from '~/assets/Workspaces.webm'
|
|
||||||
|
|
||||||
import { getLocale, getUI } from '~/utils/i18n'
|
import { getLocale, getUI } from '~/utils/i18n'
|
||||||
|
import Description from './Description.astro'
|
||||||
|
|
||||||
import Video from './Video.astro'
|
import Video from './Video.astro'
|
||||||
|
|
||||||
const locale = getLocale(Astro)
|
const locale = getLocale(Astro)
|
||||||
|
@ -130,8 +125,7 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
|
||||||
playsinline
|
playsinline
|
||||||
preload="none"
|
preload="none"
|
||||||
class="feature-video"
|
class="feature-video"
|
||||||
src={WorkspacesVideo}
|
name="workspaces"
|
||||||
data-active="true"
|
|
||||||
/>
|
/>
|
||||||
<Video
|
<Video
|
||||||
autoplay
|
autoplay
|
||||||
|
@ -140,7 +134,7 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
|
||||||
playsinline
|
playsinline
|
||||||
preload="none"
|
preload="none"
|
||||||
class="feature-video"
|
class="feature-video"
|
||||||
src={CompactModeVideo}
|
name="compact-mode"
|
||||||
/>
|
/>
|
||||||
<Video
|
<Video
|
||||||
autoplay
|
autoplay
|
||||||
|
@ -149,7 +143,7 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
|
||||||
playsinline
|
playsinline
|
||||||
preload="none"
|
preload="none"
|
||||||
class="feature-video"
|
class="feature-video"
|
||||||
src={GlanceVideo}
|
name="glance"
|
||||||
/>
|
/>
|
||||||
<Video
|
<Video
|
||||||
autoplay
|
autoplay
|
||||||
|
@ -158,7 +152,7 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
|
||||||
playsinline
|
playsinline
|
||||||
preload="none"
|
preload="none"
|
||||||
class="feature-video"
|
class="feature-video"
|
||||||
src={SplitViewsVideo}
|
name="split-views"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -176,30 +170,45 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
|
||||||
descriptionEl.textContent = descriptions[0]
|
descriptionEl.textContent = descriptions[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeToFeature({ target }: { target: HTMLElement | undefined | null }) {
|
function changeToFeature({ target }: MouseEvent | { target: HTMLElement }) {
|
||||||
target = target?.closest('.feature, .feature-tab')
|
let targetEl: HTMLElement | null = target as HTMLElement
|
||||||
if (!target) return
|
|
||||||
|
|
||||||
const index = Array.from(features).indexOf(target) % 4
|
if (target instanceof HTMLElement) {
|
||||||
if (index === -1) return
|
targetEl = target.closest('.feature, .feature-tab')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!targetEl) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = Array.from(features).indexOf(targetEl) % 4
|
||||||
|
|
||||||
|
if (index === -1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Update both mobile and desktop elements
|
// Update both mobile and desktop elements
|
||||||
features.forEach((f, i) => {
|
for (let i = 0; i < features.length; i += 1) {
|
||||||
|
const f = features[i]
|
||||||
|
|
||||||
if (i % 4 === index) {
|
if (i % 4 === index) {
|
||||||
f.setAttribute('data-active', 'true')
|
f.setAttribute('data-active', 'true')
|
||||||
} else {
|
} else {
|
||||||
f.removeAttribute('data-active')
|
f.removeAttribute('data-active')
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
// Update mobile description
|
// Update mobile description
|
||||||
const descriptionEl = document.querySelector('.feature-description')
|
const descriptionEl = document.querySelector('.feature-description')
|
||||||
|
|
||||||
if (descriptionEl && descriptions) {
|
if (descriptionEl && descriptions) {
|
||||||
descriptionEl.textContent = descriptions[index]
|
descriptionEl.textContent = descriptions[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
const videos = document.querySelectorAll('.feature-video') as NodeListOf<HTMLVideoElement>
|
const videos = document.querySelectorAll<HTMLVideoElement>('.feature-video')
|
||||||
videos.forEach((vid, i) => {
|
|
||||||
|
for (let i = 0; i < videos.length; i += 1) {
|
||||||
|
const vid = videos[i]
|
||||||
const yOffset = (i - index) * 20
|
const yOffset = (i - index) * 20
|
||||||
const zOffset = i === index ? 0 : -100 - Math.abs(i - index) * 50
|
const zOffset = i === index ? 0 : -100 - Math.abs(i - index) * 50
|
||||||
const scale = i === index ? 1 : 0.95
|
const scale = i === index ? 1 : 0.95
|
||||||
|
@ -220,16 +229,14 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
|
||||||
vid.style.zIndex = String(1 - Math.abs(i - index))
|
vid.style.zIndex = String(1 - Math.abs(i - index))
|
||||||
vid.pause()
|
vid.pause()
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const feature of features) {
|
for (const feature of features) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
feature.addEventListener('click', changeToFeature)
|
||||||
feature.addEventListener('click', changeToFeature as any)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
changeToFeature({ target: features[0] })
|
||||||
changeToFeature({ target: features[0] as any })
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
---
|
---
|
||||||
import { motion } from 'motion/react'
|
import { motion } from 'motion/react'
|
||||||
import { getTitleAnimation } from '~/animations'
|
import { getTitleAnimation } from '~/animations'
|
||||||
import HomePageVideo from '~/assets/HomePageVideo.webm'
|
|
||||||
import Button from '~/components/Button.astro'
|
import Button from '~/components/Button.astro'
|
||||||
import Description from '~/components/Description.astro'
|
import Description from '~/components/Description.astro'
|
||||||
import Title from '~/components/Title.astro'
|
import Title from '~/components/Title.astro'
|
||||||
|
@ -86,7 +85,7 @@ const {
|
||||||
{...getHeroTitleAnimation()}
|
{...getHeroTitleAnimation()}
|
||||||
>
|
>
|
||||||
<Video
|
<Video
|
||||||
src={HomePageVideo}
|
name="hero-video"
|
||||||
autoplay
|
autoplay
|
||||||
loop
|
loop
|
||||||
muted
|
muted
|
||||||
|
|
|
@ -1,27 +1,19 @@
|
||||||
---
|
---
|
||||||
const { src, class: className, ...rest } = Astro.props
|
type Props = {
|
||||||
const type = src.split('.').pop() || 'webm'
|
name: string
|
||||||
|
class?: string
|
||||||
|
} & astroHTML.JSX.VideoHTMLAttributes
|
||||||
|
|
||||||
|
const { name, class: className, ...rest }: Props = Astro.props
|
||||||
---
|
---
|
||||||
|
|
||||||
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
|
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
|
||||||
<video class:list={['w-fit', className]} data-src={src} preload="none" {...rest}>
|
<video
|
||||||
<source src="" type={`video/${type}`} />
|
class:list={['w-fit', className]}
|
||||||
|
preload="none"
|
||||||
|
poster={`/media/${name}/poster.webp`}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
<source src={`/media/${name}/video.webm`} type="video/webm" />
|
||||||
|
<source src={`/media/${name}/video.mp4`} type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
<script>
|
|
||||||
const videos = document.querySelectorAll('video[data-src]') as NodeListOf<HTMLVideoElement>
|
|
||||||
|
|
||||||
const loadVideo = (video: HTMLVideoElement) => {
|
|
||||||
const source = video.querySelector('source')
|
|
||||||
const dataSrc = video.getAttribute('data-src')
|
|
||||||
if (dataSrc && source) {
|
|
||||||
source.src = dataSrc
|
|
||||||
video.removeAttribute('data-src')
|
|
||||||
video.load()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const video of videos) {
|
|
||||||
loadVideo(video)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import SocialMediaStrip from '~/components/SocialMediaStrip.astro'
|
||||||
import ArrowRightIcon from '~/icons/ArrowRightIcon.astro'
|
import ArrowRightIcon from '~/icons/ArrowRightIcon.astro'
|
||||||
import Layout from '~/layouts/Layout.astro'
|
import Layout from '~/layouts/Layout.astro'
|
||||||
|
|
||||||
import whatsNewVideo from '~/assets/whats-new.mp4'
|
|
||||||
import Video from '~/components/Video.astro'
|
import Video from '~/components/Video.astro'
|
||||||
import { releaseNotes } from '~/release-notes'
|
import { releaseNotes } from '~/release-notes'
|
||||||
import whatsNewText from '~/release-notes/whats-new.json'
|
import whatsNewText from '~/release-notes/whats-new.json'
|
||||||
|
@ -71,7 +70,7 @@ if (latestVersion.version.split('.').length > 2 && whatsNewText[1] !== latestVer
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Video
|
<Video
|
||||||
src={whatsNewVideo}
|
name="whats-new"
|
||||||
autoplay
|
autoplay
|
||||||
loop
|
loop
|
||||||
muted
|
muted
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue