A simple live-photo component.
Github: https://github.com/LynanBreeze/live-photo
Preview
My Style
html代码1
| <iframe src="/static/live-photo/?picUrl=https://r2-assets.thelynan.com/u/A001_07251216_C317-FfGABM.jpg&videoUrl=https://r2-assets.thelynan.com/u/A001_07251216_C317-DQ6Nj6.mp4" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" style="width: 100%; aspect-ratio: 16/9;"></iframe>
|
Apple SDK
html代码1
| <iframe src="/static/live-photo/?picUrl=/static/live-photo/test/live.jpg&videoUrl=/static/live-photo/test/live.mp4&useApple=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" style="width: 100%; aspect-ratio: 16/9;"></iframe>
|
Comparison
My Style |
Apple SDK |
☑️ Better Compatibility |
|
☑️ Audio, Muted Optional |
Muted |
|
☑️ More Player Properties |
Trigger by Click |
Trigger by Hover(Desktop), Long Press(Mobile) |
Personalized Icon |
Look Exactly Same as Photos |
Options
Key |
Type |
photoSrc |
string, required |
videoSrc |
string, required |
loop |
boolean |
muted |
boolean |
useApple |
boolean |
The Making
At first, we should be aware that a Live Photo is not a mysterious file format but a combination of 1 photo and 1 video.
Apple SDK
Apple has an official JS SDK for developers. Check https://developer.apple.com/documentation/livephotoskitjs
index.html1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="https://cdn.apple-livephotoskit.com/lpk/1/livephotoskit.js"></script> </head> <body> <div data-live-photo data-photo-src="https://..." data-video-src="https://..." style="width: 320px; height: 320px"> </div> </body> </html>
|
If you want to implement it in React, it’s simple as follows:
index.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import { useRef, useEffect } from "react"; import * as LivePhotosKit from "livephotoskit";
const LivePhotosKitReact = ({ className, photoSrc, videoSrc }) => { const nodeRef = useRef(null);
useEffect(() => { const player = LivePhotosKit.Player(nodeRef.current); player.photoSrc = photoSrc; player.videoSrc = videoSrc; }, []);
return <div ref={nodeRef} className={className}></div>; };
|
My Style
All we need is switch between a <img>
and a <video>
.
index.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| import { useRef, useState } from "react";
const LivePhoto = (props) => { const { photoSrc, videoSrc, muted, loop, useApple } = props; const [imageReady, setImageReady] = useState(false); const [videoPlaying, setVideoPlaying] = useState(false); const [videoRunning, setVideoRunning] = useState(false); const [videoReady, setVideoReady] = useState(false); const videoRef = useRef(null);
const playVideo = () => { if (videoRunning) { videoRef.current.pause(); } else { setVideoPlaying(true); videoRef.current.play(); } };
const onImageLoad = () => { setImageReady(true); if ( /iphone/i.test(navigator.userAgent) && /micromessenger/i.test(navigator.userAgent) ) { setTimeout(() => { setVideoReady(true); }, 500); } };
return ( <div className='live-photo'> {useApple ? ( <LivePhotosKitReact className='live-img' photoSrc={photoSrc} videoSrc={videoSrc} /> ) : ( <> <div className='live-trigger' onClick={playVideo} style={{ opacity: Number(videoReady) }} > <div className='trigger-icon' style={{ animationPlayState: videoRunning ? "running" : "paused", }} ></div> <span className='trigger-text'>LIVE</span> </div> <img className='live-img' src={photoSrc} onLoad={onImageLoad} style={{ opacity: Number(imageReady) }} /> <video playsInline webkit-playsinline className='live-video' loop={loop} muted={muted} ref={videoRef} src={videoSrc} style={{ opacity: Number(videoPlaying) }} onCanPlay={() => setVideoReady(true)} onLoadedMetadata={() => setVideoReady(true)} onPlaying={() => setVideoRunning(true)} onPause={() => setVideoRunning(false)} onEnded={() => setVideoPlaying(false)} ></video> </> )} </div> ); };
|
Develop && Build
Develop
1
| pnpm install && pnpm run dev
|
Build