React Framework Usage Guide
ZWPlayer provides a dedicated interface package zwplayer-react for the React framework, supporting React 16.8+, 17.x, 18.x, and 19.x versions.
1. Installation Steps
1.1 Install Package
npm i zwplayer-react --save
1.2 Verify Installation
After successful installation, a zwplayer core library directory will be automatically generated in the project’s public directory. This directory must be built and published along with the project.
1.3 Version Requirements
- React 16.8+ (Hooks support required)
- Supports Create React App, Vite, Next.js, and other build tools
2. Component Usage
2.1 Basic Usage Example
import React, { useRef } from 'react';
import { ZwPlayer } from 'zwplayer-react';
function VideoPlayer() {
const playerRef = useRef(null);
const movieUrl = 'https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggso3185.mp4';
const handlePlayerReady = () => {
console.log('Player ready event.');
const player = playerRef.current;
// Player methods can be called here
};
const handlePlayerMediaEvent = (event) => {
console.log('media event:', event.type);
};
return (
<div className="player-container">
<ZwPlayer
ref={playerRef}
nodeid="main-player"
murl={movieUrl}
onready={handlePlayerReady}
onmediaevent={handlePlayerMediaEvent}
autoplay={false}
snapshotButton={true}
optionButton={true}
infoButton={true}
enableDanmu={true}
chapterButton={true}
fluid={true}
disableMutedConfirm={true}
/>
</div>
);
}
export default VideoPlayer;
2.2 Danmaku Function Example
import React, { useRef } from 'react';
import { ZwPlayer } from 'zwplayer-react';
function DanmuPlayer() {
const playerRef = useRef(null);
const movieUrl = 'https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggso3185.mp4';
const handlePlayerReady = () => {
console.log('Player ready event.');
const player = playerRef.current;
// Add test danmaku
setTimeout(() => {
if (player && player.appendDanmu) {
player.appendDanmu({
border: '1px solid #ccc',
text: 'Welcome to ZWPlayer danmaku demo!',
color: '#ff6b6b'
});
}
}, 3000);
};
const handleSendDanmu = (danmuText) => {
if (!danmuText) return;
const player = playerRef.current;
let danmu;
try {
const jtext = JSON.parse(danmuText);
danmu = {
border: '1px solid #ccc',
text: jtext['text']
};
} catch (e) {
danmu = {
border: '1px solid #ccc',
text: danmuText
};
}
if (player && player.appendDanmu) {
player.appendDanmu(danmu);
}
};
return (
<div>
<ZwPlayer
ref={playerRef}
murl={movieUrl}
onready={handlePlayerReady}
autoplay={false}
sendDanmu={handleSendDanmu}
enableDanmu={true}
danmuBarId="danmu-controlbar"
disableMutedConfirm={true}
fluid={true}
/>
<div id="danmu-controlbar" className="danmubar"></div>
</div>
);
}
export default DanmuPlayer;
Danmaku control bar styles:
.danmubar {
height: 50px;
background-color: #232323;
padding: 8px;
box-sizing: border-box;
display: flex;
}
.danmubar .zwp_danmu-controlbar {
width: 60%;
}
2.3 Logo Watermark Example
import React, { useRef } from 'react';
import { ZwPlayer } from 'zwplayer-react';
function LogoPlayer() {
const playerRef = useRef(null);
const movieUrl = 'https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggso3185.mp4';
const poster = 'https://cdn.zwplayer.cn/media/b44c43c90be3521bc352aad1e80f9cd0_thumb.jpg';
const logoConfig = {
icon: 'https://cdn.zwplayer.cn/logo.png',
dock: 'right', // Position: left, right
x: '5%', // Horizontal offset
y: '5%', // Vertical offset
width: '10%', // Width
height: '10%', // Height
opacity: 70 // Opacity 0-100
};
return (
<ZwPlayer
ref={playerRef}
murl={movieUrl}
logo={logoConfig}
poster={poster}
autoplay={false}
disableMutedConfirm={true}
fluid={true}
/>
);
}
export default LogoPlayer;
2.4 Thumbnail Example
import React, { useRef } from 'react';
import { ZwPlayer } from 'zwplayer-react';
function ThumbnailPlayer() {
const playerRef = useRef(null);
const movieUrl = 'https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggso3185.mp4';
const thumbnails = {
url: 'https://cdn.zwplayer.cn/media/b44c43c90be3521bc352aad1e80f9cd0_thumb.jpg',
width: 160,
height: 90,
row: 9,
col: 9,
total: 74
};
return (
<ZwPlayer
ref={playerRef}
murl={movieUrl}
thumbnails={thumbnails}
fluid={true}
/>
);
}
export default ThumbnailPlayer;
2.5 Chapter Segmentation Example
import React, { useRef } from 'react';
import { ZwPlayer } from 'zwplayer-react';
function ChapterPlayer() {
const playerRef = useRef(null);
const movieUrl = 'https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggso3185.mp4';
const handlePlayerReady = () => {
const player = playerRef.current;
const chapters = [
{
title: "Chapter 1",
desc: "Chapter 1 description",
time: 0,
duration: 50,
thumb: null
},
{
title: "Chapter 2",
desc: "Chapter 2 description",
time: 50,
duration: 100,
style: { background: "blue" },
image: null
},
{
title: "Chapter 3",
desc: "Chapter 3 description",
time: 100,
duration: 200,
style: { background: "green" },
image: null
}
];
if (player) {
player.setChapters(chapters);
}
};
return (
<ZwPlayer
ref={playerRef}
murl={movieUrl}
onready={handlePlayerReady}
chapterButton={true}
fluid={true}
/>
);
}
export default ChapterPlayer;
2.6 Route Switching (with React Router)
zwplayer-react has built-in support for react-router-dom. When react-router-dom is installed, the component automatically monitors route changes and safely cleans up player resources before route transitions, preventing DOM access errors.
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { ZwPlayer } from 'zwplayer-react';
function VideoPage() {
const playerRef = useRef(null);
return (
<ZwPlayer
ref={playerRef}
murl="https://cdn.zwplayer.cn/media/video.mp4"
fluid={true}
/>
);
}
// Player is automatically safely destroyed on route change
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/video" element={<VideoPage />} />
<Route path="/other" element={<div>Other Page</div>} />
</Routes>
</BrowserRouter>
);
}
Note: react-router-dom is an optional dependency and will not affect normal player usage when not installed.
3. Modified Attributes
The attributes of the ZwPlayer component are largely the same as the properties of the native zwplayer constructor parameter object, but zwplayer-react has adjusted some attributes:
| Attribute Name | Description | Notes |
|---|---|---|
| murl | Media address parameter (can be string, object, or array type). If this attribute changes during runtime, the component will automatically call the play method to open the new address. By changing the bound state variable, you can dynamically switch playback programs. |
Behavior changed |
| nodeid | Used for the id of the ZwPlayer component’s top-level parent div. If not provided, the component will automatically generate one. |
Added |
| zwplayerlib | zwplayer library address. zwplayer-react uses a dynamic loading mechanism at the underlying level, and will not compile the underlying zwplayer library into the project with React’s build command. This allows for direct replacement of the zwplayer library file after the project is compiled and published for seamless upgrades. This parameter can be omitted; if omitted, the path zwplayer/zwplayer.js in the public directory is used. |
Added |
| danmuBarId | Used to locate the id of the div element for the zwplayer danmaku input control bar. Providing this parameter avoids calling the buildDanmuControlbar function to create a danmaku control bar. The control bar’s class name is zwp_danmu-controlbar. |
Added |
| style | Inline style object applied to the player container div. | Added |
| videoprop | Video element property object, can contain url and videostyle properties. |
Added |
| onready | Player initialization completed callback function, receives the player instance as parameter. | Event property |
| onmediaevent | Media event callback function, receives the event object as parameter. | Event property |
| onneterror | Network error callback function. | Event property |
| onnetclose | Network close callback function. | Event property |
| onFileSelected | File selection callback function. | Event property |
| onFileLoaded | File loaded callback function. | Event property |
| Other | Please refer to the parameter description of the zwplayer player constructor. |
Common Attributes Description
Display Control Related:
autoplay: Whether to autoplay (boolean, defaultfalse)fluid: Whether to enable fluid layout (boolean, defaultfalse)snapshotButton: Whether to show the snapshot button (boolean)optionButton: Whether to show the option button (boolean)infoButton: Whether to show the info button (boolean)chapterButton: Whether to show the chapter menu button (boolean)enableDanmu: Whether to enable danmaku function (boolean)
Media Related:
murl: Media address (string,object, orarray)poster: Poster image address (string)thumbnails: Thumbnail configuration (object)
Function Related:
sendDanmu: Danmaku send callback function (function)disableMutedConfirm: Whether to disable muted confirmation (boolean)keepAudioWindow: Whether to keep audio window (boolean)localPlayback: Whether to play locally (boolean)recordButton: Whether to show record button (boolean)segmentButton: Whether to show segment button (boolean)
4. Method Calls
The ZwPlayer component exposes player methods through React’s forwardRef + useImperativeHandle pattern. Use useRef to get the component reference and call methods.
4.1 Obtaining Player Instance
import React, { useRef } from 'react';
import { ZwPlayer } from 'zwplayer-react';
function VideoPlayer() {
const playerRef = useRef(null);
const handlePlayerReady = () => {
const player = playerRef.current;
console.log('Player instance:', player);
};
return (
<ZwPlayer
ref={playerRef}
murl="video.mp4"
onready={handlePlayerReady}
/>
);
}
4.2 Common Methods
// Play/Pause/Resume/Stop
playerRef.current.play();
playerRef.current.pause();
playerRef.current.resume();
playerRef.current.stop();
// Seek to specified time (seconds)
playerRef.current.seekTime(30);
// Add danmaku
playerRef.current.appendDanmu({
border: '1px solid #ccc',
text: 'This is a danmaku message',
color: '#ff6b6b'
});
// Set chapters
playerRef.current.setChapters([{
title: "Chapter 1",
desc: "Chapter 1 description",
time: 0,
duration: 50
}]);
// Get current playback time
const currentTime = playerRef.current.getCurrentTime();
// Get total video duration
const duration = playerRef.current.getDuration();
// Volume and mute
playerRef.current.setMute(true);
// Fullscreen
playerRef.current.setullscr(true);
// Subtitles
playerRef.current.addSubtitle('https://example.com/subtitle.vtt', 0, 'English');
playerRef.current.removeSubtitle();
// Danmaku control
playerRef.current.setEnableDanmu(true);
// Danmaku control bar
playerRef.current.buildDanmuControlbar('danmu-bar-id', 'custom-class');
// Notify size change
playerRef.current.notifyResize(800, 450);
// Light control
playerRef.current.lightOff();
playerRef.current.lightOn();
// Get raw player instance (advanced usage)
const rawPlayer = playerRef.current.player;
// Destroy player
playerRef.current.destroy();
5. StrictMode Compatibility
React 18’s StrictMode triggers useEffect twice in development mode, which may cause duplicate player creation. zwplayer-react includes a built-in instance caching mechanism to handle this:
- Uses
window.__zwplayer_instances__global Map to track player instances - Automatically reuses existing instances when duplicate creation is detected
- Safely cleans up all resources (timers, ResizeObserver, DOM references, etc.) on component unmount
Note: This mechanism does not incur additional overhead in production mode.
6. Example Repositories
- Gitee: https://gitee.com/chenfanyu/zwplayer-react-demo
- GitHub: https://github.com/chenfanyu/zwplayer-react-demo
7. Notes
7.1 Project Configuration
- Directory Structure: Ensure a
publicdirectory exists in the project before installation. - Core Library: The
public/zwplayerdirectory must be published along with the project. - Dynamic Loading:
zwplayeruses a dynamic loading mechanism that supports seamless upgrades and will not be packaged into the final bundle. - Method Calls: Call player methods via
useRefreferences.
7.2 Best Practices
-
Use Conditional Rendering to Control Display
{showPlayer && ( <ZwPlayer ref={playerRef} murl={movieUrl} fluid={true} /> )}Use conditional rendering (
&&or ternary operator) instead of CSS hiding to ensure the player is initialized and destroyed correctly. -
Wait for Player Ready Before Calling Methods
const handlePlayerReady = () => { const player = playerRef.current; // Methods can only be called after player is ready player.seekTime(30); }; -
Dynamic Video Switching
Directly modify the
murlstate value, and the component will automatically reload:const [videoUrl, setVideoUrl] = useState('video1.mp4'); // Switch video setVideoUrl('video2.mp4'); -
Responsive Layout
.player-container { width: 100%; max-width: 1280px; margin: 0 auto; } @media (max-width: 768px) { .player-container { width: 100%; height: auto; aspect-ratio: 16/9; } }
7.3 Common Questions
Q: Why is the player not displaying?
A: Check the following points:
- Ensure the media URL is accessible.
- Check the browser console for error messages.
- Confirm the
public/zwplayerdirectory exists and contains required files. - Confirm using
{showPlayer && <ZwPlayer ... />}instead of CSS hiding.
Q: How to dynamically switch videos?
A: Directly modify the murl state value:
const [videoUrl, setVideoUrl] = useState('video1.mp4');
setVideoUrl('new-video-url.mp4');
Q: Why are there two players in StrictMode?
A: This is expected behavior in React 18 StrictMode. zwplayer-react has a built-in instance caching mechanism to automatically handle this issue without additional configuration.
Q: How to customize danmaku control bar styles?
A: Control directly through CSS class names:
.danmubar .zwp_danmu-controlbar {
width: 60%;
background-color: #232323;
}
Q: How to get the current status of the player?
A: Call the corresponding methods after obtaining the component reference via useRef:
const player = playerRef.current;
const currentTime = player.getCurrentTime();
const duration = player.getDuration();
7.4 Project Structure Recommendations
Create React App Project Structure:
your-react-project/
├── public/
│ └── zwplayer/ # Player core library (auto-generated, must be published)
├── src/
│ ├── components/
│ │ └── VideoPlayer.jsx # Player wrapper component
│ ├── pages/
│ │ └── VideoPage.jsx # Page using the player
│ ├── App.jsx
│ └── index.js
├── package.json
└── vite.config.js (or react-scripts)
7.5 Debugging Suggestions
-
Listen to Player Ready Event
const handlePlayerReady = () => { console.log('Player ready:', playerRef.current); }; -
Listen to All Media Events
const handlePlayerMediaEvent = (event) => { console.log('Media event:', event.type, event); }; -
Use Browser Developer Tools
- Check network requests to confirm
zwplayer.jsloads correctly. - Check the console for error messages.
- Use the element inspector to view the DOM structure.
- Check network requests to confirm
7.6 Performance Optimization
- Lazy Loading: For non-above-the-fold players, use conditional rendering for lazy loading.
- Destroy Instances: Player instances are automatically cleaned up when components unmount.
- Resource Preloading: Consider preloading for key videos.
- CDN Acceleration: Deploy the
zwplayercore library to a CDN and specify it using thezwplayerlibattribute.
8. Changelog
- v1.0.5: Support React 19, added route-safe switching
- v1.0.4: Added thumbnails, chapters, danmaku, and other features
- v1.0.2: Optimized StrictMode compatibility
- v1.0.1: Initial version, supports basic playback functions