Setting a transform-origin of a CSS3 pseudo 3d object - javascript

I am trying to build a "pseudo 3D" CSS3 slideshow to hold the projects for my website.
The code I have for each element is
<div class="projects">
<div class="wrapper">
<section id="widget_sp_image-8" class="widget widget_sp_image">
<h1 class="widget-title">Live Manager</h1>
<div class="widget_sp_image-description">
<p>Lorem ipsum</p>
</div>
</section>
<!-- And so on -->
</div>
</div>
Basically, all each card is set to position: absolute; and I rotate them around 360 degrees width Javascript. I want to rotate it around it itself by 45deg every time an user presses left or right, but I have difficulties setting it's transform origin. I have this as a code:
.projects .wrapper {
width: 470px;
display: block;
margin: 0 auto;
position: relative;
-webkit-transform: translateZ(-700px);
-webkit-transform-style: preserve-3d;
-webkit-transform-origin: 50%;
}
But when the left or right arrows are pressed, the slideshow start rotating awkwardly around its side, so the transform-origin doesn't do the trick.
Here is a link to the codepen project:
http://codepen.io/gbnikolov/pen/qyfzp

2 problem!
first when you translate your wrapper -720px in Z axis, so must translate your origin -720px in Z axis too!
.wrapper {
-webkit-transform-origin: 50% 50% -700px;
}
and second problem is:
wrapper.style.webkitTransform += is wrong! because in every key pressing its value will be duplicated!
currently i fix it, but it's not a good way to rotate it!
see [ THIS ]

Related

Scale in Direction based on Location in Container

I want to scale the size of a div when it's hovered over to give a more detailed view of it's content.
I had two ideas on how to do it, firstly have an onHover that when hovered shows an absolute positioned div that is perhaps 125%-130% bigger than the relative div and place it on top. (I kind of like this idea as it allows me to make the new div have different content to the one underneath)
The other idea would simply be to scale the original div using transform. I don't really want to do this though as the div thats "popping over" is a more detailed version of the underlying content.
I can do that no problem, however the part I'm getting stuck with (and can't seem to find an answer for), is to scale the div in a certain direction based on where it is located in a container row.
I created an image describing it below.
The default behaviour would be something like:
as you can see, the default behaviour is that when we scale we are aligned to the left and the extra width will go outwards to the right and the extra height will go downwards
The issue with this is, on the far right, the div that scaled has done so, but because of its position/direction, it's now gone off and to the right (outside the container).
Likewise, I'd like for the 2 centre divs to scale from the centre rather than from left to right.
Just to note, not all divs will be expanded at once, but I highlighted it that way just for the purpose of this question.
The desired result that I would like (showing all expanded), would be something like:
obviously this is kind of hard to see with them all expanded, but if I show a centre div being expanded only:
and then the right most
So what is the difference?
Firstly, each div is vertically centred based on it's relative container (that's easy to do), but the part that I'm stuck with is how to tell the centre divs to expand from the centre both vertically and horizontally, but then tell the leftmost and rightmost divs, expand from centre vertically but horizontally go left to right or right to left etc.
In the last image above, the div knows that it is on the far right of the container and shouldn't expand the default way because it would overflow out of the container, so instead it expands inwards.
Is this possible with CSS only? Or is it a combination of CSS and JS.
I hope that makes sense!
Is this the sort of thing you're looking for? The bigbox div is a child of the small box and I've absolutely positioned it then used a bunch of utility classes to position the child div. Should be fairly self-explanatory but drop me a comment and I'll elaborate further.
* {
box-sizing: border-box;
}
.smallbox {
--offset: 0.5rem;
position: relative;
display: inline-block;
aspect-ratio: 2/1;
background-color: #dae8fc;
border: 1px solid #6c8ebf;
padding: 0.5rem;
margin: 1rem;
}
.bigbox {
font-size: 1.25rem;
position: absolute;
padding: 0.5rem;
background-color: #d5e8d4;
border: 1px solid #82b366;
width: 150%;
aspect-ratio: 2/1;
opacity: 0;
z-index: 1;
}
.smallbox:hover .bigbox {
opacity: 1;
}
.left {
left: calc(-1 * var(--offset));
}
.right {
right: calc(-1 * var(--offset));
}
.top {
top: calc(-1 * var(--offset));
}
.center {
left: 50%;
translate: -50%;
}
.middle {
top: 50%;
translate: 0 -50%;
}
.bottom {
bottom: calc(-1 * var(--offset));
}
.center.middle {
top: 50%;
left: 50%;
translate: -50% -50%;
}
<div class='smallbox'>
Some content
<div class='bigbox left top'>
Some content (but bigger!)
</div>
</div>
<div class='smallbox'>
Some content
<div class='bigbox center top'>
Some content (but bigger!)
</div>
</div>
<div class='smallbox'>
Some content
<div class='bigbox right top'>
Some content (but bigger!)
</div>
</div>
<br><br>
<div class='smallbox'>
Some content
<div class='bigbox left middle'>
Some content (but bigger!)
</div>
</div>
<div class='smallbox'>
Some content
<div class='bigbox center middle'>
Some content (but bigger!)
</div>
</div>
<div class='smallbox'>
Some content
<div class='bigbox right middle'>
Some content (but bigger!)
</div>
</div>
<br> <br>
<div class='smallbox'>
Some content
<div class='bigbox bottom left'>
Some content (but bigger!)
</div>
</div>
<div class='smallbox'>
Some content
<div class='bigbox bottom center'>
Some content (but bigger!)
</div>
</div>
<div class='smallbox'>
Some content
<div class='bigbox bottom right'>
Some content (but bigger!)
</div>
</div>

CSS animation corresponding to page scroll position

How can an animation be made to correspond with page scroll position, so that when the user scrolls past it the animation goes to position A, and when the user's page scroll position is over it, it goes to position B?
Here is a mock-up of what I would like to make:
(The pivot point of the 3 pages is represented by the blue dot below them.)
I have found various examples of animations that are triggered once by page scrolling (such as AOS or ScrollTrigger), or can be re-triggered multiple times, but I haven't found any examples where the animation progress is connected to the page scroll position.
Maybe it can be done by modifying some existing example, but if not I think I will need to come up with something custom using the CSS animation property and connect it to the page scroll position somehow.
Any ideas how this can be achieved? Thanks.
It is pretty easy if you use jquery with CSS3 to achieve it. You can rotate the page and calculate the rotate value based on the scroll position.
I have made sample example below. Please see the Snippet below:
$(document).ready(function(){
$(document).scroll(function(){
var scollHeight = $(document).height();
var maxRotate = 30;
var rotateVal = 5 + (($(document).scrollTop()* maxRotate) / scollHeight);
$("#page1").css("transform", "rotate("+(-rotateVal)+"deg)");
$("#page3").css("transform", "rotate("+(rotateVal)+"deg)");
});
});
body{
background-color: rgb(252,252,230);
}
.page-container{
position: fixed;
}
.page{
background-color:white;
border:2px solid lightgray;
width:85px;
height:120px;
position:absolute;
top:20px;
left:40px;
transform-origin:bottom center -30px;
transition-duration: 0.3s;
}
#page1{
transform: rotate(-5deg);
}
#page3{
transform: rotate(5deg);
}
.data-container{
position: absolute;
right:30px;
}
.data{
background-image: url("https://i.stack.imgur.com/HwX2l.png");
width:370px;
height:283px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main-container">
<div class="page-container">
<div class="page" id="page1"></div>
<div class="page" id="page2"></div>
<div class="page" id="page3"></div>
</div>
<div class="data-container">
<div class="data" id="data1"></div>
<div class="data" id="data2"></div>
<div class="data" id="data3"></div>
</div>
</div>
You can also test it here

Shared element transition using ReactJS

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.

Slider of images with undefined height

I'm trying to create a slider of images (previous/next) so the images slide to the left when I click "previous" and to the right when I click "next" with 0.5s of slowness, so it takes some animation. And when I reach the last image and click "next", I want images to "run backwards" to the first one, the same when I'm in the first one and click "previous", so it "run forward" until the last one.
I want the same behaviour this JSFiddle shows. (but I don't need the timer to move images automatically and don't need the "triggers" buttons, just "previous" and "next").
The problem here is that my images don't have fixed size. I define a width in percentage and can't define a height because I have responsive design, the image resizes as I resize the browser window.
The jQuery to previous/next actions is pretty easy, but I just can't find a way to add this animation when I remove/add the "active" class to my images (so they become visible or not).
I have already tried putting all images side by side and showing only the first one (setting container width equals to image width), so when I click "next" I just "move" the container to the left so it begins to display the next image, but it doesn't work because once I can't define the height of the images, they will appear underneath each other, not side by side.
JSFiddle
HTML
<div class="images">
<img class="active" src="1.jpg">
<img src="2.jpg">
<img src="3.jpg">
</div>
<div class="previous">previous</div>
<div class="next">next</div>
CSS
img {
width: 100px;
display: none;
float: left;
}
img.active {
display: block;
}
jQuery
$('.next').on('click', function() {
var active = $('img.active');
var next = active.next('img');
if (next.length) {
active.removeClass('active');
next.addClass('active');
} else {
active.removeClass('active');
$('.images img:first').addClass('active');
}
});
Well the problem is the height for sliding.
First you need to have an element which is the "picture frame" which hold all the other images. That's important.
For better imagination a picture:
Now you have several technics to show and hide images. One could be to set the opacity. When using transition: opacity .15s ease-in-out; The one Picture is fading out and the next on is fading in.
For the slideshow effect is given to the position of the visible image to its width to the left and the image previously purely new to his wide to the right and then to 0. Thus, moves the current picture on the left the frame out and the new comes out right in.
And here is the difficulty if the height is not the same. If the current image 300px high and the new 400px, so the image frame here would adjust his height immediately once the new image start to be visible.
The content below would start to jump with each slide.
Is that so desired???
If yes, I can make you an example how it works.
You can actually do this in Pure CSS!
You use an ID and a label (with a for attribute=for the targeted id)
That's basically it. All you have left is to style it! (Forked from Joshua Hibbert's Pen)
body {
background: #f7f4e2;
}
/* Slides */
.slider input {
display: none;
}
/* Buttons */
.slider label {
display: none;
cursor: pointer;
position: absolute;
top: 6em;
left: 50%;
transform: translateX(-50%);
color: #fff;
background: #000;
padding: 1.36em .5em;
opacity: .6;
font-size: 19px;
font-family: fantasy;
font-weight: bold;
transition: .25s;
}
.slider label:hover {
opacity: 1;
}
.previous {
margin-left: -188px;
}
.next {
margin-left: 188px;
}
#slide1:checked ~ .buttons .slide1 {
display: block;
}
#slide2:checked ~ .buttons .slide2 {
display: block;
}
#slide3:checked ~ .buttons .slide3 {
display: block;
}
#slide4:checked ~ .buttons .slide4 {
display: block;
}
/* Images */
.slider {
position: absolute;
top: 50%;
left: 50%;
width: 400px;
height: 300px;
margin-top: -150px;
margin-left: -200px;
white-space: nowrap;
padding: 0;
float: left;
transition: .25s;
overflow: hidden;
box-shadow: 0 0 0 3.12px #e8e8e8,
0 0 0 12.64px #eaebe4,
0 0 0 27.12px #000,
0 24px 3.824em 5.12px #000;
}
.slide {
width: 500em;
transition: .25s;
}
.slider img {
float: left;
width: 400px;
height: 300px;
}
#slide1:checked ~ .slide {
margin: 0;
}
#slide2:checked ~ .slide {
margin: 0 0 0 -400px;
}
#slide3:checked ~ .slide {
margin: 0 0 0 -800px;
}
#slide4:checked ~ .slide {
margin: 0 0 0 -1200px;
}
<div class="slider">
<input type="radio" name="slide" id="slide1" checked="true" />
<input type="radio" name="slide" id="slide2" />
<input type="radio" name="slide" id="slide3" />
<input type="radio" name="slide" id="slide4" />
<div class="buttons">
<!-- Slide 1 -->
<label for="slide4" class="slide1 previous"><</label>
<label for="slide2" class="slide1 next">></label>
<!-- Slide 2 -->
<label for="slide1" class="slide2 previous"><</label>
<label for="slide3" class="slide2 next">></label>
<!-- Slide 3 -->
<label for="slide2" class="slide3 previous"><</label>
<label for="slide4" class="slide3 next">></label>
<!-- Slide 4 -->
<label for="slide3" class="slide4 previous"><</label>
<label for="slide1" class="slide4 next">></label>
</div>
<div class="slide">
<img src="http://dribbble.s3.amazonaws.com/users/322/screenshots/872485/coldchase.jpg">
<img src="http://dribbble.s3.amazonaws.com/users/322/screenshots/980517/icehut_sm.jpg">
<img src="http://dribbble.s3.amazonaws.com/users/322/screenshots/943660/hq_sm.jpg">
<img src="http://dribbble.s3.amazonaws.com/users/322/screenshots/599584/home.jpg">
</div>
</div>
Although this method is the most compatible (except for old versions of IE) and depending on how you animate it this method can be more time consuming than a JS method, but can also be faster, it just depends on how you want the animations to go, or you could use a css library that does this for you.
Here are some css image sliders I recommend.
10 Amazing Pure CSS3 Image Sliders
http://bashooka.com/coding/pure-css3-image-sliders/
Pure CSS Image Slider Without Javascript #Codeconvey is a good solution for what you're looking for, but lots of CSS
http://codeconvey.com/pure-css-image-slider/
The downside to these along with what you're working on is that you can't touch to slide on a phone or tablet which is more common now a days with photo galleries.
I recommend checking out Fotorama it's amazing! :)
Perhaps not the ideal situation but at least it will give you an idea. you can use the animation function of jQuery and I also changed your code a bit. See demo here
Within your HTML I would say this:
<div id="images">
<div class="images-wrapper">
<img src="http://www.cutestpaw.com/wp-content/uploads/2016/02/In-the-spotlight.jpg">
<img src="http://www.cutestpaw.com/wp-content/uploads/2016/02/Bath-time-with-ducky.jpg">
<img src="http://www.cutestpaw.com/wp-content/uploads/2016/03/FB_IMG_1452981788903.jpg">
<img src="http://www.pictures-of-cats.org/images/Pixiebob-cat-list-of-cat-breeds-pictures-of-cats.jpg" />
</div>
</div>
<div class="previous">
previous
</div>
<div class="next">
next
</div>
and within your jQuery code you can animate the width:
$('.images-wrapper img:gt(0)').hide();
$('.next').click(function() {
$('.images-wrapper img:first-child').animate({width:'toggle'},350).next().fadeIn().end().appendTo('.images-wrapper');
});
$('.previous').click(function() {
$('.images-wrapper img:first-child').animate({width:'toggle'},350);
$('.images-wrapper img:last-child').prependTo('.images-wrapper').fadeOut();
$('.images-wrapper img:first-child').fadeIn();
});
With this implementation the whole process of changing and adding the active class to the image is removed and replaced by animation functions
Simplest solution (I think) is to force the items to be of the same size, by placing them in a div. You can even have the div show the image without the use of an img tag, by using the background-image CSS feature (see http://www.w3schools.com/css/css3_backgrounds.asp for more details).
The item CSS could look like:
.item {
background-size: contain;
background-position: center;
}
and in each item in the HTML:
<div class='item' style='background-image: url(img1.jpg)' />
<div class='item' style='background-image: url(img2.jpg)' />
<div class='item' style='background-image: url(img3.jpg)' />
I finally got there.
HERE is the fiddle with the solution I developed.
The main problem in the implementation of this image slider was that images, althought were all the same size, have dynamic width (defined in % on CSS) and dynamic height (not defined on CSS).
The solution was basically put an "fake" image (with opacity: 0) inside my container so the container get the actual size of images I will use in the slider; put a div to "hold" the real images with position: absolute and give it a width calculted by number of images * 100%; and for last, give each image in my slider a width of x%, based on number of images.
In the jQuery, I "move" the "images holder div" always by %, never by static values, once the width of everything can change if I resize the window.
If you start to slide the images to the left and right and then resize the window, you will see that it continues to work perfectly.
I have implemented using css3 animations. However this will require manipulating animation values in css every time a slide gets added or removed.
#keyframes slideAnim {
0% {
transform: translateX(0)
}
12.5% {
transform: translateX(0%);
}
25% {
transform: translateX(-25%);
}
37.5% {
transform: translateX(-25%)
}
50% {
transform: translateX(-50%)
}
62.5% {
transform: translateX(-50%)
}
75% {
transform: translateX(00%);
}
89.5% {
transform: translateX(00%)
}
100% {
transform: translateX(00%)
}
}
Here the animation values are set such that there is a pause between slide transitions. I have added a parent frame to show only one slide at a time.
Please refer this fiddle.

weird behaviour in css transform:rotate

i trying to make this item draggable and rotatable.
however if i set transform:rotate(0deg);
i can drag everywhere in the parent container.
but if i set it to 90deg. there are some area became undraggable and it extended out of the parent container as well.
<div id="container">
<div id="myitem"><p>my rotate/drag</p></div>
CSS:
#container{
width:500px;
height:500px;
background:red;
}
#myitem{
width:115px;
height 50px;
background:black;
transform-origin:top left;
transform: rotate("90deg);
-ms-transform-origin:top left;
-ms-transform: rotate(90deg);
-webkit-transform: rotate(90deg);
-webkit-transform-origin:top left;
}
look for the example here
click here for sample of the problem
Have solucioned the problem!
If capture $(foo).offset().left when set css scale the value is not equals to real position if use transform-origin: top left;
To fix this replace
$(foo).offset().left by parseInt($(foo).css('left').replace('px',))
but need set
position after run: foo{ top: 0; left: 0; position: absolute; }
:)
The problem is who detect transform-origin and difference of positions when apply an scale(). Calculate by %?
I just running around your question, basically you want a draggable and rotatable with container...
I have done some changes to your fiddle and try to achieve this, http://jsfiddle.net/28WG3/19/
Some changes to the html too:-
<div id="container">
<div id="main"><div id="myitem"><p>my rotate/drag</p></div>
</div>
</div>
Hope this works for you...

Categories

Resources