I am trying to create an awesome "reveal" effect on my portfolio page.
Here is an example of what I am trying to visually accomplish with JS and CSS. My example was made using Photoshop.
Here is a JS FIDDLE I found and modified where I get sort of close.. But the spot light is too "hard" and not nearly as elegant as what I had in mind. I want it to feel more like a "glow" instead of a circle.
Does anyone know how to fix it? Any help would be much appreciated. I am open to any suggestions for achieving the effect.
// Create the spotlight
function createSpotlight() {
$('.spotlight').width(spotlightDiameter + 'px')
.height(spotlightDiameter + 'px');
for (var i = 0; i < numSpotlightLayers; i++) {
var layerDiameter = spotlightDiameter + (i * spotlightLayerThickness * 2);
var opacity = 1 - (i / numSpotlightLayers);
$('.spotlight').append('<div class="layer' + i + '"></div>');
$('.spotlight .layer' + i)
.width(layerDiameter + 'px')
.height(layerDiameter + 'px')
.css({borderRadius: (layerDiameter >> 1) + 'px',
opacity: opacity,
zIndex: (numSpotlightLayers - i)});
}
}
So I am going to answer my own question. Shout out and thanks to #Skyline3000 for suggesting the solution in the comment section.
The solution is to create a large div with a radial gradient containing a transparent center. Than you script that div to follow the mouse cursor. Set both the radial gradient div element and the content box "body" to a negative z-index value as to not obstruct page content. You also need to set the div to "Fixed" in the JS as to not create scroll bars when the mouse is near view port edges.
Here is a working fiddle.
https://jsfiddle.net/d4em31n2/16/
Required CSS:
position:fixed;
background: -webkit-radial-gradient(center center, circle cover, rgba(117, 245, 71, 0), rgba(0, 20, 42,1) 4%);
background: radial-gradient(center center, circle cover, rgba(117, 245, 71, 0), rgba(0, 20, 42,1) 100%) 4%);
Required JS:
var img=$('div');
$(document).ready(function(e) {
$(document).mousemove(function(e) {
var positionLeft = e.clientX - img.width()/2;
var positionTop = e.clientY - img.height()/2;
img.css({'position': 'fixed', 'left': positionLeft, 'top': positionTop});
mousePositionValueDiv.text(e.clientX+', '+e.clientY);
});
});
Related
I coded my first website and I wanted a parallax effect on my background when scrolling. It works, but on some computers &/or on some browsers &/or on some window sizes, the background jitters up and down when scrolling, while still sort of maintaining the parallax effect. I cannot figure out exactly what combination leads to the issue, it seems inconsistent.
In css I have a vertically repeating background image on the body of my page (the hexagon pattern):
body {
background: #fff9ed;
background-image: url("hexagon-side.png"), url("hexagon-side.png");
background-position: 0px 0px, 100% 0px;
background-repeat: repeat-y, repeat-y;
}
Then I used the following javascript that creates the parallax effect, making the hexagons move slower than other elements when you scroll:
window.addEventListener('scroll', function() {
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
var currentOffset = '0px ' + scrollTop / 1.2 + 'px, 100% ' + scrollTop / 1.2 + 'px';
document.getElementById("parallax").style.backgroundPosition = currentOffset;
});
Finally my body in the html file has the id parallax:
<body id="parallax">
Is there a way to fix this issue? Is there a better way to achieve this same effect? What might be causing this?
Adding
background-attachment: fixed;
to the css body, and changing the currentOffset to be
var currentOffset = '0px ' + scrollTop / -3 + 'px, 100% ' + scrollTop / -3 + 'px';
Fixed the jittering issues.
I'm trying to rotate a container with javascript and css property transform and transform-origin, the idea is to rotate it around certain coordinates (For example a pinch gesture center between the two fingers), I'm using this simple code (snippet attached) right now to rotate the container and using the onclick event to capture the anchor point. It is working properly as long as you keep clicking without moving the cursor to a different position on the container. There's an issue when you change the click position once the container has been rotated, the expected behavior is to keep track of the transformation and start rotating for that new point, however right now the container is doing an odd jump. I think that some x,y translation need to be added to the container, but i can figure out what's the correct factor to add to the container.
I'm not sure if I've illustrated well the expected behavior, to make sure here's and example: Imagine you pin a note to a surface at certain position, then, you start rotating the note, having the pin as anchor point. Now, after rotating the note a little, you put out the pin (Keeping the note at the same place), then you place the pin on a different position on the note and rotate again with that new anchor point. That's the expected behavior, hope i have explained myself well.
Here's a snippet to show it better, also available on codepen, cheers.
http://codepen.io/vasilycrespo/pen/GZeYpB
var angle = 15,
scale = 1,
origin = { x: 0, y: 0};
var transform = function (e) {
var map = document.getElementById("map");
angle += 15;
map.style.transformOrigin = e.pageX + "px " + e.pageY + "px";
map.style.transform = "rotate("+angle+"deg) scale("+ scale +")";
};
.content{
position: fixed;
top: 0px;
left: 0px;
margin-top:0;
margin-left:0;
background-color: #ccc;
width: 100%;
height: 100%;
}
.square{
position: absolute;
width: 400px;
height: 400px;
background-image: url(http://www.pnas.org/site/misc/images/15-02545.500.jpg);
background-size: cover;
}
<div class="content" onclick="transform(event)">
<div class="square" id="map"></div>
</div>
The problem is that every time you click, the div changes position based on where you click. After the first click, you should save e.pageX and e.pageY, and in the next clicks you should use the saved values. You can change your transform function to this:
var transform = (function () {
var pageX, pageY;
return function(e) {
if (typeof pageX === "undefined") {
pageX = e.pageX
pageY = e.pageY
}
var map = document.getElementById("map"), xr;
angle += 15;
map.style.transformOrigin = pageX + "px " + pageY + "px";
map.style.transform = "rotate("+angle+"deg) scale("+ scale +")";
}
}())
See updated Code Pen.
I need help showing/hiding text on a button click (specifically an arrow). I have a block of text that I have hidden and I need to slide it down in a time consistent with the arrow rotating 180 degrees. I also want it to do this only for the post above the arrow that was clicked. The solution I have come up with in this fiddle has many problems.
Here is the code:
$(function () {
var angle = -180,
height = "100%";
$(".down-arrow").click(function () {
$(".down-arrow").css({
'-webkit-transform': 'rotate(' + angle + 'deg)',
'-moz-transform': 'rotate(' + angle + 'deg)',
'-o-transform': 'rotate(' + angle + 'deg)',
'-ms-transform': 'rotate(' + angle + 'deg)',
});
$(".blog-post").animate({
'height' : height
});
angle -= 180;
height = "50px";
});
});
And these are the issues I am having:
It slides down way too fast
Once it slides back up it won't slide down again.
It does it for every post
This would be more dynamic and clean to use:
First we will take height's of all the .blog-post div's in an array.
Now making height: 50px of the div, after once we know actual height of all the div's. Which will helpful in making div smooth slide as we know height's.
Next on click of arrow class, we will toggle class which holds transform:rotate properties. Along with that we would check corresponding .blog-post div's height. So if it is more than 50px we would make it 50px, else we would take it's actual height from array and give to it.
Here is the JS/JQuery Code:
var totalNum = $('.blog-post').length; // Counting number of .blog-post div on page.
var i, myArray = [];
for (i = 0; i < totalNum; i++) {
var curHeight = $('.blog-post:eq(' + i + ')').outerHeight();
myArray.push(curHeight);
}
$('.blog-post').css('height', '50px');
$('.down-arrow').click(function () {
$(this).toggleClass('invert');
var index = $('.down-arrow').index(this);
var heightCheck = $('.blog-post:eq(' + index + ')').outerHeight();
if (heightCheck < 51) {
$('.blog-post:eq(' + index + ')').css('height', myArray[index] + 'px');
} else {
$('.blog-post:eq(' + index + ')').css('height', '50px');
}
});
Working : Fiddle
If you still do not understand feel free to ask.
I guess you should convert the 100% to pixels (with $(this).parent().innerHeight() or something like that, then it works well.
You should build some sort of toggle: keep track of which blog-post/arrow is up and which one is down (flag the blog posts or the arrows with some sort of class) and based on that, you should let it slide up or down.
Of course, you're referring to the post with a css selector. You should use a combination of $(this), .next() and .prev() functions in order to get the right post(s).
"It slides down way too fast"
Just set an animation duration. See the jquery.animate() documentation.
It seems that jquery is pretty buggy when it comes to animating using percentages. http://bugs.jquery.com/ticket/10669 http://bugs.jquery.com/ticket/9505 Try using pixels instead of percentage http://jsfiddle.net/8obybt1d/1/
"Once it slides back up it won't slide down again."
Because you are not changing the value of height back to hundred%
A rough piece of code:
if (height == "50px") {
height = "100%";
}
else {
height == "50px"
}
"It does it for every post"
Try using the 'this' keyword.
To solve point 2:
$(".blog-post").animate({
...
height = (height === "50px") ? height = "100%": height = "50px";
});
I was animating radial gradients with jQuery when I suddenly noticed something strange (check out this JSFiddle). When the mouse pointer is moved over the left side of the element the position animation is smooth, but when far to the right it isn't smooth at all (notice the jumps in position if you move your mouse slowly enough).
This feels like some kind of rounding error, but I'm not sure as to why it happens. Any ideas? I have only tested it on Google Chrome for the time being and it only happens in the horizontal direction.
CSS
html { background: #fff; }
html, body {
width: 100%;
height: 100%;
}
body { background: #000; }
JavaScript
$('body').on('mousemove', function(event) {
var x = event.pageX;
var y = event.pageY;
$(this).css('background', '-webkit-radial-gradient(' + x + 'px ' + y + 'px, transparent 10%, #000 5%)');
});
Can you replicate this or does it only happen to me?
EDIT: Works fine in Safari.
I could replicate it: like it's is said in this answer, it's not smooth because it's relying on the mousemove event only. Try to use a ticker, that's relying on time intervals. I modified your fiddle to use the ticker found in the already linked thread, here it is: http://jsfiddle.net/rh4Ljro4/
Here is the relevant javascript:
var container = $('body');
var contWidth = container.width();
var intervalId;
var mouseX, mouseY;
//this function is called 60 times per second.
function ticker(){
$(container).css('background', '-webkit-radial-gradient(' + mouseX + 'px ' + mouseY + 'px, transparent 10%, #000 5%)');
}
//this interval calls the ticker function every 16 milliseconds
intervalId = setInterval(ticker, 16); //33 millisecond is about 30 fps while 16 would be roughly 60fps
container.mousemove(function(e){
mouseX = e.offsetX; //store the current mouse position so we can reference it during the interval
mouseY = e.offsetY;
});
It was hard to explain with words, so I tried to explain with graphics.
There is a div here with its style.
Now if I change its width with 400px here...
because of it is a transformed (rotated) object, something happens and "TOP-LEFT" corner of it, moves down.
Now I want to keep its "TOP-LEFT" position fixed. But I couldnt find a correct correlation to fix it. I guess I need a trigonometric formula using rotation angle.
Also I know it is related with 'scale' and 'transform-origin' and can be easily done with them but I dont want to use any other transformation parameters. Especialy 'transform-origin' because of lack of browser support.
Does anybody here who can help me with the correlation which will be used in JavaScript to fix its corner. Maybe getBoundingClientRect() can be used for this.
Here is the FIDDLE
Thank you.
CSS transforms are really matrices, where transforming the elements are done with
matrix(a, b, c, d, tx, ty).
Then someone clever figured out it would be too complicated for webdesigners to understand such a matrix, so they added shorthand solutions, like transform: rotate() etc.
In other words, if you view the computed styles, there won't be a style whith the rotated degrees, and you can't do element.style.transform and get the rotation angle back again, all you'll get is the matrix.
Since the browsers use a matrix, all browsers that support CSS transform, also support changing the origin of that transform, so if you can rotate the element, you can change the origin.
The exception is Microsoft's filters, but even there you can rotate and change the origin, it's just a little more complicated to figure out.
As it makes no sense to not just change the origin of the transformation, and calculating it yourself would do the exact same thing, only a hundred times more complicated, you should really just add this to the CSS to solve the issue
-moz-transform-origin: 0 0;
-o-transform-origin: 0 0;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
FIDDLE
Just to confirm this, looking at MDN, at the bottom of the following pages, you'll find browser support, and it's just about the same for transform and transform-origin, as you generally never have one without the other
https://developer.mozilla.org/en-US/docs/Web/CSS/transform
https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin
As a final note, if it were me, I wouldn't even worry about IE8 and below, as those users are probably used to things looking weird these days anyway.
If you don't want to use transform-origin you can do this :
FIDDLE
$(function () {
var isScaled = false;
$('#box').on('click', function () {
if (isScaled) {
isScaled = false;
$(this).width('200').css({'top':'50px','left':'50px'})
} else {
isScaled = true;
$(this).width('400').css({'top':'24px','left':'46px'});
}
})
});
As other people has stated, you can use transform-origin. However, if you still want to do it via Javascript, I've done it for you in this jsfiddle.
Basically, what I do is to calculate the rotated position of the top left corners of each figure using the matrix transform for rotations (simplified), assuming the center point of the figures as (0, 0), which is, basically, what the browser does. Once I calculate the new positions for the corners, I calculate the difference, and substract that difference from the original left and top positions. I hope you find it instructive.
$(function () {
var isScaled = false;
var box = $('#box');
box.on('click', function () {
if (isScaled) {
isScaled = false;
$(this).width('200');
placeBox(400, 200);
} else {
isScaled = true;
$(this).width('400')
placeBox(200, 400);
}
});
var left = parseInt(box.css('left'));
var top = parseInt(box.css('top'));
var angle = (345 / 360) * 2 * Math.PI; //in radians;
function placeBox(oldWidth, newWidth) {
var midHeight = box.height() / 2;
var midOldWidth = oldWidth / 2;
var midNewWidth = newWidth / 2;
var cos = Math.cos(angle);
var sin = Math.sin(angle);
//rotation center coordinates
var cx1 = left + midOldWidth;
var cx2 = left + midNewWidth;
var cy = top + midHeight;
var mx1 = -midOldWidth * cos + midHeight * sin;
var my1 = -midOldWidth * sin - midHeight * cos;
var mx2 = -midNewWidth * cos + midHeight * sin;
var my2 = -midNewWidth * sin - midHeight * cos;
var difX = cx2 + mx2 - cx1 - mx1;
var difY = my2 - my1;
//now, position the element where it should:
box.css({
left: (left - difX) + 'px',
top: (top - difY) + 'px'
});
}
})
This Fiddle is showing the problem: http://jsfiddle.net/y343Z/19/
If you change the "shadow" size, it is moving alongside it's X Y axis.
Here one possibile soution.
http://jsfiddle.net/y343Z/18/
Just place shadow inside of the tranformed element:
<div id="box">
<div id="box-shadow" style="width:400px;"></div>
</div>
With this CSS:
#box {
width:200px;
height:200px;
position:absolute;
top:50px;
left:50px;
-moz-transform:rotate(345deg);
-webkit-transform:rotate(345deg);
-o-transform:rotate(345deg);
-ms-transform:rotate(345deg);
}
#box-shadow {
width: inherit;
height: inherit;
background-color:silver;
position:absolute;
opacity: 0.3;
}
#box {
background-color:orange;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
filter: alpha(opacity=50);
-moz-opacity: 0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
}
Just to clarify: I know that is not desired for a real shadow, since this has to be outside of the transformed box. But i think your shadow object is a "helper" that contains handles like in your screenshot.
Edit:
As other user posted, you may also use transform-origin: http://jsfiddle.net/y343Z/20/
transform-origin: left center 0;