How to use VideoJS plugins with ReactJS? - reactjs

I am trying to use videojs-offset plugin, with ReactJS.
But, it is showing me follwoing error -
TypeError: this.player.offset is not a function
import React, { Component } from 'react';
import './App.css';
import PropTypes from 'prop-types';
import "video.js/dist/video-js.css";
import videojs from 'video.js'
import videoJsContribHls from 'videojs-contrib-hls'
import offset from 'videojs-offset';
export default class VideoPlayer extends React.Component {
componentDidMount() {
// instantiate Video.js
this.player = videojs(this.videoNode, this.props, function onPlayerReady() {
console.log('onPlayerReady', this);
this.player.offset({
start: 10,
end: 300,
restart_beginning: false //Should the video go to the beginning when it ends
});
});
}
// destroy player on unmount
componentWillUnmount() {
if (this.player) {
this.player.dispose()
}
}
render() {
return (
<div>
<div data-vjs-player>
<video ref={ node => this.videoNode = node } className="video-js"></video>
</div>
</div>
)
}
}
This is a common issue while integrating ANY videojs plugin with reactJS.

This problem is solved with following change -
First, In VideoJS Options, the plugins should be initialized, like,
plugins: offset: {start: 10, end: 300, restart_beginning: false} }
if your plugin does not have any parameters, you can initialize it like plugin_name: {}
Then, In componentDidMount() method, register the plugin like this -
componentDidMount() {
videojs.registerPlugin('offset',offset);
this.player = videojs(this.videoNode, this.props, function
onPlayerReady() {
console.log('onPlayerReady', this);
});}
This solution works for integrating ANY videojs plugin with react.

Related

How to use leaflet-polylinedecorator in react 16.4.1

I'm trying to use the leaflet plugin polylinedecorator in react 16.4.1 (so without hooks). However, the only example I have been able to find on how to use this plugin in react is using hooks (see: How to use polylinedacorator with react leaflet), and I am unsure how I can adapt this to be able to use it in my code.
What I have so far is this polylinedecorator component:
import React, { Component } from "react";
import { Polyline } from "react-leaflet";
import L from "leaflet";
import "leaflet-polylinedecorator";
export default class PolylineDecorator extends Component {
componentDidUpdate() {
if (this.props.map) {
const polyline = L.polyline(this.props.positions).addTo(this.props.map);
L.polylineDecorator(polyline, {
patterns: [
{
offset: "100%",
repeat: 0,
symbol: L.Symbol.arrowHead({
pixelSize: 15,
polygon: false,
pathOptions: { stroke: true }
})
}
]
}).addTo(this.props.map);
}
}
render() {
return <></>;
}
}
That I am using like this:
import React, { Component } from "react";
import { Polyline, LayerGroup } from "react-leaflet";
import PolylineDecorator from "./PolylineDecorator";
export default class RouteLayer extends Component {
render() {
const { beginLocations } = this.props;
const locations = [];
const differentLocations: [];
beginLocations.forEach((location, index) => {
// some filtering going on here and pushing the locations to one of the
two arrays (locations, differentLocations)
});
return (
<LayerGroup>
<PolylineDecorator
map={this.props.map}
positions={locations}
color="#4e5c8d"
interactive={false}
/>
<PolylineDecorator
map={this.props.map}
positions={differentFloorLinesLocations}
color="red"
interactive={false}
/>
</LayerGroup>
);
}
}
The RouteLayer is nested inside the map as follows (for simplicity some components are left out):
<LeafletMap
ref={r => {
this.map = r;
if (this.props.setRefMap) {
this.props.setRefMap(r);
}
}}>
<RouteLayer
map={this.map ? this.map.leafletElement : null}
locations={locations}
/>
</LeafletMap>
Right now the polylines are drawn, however not quite as expected since the filtering doesn't seem to work (this filtering worked fine when I was just using polylines without the decorator).
The arrows I am trying to decorate the lines with are showing up, so that's good. However, I'm not happy with how the PolylineDecorator class is looking right now, this doesn't seem like the correct way to do this.
I'm also unsure if it is correct to pass the reference to the map in the way that I'm doing here.
Any suggestions on how to make this work correctly are appreciated.
For React version < 16.8 the following component demonstrates how to integrate L.polylineDecorator with React-Leaflet:
import React, { Component } from "react";
import { Polyline, withLeaflet } from "react-leaflet";
import L from "leaflet";
import "leaflet-polylinedecorator";
class PolylineDecorator extends Component {
constructor(props) {
super(props);
this.polyRef = React.createRef();
}
componentDidMount() {
const polyline = this.polyRef.current.leafletElement; //get native Leaflet polyline
const { map } = this.polyRef.current.props.leaflet; //get native Leaflet map
L.polylineDecorator(polyline, {
patterns: this.props.patterns
}).addTo(map);
}
render() {
return <Polyline ref={this.polyRef} {...this.props} />;
}
}
export default withLeaflet(PolylineDecorator);
Usage
export default class MyMap extends Component {
render() {
const { center, zoom } = this.props;
const polyline = [[57, -19], [60, -12]];
const arrow = [
{
offset: "100%",
repeat: 0,
symbol: L.Symbol.arrowHead({
pixelSize: 15,
polygon: false,
pathOptions: { stroke: true }
})
}
];
return (
<Map center={center} zoom={zoom}>
<TileLayer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png" />
<PolylineDecorator patterns={arrow} positions={polyline} />
</Map>
);
}
}
Here is a demo

Using Phaser together with React

I am trying to understand how I could use React for rendering all the UI elements and Phaser for rendering a game (using Canvas or WebGL) within the React application.
One way would be to use React's componentDidMount, so after I have my HTML ready I can use a div id to render the Phaser content. In this case who does the rendering? React of Phaser?
If the mentioned way is not the right one, could you suggest another?
There is a module for this on Github called react-phaser. Here is a CodePen that does not use any separate module.
var PhaserContainer = React.createClass({
game: null,
...
componentDidMount: function(){
this.game = new Phaser.Game(800, 400, Phaser.AUTO, "phaser-container",
{
create: this.create,
update: this.update
});
},
...
render: function(){
return (
<div className="phaserContainer" id="phaser-container">
</div>
);
}
...
}
This is not my CodePen. Credit goes to Matthias.R
Check this new WebComponent to integrate Phaser with any other framework 👍 https://github.com/proyecto26/ion-phaser
Example:
import React, { Component } from 'react'
import Phaser from 'phaser'
import { IonPhaser } from '#ion-phaser/react'
class App extends Component {
state = {
initialize: false,
game: {
width: "100%",
height: "100%",
type: Phaser.AUTO,
scene: {}
}
}
render() {
const { initialize, game } = this.state
return (
<IonPhaser game={game} initialize={initialize} />
)
}
}

use videojs plugins in react Video JS

As doc mentioned I ve initialized video js in react by doing something like this ...
import React from 'react';
import videojs from 'video.js'
export default class VideoPlayer extends React.Component {
componentDidMount() {
// instantiate video.js
this.player = videojs(this.videoNode, this.props, function onPlayerReady() {
console.log('onPlayerReady', this)
});
}
// destroy player on unmount
componentWillUnmount() {
if (this.player) {
this.player.dispose()
}
}
// wrap the player in a div with a `data-vjs-player` attribute
// so videojs won't create additional wrapper in the DOM
// see https://github.com/videojs/video.js/pull/3856
render() {
return (
<div data-vjs-player>
<video ref={ node => this.videoNode = node } className="video-js"></video>
</div>
)
}
}
I want to integrate VideoJs Overlay plugin in this...
so i ve done something like this...
import React from 'react';
import videojs from 'video.js'
export default class VideoPlayer extends React.Component {
componentDidMount() {
// instantiate video.js
this.player = videojs(this.videoNode, this.props, function onPlayerReady() {
player.overlay({
content: 'Default overlay content',
debug: true,
overlays: [{
content: 'The video is playing!',
start: 'play',
end: 'pause'
}, {
start: 0,
end: 15,
align: 'bottom-left'
}, {
start: 15,
end: 30,
align: 'bottom'
}, {
start: 30,
end: 45,
align: 'bottom-right'
}, {
start: 20,
end: 'pause'
}]
});
});
}
// destroy player on unmount
componentWillUnmount() {
if (this.player) {
this.player.dispose()
}
}
render() {
return (
<div data-vjs-player>
<video ref={ node => this.videoNode = node } className="video-js" id="videojs-overlay-player"></video>
</div>
)
}
}
While doing this it give me error like player.overlay is not function...
and if i do videojs.registerPlugin('overlay', overlay);
and call overlay function it gives me error like component Overlay is undefined
How to workout videojs plugins in react way????
You need to import videojs-overlay package before you use it.
Follow these steps :
Install the plugin: npm i videojs-overlay --save
Import the package in Player class : import overlay from 'videojs-overlay';
Register the plugin before instantiating the player: videojs.registerPlugin('overlay', overlay);
Then, player.overlay({... will work as intended.

How can I use getSVG() with react-highcharts?

I'm trying to get the SVG string for each highchart and log it to the console before I starting working on building out my function.
I think the issue I'm having is with the way that I'm calling getSVG(), but I'm not sure.
I've tried a number of things and can't seem to get it to work.
The documentation isn't very clear about it:
https://github.com/kirjs/react-highcharts
Edit: I found a similar issue here, but still can't get it to work:
https://github.com/kirjs/react-highcharts/issues/186
import React, { Component } from 'react';
import RHC from 'react-highcharts';
import Highcharts from 'highcharts';
import HighchartsExporting from 'highcharts/modules/exporting';
HighchartsExporting(Highcharts);
const ReactHighcharts = RHC.withHighcharts(Highcharts);
class Chart extends Component {
componentDidMount() {
console.log(this.refs[this.props.name].getSVG());
}
render() {
return (
<ReactHighcharts config={this.props.config} ref={this.props.name}/>
);
}
}
export default Chart;
I'm getting this error:
TypeError: this.refs[this.props.name].getSVG is not a function. (In 'this.refs[this.props.name].getSVG()', 'this.refs[this.props.name].getSVG' is undefined)
Follow the below codes to implement in yours:
const ReactHighcharts = require('react-highcharts');
class MyComponent extends React.Component {
componentDidMount() {
let chart = this.refs.chart.getChart();
let svg = chart.getSVG(); // This is your SVG
}
render() {
return <ReactHighcharts config={config} ref="chart"/>;
}
}
If the above code under componentDidMount() didn't work, then try this code:
componentDidUpdate() {
if (this.refs.chart) {
let chart = this.refs.chart.refs.chart;
let html = document.createElement('html');
html.innerHTML = chart.innerHTML;
let svg = html.getElementsByTagName('svg')[0].outerHTML; // This is your SVG
}
}
import React from 'react';
import HighchartsReact from 'highcharts-react-official';
import Highcharts from 'highcharts/highcharts';
import exporting from 'highcharts/modules/exporting';
exporting(Highcharts)
class Chart extends Component {
componentDidMount() {
console.log(this.refs[chartRef].getSVG());
}
render() {
return (
<HighchartsReact
highcharts={Highcharts}
options={...yourOptions}
ref="chartRef"
/>);
}
}
export default Chart;
Here you can access getSVG. just include exporting(Highcharts)

Can't find an internal method in a React container component

I'm trying to get AJAX-retrieved data into a parent React component so it can be fed down to a child component. I'm using the popular pattern for this defined here where a comment list is used as the example:
components/CommentList.js
import React from 'React';
export class CommentList extends React.Component {
constructor(props) {
super(props);
}
render() {
return <ul> {this.props.comments.map(renderComment)} </ul>;
}
renderComment({body, author}) {
return <li>{body}—{author}</li>;
}
}
components/CommentListContainer.js
import React from 'React';
import { CommentList } from './CommentList';
export class CommentListContainer extends React.Component {
constructor() {
super();
this.state = { comments: [] }
}
componentDidMount() {
$.ajax({
url: "http://get/some/api",
dataType: 'json',
success: function(comments) {
this.setState({comments: comments});
}.bind(this)
});
}
render() {
return <CommentList comments={this.state.comments} />;
}
}
index.js: the entry point for webpack
import React from 'react'
import { render } from 'react-dom'
import { CommentListContainer } from './components/CommentListContainer';
window.React = React;
render(
<CommentListContainer />,
document.getElementById('nav__react-target')
)
When doing all this, I get the following error:
Uncaught ReferenceError: renderComment is not defined
I've move the methods around as well as tweaked the importing of dependencies in various spots with no luck. Any ideas?
Thanks in advance.
You don't have unguarded references to sibling methods with ES2015 classes (as you do in Java / C#, etc.) - instead you need to explicitly reference this to get at the methods of the class:
render() {
// I changed map(renderComment) to map(this.renderComment)
return <ul>{this.props.comments.map(this.renderComment)}</ul>;
}

Resources