Move a square using the coordinate system in reactjs - reactjs

I need to move this square using _dragTask() function, and i also need to do to it by using the coordinate system. Anyone can do that?
import React from 'react';
import './App.css';
class App extends React.Component {
componentDidMount() {
}
constructor(props) {
super(props);
this.state = {
MainContainer: {backgroundColor: "#282c34", display: "flex", minHeight: "100vh"},
ObjectMap: [],
}
this._createObject = this._createObject.bind(this);
this._createBox = this._createBox.bind(this);
this._buttonCreateBox1 = this._buttonCreateBox1.bind(this);
this._dragTask = this._dragTask.bind(this);
}
_createObject = (object) => {
var ObjectMap = this.state.ObjectMap;
ObjectMap.push(object);
this.setState({ObjectMap: ObjectMap});
}
_createBox = (style) => {
var object = {position: "absolute", top: this.state.positionX, left: this.state.positionY};
var styleObject = Object.assign({},
object, style
)
return (
<div style={styleObject} draggable="true" onDragEnd={(event) => {this._dragTask(event)}}>
</div>
);
}
_dragTask(event) {
event.persist();
this.setState({positionX: event.screenX, positionY: event.screenY}, () => { console.log("Page X:"+ this.state.positionX + " Page Y:" + this.state.positionY); });
}
_buttonCreateBox1 = () => {
this._createObject(this._createBox({backgroundColor: "white", width: "300px", height: "300px"}));
}
render() {
return (
<div style={this.state.MainContainer}>
<button type="button" onClick={ this._buttonCreateBox1 }>Click Me!</button>
{
this.state.ObjectMap.map((item, index) => {
return item
})
}
</div>
);
}
}
export default App;
Right now, the object it created by printed in the screen by the mainloop, and added to it by _createObject() function.

just change your _dragTask method to this
_dragTask(event) {
event.target.style.top = event.clientY + "px";
event.target.style.left = event.clientX + "px";
}
and change the style of the wrapper to have position: relative
constructor(props) {
super(props);
this.state = {
MainContainer: {
backgroundColor: "#282c34",
position: "relative",
display: "flex",
minHeight: "100vh"
},
ObjectMap: []
};
...
checkout this sandbox to see full example

Related

How to Convert a Class Component to a Functional Component in React?

I had never used React Class Components And Want to shoot confetti when some event happened. I'm confused with Class Component. Hope You can help with this issue. tried by creating arrow functions and removing this keyword .But I can't understand how to transform getInstance() function even why it is there?
import React, { Component } from 'react';
import ReactCanvasConfetti from 'react-canvas-confetti';
export default class Confetti extends Component {
getInstance = (instance) => {
// saving the instance to an internal property
this.confetti = instance;
}
onClickDefault = () => {
// starting the animation
this.confetti();
}
onClickCustom = () => {
// starting the animation with custom settings
this.confetti({ particleCount: Math.ceil(Math.random() * 1000), spread: 180 });
}
onClickCallback = () => {
// calling console.log after the animation ends
this.confetti().then(() => {
console.log('do something after animation');
});
}
onClickReset = () => {
// cleaning the canvas
this.confetti.reset();
}
render() {
const style = {
position: 'fixed',
width: '100%',
height: '100%',
zIndex: -1
};
const stylediv = {
position: 'fixed',
width: '100%',
height: '100%',
zIndex: 300000
};
return (
<>
<div style={stylediv}>
<ReactCanvasConfetti
// set the styles as for a usual react component
style={style}
// set the class name as for a usual react component
className={'yourClassName'}
// set the callback for getting instance. The callback will be called after initialization ReactCanvasConfetti component
refConfetti={this.getInstance}
/>
<button onClick={this.onClickDefault}>Fire with default</button>
<button onClick={this.onClickCustom}>Fire with custom</button>
<button onClick={this.onClickCallback}>Fire with callback</button>
<button onClick={this.onClickReset}>Reset</button>
</div>
</>
);
}
}
I'm trying to create Functional Component of the above Class Component
import React, { useRef } from 'react';
import ReactCanvasConfetti from 'react-canvas-confetti';
const Confetti = () => {
const Ref = useRef()
const getInstance = (instance) => {
if (Ref.current) {
Ref.current.confetti = instance
}
}
const onClickDefault = () => {
Ref.current.confetti();
}
const onClickCustom = () => {
Ref.current.confetti({ particleCount: Math.ceil(Math.random() * 1000),
spread: 180 });
}
const onClickCallback = () => {
Ref.current.confetti().then(() => {
console.log('do something after animation');
});
}
const onClickReset = () => {
Ref.current.confetti.reset();
}
const style = {
position: 'fixed',
width: '100%',
height: '100%',
zIndex: -1
};
const stylediv = {
position: 'fixed',
width: '100%',
height: '100%',
zIndex: 300000
};
return (
<>
<div ref={Ref} style={stylediv}>
<ReactCanvasConfetti
style={style}
className={'yourClassName'}
refConfetti={getInstance}
/>
<button onClick={onClickDefault}>Fire with default</button>
<button onClick={onClickCustom}>Fire with custom</button>
<button onClick={onClickCallback}>Fire with callback</button>
<button onClick={onClickReset}>Reset</button>
</div>
</>
);
}
export default Confetti

How can I send a canvas with a filter through openvidu?

In progress of a project using WebRTC
I found the code to apply the filter using face_mesh.
The code is as follows
import { FaceMesh } from "#mediapipe/face_mesh";
import React, { useRef, useEffect, createRef } from "react";
import * as Facemesh from "#mediapipe/face_mesh";
import * as cam from "#mediapipe/camera_utils";
import Webcam from "react-webcam";
import "../stream/StreamComponent.css";
function Filter() {
const webcamRef = useRef(null);
const canvasRef = useRef(null);
const connect = window.drawConnectors;
var camera = null;
function onResults(results) {
// const video = webcamRef.current.video;
const videoWidth = webcamRef.current.video.videoWidth;
const videoHeight = webcamRef.current.video.videoHeight;
const videoRef = createRef();
console.log(videoRef);
console.log(connect);
// Set canvas width
canvasRef.current.width = videoWidth;
canvasRef.current.height = videoHeight;
const canvasElement = canvasRef.current;
const canvasCtx = canvasElement.getContext("2d");
canvasCtx.save();
canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
canvasCtx.drawImage(
results.image,
0,
0,
canvasElement.width,
canvasElement.height
);
if (results.multiFaceLandmarks) {
for (const landmarks of results.multiFaceLandmarks) {
connect(canvasCtx, landmarks, Facemesh.FACEMESH_TESSELATION, {
color: "#C0C0C070",
lineWidth: 1,
});
connect(canvasCtx, landmarks, Facemesh.FACEMESH_RIGHT_EYE, {
color: "#FF3030",
});
connect(canvasCtx, landmarks, Facemesh.FACEMESH_RIGHT_EYEBROW, {
color: "#FF3030",
});
connect(canvasCtx, landmarks, Facemesh.FACEMESH_LEFT_EYE, {
color: "#30FF30",
});
connect(canvasCtx, landmarks, Facemesh.FACEMESH_LEFT_EYEBROW, {
color: "#30FF30",
});
connect(canvasCtx, landmarks, Facemesh.FACEMESH_FACE_OVAL, {
color: "#E0E0E0",
});
connect(canvasCtx, landmarks, Facemesh.FACEMESH_LIPS, {
color: "#E0E0E0",
});
}
}
canvasCtx.restore();
}
// }
// setInterval(())
useEffect(() => {
const faceMesh = new FaceMesh({
locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/#mediapipe/face_mesh/${file}`;
},
});
faceMesh.setOptions({
maxNumFaces: 1,
minDetectionConfidence: 0.5,
minTrackingConfidence: 0.5,
});
faceMesh.onResults(onResults);
if (
typeof webcamRef.current !== "undefined" &&
webcamRef.current !== null
) {
camera = new cam.Camera(webcamRef.current.video, {
onFrame: async () => {
await faceMesh.send({ image: webcamRef.current.video });
},
width: 640,
height: 480,
});
camera.start();
}
}, []);
return (
<center>
<div className="Filter">
<Webcam
ref={webcamRef}
style={{
position: "absolute",
marginLeft: "auto",
marginRight: "auto",
left: 0,
right: 0,
textAlign: "center",
zindex: 9,
width: 640,
height: 480,
}}
/>{" "}
<canvas
ref={canvasRef}
className="output_canvas"
style={{
position: "absolute",
marginLeft: "auto",
marginRight: "auto",
left: 0,
right: 0,
textAlign: "center",
zindex: 9,
width: 640,
height: 480,
}}
></canvas>
</div>
</center>
);
}
export default Filter;
So I'm trying to send a screen with a filter through openvidu
The openvidu code that exports the default camera screen is as follows
import React, { Component } from "react";
import "./StreamComponent.css";
export default class OvVideoComponent extends Component {
constructor(props) {
super(props);
this.videoRef = React.createRef();
}
componentDidMount() {
if (this.props && this.props.user.streamManager && !!this.videoRef) {
console.log("PROPS: ", this.props);
this.props.user.getStreamManager().addVideoElement(this.videoRef.current);
}
}
componentDidUpdate(props) {
if (props && !!this.videoRef) {
this.props.user.getStreamManager().addVideoElement(this.videoRef.current);
}
}
render() {
return (
<video
autoPlay={true}
id={"video-" + this.props.user.getStreamManager().stream.streamId}
ref={this.videoRef}
muted={this.props.mutedSound}
/>
);
}
}
I think apply a canvas object or a canvas.captureStream() to an element**.props.user.getStreamManager().addVideoElement()**
But I don't know how to apply it
It's my first time using openvidu, so I'm facing a lot of difficulties
I'm so sorry if you don't have enough explanation

Dropping Over a Component inside nested Drop Targets giving error

Here is my Container Class
Code on Sandbox
`import React, { Component } from "react";
import { DropTarget } from "react-dnd";
import Box from "./Box";
class Container extends Component {
state = {
Boxes: [
{ left: 60, top: 30, text: "ITEM_1" },
{ left: 100, top: 70, text: "ITEM_2" }
]
};
render() {
const { connectDropTarget } = this.props;
return connectDropTarget(
<div
className="container"
style={{ width: "100%", height: "100vh", background: "yellow" }}
>
{this.state.Boxes.map((box, index) => {
return (
<Box
id={index}
key={index}
left={box.left}
top={box.top}
text={box.text}
moveBox={this.moveBox}
/>
);
})}
</div>
);
}
moveBox(id, left, top) {
const allBoxes = this.state.Boxes;
const singleBox = this.state.Boxes[id];
singleBox.left = left;
singleBox.top = top;
const newBox = allBoxes.filter((box, index) => index !== id);
newBox.push(singleBox);
this.setState({ Boxes: newBox });
}
}
export default DropTarget(
"items",
{
// Spec Object Started
drop(props, monitor, component) {
const item = monitor.getItem();
const delta = monitor.getDifferenceFromInitialOffset();
const left = Math.round(item.left + delta.x);
const top = Math.round(item.top + delta.y);
component.moveBox(item.id, left, top);
}
}, //Spec Oject Ended Here
(connect, monitor) => ({
connectDropTarget: connect.dropTarget()
})
)(Container);
`
And Here is my Box Class
import React, { Component } from "react";
import { DragSource, DropTarget } from "react-dnd";
import flow from "lodash/flow";
let whichDragging = "items";
class Box extends Component {
state = {};
render() {
const { left, top, text, connectDragSouce, connectDropTarget } = this.props;
return connectDragSouce(
connectDropTarget(
<div
style={{
width: "20%",
border: "2px dotted black",
margin: "auto",
position: "relative",
top: top,
left: left
}}
>
{text}
</div>
)
);
}
}
export default flow(
DragSource(
whichDragging,
{
beginDrag(props, monitor, component) {
console.log(component);
const { left, top, text, id } = props;
return {
left,
top,
text,
id
};
}
},
(connect, monitor) => ({
connectDragSouce: connect.dragSource()
})
),
DropTarget(
whichDragging,
{
drop(props, monitor, component) {
whichDragging = "nested";
const item = monitor.getItem();
const delta = monitor.getDifferenceFromInitialOffset();
const left = Math.round(item.left + delta.x);
const top = Math.round(item.top + delta.y);
console.log("Logging");
console.log(component);
// whichDragging = "items";
}
},
(connect, monitor) => ({
connectDropTarget: connect.dropTarget()
})
)
)(Box);
Simple Dragging Dropping Working fine but when i drop item_1 over item_2 or vice versa i got error and my Component in drop shows DragDropContainer in console.log i want to get the id|key of component over which one component is dropped and not able to find any solution since 2 days any help will be appriciated.

react native multiple video with Swiper component play pause issue

I have multiple videos in the swiper to show videos one by one, but all the videos are loaded and playing at the same time and audios are messed up, I want current video only play at a time.
import * as React from 'react';
import { Text, View, StyleSheet,Image, Dimensions } from 'react-native';
import { Constants } from 'expo';
import { Video } from 'expo';
import Swiper from './Swiper';
import InViewPort from './InViewport';
const screenWidth = Dimensions.get('window').width ;
const screenHeight = Dimensions.get('window').height;
export default class App extends React.Component {
constructor(props) {
super(props);
// Your source data
this.state = {
images: {},
muted : false,
paused: true,
};
this.player = Array();
this.onChangeImage = this.onChangeImage.bind(this);
}
videoError(err){
console.warn(err);
}
pauseVideo = () => {
var curr = this.state.currentIndex;
console.warn(curr);
if(this.player[curr]) {
this.setState({paused: true });
}
}
playVideo = () => {
var curr = this.state.currentIndex;
console.warn(curr);
if(this.player[curr]) {
this.setState({paused: false});
}
}
handlePlaying = (isVisible) => {
isVisible ? this.playVideo() : this.pauseVideo();
}
onChangeImage (index) {
this.setState({ currentIndex: index});
}
render() {
let items = Array.apply(null, Array(15)).map((v, i) => {
return {
id: i,
caption: i + 1,
source: { uri: 'http://placehold.it/200x200?text=' + (i + 1) },
dimension: '{ width: 150, height: 150 }',
};
});
return(
<View style={styles.DefaultView}>
<Swiper
showsPagination={false}
onIndexChanged={this.onChangeImage}
index={0}
>
{items.map((item, key) => {
if(key==1 || key ==5){
return (
<InViewPort onChange={this.handlePlaying} key={key}>
<Video onError={this.videoError}
muted={this.state.muted}
paused={this.state.paused}
source={{uri: 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4' }}
style={styles.backgroundVideo}
ref={(ref) => {
this.player[key] = ref;
}}
controls={true}
/>
</InViewPort>
)
}else{
return(
<Image
resizeMode='contain'
style={{width:screenWidth, height: screenHeight}}
source={item.source}
key={key}
/>
)
}
})}
</Swiper>
</View>
)
}
}
const styles = StyleSheet.create({
scrollView: {
flex: 1,
flexDirection: 'row',
},
DefaultView: {
flex: 1,
backgroundColor: '#000',
width: screenWidth,
justifyContent:'center',
alignItems:'center'
},
iconContainer: {
flexDirection: "row",
justifyContent: "space-evenly",
width: 150,
},
backgroundVideo: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
width: screenWidth,
height: 300,
marginTop:'50%',
position:'absolute',
},
});
I need some idea on this, we have a player reference to be used, also swiper component have onIndexChanged which will trigger when we moved to next video, how we can link the reference of the player to onIndexChanged and when we do swipe how we make it current video only to play?
As per Andrew suggestion I have used InPortView component too determine the current view of swipe, but still I am not sure how to make reference for video elements to be used in the functions for play and pause the concern video.
Components used:
For video react-native-video
For Swiper : react-native-swiper
Updated Full code with Expo example : Expo Snack
So taking your snack. I managed to get it to work.
I moved the Video out into its own component and passed a few additional props to it, the index in the array and the currentIndex showing.
export default class App extends React.Component {
constructor(props) {
super(props);
// Your source data
this.state = {
images: {},
muted : false,
paused: true,
currentIndex: 0
};
}
onChangeImage = (index) => {
console.log('currentIndex ', index)
this.setState({ currentIndex: index});
}
render() {
let items = Array.apply(null, Array(15)).map((v, i) => {
return {
id: i,
caption: i + 1,
source: { uri: 'http://placehold.it/200x200?text=' + (i + 1) },
dimension: '{ width: 150, height: 150 }',
};
});
return(
<View style={styles.DefaultView}>
<Swiper
showsPagination={false}
onIndexChanged={this.onChangeImage}
index={0}
>
{items.map((item, key) => {
if(key==1 || key ==5){
return (
<VideoPlayer key={key} index={key} currentIndex={this.state.currentIndex}/>
)
}else{
return(
<Image
resizeMode='contain'
style={{width:screenWidth, height: screenHeight}}
source={item.source}
key={key}
/>
)
}
})}
</Swiper>
</View>
)
}
}
The video component uses react-native-inviewport to help handle whether or not it is in the viewport. However it doesn't play nicely with react-native-swiper but it is possible to get it to work.
export default class VideoPlayer extends React.Component {
pauseVideo = () => {
if(this.video) {
this.video.pauseAsync();
}
}
playVideo = () => {
if(this.video) {
this.video.playAsync();
}
}
handlePlaying = (isVisible) => {
this.props.index === this.props.currentIndex ? this.playVideo() : this.pauseVideo();
}
render() {
return (
<View style={styles.container}>
<InViewPort onChange={this.handlePlaying}>
<Video
ref={ref => {this.video = ref}}
source={{ uri: 'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4' }}
rate={1.0}
volume={1.0}
isMuted={false}
resizeMode="cover"
shouldPlay
style={{ width: WIDTH, height: 300 }}
/>
</InViewPort>
</View>
)
}
}
When I used the InViewPort component alone it seemed to think that the video in position 6 was in the viewport and would play it. So what I use the InviewPort is to perform a check to compare the index of the video with the currentIndex if they match play the video otherwise pause. I suppose this could be updated to use componentDidUpdate to handle the changes in the props. However, additional checks will need to be performed when the component mounts so that it doesn't play the video.
Here is my snack with it working. https://snack.expo.io/#andypandy/swiper-video

Changing styles when scrolling React

I want to add the scrolling effect. At the start, the elements have the opacity: 0.2 property. When element is reached in the browser window, it is to replace the property with opacity: 1. At this moment, when I scroll, all elements change the property to opacity: 1. How to make this value when element is reached in the browser, the rest of the elements have the property opacity: 0.2
class QuestionListItem extends Component {
constructor() {
super();
this.state = {
opacity: 0.2,
};
}
componentDidMount = () => {
window.addEventListener('scroll', () => {
this.setState({
opacity: 1,
});
});
};
render() {
const { question } = this.props;
const { opacity } = this.state;
return (
<div>
<li
key={question.id}
className="Test__questions-item"
style={{ opacity: `${opacity}` }}
ref={
(listener) => { this.listener = listener; }
}
>
<p>
{question.question}
</p>
<QuestionAnswerForm />
</li>
</div>
);
}
}
I want effect like this https://anemone.typeform.com/to/jgsLNG
A proper solution could look like this. Of course, this is just a concept. You can fine-tune the activation/deactivation logic using props from getBoundingClientRect other than top (e.g. height, bottom etc).
Important that you should not set the component's state on every single scroll event.
const activeFromPx = 20;
const activeToPx = 100;
class ScrollItem extends React.Component {
state = {
isActive: false
}
componentDidMount = () => {
window.addEventListener('scroll', this.handleScroll);
this.handleScroll();
};
handleScroll = () => {
const { top } = this.wrapRef.getBoundingClientRect();
if (top > activeFromPx && top < activeToPx && !this.state.isActive) {
this.setState({ isActive: true });
}
if ((top <= activeFromPx || top >= activeToPx) && this.state.isActive) {
this.setState({ isActive: false });
}
}
setWrapRef = ref => {
this.wrapRef = ref;
}
render() {
const { isActive } = this.state;
return (
<div
className={`scroll-item ${isActive && 'scroll-item--active'}`}
ref={this.setWrapRef}
>
{this.props.children}
</div>
)
}
}
class ScrollExample extends React.Component {
render() {
return (
<div className="scroll-wrap">
<ScrollItem>foo</ScrollItem>
<ScrollItem>bar</ScrollItem>
<ScrollItem>eh</ScrollItem>
</div>);
}
}
ReactDOM.render(<ScrollExample />, document.getElementById('root'))
.scroll-wrap {
height: 300vh;
background: lightgray;
padding-top: 55px;
}
.scroll-item {
height: 60vh;
background: lightcyan;
margin: 10px;
opacity: 0.2;
}
.scroll-item--active {
opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You can include an isInViewport-like implementation as this one: https://gist.github.com/davidtheclark/5515733 then use it on your component.
componentDidMount = () => {
window.addEventListener('scroll', (event) => {
if (isElementInViewport(event.target) {
this.setState({
opacity: 1,
});
}
});
};
There's also read-to-use react-addons for this: https://github.com/roderickhsiao/react-in-viewport

Resources