Center div Vertical/Horizontal without flexbox - javascript

/**
* tiltfx.js
* http://www.codrops.com
*
* Licensed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*
* Copyright 2015, Codrops
* http://www.codrops.com
*/
;
(function(window) {
'use strict';
/**
* **************************************************************************
* utils
* **************************************************************************
*/
// from https://gist.github.com/desandro/1866474
var lastTime = 0;
var prefixes = 'webkit moz ms o'.split(' ');
// get unprefixed rAF and cAF, if present
var requestAnimationFrame = window.requestAnimationFrame;
var cancelAnimationFrame = window.cancelAnimationFrame;
// loop through vendor prefixes and get prefixed rAF and cAF
var prefix;
for (var i = 0; i < prefixes.length; i++) {
if (requestAnimationFrame && cancelAnimationFrame) {
break;
}
prefix = prefixes[i];
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame'];
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] ||
window[prefix + 'CancelRequestAnimationFrame'];
}
// fallback to setTimeout and clearTimeout if either request/cancel is not supported
if (!requestAnimationFrame || !cancelAnimationFrame) {
requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
cancelAnimationFrame = function(id) {
window.clearTimeout(id);
};
}
function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
}
// from http://www.quirksmode.org/js/events_properties.html#position
function getMousePos(e) {
var posx = 0;
var posy = 0;
if (!e) var e = window.event;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
} else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
return {
x: posx,
y: posy
}
}
// from http://www.sberry.me/articles/javascript-event-throttling-debouncing
function throttle(fn, delay) {
var allowSample = true;
return function(e) {
if (allowSample) {
allowSample = false;
setTimeout(function() {
allowSample = true;
}, delay);
fn(e);
}
};
}
/***************************************************************************/
/**
* TiltFx fn
*/
function TiltFx(el, options) {
this.el = el;
this.options = extend({}, this.options);
extend(this.options, options);
this._init();
this._initEvents();
}
/**
* TiltFx options.
*/
TiltFx.prototype.options = {
// number of extra image elements (div with background-image) to add to the DOM - min:1, max:5 (for a higher number, it's recommended to remove the transitions of .tilt__front in the stylesheet.
extraImgs: 2,
// the opacity value for all the image elements.
opacity: 0.7,
// by default the first layer does not move.
bgfixed: true,
// image element's movement configuration
movement: {
perspective: 1000, // perspective value
translateX: -10, // a relative movement of -10px to 10px on the x-axis (setting a negative value reverses the direction)
translateY: -10, // a relative movement of -10px to 10px on the y-axis
translateZ: 20, // a relative movement of -20px to 20px on the z-axis (perspective value must be set). Also, this specific translation is done when the mouse moves vertically.
rotateX: 2, // a relative rotation of -2deg to 2deg on the x-axis (perspective value must be set)
rotateY: 2, // a relative rotation of -2deg to 2deg on the y-axis (perspective value must be set)
rotateZ: 0 // z-axis rotation; by default there's no rotation on the z-axis (perspective value must be set)
}
}
/**
* Initialize: build the necessary structure for the image elements and replace it with the HTML img element.
*/
TiltFx.prototype._init = function() {
this.tiltWrapper = document.createElement('div');
this.tiltWrapper.className = 'tilt';
// main image element.
this.tiltImgBack = document.createElement('div');
this.tiltImgBack.className = 'tilt__back';
this.tiltImgBack.style.backgroundImage = 'url(' + this.el.src + ')';
this.tiltWrapper.appendChild(this.tiltImgBack);
// image elements limit.
if (this.options.extraImgs < 1) {
this.options.extraImgs = 1;
} else if (this.options.extraImgs > 5) {
this.options.extraImgs = 5;
}
if (!this.options.movement.perspective) {
this.options.movement.perspective = 0;
}
// add the extra image elements.
this.imgElems = [];
for (var i = 0; i < this.options.extraImgs; ++i) {
var el = document.createElement('div');
el.className = 'tilt__front';
el.style.backgroundImage = 'url(' + this.el.src + ')';
el.style.opacity = this.options.opacity;
this.tiltWrapper.appendChild(el);
this.imgElems.push(el);
}
if (!this.options.bgfixed) {
this.imgElems.push(this.tiltImgBack);
++this.options.extraImgs;
}
// add it to the DOM and remove original img element.
this.el.parentNode.insertBefore(this.tiltWrapper, this.el);
this.el.parentNode.removeChild(this.el);
// tiltWrapper properties: width/height/left/top
this.view = {
width: this.tiltWrapper.offsetWidth,
height: this.tiltWrapper.offsetHeight
};
};
/**
* Initialize the events on the main wrapper.
*/
TiltFx.prototype._initEvents = function() {
var self = this,
moveOpts = self.options.movement;
// mousemove event..
this.tiltWrapper.addEventListener('mousemove', function(ev) {
requestAnimationFrame(function() {
// mouse position relative to the document.
var mousepos = getMousePos(ev),
// document scrolls.
docScrolls = {
left: document.body.scrollLeft + document.documentElement.scrollLeft,
top: document.body.scrollTop + document.documentElement.scrollTop
},
bounds = self.tiltWrapper.getBoundingClientRect(),
// mouse position relative to the main element (tiltWrapper).
relmousepos = {
x: mousepos.x - bounds.left - docScrolls.left,
y: mousepos.y - bounds.top - docScrolls.top
};
// configure the movement for each image element.
for (var i = 0, len = self.imgElems.length; i < len; ++i) {
var el = self.imgElems[i],
rotX = moveOpts.rotateX ? 2 * ((i + 1) * moveOpts.rotateX / self.options.extraImgs) / self.view.height * relmousepos.y - ((i + 1) * moveOpts.rotateX / self.options.extraImgs) : 0,
rotY = moveOpts.rotateY ? 2 * ((i + 1) * moveOpts.rotateY / self.options.extraImgs) / self.view.width * relmousepos.x - ((i + 1) * moveOpts.rotateY / self.options.extraImgs) : 0,
rotZ = moveOpts.rotateZ ? 2 * ((i + 1) * moveOpts.rotateZ / self.options.extraImgs) / self.view.width * relmousepos.x - ((i + 1) * moveOpts.rotateZ / self.options.extraImgs) : 0,
transX = moveOpts.translateX ? 2 * ((i + 1) * moveOpts.translateX / self.options.extraImgs) / self.view.width * relmousepos.x - ((i + 1) * moveOpts.translateX / self.options.extraImgs) : 0,
transY = moveOpts.translateY ? 2 * ((i + 1) * moveOpts.translateY / self.options.extraImgs) / self.view.height * relmousepos.y - ((i + 1) * moveOpts.translateY / self.options.extraImgs) : 0,
transZ = moveOpts.translateZ ? 2 * ((i + 1) * moveOpts.translateZ / self.options.extraImgs) / self.view.height * relmousepos.y - ((i + 1) * moveOpts.translateZ / self.options.extraImgs) : 0;
el.style.WebkitTransform = 'perspective(' + moveOpts.perspective + 'px) translate3d(' + transX + 'px,' + transY + 'px,' + transZ + 'px) rotate3d(1,0,0,' + rotX + 'deg) rotate3d(0,1,0,' + rotY + 'deg) rotate3d(0,0,1,' + rotZ + 'deg)';
el.style.transform = 'perspective(' + moveOpts.perspective + 'px) translate3d(' + transX + 'px,' + transY + 'px,' + transZ + 'px) rotate3d(1,0,0,' + rotX + 'deg) rotate3d(0,1,0,' + rotY + 'deg) rotate3d(0,0,1,' + rotZ + 'deg)';
}
});
});
// reset all when mouse leaves the main wrapper.
this.tiltWrapper.addEventListener('mouseleave', function(ev) {
setTimeout(function() {
for (var i = 0, len = self.imgElems.length; i < len; ++i) {
var el = self.imgElems[i];
el.style.WebkitTransform = 'perspective(' + moveOpts.perspective + 'px) translate3d(0,0,0) rotate3d(1,1,1,0deg)';
el.style.transform = 'perspective(' + moveOpts.perspective + 'px) translate3d(0,0,0) rotate3d(1,1,1,0deg)';
}
}, 60);
});
// window resize
window.addEventListener('resize', throttle(function(ev) {
// recalculate tiltWrapper properties: width/height/left/top
self.view = {
width: self.tiltWrapper.offsetWidth,
height: self.tiltWrapper.offsetHeight
};
}, 50));
};
function init() {
// search for imgs with the class "tilt-effect"
[].slice.call(document.querySelectorAll('img.tilt-effect')).forEach(function(img) {
new TiltFx(img, JSON.parse(img.getAttribute('data-tilt-options')));
});
}
init();
window.TiltFx = TiltFx;
})(window);
.tilt {
overflow: hidden;
position: relative;
width: 100%;
height: 100%;
margin: 0 auto;
}
.tilt__back {
position: relative;
}
.tilt__front {
position: absolute;
top: 0;
left: 0;
}
.tilt__back,
.tilt__front {
width: 100%;
height: 100%;
background-position: 50% 50%;
background-repeat: no-repeat;
background-size: cover;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
<div class="megawrapper">
<div class="w-section home-page" style="transform: translateX(0px) translateY(0px);">
<div class="home_logo" style="pointer-events:none;"></div>
<div class="home_centralarea" data-ix="home-darkfield" style="opacity: 1; transition: opacity 500ms;">
<div class="home_parallaxpic_wrapper">
<div class="home_parallaxpic" data-ix="home-parallaxpic" style="opacity: 0.4; transition: opacity 1000ms;">
<img class="hero__img tilt-effect" data-tilt-options='{ "extraImgs":3, "bgfixed":false, "opacity" : 0.5, "movement": { "perspective" : 1200, "translateX" : -5, "translateY" : -5, "rotateX" : -5, "rotateY" : -5 } }' src="<?php echo get_template_directory_uri(); ?>/images/road.jpeg"
/>
</div>
</div>
</div>
</div>
</div>
I want to replicate HTML structure of this website (www.danielspatzek.com/). But I cant get my divs to center properly. The website has two main divs, .home-page which contains the fully stretched background image and .tilt which injects the tiltfx effect on the background image. The div .tilt has a scaled down height/width due to a padding of 60px applied on it by its parent div .home-page
I replicated the HTML structure but when I apply the 60px padding in .home-page all divs get pushed right/down and is no longer centered.
The original website html is:
<div class="megawrapper">
<div class="w-section home-page" style="transform: translateX(0px) translateY(0px);">
<div class="home_logo" style="pointer-events:none;"></div>
<div class="home_centralarea" data-ix="home-darkfield" style="opacity: 1; transition: opacity 500ms;">
<div class="home_parallaxpic_wrapper">
<div class="home_parallaxpic" data-ix="home-parallaxpic" style="opacity: 0.4; transition: opacity 1000ms;">
<img class="hero__img tilt-effect" data-tilt-options='{ "extraImgs":3, "bgfixed":false, "opacity" : 0.5, "movement": { "perspective" : 1200, "translateX" : -5, "translateY" : -5, "rotateX" : -5, "rotateY" : -5 } }' src="<?php echo get_template_directory_uri(); ?>/images/road.jpeg" />
</div>
</div>
</div>
</div>
</div>
The javascript file tiltfx.js removes .tilt-effect and replaces it with .tilt so the HTML is:
<div class="megawrapper">
<div class="w-section home-page" style="transform: translateX(0px) translateY(0px);">
<div class="home_logo" style="pointer-events:none;"></div>
<div class="home_centralarea" data-ix="home-darkfield" style="opacity: 1; transition: opacity 0ms;">
<div class="home_parallaxpic_wrapper">
<div class="home_parallaxpic" data-ix="home-parallaxpic" style="opacity: 0.4; transition: opacity 0ms;">
<div class="tilt"><div class="tilt__back" style="background-image: url("http://www.danielspatzek.com/themes/Theme/images/bg_home_street.jpg"); transform: perspective(1200px) translate3d(0.787151px, -0.0129973px, 0px) rotate3d(1, 0, 0, -0.0129973deg) rotate3d(0, 1, 0, 0.787151deg) rotate3d(0, 0, 1, 0deg);"></div>
</div>
</div>
</div>
</div>
My recreation HTML and CSS looks like this:
<div class="megawrapper">
<div class="home-page" style="transform: translateX(0px) translateY(0px);">
<img class="tilt-effect" data-tilt-options='{ "extraImgs":3, "bgfixed":false, "opacity" : 0.5, "movement": { "perspective" : 1200, "translateX" : -5, "translateY" : -5, "rotateX" : -5, "rotateY" : -5 } }' src="<?php echo get_template_directory_uri(); ?>/images/road.jpeg" />
</div>
.megawrapper {
position: absolute;
overflow-x: hidden;
overflow-y: hidden;
width: 100%;
height: 100%;
}
.home-page {
position: absolute;
z-index: 0;
width: 100%;
height: 100%;
background-color: #3c3c3e;
background-image: url(images/road.jpeg);
background-position: 50% 50%;
background-size: cover;
background-repeat: no-repeat;
}
.tilt {
overflow: hidden;
position: relative;
width: 100%;
height: 100%;
margin: 0 auto;
}
.tilt__back {
position: relative;
}
.tilt__front {
position: absolute;
top: 0;
left: 0;
}
.tilt__back, .tilt__front {
width: 100%;
height: 100%;
background-position: 50% 50%;
background-repeat: no-repeat;
background-size: cover;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
I cant seem to get the same layout as the website. I dont know why .tilt would not center properly when I apply padding of 60 px on .home-page. I dont want to use flexbox to achieve the same result

use box-sizing:border-box; on your .home_page it will work fine.I'm added the snippet below.
html,body{
width:100%;
height:100%;
}
.home_page{
width:100%;
height:100%;
background-color:#3c3c3e;
background-image: url(https://i.stack.imgur.com/wwy2w.jpg);
background-position: 50% 50%;
background-size: cover;
background-repeat: no-repeat;
padding:60px;
box-sizing:border-box;
}
.tilt {
overflow: hidden;
position: relative;
width: 100%;
height: 100%;
margin: 0 auto;
background-color:yellow;
}
<div class="home_page">
<div class="tilt"></div>
</div>

Here is a good way.
<div class="divToCenterStuffIn">
<div class="vertCenter">
Vertical Center
</div>
</div>
<div class="divToCenterStuffIn">
<div class="horzCenter">
Horizontal Center
</div>
</div>
<div class="divToCenterStuffIn">
<div class="trueCenter">
True Center
</div>
</div>
.divToCenterStuffIn {
position: relative;
display: block;
width: 10rem;
height: 10rem;
}
.vertCenter
{
position: absolute;
display: block;
top:50%;
-ms-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
}
.horzCenter
{
position: absolute;
display: block;
left: 50%;
-ms-transform: translateX(-50%);
-moz-transform: translateX(-50%);
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
}
.trueCenter {
position: absolute;
display: block;
left: 50%;
top: 50%;
-ms-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}

Related

How do I perform a rotation animation on top of a base angle other than 0?

In JS I have some code that transform rotates the heads of my three sprites to follow the cursor on the screen. Additionally, I have a CSS keyframe animation I made to sort of "rattle the heads". My issue is, that this animation uses what seems to be a datum of 0deg and I want it to instead use the current angle with the mouse as the centre.
I have this value as angle1, 2, 3, in JS but not in CSS. Is there a way to use this angle in CSS? So instead my animation would do something like transform: rotate(baseAngle + 90) etc? See below for SC.
I also a feel a gif of the behaviour is pretty valuable here:
https://gyazo.com/90855776c7803c63b72d378cb4a3c194
JS for tracking mouse movement:
(function() {
document.onmousemove = handleMouseMove;
function handleMouseMove(event) {
var scrollMaxY, dot, eventDoc, doc, body, pageX, pageY;
// IE-isms
event = event || window.event;
maxY = window.innerHeight || (document.documentElement.innerHeight - document.documentElement.clientHeight)
// If pageX/Y aren't available and clientX/Y are,
if (event.pageX == null && event.clientX != null) {
eventDoc = (event.target && event.target.ownerDocument) || document;
doc = eventDoc.documentElement;
body = eventDoc.body;
event.pageX = event.clientX +
(doc && doc.scrollLeft || body && body.scrollLeft || 0) -
(doc && doc.clientLeft || body && body.clientLeft || 0);
event.pageY = event.clientY +
(doc && doc.scrollTop || body && body.scrollTop || 0) -
(doc && doc.clientTop || body && body.clientTop || 0 );
}
// TODO: Use x/y values to rotate heads
angle1 = Math.atan2( event.pageY - head1[0], event.pageX - head1[1]);
angle2 = Math.atan2( event.pageY - head2[0], event.pageX - head2[1]);
angle3 = Math.atan2( event.pageY - head3[0], event.pageX - head3[1]);
$("#kodama-head1").css("transform", "rotate(" + angle1 + "rad)");
$("#kodama-head2").css("transform", "rotate(" + angle2 + "rad)");
$("#kodama-head3").css("transform", "rotate(" + angle3 + "rad)");
}
})();
My CSS keyframes animation:
#keyframes RattleHeads {
0% {
transform: rotate(90deg);
-webkit-transition: all 600ms cubic-bezier(0.075, 0.82, 0.165, 1);
transition: all 600ms cubic-bezier(0.075, 0.82, 0.165, 1);
}
55% {
transform: rotate(-60deg);
}
69% {
transform: rotate(45deg);
}
78% {
transform: rotate(-30deg);
}
85% {
transform: rotate(20deg);
}
91% {
transform: rotate(-15deg);
}
95% {
transform: rotate(10deg);
}
98% {
transform: rotate(-5deg);
}
100% {
transform: rotate(0deg);
}
}
Lastly, the JS being used to apply rattling animation:
$("body").click(function(){
var KodamaHead;
var random = Math.random() * 3;
if (random > 2){
KodamaHead = $("#kodama-head3");
}
else if (random > 1){
KodamaHead = $("#kodama-head2");
}
else{
KodamaHead = $("#kodama-head1");
}
// add animation
KodamaHead.addClass("rattling");
// remove animation on completion
KodamaHead.one("webkitAnimationEnd oanimationend oAnimationEnd msAnimationEnd animationend",
function(e) {
$(this).removeClass("rattling");
});
});
Simply wrap your head element inside an other element.
The transform of the inner element will now be relative to the one of the wrapper.
In the following example, we apply the mouse driven rotation to the inner .head elements, while applying the CSS driven one (onclick) on the .wrapper elements.
Since here both share the same transform-origin , it could also have been done the other way around.
$("body").click(function() {
var random = Math.floor(Math.random() * 3);
// Target one of the `.wrapper` elements
var KodamaHead = $('.persona .wrapper').eq(random);
// add animation
KodamaHead.addClass("rattling");
// remove animation on completion
KodamaHead.one("webkitAnimationEnd oanimationend oAnimationEnd msAnimationEnd animationend",
function(e) {
$(this).removeClass("rattling");
});
});
(function() {
// get Elements rotation anchor
var head1 = getAnchor('#kodama-head1');
var head2 = getAnchor('#kodama-head2');
var head3 = getAnchor('#kodama-head3');
document.onmousemove = handleMouseMove;
function handleMouseMove(event) {
// removed some backward compatibility fluffs
// feel free to add it back
// calculations were off by half a π
angle1 = Math.atan2(event.pageY - head1[0], event.pageX - head1[1]) - Math.PI / 2;
angle2 = Math.atan2(event.pageY - head2[0], event.pageX - head2[1]) - Math.PI / 2;
angle3 = Math.atan2(event.pageY - head3[0], event.pageX - head3[1]) - Math.PI / 2;
$("#kodama-head1").css("transform", "rotate(" + angle1 + "rad)");
$("#kodama-head2").css("transform", "rotate(" + angle2 + "rad)");
$("#kodama-head3").css("transform", "rotate(" + angle3 + "rad)");
}
})();
// get anchor position (center, center)
function getAnchor(sel) {
var el = document.querySelector(sel),
rect = el.getBoundingClientRect();
return [rect.top + rect.height / 2, rect.left + rect.width / 2];
}
.rattling {
animation: RattleHeads 2s linear;
}
.persona {
display: inline-block;
height: 90vh;
width: 20vw;
border: 1px solid;
}
.head {
display: inline-block;
height: 20vw;
width: 20vw;
border: 1px solid;
position: relative;
}
.head::before,
.head::after {
content: '•';
color: white;
font-size: 18px;
line-height: 12px;
width: 2vmax;
height: 2vmin;
position: absolute;
top: 5vw;
left: 7vw;
background: black;
border-radius: 20%;
}
.head::after {
left: auto;
right: 7vw;
}
#keyframes RattleHeads {
0% {
transform: rotate(0deg);
}
55% {
transform: rotate(-60deg);
}
69% {
transform: rotate(45deg);
}
78% {
transform: rotate(-30deg);
}
85% {
transform: rotate(20deg);
}
91% {
transform: rotate(-15deg);
}
95% {
transform: rotate(10deg);
}
98% {
transform: rotate(-5deg);
}
100% {
transform: rotate(0deg);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="persona">
<div class="wrapper"><!-- rattling -->
<div id="kodama-head1" class="head"><!-- look-at -->
</div>
</div>
</div>
<div class="persona">
<div class="wrapper"><!-- rattling -->
<div id="kodama-head2" class="head"><!-- look-at -->
</div>
</div>
</div>
<div class="persona">
<div class="wrapper"><!-- rattling -->
<div id="kodama-head3" class="head"><!-- look-at -->
</div>
</div>
</div>

How to switch between transform-origin and scrollbars

I have this code above who switch between CSS transform-origin and scale to CSS width and scrollbars.
I need to make this switch because I am having a pinch to zoom for a DIV wrap I'm using in my website.
I'm using CSS translateX and translateY and Scale for a smoother pinch zoom, but after the zoom take place, I need to return back to width and scrollbar so the user can move across the layout.
I have here an example of how I'm doing the switch and there is a bit margin on top that I can't really set mind my on.
what is the correct way to do so?
var isOrigin = false;
var originX = 500;
var originY = 200;
var scale = 1.5;
var deltaX = 0;
var deltaY = 0;
var from_origin_to_scroll = function () {
if (isOrigin) { from_scroll_to_origin(); return; }
var wrap = $('.containter .wrap');
//reset scroll
const el = document.scrollingElement || document.documentElement;
$('.containter')[0].scrollLeft = 0;
el.scrollTop = 0;
wrap.css({
transformOrigin: originX + "px " + originY + "px",
transform: "translate3d(" + deltaX + "px," + deltaY + "px, 0) " +
"scale3d(" + scale + "," + scale + ", 1) ",
width: 100 + '%'
});
isOrigin = true;
$('.info').html('layout set by origin and scale');
}
var from_scroll_to_origin = function () {
var wrap = $('.containter .wrap');
wrap.css({
transformOrigin: originX + "px " + originY + "px",
transform: "translate3d(" + 0 + "px," + 0 + "px, 0) " +
"scale3d(" + 1 + "," + 1 + ", 1) ",
width: (100 * scale) + '%'
});
$('.containter')[0].scrollLeft = originX * (scale - 1);
const el = document.scrollingElement || document.documentElement;
el.scrollTop = originY * (scale - 1);
isOrigin = false;
$('.info').html('layout set by width and scroll');
}
body {
margin: 0;
padding: 0;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
width:100vw;
}
.top{
position: fixed;
width: 100%;
background-color: #333;
line-height: 40pt;
text-align: center;
color: #f1f1f1;
font-size: 20pt;
left: 0;
top: 0;
z-index: 10;
}
.top .info{
}
.header_content
{
background-color: #e1e1e1;
line-height:130pt;
}
.containter {
width:100%;
box-sizing: border-box;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.containter .wrap {
display: flex;
flex-direction: column;
width: 100%;
}
.containter .wrap img {
width: 100%;
margin-top: 30pt;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="top">
<div class="info" onclick="from_origin_to_scroll()">click to switch</div>
</div>
<div class="header_content">
this is a header content - needs to be added to overall calculation
</div>
<div class="containter">
<div class="wrap">
<img src="https://thumb7.shutterstock.com/display_pic_with_logo/91858/594887747/stock-photo-dreams-of-travel-child-flying-on-a-suitcase-against-the-backdrop-of-sunset-594887747.jpg" />
<img src="https://thumb9.shutterstock.com/display_pic_with_logo/1020994/556702975/stock-photo-portrait-of-a-happy-and-proud-pregnant-woman-looking-at-her-belly-in-a-park-at-sunrise-with-a-warm-556702975.jpg" />
<img src="https://thumb7.shutterstock.com/display_pic_with_logo/234100/599187701/stock-photo-funny-little-girl-plays-super-hero-over-blue-sky-background-superhero-concept-599187701.jpg" />
<img src="https://thumb1.shutterstock.com/display_pic_with_logo/1316512/661476343/stock-photo-funny-pineapple-in-sunglasses-near-swimming-pool-661476343.jpg" />
<img src="https://thumb1.shutterstock.com/display_pic_with_logo/2114402/689953639/stock-photo-adult-son-hugging-his-old-father-against-cloudy-sky-with-sunshine-689953639.jpg" />
<img src="https://thumb7.shutterstock.com/display_pic_with_logo/172762/705978841/stock-photo-businessman-looking-to-the-future-for-new-business-opportunity-705978841.jpg" />
</div>
</div>
In your case the possible solution is to detect when the user is trying to zoom, and when just to scroll.
const $container = $(".container");
$container.on('touchstart', function (e) {
if (e.touches.length > 1){
//more than one finger is detected on the screen,
//change mode to transform-origin
from_scroll_to_origin()
}
});
$container.on('touchend', function (e) {
//change mode to scrollbars
from_origin_to_scroll()
});

Problems calculating rotation degrees

Got some math issues in my code that i can't figure out.
When you press on one of the red circles it should take the closest path (left or right) and rotate down to the bottom, it's kinda working, but there are a few issues with it.
e.g. If you start by pressing '8' and then '3', the container is only rotating 45 degrees in the wrong direction.
And the second issue is that the numbers are spinning around when the wheel is rotating.
Here is a jsfiddle to the code: https://jsfiddle.net/she4x2w6/10/
$('.item').click(function() {
var currentId = $('#container').data('id');
var nextId = $(this).data('id');
var currentRotation = (360 / items.length) * currentId - (360 / items.length);
var nextRotation = (360 / items.length) * nextId - (360 / items.length);
var deg;
if (currentRotation - nextRotation > 180 || nextRotation - currentRotation > 180) {
deg = nextRotation > 180 ? 360 - nextRotation : nextRotation - 360;
} else {
deg = -Math.abs(nextRotation);
}
var itemDeg = nextRotation <= 180 ? nextRotation : -Math.abs(360 - nextRotation);
$('#container').css({
transition: 'transform 0.6s',
transform: 'rotate(' + deg + 'deg)'
})
$('.item').css({
transition: 'transform 0.6s',
transform: 'rotate(' + itemDeg + 'deg)'
})
CSS rotate() function rotates an element to given angle while you are trying to rotate your element by a given angle.
rotate() -CSS | MDN
I had to change some of your approach to get it working:
var radius = 100; // adjust to move out items in and out
var items = $('.item'),
container = $('#container'),
width = container.width(),
height = container.height();
var angle = 0,
step = (2 * Math.PI) / items.length,
angle = Math.PI/2;
items.each(function() {
var x = Math.round(width / 2 + radius * Math.cos(angle) - $(this).width() / 2);
var y = Math.round(height / 2 + radius * Math.sin(angle) - $(this).height() / 2);
$(this).css({
left: x + 'px',
top: y + 'px'
});
angle += step;
});
$('#container').data('deg', 0);
$('.item').click(function() {
var currentId = $('#container').data('id');
var nextId = $(this).data('id');
var currentDeg =$('#container').data('deg');
var deg;
var degg = ((nextId+items.length-1)%items.length)*(360 / items.length);
if (degg>=180) {
deg = 360-degg;
} else {
deg = -degg;
}
var t = (currentDeg - deg) % 360;
if (t<0) {
t = 360+t;
}
if (t<180) {
deg = currentDeg-t;
} else {
deg = currentDeg+360-t;
}
var itemDeg = -deg;
var time = Math.abs(deg-currentDeg)/100;
$('#container').css({
transition: 'transform ' + time + 's',
transform: 'rotate(' + deg + 'deg)'
})
$('.item').css({
transition: 'transform ' + time + 's',
transform: 'rotate(' + itemDeg + 'deg)'
})
$('#container').data('id', nextId).data('deg', deg);
});
body {
padding: 2em;
}
#container {
width: 200px;
height: 200px;
margin: 10px auto;
border: 1px solid #000;
position: relative;
border-radius: 50%;
}
.item {
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
border-radius: 50%;
position: absolute;
background: #f00;
}
.item p {
margin: 0;
}
.active .item-content {
opacity: 1 !important;
transition: opacity ease 0.6s;
}
.item .item-content {
opacity: 0;
transition: opacity ease 0.3s;
margin: auto;
position: absolute;
width: 230px;
transform: translate(-50%);
left: 50%;
pointer-events: none;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container" data-id="1">
<div data-id="1" class="item">1</div>
<div data-id="2" class="item">2</div>
<div data-id="3" class="item">3</div>
<div data-id="4" class="item">4</div>
<div data-id="5" class="item">5</div>
<div data-id="6" class="item">6</div>
<div data-id="7" class="item">7</div>
<div data-id="8" class="item">8</div>
<div data-id="9" class="item">9</div>
</div>

Animating newly created objects with different keyframes values

So I'm trying to make simple animation. When you press somewhere inside blue container, a circle should be created in this place and then go up. After some research I found how to put JS values into keyframes, but it's changing values for every object not just for freshly created. If you run snipped and press somewhere high and then somewhere low you will see what I'm talking about.
I found some AWESOME solution with Raphael library, but I'm a beginner and I'm trying to make something like this in JS. Is it even possible? How?
var bubble = {
posX: 0,
posY: 0,
size: 0
};
var aquarium = document.getElementById("container");
var ss = document.styleSheets;
var keyframesRule = [];
function findAnimation(animName) { //function to find keyframes and insert replace values in them
for (var i = 0; i < ss.length; i++) {
for (var j = 0; j < ss[i].cssRules.length; j++) {
if (window.CSSRule.KEYFRAMES_RULE == ss[i].cssRules[j].type && ss[i].cssRules[j].name == animName) {
keyframesRule.push(ss[i].cssRules[j]);
}
}
}
return keyframesRule;
}
function changeAnimation (nameAnim) { //changing top value to cursor position when clicked
var keyframesArr = findAnimation(nameAnim);
for (var i = 0; i < keyframesArr.length; i++) {
keyframesArr[i].deleteRule("0%");
keyframesArr[i].appendRule("0% {top: " + bubble.posY + "px}");
}
}
function createBubble(e) {
"use strict";
bubble.posX = e.clientX;
bubble.posY = e.clientY;
bubble.size = Math.round(Math.random() * 100);
var bubbleCircle = document.createElement("div");
aquarium.appendChild(bubbleCircle);
bubbleCircle.className = "bubble";
var bubbleStyle = bubbleCircle.style;
bubbleStyle.width = bubble.size + "px";
bubbleStyle.height = bubble.size + "px";
bubbleStyle.borderRadius = (bubble.size / 2) + "px";
//bubbleStyle.top = bubble.posY - (bubble.size / 2) + "px";
bubbleStyle.left = bubble.posX - (bubble.size / 2) + "px";
changeAnimation("moveUp");
bubbleCircle.className += " animate";
}
aquarium.addEventListener("click", createBubble);
//console.log(bubble);
body {
background-color: red;
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100%;
position: fixed;
top: 80px;
left: 0;
background-color: rgb(20,255,200);
}
#surface {
width: 100%;
height: 40px;
position: fixed;
top: 40px;
opacity: 0.5;
background-color: rgb(250,250,250);
}
.bubble {
position: fixed;
border: 1px solid blue;
}
.animate {
animation: moveUp 5s linear;//cubic-bezier(1, 0, 1, 1);
-webkit-animation: moveUp 5s linear;//cubic-bezier(1, 0, 1, 1);
}
#keyframes moveUp{
0% {
top: 400px;
}
100% {
top: 80px;
}
}
#-webkit-keyframes moveUp{
0% {
top: 400px;
}
100% {
top: 80px;
}
}
<body>
<div id="container">
</div>
<div id="surface">
</div>
</body>
Here is a possible solution. What I did:
Remove your functions changeAnimation () and findAnimation() - we don't need them
Update the keyframe to look like - only take care for the 100%
#keyframes moveUp { 100% {top: 80px;} }
Assign top of the new bubble with the clientY value
After 5 seconds set top of the bubble to the offset of the #container(80px) - exactly when animation is over to keep the position of the bubble, otherwise it will return to initial position
var bubble = {
posX: 0,
posY: 0,
size: 0
};
var aquarium = document.getElementById("container");
function createBubble(e) {
"use strict";
bubble.posX = e.clientX;
bubble.posY = e.clientY;
bubble.size = Math.round(Math.random() * 100);
var bubbleCircle = document.createElement("div");
aquarium.appendChild(bubbleCircle);
bubbleCircle.className = "bubble";
var bubbleStyle = bubbleCircle.style;
bubbleStyle.width = bubble.size + "px";
bubbleStyle.height = bubble.size + "px";
bubbleStyle.borderRadius = (bubble.size / 2) + "px";
bubbleStyle.top = bubble.posY - (bubble.size / 2) + "px";
bubbleStyle.left = bubble.posX - (bubble.size / 2) + "px";
bubbleCircle.className += " animate";
// The following code will take care to reset top to the top
// offset of #container which is 80px, otherwise circle will return to
// the position of which it was created
(function(style) {
setTimeout(function() {
style.top = '80px';
}, 5000);
})(bubbleStyle);
}
aquarium.addEventListener("click", createBubble);
body {
background-color: red;
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100%;
position: fixed;
top: 80px;
left: 0;
background-color: rgb(20, 255, 200);
}
#surface {
width: 100%;
height: 40px;
position: fixed;
top: 40px;
opacity: 0.5;
background-color: rgb(250, 250, 250);
}
.bubble {
position: fixed;
border: 1px solid blue;
}
.animate {
animation: moveUp 5s linear;
/*cubic-bezier(1, 0, 1, 1);*/
-webkit-animation: moveUp 5s linear;
/*cubic-bezier(1, 0, 1, 1);*/
}
#keyframes moveUp {
100% {
top: 80px;
}
}
#-webkit-keyframes moveUp {
100% {
top: 80px;
}
}
<body>
<div id="container"></div>
<div id="surface"></div>
</body>
The problem about your code was that it is globally changing the #keyframes moveUp which is causing all the bubbles to move.
The problem with your code is that you're updating keyframes which are applied to all bubbles. I tried another way of doing it by using transition and changing the top position after the element was added to the DOM (otherwise it wouldn't be animated).
The main problem here is to wait the element to be added to the DOM. I tried using MutationObserver but it seems to be called before the element is actually added to the DOM (or at least rendered). So the only way I found is using a timeout which will simulate this waiting, although there must be a better one (because it may be called too early, causing the bubble to directly stick to the top), which I would be happy to hear about.
var bubble = {
posX: 0,
posY: 0,
size: 0
};
var aquarium = document.getElementById("container");
function createBubble(e) {
"use strict";
bubble.posX = e.clientX;
bubble.posY = e.clientY;
bubble.size = Math.round(Math.random() * 100);
var bubbleCircle = document.createElement("div");
aquarium.appendChild(bubbleCircle);
bubbleCircle.classList.add("bubble");
var bubbleStyle = bubbleCircle.style;
bubbleStyle.width = bubble.size + "px";
bubbleStyle.height = bubble.size + "px";
bubbleStyle.borderRadius = (bubble.size / 2) + "px";
bubbleStyle.top = bubble.posY - (bubble.size / 2) + "px";
bubbleStyle.left = bubble.posX - (bubble.size / 2) + "px";
setTimeout(function() {
bubbleCircle.classList.add("moveUp");
}, 50);
}
aquarium.addEventListener("click", createBubble);
body {
background-color: red;
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100%;
position: fixed;
top: 80px;
left: 0;
background-color: rgb(20, 255, 200);
}
#surface {
width: 100%;
height: 40px;
position: fixed;
top: 40px;
opacity: 0.5;
background-color: rgb(250, 250, 250);
}
.bubble {
position: fixed;
border: 1px solid blue;
transition: 5s;
}
.moveUp {
top: 80px !important;
}
<body>
<div id="container">
</div>
<div id="surface">
</div>
</body>
Also, I used the classList object instead of className += ... because it is more reliable.

Rotating an image when user scrolls up and down the screen

I am fairly new to writing in html, css, and coding in javascript.
I digress; i am trying to have an image of a gear rotate when the a user scrolls up and down the screen (i am hoping to give it an elevator effect when i add a belt).
I am using the jquery $(window).scroll(function(). I know it is working because when i use console.log("hi") it writes every time i scroll. My problem is the .animate() function that doesn't seem to work. I even tried downloading "http://jqueryrotate.com/" and using that to rotate.
Any help would be much appreciated!
## HTML ##
<div class="left_pulley">
<img src="gear2.png" />
</div>
<div class="right_pulley">
<img src="gear2.png" />
</div>
## CSS ##
.left_pulley
{
position: absolute;
margin: 0;
padding: 0;
top: 263px;
left: 87%;
height: 35px;
width: 35px;
}
.left_pulley img
{
width: 100%;
}
.right_pulley
{
position: absolute;
margin: 0;
padding: 0;
top: 263px;
left: 94.2%;
height: 35px;
width: 35px;
}
.right_pulley img
{
width: 100%;
}
## JS ##
First using .rotate({})
$(".left_pulley").rotate({bind:
$(window).scroll(function() {
if ($(this).scrollTop() > 0) {
$(.left_pulley).rotate({
angle: 0,
animateTo: 180,
})
})
})
})
Now using .animate({}) to try and just move it at all.
$(window).scroll(function() {
if ($(this).scrollTop() > 0) {
var scott = $('img');
scott.animate({
left: 180
}
}
});
$(window).scroll(function() {
if ($(this).scrollTop() > 0) {
var scott = $('img');
scott.animate({
left: 180
}
function() {
console.log("hi");
}
});
console.log("hi2");
}
});
.left_pulley {
position: absolute;
margin: 0;
padding: 0;
top: 263px;
left: 87%;
height: 35px;
width: 35px;
}
.left_pulley img {
width: 100%;
}
.right_pulley {
position: absolute;
margin: 0;
padding: 0;
top: 263px;
left: 94.2%;
height: 35px;
width: 35px;
}
.right_pulley img {
width: 100%;
}
<div class="left_pulley">
<img src="gear2.png" />
</div>
<div class="right_pulley">
<img src="gear2.png" />
</div>
[
picture of gears i want to rotate.
]1
You should look into the CSS3 transform property, more specifically the rotate() function. Here
It would also be beneficial to add a transistion property to create an animated 'tween' between rotation values. Here. Make sure to add this transition to the transition property (as this is where rotation is set).\
You can then change the rotation of the gear (with automatic animation!) using jquery by setting the css value of the transition property, for example:
#gear{
transition: transform 300ms;
transform: rotate(7deg);
transform-origin:90% 90%;
position:absolute;
left:100px;
top:100px;
font-size:10rem;
width:100px;
height:100px;
}
You can test it out here by hitting run.
https://jsfiddle.net/oc4hhons/
Borrowing heavily from https://stackoverflow.com/a/17348698/2026508
You could do something like this:
var degrees = 0;
var prevScroll = 0;
$(window).scroll(function() {
if ($(window).scrollTop() > 0) {
if (prevScroll > $(window).scrollTop()) {
$('.woo').css({
'-webkit-transform': 'rotate(' + degrees+++'deg)',
'-moz-transform': 'rotate(' + degrees+++'deg)',
'-ms-transform': 'rotate(' + degrees+++'deg)',
'transform': 'rotate(' + degrees+++'deg)'
});
console.log('prevScroll greater:', prevScroll)
} else if (prevScroll < $(window).scrollTop()) {
$('.woo').css({
'-webkit-transform': 'rotate(' + degrees--+'deg)',
'-moz-transform': 'rotate(' + degrees--+'deg)',
'-ms-transform': 'rotate(' + degrees--+'deg)',
'transform': 'rotate(' + degrees--+'deg)'
});
console.log('prevScroll less:', prevScroll)
}
prevScroll = $(window).scrollTop()
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="height: 40px; width: 100px;background-image: url(' gear2.png ');background-color:blue;" class="woo">turn</div>
JS Fiddle-Updated, now they rotate together same direction but the rotation is depending on whether the scroll is up or down:
JS:
var $gears = $('.gear'),
$i = 0,
$scrollBefore = 0;
$(window).scroll(function () {
if($(this).scrollTop() > $scrollBefore){
$scrollBefore = $(this).scrollTop();
$gears.css("transform", "rotate(" + ($i+=4) + "deg)");
}else if($(this).scrollTop() < $scrollBefore){
$scrollBefore = $(this).scrollTop();
$gears.css("transform", "rotate(" + ($i-=4) + "deg)");
}
});
this JS Fiddle 2, makes them rotate in opposite directions, and each gear direction switches depending if the scrolling is up or down:
JS:
var $gearLeft = $('.left_pulley'),
$gearRight = $('.right_pulley'),
$i = 0,
$j = 0,
$scrollBefore = 0;
$(window).scroll(function() {
if ($(this).scrollTop() > $scrollBefore) {
$scrollBefore = $(this).scrollTop();
$gearLeft.css("transform", "rotate(" + ($i += 4) + "deg)");
$gearRight.css("transform", "rotate(" + ($j -= 4) + "deg)");
} else if ($(this).scrollTop() < $scrollBefore) {
$scrollBefore = $(this).scrollTop();
$gearLeft.css("transform", "rotate(" + ($i -= 4) + "deg)");
$gearRight.css("transform", "rotate(" + ($j += 4) + "deg)");
}
});
Thanks for all the help everyone!
Just want to post my finial code in case anyone else needs help in the future.
/* Scott Louzon 11/24/15
This code is used to rotate two images of a gears when user scrolls */
/*This function see's when user scrolls then calls rotate_right & rotate_left
accordingly */
var scroll_at = 0; //variable to keep track of
//scroll postion
$(window).scroll(function() {
if ($(this).scrollTop() > 0) //if scroll postion is not at
{ //top do this
if ($(this).scrollTop() > scroll_at) //if scroll postion is > than b4
{
rotate_down();
}
else if ($(this).scrollTop() < scroll_at) //if scroll postion is < than b4
{
rotate_up();
}
scroll_at = $(this).scrollTop(); //set varible to were scroll
//postion is at now
}
})
//Both these functions call css to rotate the image of a gear
var rotation = 0;
function rotate_down()
{
rotation+= 8;
$(".left_pulley").css("transform","rotate("+ rotation +"deg)");
$(".right_pulley").css("transform","rotate("+ (-1 * rotation) +"deg)");
}
function rotate_up()
{
rotation += 8;
$(".left_pulley").css("transform","rotate("+ (-1 * rotation)+"deg)");
$(".right_pulley").css("transform","rotate("+ rotation +"deg)");
}
.left_pulley
{
position: absolute;
margin: 0;
padding: 0;
/*Used for gear rotation */
transition: transform 1ms;
transform-origin:50% 50%;
top: 263px;
left: 87%;
height: 35px;
width: 35px;
}
.left_pulley img
{
width: 100%;
}
.right_pulley
{
position: absolute;
margin: 0;
padding: 0;
/* Used for gear rotation */
transition: transform 1ms;
transform-origin:50% 50%;
top: 263px;
left: 94.2%;
height: 35px;
width: 35px;
}
.right_pulley img
{
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="left_pulley">
<img src="gear2.png" />
</div>
<div class="right_pulley">
<img src="gear2.png" />
</div>

Categories

Resources