I have a requirement where I need to play a html video with time jumps.
Scenario is like this:-
I have an array that contains time markers like this const obj = [{start: 2.64, end: 5.79}, {start: 7.95, end: 8.69}].
The requirement is that the video should start from 2.64 and play till 5.79 and then jump to 7.95 and then end at 8.69 and so on.
My solution is like this:-
const timers = this.state.timers;
let video = this.videoRef;
if (video) {
let index = 0;
video.addEventListener("timeupdate", () => {
if (parseInt(video.currentTime) == parseInt(timers[timers.length - 1].end)) {
video.pause()
}
if (timers[index]) {
if (parseInt(video.currentTime) == parseInt(timers[index].end)) {
if (index <= timers.length - 1) {
index++;
if (timers[index]) {
video.currentTime = timers[index].start;
}
}
}
}
this.setState({
tickTime: Math.ceil(video.currentTime)
})
})
video.play().then(res => {
video.currentTime = timers[0].start
})
}
It is working fine but when the video currenttime is like 2.125455 and in time object has end time 2.95, the parseInt function make both the time 3 and the video jumps to 3, so the 8 ms never plays, these 8ms are also very critical in my case
any solution on this please?
I am stuck for a while now
Well, I was able to resolve the problem
Thanks anyways
Here is the solution if anyone else facing it
const timers = this.state.timers;
let video = this.videoRef;
if (video) {
let index = 0;
video.addEventListener("timeupdate", () => {
if (video.currentTime >= timers[timers.length - 1].end) {
video.pause()
}
if (timers[index]) {
if ((video.currentTime) >= (timers[index].end)) {
if (index <= timers.length - 1) {
index++;
if (timers[index] && video.currentTime < timers[index].start) {
video.currentTime = timers[index].start;
}
}
}
}
this.setState({
tickTime: Math.ceil(video.currentTime)
})
})
video.play().then(res => {
video.currentTime = timers[0].start
})
}
Related
Is it possible to create a graph sorted in each time interval using Highcharts?
For expample, in this picture for January data will be in order: New York, Tokyo, London, Berlin. The same for each months - data should be shown decrease order
Highcharts doesn't have a built-in function to do that, but for example you can use the render event and organize columns, by changing their positions in the way you need.
events: {
render: function() {
var series = this.series,
longestSeries = series[0],
sortedPoints = [],
selectedPoints = [];
// find a series with the highest amount of points
series.forEach(function(s) {
if (s.points.length > longestSeries.points.length) {
longestSeries = s;
}
});
longestSeries.points.forEach(function(point) {
series.forEach(function(s) {
selectedPoints.push(s.points[point.index]);
});
sortedPoints = selectedPoints.slice().sort(function(a, b) {
return b.y - a.y;
});
selectedPoints.forEach(function(selectedPoint) {
if (
selectedPoints.indexOf(selectedPoint) !==
sortedPoints.indexOf(selectedPoint) &&
selectedPoint.graphic
) {
// change column position
selectedPoint.graphic.attr({
x: sortedPoints[selectedPoints.indexOf(selectedPoint)].shapeArgs.x
});
}
});
sortedPoints.length = 0;
selectedPoints.length = 0;
});
}
}
Live demo: https://jsfiddle.net/BlackLabel/tnrch8v1/
API Reference:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr
#ppotaczek Thank You for help a lot! I solve my issue, but i had to make some changes to your code:
events: {
render: function() {
if (this.series.length === 0) return
var series = this.series,
longestSeries = series[0],
sortedPoints = [],
selectedPoints = [];
// find a series with the highest amount of points
series.forEach(function(s) {
if (s.points.length > longestSeries.points.length) {
longestSeries = s;
}
});
longestSeries.points.forEach(function(point) {
series.forEach(function(s) {
selectedPoints.push(s.points[point.index]);
});
sortedPoints = selectedPoints.slice().sort(function(a, b) {
return b.y - a.y;
});
selectedPoints.forEach(function(selectedPoint) {
if (
selectedPoints.indexOf(selectedPoint) !==
sortedPoints.indexOf(selectedPoint) &&
selectedPoint.graphic
) {
// change column position
selectedPoint.graphic.attr({
x: selectedPoints[sortedPoints.indexOf(selectedPoint)].shapeArgs.x
});
}
});
sortedPoints.length = 0;
selectedPoints.length = 0;
});
}
},
}
So i changed:
// change column position
selectedPoint.graphic.attr({
x: sortedPoints[selectedPoints.indexOf(selectedPoint)].shapeArgs.x
});
to:
// change column position
selectedPoint.graphic.attr({
x: selectedPoints[sortedPoints.indexOf(selectedPoint)].shapeArgs.x
});
I have a vue function call which is triggered when selecting a radio button but it seems that my code inside my $nextTick is running before my previous line of code is finished. I don't want to use setTimout as I don't know how fast the user connection speed is.
findOrderer() {
axios.post('/MY/ENDPOINT')
.then((response) => {
this.orderers = response.data.accounts;
console.log('FIND_ORDER', this.orderers)
...OTHER_CODE
}
rbSelected(value) {
this.findOrderer();
this.newOrderList = [];
this.$nextTick(() => {
for (var i = 0, length = this.orderers.length; i < length; i++) {
console.log('FOR')
if (value.srcElement.value === this.orderers[i].accountType) {
console.log('IF')
this.newOrderList.push(this.orderers[i]);
}
}
this.$nextTick(() => {
this.orderers = [];
this.orderers = this.newOrderList;
console.log('orderers',this.orderers)
})
})
}
Looking at the console log the 'FINE_ORDERER' console.log is inside the 'findOrderer' function call so I would have expected this to be on top or am I miss using the $nextTick
That's expected, since findOrderer() contains asynchronous code. An easy way is to simply return the promise from the method, and then await it instead of waiting for next tick:
findOrderer() {
return axios.post('/MY/ENDPOINT')
.then((response) => {
this.orderers = response.data.accounts;
console.log('FIND_ORDER', this.orderers);
});
},
rbSelected: async function(value) {
// Wait for async operation to complete first!
await this.findOrderer();
this.newOrderList = [];
for (var i = 0, length = this.orderers.length; i < length; i++) {
console.log('FOR')
if (value.srcElement.value === this.orderers[i].accountType) {
console.log('IF')
this.newOrderList.push(this.orderers[i]);
}
}
this.orderers = [];
this.orderers = this.newOrderList;
console.log('orderers',this.orderers)
}
I'm trying another solution to my problem:
The thing is: im rendering a Sketch component with a background image and sketching over it
onReady = async () => {
const { layoutWidth, layoutHeight, points } = this.state;
this.sketch.graphics = new PIXI.Graphics();
const linesStored = this.props.screenProps.getSketchLines();
if (this.sketch.stage) {
if (layoutWidth && layoutHeight) {
const background = await PIXI.Sprite.fromExpoAsync(this.props.image);
background.width = layoutWidth * scaleR;
background.height = layoutHeight * scaleR;
this.sketch.stage.addChild(background);
this.sketch.renderer._update();
}
if (linesStored) {
for(let i = 0; i < linesStored.length; i++) {
this.sketch.stage.addChild(linesStored[i])
this.sketch.renderer._update();
}
}
}
};
this lineStored variable is returning a data i've saved onChange:
onChangeAsync = async (param) => {
const { uri } = await this.sketch.takeSnapshotAsync();
this.setState({
image: { uri },
showSketch: false,
});
if (this.sketch.stage.children.length > 0) {
this.props.screenProps.storeSketchOnState(this.sketch.stage.children);
}
this.props.callBackOnChange({
image: uri,
changeAction: this.state.onChangeAction,
startSketch: this.startSketch,
undoSketch: this.undoSketch,
});
};
storeSketchOnState saves this.sketch.stage.children; so when i change screen and back to the screen my Sketch component in being rendered, i can retrieve the sketch.stage.children from App.js state and apply to Sketch component to persist the sketching i was doing before
i'm trying to apply the retrieved data like this
if (linesStored) {
for(let i = 0; i < linesStored.length; i++) {
this.sketch.stage.addChild(linesStored[i])
this.sketch.renderer._update();
}
}
```
but it is not working =(
I'm writing Webrtc chrome desktop app by accessing 2 camera simultaneously using latest Chrome Windows version.
Accessing camera list by navigator.mediaDevices.enumerateDevices() is ok but accessing these device by their specific id using navigator.mediaDevices.getUserMedia not work.
It only occurs sometimes. But no error in the catch.
So, I tried navigator.mediaDevices.getUserMedia is really exists or not.
if (navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
}
Yes, it was.
Just not getting any log info in calling navigator.mediaDevices.getUserMedia()
getVideoSources_ = function() {
return new Promise(function(resolve, reject) {
if (typeof navigator.mediaDevices.enumerateDevices === 'undefined') {
alert('Your browser does not support navigator.mediaDevices.enumerateDevices, aborting.');
reject(Error("Your browser does not support navigator.mediaDevices.enumerateDevices, aborting."));
return;
}
requestVideoSetTimeout = 500;
navigator.mediaDevices.enumerateDevices().then((devices) => {
// get the list first by sorting mibunsho camera in first place
for (var i = 0; i < devices.length; i++) {
log("devices[i]", JSON.stringify(devices[i]));
log("devices[i].label", devices[i].label);
if (devices[i].kind === 'videoinput' && devices[i].deviceId && devices[i].label) {
if (devices[i].label.indexOf("USB_Camera") > -1) {
deviceList[1] = devices[i];
} else {
deviceList[0] = devices[i];
}
}
}
// request video by sorted plan
for (var i = 0; i < deviceList.length; i++) {
requestVideo_(deviceList[i].deviceId, deviceList[i].label, resolve, reject);
requestVideoSetTimeout = 1000; // change requestVideoSetTimeout for next video request
}
}).catch((err) => {
log("getVideoSources_:" + err.name + ": " + err.message);
reject(Error("getVideoSources_ catch error"));
});
});
}
getVideoSources_().then(function(result) {
....
}).catch(function(err) {
....
});
function requestVideo_(id, label, resolve, reject) {
if (navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
log("navigator.mediaDevices.getUserMedia found!");
navigator.mediaDevices.getUserMedia({
video: {
deviceId: {exact: id},
width: 640,
height: 480,
frameRate: {
ideal: 20,
max: 20
}
},
audio: false}).then(
(stream) => {
log("***requestVideo_", id);
log("***requestVideo_", label);
log("***requestVideo_", stream);
// USB_Camera is face camera
if (label.indexOf("USB_Camera") > -1) {
log("***requestVideo_001");
myStream2 = stream;
log("***requestVideo_myStream2", myStream2);
} else {
log("***requestVideo_002");
myStream = stream;
log("***requestVideo_myStream", myStream);
getUserMediaOkCallback_(myStream, label);
}
resolve("###Video Stream got###");
stream.getVideoTracks()[0].addEventListener('ended', function(){
log("***Camera ended event fired. " + id + " " + label);
endedDevice[id] = label;
});
},
getUserMediaFailedCallback_
).catch((error) => {
log('requestVideo_: ' + error.name);
reject(Error("requestVideo_ catch error" + error.name));
});
}
}
function getUserMediaFailedCallback_(error) {
log("getUserMediaFailedCallback_ error:", error.name);
alert('User media request denied with error: ' + error.name);
}
#Kaiido is right, resolve is called in a for-loop here, which is all over the place, and before all the code has finished. Any error after this point is basically lost.
This is the promise constructor anti-pattern. In short: Don't write app code inside promise constructors. Don't pass resolve and reject functions down. Instead, let functions return promises up to you, and add all app code in then callbacks on them. Then return all promises so they form a single chain. Only then do errors propagate correctly.
See Using promises on MDN for more.
I am trying to implement a drag and drop solution in react-native and I want to make my flatlist scroll if I drag an item in the upper 10 percent and bottom 10 percent of the view. So far the only way i can get it to happen is by calling a function that recursively dispatches a this._flatList.scrollToOffset({ offset, animated: false });. The recursive call stops when a certain condition is met but the scrolling effect is choppy. Any advice on making that smoother?
// on move pan responder
onPanResponderMove: Animated.event([null, { [props.horizontal ? 'moveX' : 'moveY']: this._moveAnim }], {
listener: (evt, gestureState) => {
const { moveX, moveY } = gestureState
const { horizontal } = this.props
this._move = horizontal ? moveX : moveY;
const { pageY } = evt.nativeEvent;
const tappedPixel = pageY;
const topIndex = Math.floor(((tappedPixel - this._distanceFromTop + this._scrollOffset) - this._containerOffset) / 85);
const bottomIndex = Math.floor(((tappedPixel + (85 - this._distanceFromTop) + this._scrollOffset) - this._containerOffset) / 85);
this.setTopAndBottom(topIndex, bottomIndex);
this.scrolling = true;
this.scrollRec();
}
}),
// recursive scroll function
scrollRec = () => {
const { activeRow } = this.state;
const { scrollPercent, data, } = this.props;
const scrollRatio = scrollPercent / 100;
const isLastItem = activeRow === data.length - 1;
const fingerPosition = Math.max(0, this._move - this._containerOffset);
const shouldScrollUp = fingerPosition < (this._containerSize * scrollRatio); // finger is in first 10 percent
const shouldScrollDown = !isLastItem && fingerPosition > (this._containerSize * (1 - scrollRatio)) // finger is in last 10
const nextSpacerIndex = this.getSpacerIndex(this._move, activeRow);
if (nextSpacerIndex >= this.props.data.length) { this.scrolling = false; return this._flatList.scrollToEnd(); }
if (nextSpacerIndex === -1) { this.scrolling = false; return; }
if (shouldScrollUp) this.scroll(-20);
else if (shouldScrollDown) this.scroll(20);
else { this.scrolling = false; return; };
setTimeout(this.scrollRec, 50);
}
/
Yeah, pass an options object to your Animated.event with your listener with useNativeDriver set to true
Animated.event([
null,
{ [props.horizontal ? "moveX" : "moveY"]: this._moveAnim },
{
listener: ...,
useNativeDriver: true
}
]);
Should make things significantly smoother.
edit: I feel I should add that there is probably a saner way to accomplish this, are you only using a FlatList because of it's "infinite" dimensions?