Shared element transition using ReactJS - javascript

In Android, shared element transition allows 2 exact same elements existing in both pages to link together when transitioning pages, just like the album art in the gif shown below:
I wonder if it is possible to achieve the same kind of transition with ReactJS between classes. If so, any examples? If not, what about with jQuery?

You can do this transition almost entirely with the CSS transform property. React JS is all about manipulating the DOM, but you don't need to do that here much.
The animation:
Hides the text content of the small panel.
Scales the picture and text background to fill full screen.
Puts in the new text content.
Of those 1 and 3 are easy with React, so you only really need the transition animation.
Here is a very very basic example using no JS at all:
body {
background-color: #ccc;
}
.card {
width: 150px;
padding: 0;
margin: 0;
background-color: #fff;
position: absolute;
top: 0: left: 0;
z-index: 1;
/* Transition properties mean changes to them are animated */
transition-property: transform;
transition-timing-function: ease-in-out;
transition-duration: 500ms;
transform-origin: top left;
}
.card>img {
width: 150px;
height: 150px;
margin: 0;
padding: 0;
}
.card>.content {
width: 150px;
height: 50px;
background-color: #fff;
margin: 0;
}
/* This is only for the purposes of this demo.
* In production you'd have an underlying grid layout and JS to figure out the position */
.card:nth-of-type(2) {
left: 175px;
}
.card:nth-of-type(3) {
top: 230px;
}
.card:nth-of-type(4) {
top: 230px;
left: 175px;
}
/* On hover transform the card to full size and translate it to the top left
* Note that translate comes before scale. */
.card:nth-of-type(1):hover {
transform: scale(2.1667);
z-index: 2;
}
.card:nth-of-type(2):hover {
transform: translate(-175px, 0) scale(2.1667);
z-index: 2;
}
.card:nth-of-type(3):hover {
transform: translate(0, -230px) scale(2.1667);
z-index: 2;
}
.card:nth-of-type(4):hover {
transform: translate(-175px, -230px) scale(2.1667);
z-index: 2;
}
<div class="card">
<img src="http://via.placeholder.com/325/F50057/ffffff">
<div class="content"></div>
</div>
<div class="card">
<img src="http://via.placeholder.com/325/F44336/ffffff">
<div class="content"></div>
</div>
<div class="card">
<img src="http://via.placeholder.com/325/1DE9B6/000000">
<div class="content"></div>
</div>
<div class="card">
<img src="http://via.placeholder.com/325/FFEB3B/000000">
<div class="content"></div>
</div>
The basic trick is to use CSS transform with translate and scale - these properties can be handled by the graphics card and so keep animations smooth even on mobile.
Note that the CSS is rather clunky - I've done it like that just to show that it can be done with pure CSS. In practice you're going to want some JS to set the offset properties, hook up a click event, etc.
Another trick (which I haven't done here) is to scale the animation backwards - start with the full size control and translate/scale it down into the position it appears to start in. When the user clicks on it remove the transform - that saves the browser from having to recalculate the full sized object's DOM before starting the animation.

I am not sure if I understand the question correctly because I am unaware of Android framework. Here is my solution based upon ReactJS knowledge:
Steps:
Maintain 2 state variables: CurrentMode & NextMode. Possible values are 1 & 2.
At the click of album change the NextMode to 2. And in code compare the values of CurrentMode & NextMode. If CurrentMode < NextMode than set the size accordingly.
Similarly when CurrentMode > NextMode than set the size accordingly.

You can do this with mauerwerk: https://github.com/drcmda/mauerwerk
It's basically a grid where each cell gets a status whether it's in thumbnail or opened mode. You can use this status to switch or transition between contents, whether you want to fade them or let parts stand is up to you. There's an additional toggle function which you can use to toggle a cell open/closed.

Related

Javscript detect the state of a div so I can toggle between 2 functions? (without jQuery)

I have a sidebar and I have 2 functions.
One opens it and the other one closes it.
Here are the two functions.
function openNav() {
document.getElementById("myNav").style.width = "100%";
}
function closeNav() {
document.getElementById("myNav").style.width = "0%";
}
I want to create a condition between both so I can toggle them but for that I need to detect if it's opened or closed.
How can I detect it so I can create a toggle function calling the functions above?
You don't need two functions. You can do this with just one CSS class and one function that toggles that one class on the sidebar element.
To do this, add the default width of 0% on the sidebar and then create another class, lets call it .sidebarToggle, that changes the width to 100%.
In javascript, you just need one function, lets call it toggleSidebar() that just toggles the .sidebarToggle class. This way, you not only need less code but also don't need to worry about checking whether the sidebar is opened or closed.
A Better Solution
A better approach is to change the transform property of the sidebar instead of the width. Changing transform property, in this case, is better as compared to changing width, because if you change the width, you will have to handle the:
resizing of the child elements of the sidebar as the sidebar's width is increased or decreased.
remove the left or right padding (if there's any) on the sidebar when the width of the sidebar is 0px or 0%. If you don't remove the padding, sidebar will not completely hide on 0px or 0% width.
With transform, you don't need to worry about the above mentioned points because, instead of resizing, we just translate the sidebar from one point to another.
Animating transform property is also more efficient as compared to animating the width property because changing transform property doesn't causes the browser to go through Layout and Paint steps of its critical rendering path whereas changing the width property will cause the browser to again go through these steps.
Following code snippet shows an example:
const btn = document.querySelector('button');
const sidebar = document.querySelector('.sidebar');
btn.addEventListener('click', () => {
sidebar.classList.toggle('sidebarToggle');
});
body {
margin: 0;
}
.sidebar {
display: flex;
flex-direction: column;
background: #666;
color: #fff;
padding: 15px 25px;
box-sizing: border-box;
width: 30%;
height: 100vh;
transform: translateX(-100%);
position: absolute;
transition: transform 0.5s ease;
}
span {
margin: 5px 0;
}
.sidebarToggle {
transform: translateX(0);
}
button {
position: absolute;
right: 0;
background: green;
color: #fff;
padding: 15px 25px;
}
<div class="sidebar">
<span>Item 1</span>
<span>Item 2</span>
<span>Item 3</span>
<span>Item 4</span>
</div>
<button>Toggle Sidebar</button>
This is best done with classes. That way, stying is better separated from behaviour and there is even a toggle function built in:
document.getElementById("button").onclick = function() {
document.getElementById("myNav").classList.toggle("width100");
};
#myNav {
background-color: red;
display: block;
height: 100px;
width: 0%;
}
#myNav.width100 {
width: 100%;
}
<nav id="myNav"></nav>
<button id="button">Toggle</button>

How to scale down and translate right to left using CSS?

I have a background of backend developer (nodejs) and I'm starting to develop web application. So I'm really new to HTML5, CSS. You can check the small web application here.
Now I want to add some animations to the web application. The first animation is a scale down of the current state and a translation right to left of the new state and I don't know where to start. I'm using ui-router, Restangular and ngAnimate as AngularJS dependencies, LESS for CSS pre-processing.
Any idea how can I achieve these animations (scale down the current state and translate right to left the next state) ?
Thanks.
Your question is not clear enough, but from what I understand, here is an example to help you. You can add a class to your element in javascript and use CSS translate and transform :
var button = document.getElementById('button'),
box = document.getElementById('box')
button.addEventListener('click', function() {
box.classList.add("move");
});
div {
width: 100px;
height: 100px;
margin: 0 auto;
background-color: orange;
transition: all 1s;
}
button {
display: block;
width: 100px;
margin: 0 auto;
}
.move {
transform: translate(-200px, 0);
height: 50px;
width: 50px;
}
<div id="box"></div>
<button id="button">click me</button>

How to make an element slide in with CSS3 transitions?

I really want to know how to make a sliding transition and im not sure if it can be done with pure css or if javascript is needed. I will give an example website. The transition i am talking about is when you select one of the square icons on left side bar and the blue description slides in to the div.
into the arctic
You could use the CSS animate property to animate the object by changing the margin and/or padding to create a sliding effect
It's quite easy to do in CSS, just position the containing div (with a class or id) in the non visible position and add a class when it needs to be visible (for adding that class you need JavaScript).
The class for visibility gets the final positioning.
On the base class you define a CSS transition that animates the properties that change, eg:
div.base {
transition: left 2s;
position:relative;
left:-200px; /* behind something else */
}
div.visible {
left:0px;
}
Edit: if performance is an issue you should use transform instead of left, e.g. transform: translate(-200px,0);. This also makes it possible to position the element how you need it, e.g. floating.
It is possible to do this purely in CSS depending on what you want to use as a trigger for the animation.
For a more persistent state like the linked example, it can be done with the checkbox (or radio) hack.
Note: just because it can be done, doesn't mean it should be done. While there are cases where this might work well for you, in general, you will have more control over the behavior and more flexibility in your markup by using javascript to trigger the animation. Browser support will also be a consideration.
For more information on the checkbox hack:
CSS Tricks: Stuff you can do with the “Checkbox Hack”
The CSS Ninja: Pure CSS collapsible tree menu
A simplistic example:
HTML:
<label for="toggle-1">A</label>
<input class="A" type="checkbox" id="toggle-1">
<label for="toggle-2">B</label>
<input class="B" type="checkbox" id="toggle-2">
<label for="toggle-3">C</label>
<input class="C" type="checkbox" id="toggle-3">
<div class="A">Panel A</div>
<div class="B">Panel B</div>
<div class="C">Panel C</div>
CSS:
/* Positions the checkbox off the screen */
input[type=checkbox] {
position: absolute;
top: -9999px;
left: -9999px;
}
/* Initial DIV position off screen - this is the panel */
div {
position: absolute;
width: 400px;
height: 100px;
line-height: 100px;
left: -400px;
-webkit-transition: left .5s ease;
}
/* Toggled State */
input[type=checkbox].A:checked ~ div.A,
input[type=checkbox].B:checked ~ div.B,
input[type=checkbox].C:checked ~ div.C {
left: 0;
}
demo fiddle
How it works: The checkbox is positioned offscreen. When the user clicks on a label, the associated checkbox is toggled. If the checkbox is checked, the matching sibling selector is triggered setting left to 0px - moving the panel to the right. If the checkbox is unchecked, the selector no longer matches causing the left property to revert to its original -400px value, moving the panel to the left.
Problems with this version: because these are checkboxes, they remain checked until some user action is performed. If the user doesn't close one of the panels the next panel to open will slide over or under the already open panel depending on its order in the DOM or z-index.
It is possible to do this with radio buttons as well, but the problem there is that there is no way to unselect a radio button in a pure CSS implementation, so, once selected a panel would always be visible until the next panel is selected.
You could mixin some javascript with the above to get the behavior you like or place more control in javascript.
A simplistic javascript example (I'd suggest finding better code than this!):
HTML
<div class="sel">A</div>
<div class="sel">B</div>
<div class="sel">C</div>
<div class="panel A">Panel A</div>
<div class="panel B">Panel B</div>
<div class="panel C">Panel C</div>
CSS (similar to what you had before but without the checkbox selectors)
/* Default State */
.panel {
position: absolute;
background: green;
width: 400px;
height: 100px;
line-height: 100px;
color: white;
text-align: center;
left: -400px;
-webkit-transition: left .5s ease;
}
/* Toggled State */
.opened {
left: 0;
}
Code:
var selectors = document.querySelectorAll('.sel');
var curSelected;
function select(evt) {
var panels = document.querySelectorAll('.opened');
var target = evt.target.innerText.trim();
var i;
for(i = 0; i < panels.length; ++i) {
panels[i].classList.toggle('opened');
}
if(target !== curSelected) {
document.querySelector('.panel.' + target).classList.toggle('opened');
curSelected = target;
} else {
curSelected = false;
}
}
for(var i = 0; i < selectors.length; ++i) {
selectors[i].addEventListener('click', select);
}
demo fiddle

background image shaky on div resize

I want to use HTML to create an "opening" effect of one on top of another one.
After some research i figured out a way (see JSFiddle).
I now have the problem that the background image moves a little bit when the circle is resizing.
Can anyone help me figure out how to get the background image to stand still.
The image in the circle needs to keep same zoom level when opening.
The circle needs to be centered and the bottom half needs to be out of the window.
Circle css is this:
.circle {
width: 0px;
height: 0px;
z-index: 10;
position: absolute;
border-radius: 50%;
overflow: hidden;
margin: 0 auto;
left: 50%;
-moz-transform: translate(-50%, 50%);
-webkit-transform: translate(-50%, 50%);
bottom: 0;
-moz-transition: all 1.5s;
-webkit-transition: all 1.5s;
}
JSFiddle: http://jsfiddle.net/GmvUQ/2/
Update,
Let me explain a little more. i notice that my question is not clear enough.
I have a few screenshot for the effect i want to create:
1st frame:
2nd frame
The entire effect is already working but when the transition is in progress (The circle with the image is getting bigger or smaller) the image inside the circle moves a little bit.
This is probably because of the calculations that need to be done by Javascript / CSS positioning.
I would like some help how to let this image stand entirely still during resize transition.
Thanks!
DEMO: http://jsfiddle.net/GmvUQ/5/
Updated HTML
<div>
<div class="buttons">
<button onclick="changeboleto(0)">Click here</button>
<button onclick="changeboleto(500)">Click here</button>
<button onclick="changeboleto(1000)">Click here</button>
</div>
<div class="circle girl">
</div>
<div class="circle lamborghini">
</div>
</div>
Note that I've removed the nested </div> elements within each .circle. Instead I've added an extra class for each, which sets the background-image (and some positioning for them, if necessary).
Updated CSS
.circle {
width: 250px;
height: 250px;
z-index: 10;
position: absolute;
border-radius: 50%;
overflow: hidden;
margin: 0 auto;
background-repeat: no-repeat;
background-size: cover;
background-origin: content-box;
background-position: center center;
}
.lamborghini {
background-image: url(http://www.hdwallpapers.in/walls/2013_wheelsandmore_lamborghini_aventador-wide.jpg);
}
.girl {
background-image: url(http://www.hdwallpapers.in/walls/colorful_background_girl-normal5.4.jpg);
top: 50%;
}
.buttons {
position: relative;
z-index: 5;
}
I've moved most of the CSS in to the .circle class as it is common to both image sets. Pay special attention to the values for the background-* attributes.
Updated JQuery
function changeboleto(pix) {
circleHeight = pix;
circleWidth = pix;
$('.circle').animate({
'width' : circleWidth,
'height': circleHeight
}, 1500, 'linear');
//css('width', circleWidth).css('height', circleHeight);
changeCircleBackgroundToWindow();
}
function changeCircleBackgroundToWindow() {
windowWidth = $(window).width();
windowHeight = $(window).height();
$(".circle > div").animate({
'width' : windowWidth,
'height': windowHeight
}, 1500, 'linear');
$(".circle > div").animate({
'width' : windowWidth,
'height': windowHeight
}, 1500, 'linear');
//$(".circle-background").css("width", windowWidth).css("height", windowHeight);
//$(".circle-background2").css("width", windowWidth).css("height", windowHeight);
}
Rather than mix JQuery and CSS transitions I've lumped all the animation together in the JQuery.
I've used the animate() function and specified the easing method. The default easing is swing but I've used linear as this progresses the animation at a constant pace.
Edit
The solution above includes CSS that allows the image to scale with the animation. However you are requesting that the image stays at the same "zoom level" throughout.
To achieve this simply remove a line from the CSS, namely this one:
.circle {
...
background-size: cover;
...
}
I know this is 5 years too late, but I found this thread via a search engine and thought I'd provide my own thoughts.
This effect can also be achieved with clip-path, which is a bit more forgiving than jquery's animate (which can still result in image shakiness if you're animating certain/enough properties).
clip-path has the additional benefit of not needing javascript at all if you're doing, say, hovers rather than button clicks. It also results in a simpler HTML file.
I've made an updated version of the original question's jsfiddle, http://jsfiddle.net/GmvUQ/13/ which demonstrates doing this with clip-path. It's still using jquery to handle the button clicks, but the "magic" all happens via CSS transitions, rather than javascript animations.
JQuery:
function changeboleto(pix) {
...
$('.circle-background').css('clip-path', 'circle(' + pix/2 + 'px at 50% 100%)');
}
CSS (including original CSS from original fiddle):
.circle-background {
position: absolute;
z-index: 10;
clip-path: circle(0% at 50% 100%);
background:url(http://www.hdwallpapers.in/walls/colorful_background_girl-normal5.4.jpg);
background-size: cover;
-webkit-transition: all 1.5s;
-moz-transition: all 1.5s;
bottom: 0%;
left: 50%;
-moz-transform: translateX(-50%);
-webkit-transform: translateX(-50%);
}
What this does is simply cause the CSS to transition on the clip-path property, animating the circle expansion. Because the image itself never moves, just the boundaries between which it displays, it never shakes.
Full screen demo
JSFiddle: http://jsfiddle.net/7bP7Z/4/ (Click around to see things grow)
Okay, so now that the question has more clarification I have revisited the drawing board and have come up with a better solution.
HTML
<div class="circle">
<div class="circle-overlay"></div>
<img src="http://www.hdwallpapers.in/walls/2013_wheelsandmore_lamborghini_aventador-wide.jpg" />
</div>
<div class="circle">
<div class="circle-overlay"></div>
<img src="http://www.hdwallpapers.in/walls/colorful_background_girl-normal5.4.jpg" />
</div>
Note the changes to the structure:
A containing element
An "overlay" element
An </img>
CSS
.circle {
position: relative;
overflow: hidden;
}
.circle-overlay {
position: absolute;
left: 50%;
margin-left: -150px;
bottom: -150px;
border-radius: 50%;
width: 300px;
height: 300px;
box-shadow: 0px 0px 0px 3000px white;
}
Nice and simple CSS!
The majority of the code is used to position our .circle-overlay class. This class provides a transparent circle (using border-radius) and utilises one of my favourite new CSS features - box-shadow - to apply a solid, white "outline" of an arbitrarily large value that covers the image below it. Have a play with the colour and size (adjust the 300px value) of the box-shadow to see how this works.
JQuery
$('.circle').click(function() {
var c = $(this).children('.circle-overlay');
var w = c.width() + 100;
c.animate({
'width' : w,
'height': w,
'bottom': (w*-0.5),
'margin-left': (w*-0.5)
}, 500, 'linear');
});
Once again, keeping things nice and simple!
The above JQuery performs a very simple task. It increases the size of the circle-overlay whilst maintaining its bottom, centre positioning on every click.
This should be a very smooth animation and the image should not "judder" or "shake" as the image is not being manipulated.

CSS or JavaScript to highlight certain area of image opacity

I'm looking to do something like this but with CSS or JavaScript.
I need to highlight a certain part of an image but everything I find is how to do it in Photoshop. Can I do this with CSS or maybe JavaScript?
Am I even asking the right question?
EDIT:
Well here is a great submission but I have a follow up question:
I need this for a mobile device and portrait and landscape views as well for many devices like: iOS, iPad, Android, WebOS, Etc... So the fixed position I'm not sure will work.
Any advice?
You could use background-position with absolutely positioned divs as follows:
CSS:
.container {
position:relative;
height:455px;
width:606px;
}
.container div {
position:absolute;
background-image:url(http://www.beachphotos.cn/wp-content/uploads/2010/07/indoensianbeach.jpg);
}
.container .bg-image {
opacity:0.3;
height:455px;
width:606px;
}
.container div.highlight-region {
height:50px;
width:50px;
opacity:0;
}
.container div.highlight-region:hover {
opacity:1;
}
HTML:
<div class="container">
<div class="bg-image"></div>
<div class="highlight-region" style="top:50px;left:50px;background-position: -50px -50px;"></div>
<div class="highlight-region" style="top:150px;left:150px;background-position: -150px -150px;"></div>
</div>
Please see http://jsfiddle.net/MT4T7/ for an example
Credit to beachphotos.com for using their image.
EDIT (response to OP comment): Please also see http://jsfiddle.net/zLazD/ I turned off the hover aspect. also added some borders.
CSS changes:
.container div.highlight-region {
height:50px;
width:50px;
border: 3px solid white;
}
/* removed :hover section */
You can probably fake it, here is a sample:
http://jsfiddle.net/erick/JMBFS/3/
I covered the image with an opaque element. The color of the element is the same as the background of the image. Used z-index to put it on top.
You sure can. For example, most crop plugins provide "highlighting" as the basis of their UI. So for a complete cross-browser solution, just use an existing plugin, like Jcrop.
Of course, you might want it to be fixed, in which case you can programmatically tell the plugin which section to highlight and that the user shouldn't be able to move it, and then it will act as a highlighter, not a cropper.
These are the steps you can take to highlight a part of an image:
Access the image in JavaScript, and dynamically add another identical image immediately after it. (this could be done just in HTML, but it would change the semantics of your markup)
Position the second image over the first image
Apply a css mask on the second image so that only the "highlighted" part shows up
When the user hovers over the images' container, adjust the opacity of the first image.
I can provide more technical details on this later if need be.
What about overlaying the cropped image (with 100% opacity) on top of the whole image (with 30% opacity)?
This answer is only a proof of concept
body {
margin: 0 0 0 0;
padding: 0 0 0 0;
}
.img {
position: absolute;
top: 0;
left: 0;
}
.img-base {
opacity: 0.3;
z-index: -99;
}
.img-overlay {
opacity: 1.0;
}
.cropper{
width: 150px; /* input width and height of the box here */
height: 120px;
overflow: hidden;
position: relative;
padding: 0 0 0 0;
margin: 0 0 0 0;
left: 90px; top: 170px; /* input starting location of the box here */
}
#overlay1 {
position: absolute;
left: 0px; right: 0px;
margin-left: -90px; margin-top: -170px; /* input starting location of the box here */
}
<img src="https://images.unsplash.com/photo-1583355862089-81e9e6e50f7a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=334&q=80" class="img img-base">
<div class="cropper">
<img src="https://images.unsplash.com/photo-1583355862089-81e9e6e50f7a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=334&q=80" class="img img-overlay" id="overlay1">
</div>

Categories

Resources