React - Remove image based on position within window - reactjs

I have a video running in the background of my app. The problem is when you go all the way to the bottom of the site, the video pokes out from underneath if you overscroll. I need to not see the video peak out from under the rest of the app.
I'm in React, so it's a bit tricky. I tried this:
let styles = "video-foreground"
function parallax(){
let ypos = window.pageYOffset;
if(ypos > 420) {
styles = "video-blackout"
} else {
styles = "video-foreground"
}
}
window.addEventListener('scroll', parallax);
CSS
.video-blackout {
display: none;
}
"styles" is the style I put on the video. But this doesn't work well. It sometimes doesn't get rid of the video for a few seconds. Other times it doesn't put the video back after you scroll back up for a few seconds. I'm not sure why the delay happens, but it does.
Is there a better way to do this?

This worked. Injecting the style was creating a delay. Doing it directly worked.
function parallax(){
let ypos = window.pageYOffset;
if(ypos > 420) {
document.getElementById('banner').style.display = 'none';
} else {
document.getElementById('banner').style.display = 'block';
}
}
window.addEventListener('scroll', parallax);

Related

how to fix this Error Cannot use the same canvas during multiple render() operations

I am using canvas in react and rendering pdf's as images using the canvas.
Now, when I get new data i.e another pdf get's added, then
again have to use the canvases for that.
I am not sure how to fix this error or how to remove the canvas or even clear the canvas before using it again.
Here's the relevant code:
pdfLoop = (item,index) => {
var that = this;
PDFJS.getDocument(item).then(function getPdfHelloWorld(pdf) {
//
// Fetch the first page
console.log('url is : ',item);
pdf.getPage(1).then(function getPageHelloWorld(page) {
var scale = 0.5;
var viewport = page.getViewport(scale);
let cref = 'canvas'+index;
let imgref ='img'+index;
console.log('cref no : ',cref);
console.log('img no : ',imgref);
// Prepare canvas using PDF page dimensions
//
var canvas = that.canvasRefs[cref];
//let imagez = that.imageRefs[imgref];
var context = canvas.getContext('2d');
context.globalcompositeoperation = 'source-over';
// context.fillStyle = "#fff";
//draw on entire canvas
//context.fillRect( 0, 0, canvas.width, canvas.height );
canvas.height = viewport.height;
canvas.width = viewport.width;
//imagez.src = canvas.toDataURL("image/png");
//
// Render PDF page into canvas context
//
//page.render({canvasContext: context, viewport: viewport});
var task = page.render({canvasContext: context, viewport: viewport})
task.promise.then(function(){
//console.log(canvas.toDataURL('image/png'));
let imgItem = {imgref:canvas.toDataURL('image/png'),page:index+1,rotate:0}
let newState = that.state.imgsrc;
newState[index] = imgItem;
//let newState = that.state.imgsrc.concat(imgItem);
that.setState({
imgsrc:newState
});
//imagez.src = canvas.toDataURL('image/png')
});
});
});
}
In case someone stumbles across this, the error message states the following Use different canvas or ensure previous operations were cancelled or completed.
When getting the document, if there already is a document, it has to be destroyed. I.e:
PDFJS.getDocument({ url: pdf_url }).promise
.then((pdf_doc) => {
if (this.pdf_doc) {
this.pdf_doc.destroy();
}
this.pdf_doc = pdf_doc;
this.total_pages = this.pdf_doc.numPages;
})
I have no idea if this is a good solution, but at least it worked for me.
I've had the same exact problem as you, but my solution was a bit different than the answers previously posted.
For me the problem was the fact that I was unnecessarily re-rendering with a state change. Check if you aren't re-rendering the component without properly clearing the canvas, or if you even need to re-render at all (in my case I didn't).
Hopefully this could help
In order to avoid this situation, put your canvas object in a div object as is shown below:
<div id="div_canvas">
<canvas id="cnv"></canvas>
</div>
Then, before to call pdf.js functions, remove the "div_canvas" content and recreate it:
$("#div_canvas").html("");
$("#div_canvas").html("<canvas id='cnv'></canvas>");
I had exactly the same issue when working with PDF.js, the solution to this is,
You will have to clear your context after the render completes.
if (context) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
}
This will make sure that the context is cleared and ready for the next render and the error disappears.
this worked for me.
In some cases, this error will be displayed when the pdf has action buttons such as next/previous or scaling.
In this cases, often you have a function for rendering pdf page such as:
renderPage(num) {
// Using promise to fetch the page
pdfDoc.getPage(num).then(function (page) {
const viewport = page.getViewport({scale: scale});
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
const renderContext = {
canvasContext: ctx,
viewport: viewport
};
page.render(renderContext);
});
}
To fix the error just perform following changes:
Add two variable for controlling conflict and cache waiting page number:
pageRendering = false; // Check conflict
pageNumPending = null; // Cache waiting page number
Use these variables as follow:
renderPage(num) {
if (this.pageRendering) { // Check if other page is rendering
this.pageNumPending = num; // Cache waited page number until previous page rendering completed
} else {
this.pageRendering = true;
// Using promise to fetch the page
pdfDoc.getPage(num).then(function (page) {
const viewport = page.getViewport({scale: scale});
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
const renderContext = {
canvasContext: ctx,
viewport: viewport
};
const renderTask = page.render(renderContext);
// Wait for rendering to finish
renderTask.promise.then(function () {
this.pageRendering = false;
if (pageNumPending !== null) {
// Waited page must be rendered
this.renderPage(pageNumPending);
// Must be set to null to prevent infinite loop
this.pageNumPending = null;
}
});
});
One possible cause: React Strict mode renders twice

Angular1 perfect scrollbar : After refreshing the data, how to get it back to the top

I set the scroll bar for the table. When I scroll to the bottom of the current page and click on the next page, the scroll position does not get back to the top. How can I get it back to the top after the data is refreshed? Thanks.
It could be done a lot of ways, how are you handling pagination? You could place a ng-click on the pagination button that scrolls you to the top. A code sample or plunkr would be helpful.
You could do something like below using regular JS.
var btn = document.getElementById('x');
btn.addEventListener("click", function() {
var i = 10;
var int = setInterval(function() {
window.scrollTo(0, i);
i += 10;
if (i == 200) clearInterval(int);
}, 20);
})
body {
background: lightblue;
height: 600px;
}
\HTML in view layer
<button id='x'>click</button>

Animating a height value for text input

So i am using react-native-autogrow-textinput in order to have an editable document viewable in my application. I am currently trying to work around the keyboard in order to adjust the height of textinput box, so that all text is visible. I have found the following code to do so
componentWillMount () {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow.bind(this));
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide.bind(this));
}
componentWillUnmount () {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
keyboardDidShow(e){
let newSize = Dimensions.get('window').height- e.endCoordinates.height - 150;
console.log(e.endCoordinates);
this.setState({docViewHeight: newSize});
}
keyboardDidHide(e){
let newSize = Dimensions.get('window').height - 170;
this.setState({docViewHeight: newSize})
}
However, the result i am getting is: When the keyboard is animating off screen, the height of the textinput remains the same, let newSize = Dimensions.get('window').height- e.endCoordinates.height - 150, untill the keyboard has finished sliding off screen.
The height then adjusts to fill the whole screen again, except it sort of 'pops' into the new height. How do i get the value of this height to gradually grow, so it looks like it is simply extending to fit the whole screen? Ill post my Autogrow TextInput code below also. Any help would be much appreciated.
<AutoGrowingTextInput
ref="editText"
editable = {this.state.editting}
style = {{fontSize: fontProperties.fontSize+3, marginLeft: 18, marginRight: 18, marginTop: 15}}
/*animate this*/ minHeight = {this.state.docViewHeight}
animation = {{animated: true, duration: 300}}
//has some other confidential props here for onChange etc
</AutoGrowingTextInput>
Found the answer myself, after digging through some library files.
The solution is to use a keyboardWillHide event listener instead of keyboardDidHide.
This will fire before the keyboard begins its outro animation. Ive put the code below.
componentWillMount () {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow.bind(this));
this.keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide.bind(this));
}
componentWillUnmount () {
this.keyboardDidShowListener.remove();
this.keyboardWillHideListener.remove();
}
keyboardWillHide(e){
let newSize = Dimensions.get('window').height - 170;
this.setState({docViewHeight: newSize})
}

How to trigger animations in a React app based on the scroll position

Let's say I need to add an element to the navbar when the user have scrolled past the header of the site. How can I do something like this in React without using jQuery?
You can do some thing like this: (this function was copied from my own react-sticky-dynamic-header that I created before: https://github.com/thinhvo0108/react-sticky-dynamic-header )
componentDidMount() {
var h1 = parseInt(this.refs.header.offsetHeight);
window.addEventListener('scroll', this._calcScroll.bind(this, h1));
}
componentWillUnmount() {
window.removeEventListener('scroll', this._calcScroll)
}
_calcScroll(h1) {
var _window = window;
var heightDiff = parseInt(h1);
var scrollPos = _window.scrollY;
if (scrollPos > heightDiff) {
// here this means user has scrolled past your header,
// you may rerender by setting State or do whatever
this.setState({
//stateKey: stateValue,
});
} else {
// here the user has scrolled back to header's territory,
// it's optional here for you to remove the element on navbar as stated in the question or not
this.setState({
//stateKey: stateValue,
});
}
}
render() {
return (
<div ref="header">YOUR HEADER HERE</div>
);
}
For a smooth animation when your element added or removed from the navbar, you can just add this into the element's CSS style:
#your-element{
transition: opacity 0.3s ease-in;
}
You can try to install my library to see if it can extend your needs:
https://www.npmjs.com/package/react-sticky-dynamic-header
Feel free to post here some errors if any, thanks

Responsive sticky sidebar, need to update width

I've got a responsive sticky sidebar started here: http://codepen.io/cmegown/pen/fjqzH. I've got the sticky part down, and it's responsive in relation to the width of the original viewport width. However, if you scroll down and then change the viewport size you'll see that the width of the sidebar does not change.
I know I need to update the sidebarWidth variable, but I'm sure exact how/where to do that.
Any help is appreciated, thanks!
EDIT:
This one kind of got left behind amid some other projects, but I'm back to finish this. I got a little further, but still can't seem to figure out how to update the sidebar width if the user scrolls down the page then expands their browser (or rotates their device). I have some commented code in the JS panel where I left off.
Just put the width calculation in your scroll function.
$(function () {
// cache selectors
var wrapper = $('.wrapper');
var sidebar = $('.sidebar');
// get some maths
var sidebarTop = sidebar.offset().top;
var sidebarOffset = 25; // is .wrapper padding
// sticky logic
$(window).on('scroll', function () {
var windowTop = $(window).scrollTop();
var sidebarWidth = Math.round(wrapper.width() * 0.3); // is .sidebar width
if (sidebarTop < (windowTop + sidebarOffset)) {
sidebar.css({
position: 'fixed',
top: sidebarOffset,
width: sidebarWidth
})
} else {
sidebar.css({
position: 'static',
width: '30%' // original CSS value
})
}
})
})
There's a little bit of overhead there, since it has to calculate the width every time you scroll. The alternative would be to put it into a $(window).resize() function so it figures out the width when you resize the window.

Resources