Absolute center *above* div with different sized content - javascript

I have this script:
http://jsfiddle.net/ZhXf5/3/
When you hover over one of the boxes, the "popup" div is positioned above the box with different sized images. How can I make these different sized images centered above the div?

You need to do a bit more math after the image has been loaded to place the thumbnail correctly (updated jsfiddle):
$("document").ready(function () {
$("div.box").hover(function() {
var positionleft = $(this).position().left + $(this).outerWidth() / 2;
var positiontop = $(this).position().top;
var img = $("<img src='"+$(this).text()+"' />");
$("div.popup div.image").html(img);
img.load(function() {
$("div.popup").css({
display: 'block',
left: positionleft - (img.outerWidth() / 2),
top: positiontop - img.outerHeight() - 20,
});
});
});
});​

Related

Cornerstone image viewer Resize canvas size onclick button

Am using Cornerstone Image viewer.
I want to split the screen into 3 columns.
Initially left and right side div should hide and middle div should full window size display.
when i click show left div screen has to reduce and fit into 2 div's.
When i click show right div hide left and show with right and middle div's.
function resizeStudyViewer() {
var studyRow = $(studyViewer).find('.studyContainer')[0];
var height = $(studyRow).height();
var width = $(studyRow).width();
$(seriesList).height("100%");
$(parentDiv).width(width - $(studyViewer).find('.thumbnailSelector:eq(0)').width());
$(parentDiv).css({ height: '100%' });
$(imageViewerElement).css({ height: $(parentDiv).height() - $(parentDiv).find('.text-center1:eq(0)').height() });
$(imageViewerElement).css({ height: '100%'});
imageViewer.forEachElement(function (el, vp) {
cornerstone.resize(el, true);
if ($(el).data('waiting')) {
var ol = vp.find('.overlay-text');
if (ol.length < 1) {
ol = $('<div class="overlay overlay-text">Please drag a stack onto here to view images.</div>').appendTo(vp);
}
var ow = vp.width() / 2, oh = vp.height() / 2;
ol.css({ top: oh, left: ow - (ol.width() / 2) });
}
});
}
// Call resize viewer on window resize
$(window).resize(function () {
resizeStudyViewer();
});

Parallax with zoom on scroll

I've tried to find similar posts about this but failed to do so. What I'm trying to do is set up a parallax background that has a moderate zoom upon scrolling. I have the parallax down, that was simple enough, but the zoom on scroll is causing me difficulties.
if ($(".zoomImage").length == 0)
{
console.warn("You're attempting to set hero images without an existing class. '.heroImage'");
return;
}
$(document).scroll(function(){
var scrollpos = $(this).scrollTop();
var screenHeight = $(window).height();
var screenWidth = $(window).width();
$(".zoomImage").each(function(){
var offset = $(this).offset().top;
// Only modify when top is at top of browser on screen.
if (offset < scrollpos && scrollpos < offset + screenHeight)
{
var heroEffectPerc = 100 + 25 * (scrollpos - offset) / (screenHeight * 1.0);
$(this).css("background-size", heroEffectPerc + "% auto");
}
});
});
This is where I'm doing the zoom for the image, the parallax is done in pure CSS as represented below. The issue I'm having is figuring out the mathematics to make sure that the image doesn't escape the edge of its parent when the screen gets excessively wide or tall and still achieve the same effect. 1:
CSS:
pageCanvas
{
position: relative;
background-repeat: no-repeat;
background-position: center;
background-size: auto 100%;
background-color: white;
display: block;
left: 0;
top: 0;
width: 100%;
height: 100vh;
}
pageCanvas.parallax
{
background-attachment: fixed;
}
.
<pageCanvas class="parallax zoomImage" style="background-image: url('./Images/DisplayBackground.png');">
<banner>
<header>
Company name
</header>
<description>
I don't want to<br><span style="margin-left: 200px;">advertise here.</span>
</description>
</banner>
</pageCanvas>
I've tried to get it working, but either have an issue with one of the following:
White background shows on too wide.
White background shows on too tall.
Image stretching.
Do I need to bring in the images origin ratio with this or something? If I figure out a solution prior to an answer given, I'll post it.
Although the original was in a namespace, I'm going to place this answer as if it were not because I hadn't specified. Either way, I found the solution.
The first step was finding the ratio of the original image;
$(".zoomImage").each(function(index){
var bg = $(this).css('background-image');
bg = bg.replace('url(','').replace(')','').replace(/\"/gi, "");
// get image size.
var tmpImg = new Image();
tmpImg.src=bg;
$(tmpImg).one('load', function(){
orgWidth = tmpImg.width;
orgHeight = tmpImg.height;
bgImageRatios[index] = orgHeight / (orgWidth * 1.0);
});
});
To make life easier, I placed them in an array that was global to the name space. This is so I don't have to A) keep finding the ratio of the image, and B) can access it similarly to initializing later on. It should be noted that this method would require being called again in the instance there is any more or less '.zoomImage' classes brought into instance, as the array will be incorrect at that point.
What I did next was place the original code that loops the class into a function.
function zoomImage(scrollpos, screenHeight, screenWidth)
{
//console.log(screenHeight);
$(".zoomImage").each(function(index){
var offset = $(this).offset().top;
if (offset < scrollpos && scrollpos < offset + screenHeight)
{
var heroEffectPerc = 100 + 25 * (scrollpos - offset) / (screenHeight * 1.0);
if ((bgImageRatios[index] * screenWidth / screenHeight) > 1)
$(this).css("background-size", heroEffectPerc + "% auto");
else
$(this).css("background-size", "auto " + heroEffectPerc + "%");
}
});
}
I put it into a function because it would have been placed into two separate locations otherwise. (that's just messy coding). I updated the image size as follows.
$(window).on("resize", function(){
var scrollpos = $(document).scrollTop();
var screenHeight = $(this).height();
var screenWidth = $(this).width();
pageCanvas.zoomImage(scrollpos, screenHeight, screenWidth);
});
$(document).on("scroll", function(){
var scrollpos = $(this).scrollTop();
var screenHeight = $(window).height();
var screenWidth = $(window).width();
pageCanvas.zoomImage(scrollpos, screenHeight, screenWidth);
});
The following sources helped me solve my answer:
Can I get div's background-image url?
How to get image size from URL
Credit is due to them.

whay can't I change both image height and width at same time with javascript?

I have an image in a div and I want the image to stay centered at all times.
If the width of the image is wider than the screen, then I want the image to expand to the width of the view port. And if the image is shorter than the height of the view port then I want it to expand to the height of the view port.
In my code, when I expand the width, the height expands automatically, which is great since I don't have to calculate it. The height does the same thing. When the height is expanded, the width stays proportional.
However, if the width changes in such a way that the height is now smaller than then view port, then I need to check the height and bring it back up to the view port height (which should expand the width again but it doesn't). When I have to change both height and width at the same time, the automatic proportioning doesn't work. If I do one or the other, it does work.
How can I accomplish this so they can both be changed and work without distorting the image?
my code:
inner_width = $(window).innerWidth();
inner_height = $(window).innerHeight();
if (inner_width < original_pic_width ) {
$(pic).css({'width': original_pic_width});
}
else {
$(pic).css({'width' : inner_width });
}
if (inner_height < original_pic_height){
$(pic).css({'height': original_pic_height});
}
else {
$(pic).css({'height' : inner_height });
}
CSS contain is pretty nice.
$("div").css({
backgroundImage: "url(" + $("img").prop('src') + ")",
backgroundSize:"contain",
backgroundRepeat: "no-repeat"
});
div { width:200px; height:200px; border:1px solid red;}
div img { display:none }
<div>
<img src="http://www.somebodymarketing.com/wp-content/uploads/2013/05/Stock-Dock-House.jpg"/>
</div>
<script src="https://code.jquery.com/jquery-2.2.3.min.js"
integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo="
crossorigin="anonymous"></script>
Here is a possible solution (not sure to understand clearly what you want though). Note that I'm not absolutely sure that the centering method is cross-browser.
var div = $("div");
var img = $("img");
var imgw = img.width();
var imgh = img.height();
var imgr = imgw / imgh;
var sizes = [300, 120];
var i = 0;
setInterval(function () {
div.width(sizes[i]);
i = (i + 1) % 2;
adjust();
}, 1000);
function adjust () {
var divw = div.width();
var divh = div.height();
var divr = divw / divh;
if (divr < imgr) {
img.width("100%");
img.height("auto");
} else {
img.width("auto");
img.height("100%");
}
}
div {
position: relative;
}
img {
display: block;
position: absolute;
top: 0; bottom: 0;
right: 0; left: 0;
margin: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="width:120px;height:120px;border:10px solid #5900CC;">
<img style="width:100%;" src="http://i.stack.imgur.com/jKXi2.jpg" />
</div>
If you set both height and width... both dimensions, height and width will be set.
It should be enough to set just one dimension if you set the width=viewport's width if it's horizontal (width>height) or the height=viewport's height if it's vertical.
Find which dimension you have to change and change that one only. You can do that by checking the difference between the image's width and the window's innderWidth, and the difference between the image's height and the window's innerHeight. Whichever difference is greater is the one you need to change only. That should take care of the other dimension without having to resize both.

jQuery Image Viewport Calculation Algorithm to Avoid Scrollbars

I am creating an image hover effect but I am having problem with it. When I hover over certain images, the scrollbars appear which I want to avoid but don't know how to do so. I believe it has to do with viewport and calculations but am not sure how that is done.
Example Here
JSBin Code
Here is the code:
$('.simplehover').each(function(){
var $this = $(this);
var isrc = $this[0].src, dv = null;
$this.mouseenter(function(e){
dv = $('<div />')
.attr('class', '__shidivbox__')
.css({
display: 'none',
zIndex : 9999,
position: 'absolute',
top: e.pageY + 20,
left: e.pageX + 20
})
.html('<img alt="" src="' + isrc + '" />')
.appendTo(document.body);
dv.fadeIn('fast');
})
.mouseleave(function(){
dv.fadeOut('fast');
});
});
Can anyone please help me how do I make it so that hovered image appears at such place that scrollbars dont appear? (Of course we can't avoid scrollbar if image size is very very big)
I just want to show original image on zoom while avoiding scrollbars as much as possible.
Please note that I am planning to convert it into jQuery plugin and therefore I can't force users of plugin to have overflow set to hidden. The solution has do with viewport, left, top, scroll width and height, window width/height properties that I can incorporate into plugin later on.
Update:
I have come up with this:
http://jsbin.com/upuref/14
However, it is very very hacky and not 100% perfect. I am looking for a better algorithim/solution. I have seen many hover plugins that do this very nicely but since I am not that good at this, I can't do it perfectly well. For example Hover Zoom Chrome Plugin does great job of showing hovered images at appropriate place based on their size.
Like this:
html{overflow-x:hidden;}
html{overflow-y:hidden;}
All you need to do is add these definitions to your CSS and you're done.
Update with Resize: this is the mouseenter code for resizing and repositioning the pictures BOTH horizontally and vertically. Now, no matter where the HOVER image shows up, it's resized and positioned to always show in full AND uncut. As far as the scrollbars are concerned, if you show more thumbnails than can fit on the page, you will have scrollbars even before the HOVER images show up.
FINAL AND WORKING UPDATE: Because you had focused on the scrollbars being hidden, I think you overlooked the fact that if you put more thumbnails than the viewport can contain, the scrollbars would show up anyway and that therefore, since the user can scroll down the document, when you calculate the position of the hover image, not only do you need to account for the resize but you also to account for the scrollTop position too! FINAL JSBIN HERE, all pictures are showing RESIZED and in FULL no matter where the scrollTop is and no matter what the viewport size is.
$this.mouseenter(function () {
dv = $('<div />')
.attr('class', '__shidivbox__')
.css({
'display': 'none',
'z-index': 9999,
'position': 'absolute',
'box-shadow': '0 0 1em #000',
'border-radius': '5px'
})
.html('<img alt="" src="' + isrc + '" />')
.appendTo(document.body);
var DocuWidth = window.innerWidth;
var DocuHeight = window.innerHeight;
var DvImg = dv.find('img');
var TheImage = new Image();
TheImage.src = DvImg.attr("src");
var DivWidth = TheImage.width;
var DivHeight = TheImage.height;
if (DivWidth > DocuWidth) {
var WidthFactor = (DivWidth / DocuWidth) + 0.05;
DivHeight = parseInt((DivHeight / WidthFactor), 10);
DivWidth = parseInt((DivWidth / WidthFactor), 10);
}
var ThumbHeight = $this.height();
var ThumbWidth = $this.width();
var ThumbTop = $this.position().top;
var ThumbLeft = $this.position().left;
var SpaceAboveThumb = ThumbTop - $(document).scrollTop();
var SpaceBelowThumb = DocuHeight - ThumbTop - ThumbHeight + $(document).scrollTop();
var MaxHeight = Math.max(SpaceAboveThumb, SpaceBelowThumb);
if (DivHeight > MaxHeight) {
var HeightFactor = (DivHeight / MaxHeight) + 0.05;
DivHeight = parseInt((DivHeight / HeightFactor), 10);
DivWidth = parseInt((DivWidth / HeightFactor), 10);
}
var HoverImgLeft = 0;
var HoverImgTop = 0;
if (SpaceBelowThumb > SpaceAboveThumb) {
HoverImgTop = ThumbTop + ThumbHeight;
} else {
HoverImgTop = ThumbTop - DivHeight;
}
HoverImgTop = (HoverImgTop < 0) ? 0 : HoverImgTop;
HoverImgLeft = (DocuWidth - DivWidth) / 2;
dv.find('img').css({
'width': DivWidth,
'height': DivHeight,
'border-radius': '5px'
});
dv.css({
'left': HoverImgLeft,
'top': HoverImgTop
});
dv.fadeIn('fast');
});
Well, this looks fun. Anyway, here's my answer. I've been watching this for a few days and though I'd chip in too. The following will make sure that the hovering images do not go out of the viewport and in the event that the width of the image is bigger than the available space for display, the display of the image will be resized (You can comment out the code that does this if you don't want it. Just look for the word "resize" in the code).
var $document = $(document);
$('.simplehover').each(function(){
var $this = $(this);
// make sure that element is really an image
if (! $this.is('img')) return false;
var isrc = $this[0].src, ibox = null;
if (! isrc) return false;
ibox = $('<img />')
.attr('class', 'simpleimagehover__shidivbox__')
.css({
display: 'none',
zIndex : 99,
MozBoxShadow: '0 0 1em #000',
WebkitBoxShadow: '0 0 1em #000',
boxShadow: '0 0 1em #000',
position: 'absolute',
MozBorderRadius : '10px',
WebkitBorderRadius : '10px',
borderRadius : '10px'
})
.attr('src', isrc)
.appendTo(document.body);
$this.bind('mouseenter mousemove', function(e) {
$('.simpleimagehover__shidivbox__').hide();
var left = e.pageX + 5,
top = e.pageY + 5,
ww = window.innerWidth,
wh = window.innerHeight,
w = ibox.width(),
h = ibox.height(),
overflowedW = 0,
overflowedH = 0;
// calucation to show element avoiding scrollbars as much as possible - not a great method though
if ((left + w + $document.scrollLeft()) > ww)
{
overflowedW = ww - (left + w + $document.scrollLeft());
if (overflowedW < 0)
{
left -= Math.abs(overflowedW);
}
}
// 25 is just a constant I picked arbitrarily to compensate pre-existing scrollbar if the page itself is too long
left -= 25;
left = left < $document.scrollLeft() ? $document.scrollLeft() : left;
// if it's still overflowing because of the size, resize it
if (left + w > ww)
{
overflowedW = left + w - ww;
ibox.width(w - overflowedW - 25);
}
if (top + h > wh + $document.scrollTop())
{
overflowedH = top + h - wh - $document.scrollTop();
if (overflowedH > 0)
{
top -= overflowedH;
}
}
top = top < $document.scrollTop() ? $document.scrollTop() : top;
ibox.css({
top: top,
left: left
});
ibox.show();
});
$('.simpleimagehover__shidivbox__').mouseleave(function(){
$('.simpleimagehover__shidivbox__').hide();
});
$document.click(function(e){
$('.simpleimagehover__shidivbox__').hide();
});
$document.mousemove(function(e){
if (e.target.nodeName.toLowerCase() === 'img') {
return false;
}
$('.simpleimagehover__shidivbox__').hide();
});
});
While my solution itself is not perfect, you might find something useful in there that can help you determine the viewport. Also, you might want to think about the performance of the code. Since this is a plugin that you're building, you'll want to make some optimizations before releasing it to public. Basically, just make sure it's not slow.
You can position the image based on the available width: http://jsbin.com/upuref/19/
This demo takes in account the available space for positioning the image (i.e. the window width minus the image width). Also I've improved the event order, with the popup div only starting its fade-in after the image has been loaded.
My answer too (JSBin DEMO)
$('.simplehover').each(function(){
var $this = $(this);
// make sure that element is really an image
if (! $this.is('img')) return false;
var isrc = $this[0].src, dv = null;
if (! isrc) return false;
$this.mouseenter(function(e){
// mouse x position
var initXPos = e.pageX;
var initYPos = e.pageY+20-$(window).scrollTop();
var windowWidth = $(window).width();
var windowHeight = $(window).height();
// load original image
var $img = $('<img/>');
$img.on('load',function(eload) {
var widthImage = this.width;
var heightImage = this.height;
// set inline style for get sizes after (see problems webkit and cache)
$(this).css('width',widthImage);
$(this).css('height',heightImage);
var ratio = widthImage/heightImage;
var finalXPos = initXPos+widthImage>windowWidth? windowWidth-widthImage-5 : initXPos;
var finalYPos = initYPos;
var img = this;
// resize image if is bigger than window
if(finalXPos<0) {
finalXPos = 0;
$img.css('width', windowWidth-10);
$img.css('height',(windowWidth-10)/ratio);
}
// If overflow Y
if(finalYPos+getSize($img,'height')>windowHeight) {
// calculate where is more space (top or bottom?)
var showOnTop = (windowHeight-initYPos-10)<windowHeight/2;
if(showOnTop) {
if(initYPos<getSize($img,'height')) {
$img.height(initYPos-30);
$img.width(getSize($img,'height')*ratio);
}
finalYPos = 0;
finalXPos = initXPos+getSize($img,'width')>windowWidth? windowWidth-getSize($img,'width')-5 : initXPos;
}else {
// show on bottom
if(windowHeight-initYPos<getSize($img,'height')) {
$img.height(windowHeight-initYPos-10);
$img.width(getSize($img,'height')*ratio);
}
finalXPos = initXPos+getSize($img,'width')>windowWidth? windowWidth-getSize($img,'width')-5 : initXPos;
}
}
dv = $('<div />')
.attr('class', '__shidivbox__')
.css({
display: 'none',
zIndex : 9999,
position: 'absolute',
MozBorderRadius : '5px',
WebkitBorderRadius : '5px',
borderRadius : '5px',
top: finalYPos+$(window).scrollTop(),
left: finalXPos
}).append($img)
.appendTo(document.body);
dv.fadeIn('fast');
});
// load the original image (now is the same, but I think is better optimize it)
$img.attr("src",$this.attr("src"));
function getSize($el,widthOrHeight) {
// horrible but working trick :)
return +$el.css(widthOrHeight).replace("px","");
}
})
.mouseleave(function(){
dv.fadeOut('fast');
});
});
this script adapt the image to window size and adjust x position if needed.

Trying to make a div appear in the centre of a scrollable page - bug in my code?

Just as a preface to make sure I am clear, I don't want the div to appear dead centre in the middle of the page, I want it in the middle of the viewable window. So if you imagine a long page and the user has scrolled down to near the bottom and clicks the button the div will appear in the centre of the screen near the bottom of the page.
here is my code, which doesn't work in chrome:
function centerdiv() {
var scrolledX, scrolledY;
scrolledX = document.body.scrollLeft;
scrolledY = document.body.scrolltop;
var centerX, centerY;
centerX = document.body.clientWidth;
centerY = document.body.clientHeight;
var leftoffset = scrolledX + (centerX - 100) / 2;
var topoffset = scrolledY + (centerY - 100) / 2;
$('.current div[name="popup"]').css({'top' : topoffset + 'px', 'left':
leftoffset + 'px'});}
$(function() {
$("html").ajaxStart(function() {
centerdiv();
$(".current div[name=popup]").show();
});
$("html").ajaxComplete(function() {
$(".current div[name=popup]").hide();
});
});
Note, this is for an iphone mobile website and the ajaxstart function attaching to the html is crucial as it doesn't work on the iphone any other way on my website.
You forget to set position to absolute, or fixed
$('.current div[name="popup"]').css({'top' : topoffset + 'px', 'left':
leftoffset + 'px', 'position':'absolute' });}
Here is my solution that works fine:
var winH = $(window).height();
var winW = $(window).width();
$(this).css('top', winH/2 - $(this).height()/2);
$(this).css('left', winW/2 - $(this).width()/2);
$(this).show();
$(this) must refer to the DIV element you want to show in the center.
wh = $(window).height();
dh = $("#div").height();
$("#div").css("top",(wh - dh)/ 2 + $(window).scrollTop() + 'px');
Edit:
Not the same for width, it's actually:
ww = $(width).width();
dw = $("#div").width();
$("#div").css("left",(ww - dw)/ 2 + 'px');
But it really depends if you have a fixed viewport or not, there are many ways to center it...
Good Luck!
If you don't have horizontal scrolling you can do it partially with straight CSS
div{
left: 50%;
margin-left: -[box_width / 2]px;
}

Categories