I'm looking for an effect very similar to this:
http://jsfiddle.net/G5Xrz/
function rnd(max) { return Math.floor(Math.random()*(max+1)) }
function showImage(container, maxwidth, maxheight, imgsrc, imgwidth, imgheight) {
var id = "newimage" + rnd(1000000);
$(container).append(
"<img id='" + id + "' src='" + imgsrc +
"' style='display:block; float:left; position:absolute;" +
"left:" + rnd(maxwidth - imgwidth) + "px;" +
"top:" + rnd(maxheight - imgheight) + "px'>");
$('#' + id).fadeIn();
return id;
}
setInterval(
function() {
showImage("#container", 400, 600,
"http://placekitten.com/" + (90 + rnd(10)) + "/" + (90 + rnd(10)),
100, 100);
}, 700);
But i'd prefer a flexible layout, ie images not bound by a div with predefined height and width, instead responding to the dimensions of the browser.
The following piece of code seems to have a more appropriate way of generating the random positions:
http://jsfiddle.net/Xw29r/15/
function makeNewPosition(){
// Get viewport dimensions (remove the dimension of the div)
var h = $(window).height() - 50;
var w = $(window).width() - 50;
var nh = Math.floor(Math.random() * h);
var nw = Math.floor(Math.random() * w);
return [nh,nw];
}
function animateDiv(){
var newq = makeNewPosition();
var oldq = $('.a').offset();
var speed = calcSpeed([oldq.top, oldq.left], newq);
$('.a').animate({ top: newq[0], left: newq[1] }, speed, function(){
animateDiv();
});
};
However I'm very much a beginner with javascript and I don't know how to combine the two.
Can anyone help?
Thanks
Take this part from the second code:
// Get viewport dimensions (remove the dimension of the div)
var h = $(window).height() - 50;
var w = $(window).width() - 50;
and use those variables h and w with the browser height and width (minus 50) as the appropriate parameters in this part of the first code:
setInterval(
function() {
showImage("#container", 400, 600,
"http://placekitten.com/" + (90 + rnd(10)) + "/" + (90 + rnd(10)),
100, 100);
}, 700);
Also, the first code has this HTML:
<div id="container" style="width:400px; height:600px; background: green; position:relative"></div>
That hard-codes the height and width at pixel values. You can use a CSS percentage value to make the width respond to the parent container's size. However, you will need JS to set the height properly; a percentage for the height does nothing
Putting that all together (and removing the "minus 50" part), you get this:
jsFiddle demo
<div id="container" style="width:100%; height:100px; background: green; position:relative"></div>
function adjustContainerHeight(height) {
$('#container').height(height);
}
adjustContainerHeight($(window).height());
setInterval(
function() {
var h = $(window).height();
var w = $(window).width();
adjustContainerHeight(h);
showImage("#container", w, h,
"http://placekitten.com/" + (90 + rnd(10)) + "/" + (90 + rnd(10)),
100, 100);
}, 700);
This updates the height of the container when the page is first loaded, and once again whenever the random image is placed. More robust code would have a separate height-adjusting event handler that updates the height whenever the page size changes.
Related
I have elements positioned on top of am img in the following way:
<div style={{ display: "inline-block", position: "relative" }} >
<img />
<div style={{ position: "absolute", left: 0, right: 0, top: 0, bottom: 0, width: "100%", height: "100%" }} >
<child elements I'm trying to position />
</div>
</div>
The child elements use the top, left, width, height properties to position themselves on top of the image.
I'm trying to make them scale with the image (- when the image's width and height changes I want them to stay in the same place and scale to the image):
width: Math.round(((box.x2 - box.x1) / imgWidth) * 100) + "%",
height: Math.round(((box.y2 - box.y1) / imgHeight) * 100) + "%",
left: Math.round((box.x1 / imgWidth) * 100) + "%",
top: Math.round((box.y1 / imgHeight) * 100) + "%"
But the results when using percentage are a little off than just using the coordinates.
Is there a better way to position the elements (boxes) so they scale with the image? Is there something wrong with the formula I'm using?
Edit:
For example:
The squares are the child elements I mentioned and when the user zooms in or out of the page or if the image's size changes I want the squares position on the image to be preserved and their scale match the image's scale
Ok, so this may not fit into your project straight off the bat but you should be able to get it working with a little bit of tweaking.
Use some JavaScript to calculate the absolute positioning of the child elements to a percentage.
var imgWrapper = document.getElementById("wrapper");
var children = document.getElementsByClassName("child");
window.onresize = function(event) {
var imgWidth = imgWrapper.offsetWidth;
var imgHeight = imgWrapper.offsetHeight;
for (var i = 0; i < children.length; i++)
{
// - Current child element
var child = children.item(i);
// - Child positions
var currentTop = child.offsetTop;
var currentLeft = child.offsetLeft;
var currentBottom = imgHeight - (currentTop + child.offsetHeight);
var currentRight = imgWidth - (currentLeft + child.offsetWidth);
var newTop = (100 * currentTop / imgHeight);
var newLeft = (100 * currentLeft / imgWidth);
var newBottom = (100 * currentBottom / imgHeight);
var newRight = (100 * currentRight / imgWidth);
child.style.top = newTop + "%";
child.style.left = newLeft + "%";
child.style.bottom = newBottom + "%";
child.style.right = newRight + "%";
}
};
http://next.plnkr.co/edit/E8RbqFTClYklW4w7
I am practicing my vanilla javascript, by writing an image gallery application.
The function I am working on is the swap from my imageRoll to my mainImage.
The swap works fine, and the height/width calculation works fine as well... but when I tell it to calculate the margin of the parent element and the new image, it fails unless you click the source image a second time.
JSFiddle: https://jsfiddle.net/un64w9hh/2/
Here's the function code:
function galleryToMainImg() {
var gNumList = this.parentNode.classList;
var gNum = gNumList[0].slice(1,2);
var imgId = "g" + gNum + "MainImage";
var imgName = document.getElementById(imgId);
var height = this.offsetHeight;
var width = this.offsetWidth
var styles;
var ratio;
imgName.src = this.src;
if (height > width) {
ratio = (width / height) * 100;
styles = "height:100%; margin: 0px " + ((imgName.parentNode.offsetWidth - imgName.offsetWidth) / 2) + "px;";
} else if (width > height){
ratio = (height / width) * 100;
styles = "width:100%; margin: " + ((imgName.parentNode.offsetHeight - imgName.offsetHeight) / 2) + "px 0px;";
} else {
ratio = 1;
styles = "width:100%; margin: " + ((imgName.parentNode.offsetHeight - imgName.offsetHeight) / 2) + "px 0px;";
}
imgName.style = styles;
}
Interestingly enough, as long as the images clicked from the gallery are the same layout (portrait vs landscape) it works every time after the first one. But if you switch layout, it breaks every time.
First click:
<img id="g1MainImage" src="./images/image01.png" alt="Caption" style="height: 100%; margin: 0px;">
Second click:
<img id="g1MainImage" src="http://ne.fario.us/designs/ImageGallery/images/image01.png" alt="Caption" style="height: 100%; margin: 0px 9px;">
I'm just not sure what is going on. Any help would be greatly appreciated.
I have been playing with your code for quite a while, your function galleryToMainImg() is just fine, ratio and .offsetWidth properties OK. I have eliminated every margin property from your .css and error persists.
Leaving calculations on the side, this works decently (no error, but I still have no margin properties applied by .css):
function galleryToMainImg() {
gNumList = this.parentNode.classList;
gNum = gNumList[0].slice(1,2);
imgId = "g" + gNum + "MainImage";
imgName = document.getElementById(imgId);
height = this.offsetHeight;
width = this.offsetWidth;
styles='';
ratio='';
imgName.src = this.src;
if (height > width) {
ratio = (width / height) * 100;
styles = 'height:100%; margin-left: 38%; margin-top: 0%'; /*+((imgName.parentNode.offsetWidth - imgName.offsetWidth) / 2)*/
} else if (width > height){
ratio = (height / width) * 100;
styles = "width:100%; margin-left: 7%; margin-top: 0%";/*+ ((imgName.parentNode.offsetHeight - imgName.offsetHeight) / 2) + "px;"*/
} /*else {
ratio = 1;
styles = 'width:100%; margin: "' + ((imgName.parentNode.offsetHeight - imgName.offsetHeight) / 2) + 'px;"';
}*/
imgName.style = styles;
}
Hope it is helpful for future examination.
that's normal because you change the image size on the click. I updated your fiddle to see the alerts. See hier jsfiddle.net/un64w9hh/4/
if i zoom the image it will going to the right. here is my js function below. the moment i zoom the image the background actual width and height is constant only the background size should be dynamic. that's the reason why it looks like if it zoom it will going to the right not in the center. what i want is when i zoom the image it zoom it forward to the center of the image.
function zooms(zoomType) {
switch(zoomType) {
case '+':
newW += 10;
break;
case '-':
newW -= 10;
break
}
if(newW <= 0) {
newW = 0;
} else {
if(newW >= 100) {
newW = 100;
}
}
return newW;
}
function backgroundAdjust(num, el) {
wid = (parseInt(num)+parseInt(el.width()));
el.css({
'background-size': wid + 'px auto'
});
return;
}
$('input.zoomButton').click(function() {
zoomType = $(this).val();
zoomNum = zooms(zoomType);
backgroundAdjust(zoomNum, $('#uploadImage'));
});
This should work if your image is square : it offsets the background image so its center remains at the center of the containing element.
var posx = (el.width()-wid)/2;
var posy = (el.height()-wid)/2;
el.css({
'background-size': wid + 'px auto',
'background-position': posx +'px ' +posy +'px'
});
What worked for me was scrolling the container element by half the value of same amount you are increasing the width and height of the image. For this you can use scrollBy. Eg. if your container element is el and the image inside is img. Now to zoom-in if you are increasing the width and height by 10% of the current 'x' px and height by 'y' px, Your zoom-in function would look like below:
function zoomIn() {
let imgWidth = img.width.replace(/px/g,""); // removing 'px'
let imgHeight = img.height.replace(/px/g,""); // removing 'px'
let x = imgWidth + (imgWidth*0.1);
let y = imgHeight + (imgHeight*0.1);
el.scrollBy(x/2, y/2);
}
This is how I get the click position when clicking on an image to do some image transformation. But my problem is, that the image has the CSS attribute max-width: 1000px. So the code works only for images which are smaller. For larger images the position result is not the real pixel which was clicked on.
My question is, if it is possible to calculate the correct click position for the natural sized image. An alternative would be to set some data attributes with the real image size like data-width: '1200px' and data-height: '1000px'. But still I have to do some calculation.
parentPosition = getPosition(event.currentTarget),
x = event.clientX - parentPosition.x,
y = event.clientY - parentPosition.y;
function getPosition(element) {
var xPosition = 0;
var yPosition = 0;
while (element) {
xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition };
}
If you know natural size and current size, i think you can just do this:
naturalClickPosX = (naturalWidth / currentWidth) * currentClickPosX;
naturalClickPosY = (naturalHeight / currentHeight) * currentClickPosY;
Have a look at this JSFiddle
HTML
<img src="http://placehold.it/1200x1000" width="1000">
JavaScript
$('img').on("click", function(e){
var $img = $(this);
var currentClickPosX = e.pageX - $img.offset().left;
var currentClickPosY = e.pageY - $img.offset().top;
var currentWidth = $img.width();
var currentHeight = $img.height();
var naturalWidth = this.naturalWidth;
var naturalHeight = this.naturalHeight;
var naturalClickPosX = ((naturalWidth / currentWidth) * currentClickPosX).toFixed(0);
var naturalClickPosY = ((naturalHeight / currentHeight) * currentClickPosY).toFixed(0);
alert("Current X: " + currentClickPosX + " Current Y: " + currentClickPosY +
"\r\nNatural X: " + naturalClickPosX + " Natural Y: " + naturalClickPosY);
});
try this , will work on all sizes
$('.img-coordinate').click(function(e){
var parentOffset = $(e.target).parent().offset();
// here the X and Y on Click
X = e.pageX - $(e.target).offset().left;
Y = e.pageY - $(e.target).offset().top;
alert(X + ' , ' + Y );
});
working fiddel : https://jsfiddle.net/h09kfsoo/
I need to send a multiplier to my server so I can properly manage my image. The client can upload images, and onload I want to immediatly figure out the difference between natural and client width. The image is in a container which is 350px and the image is set to min-width: 100%; I tried below, and oddly it worked a few times.
When I run this I get a correct naturalWidth, but clientWidth is 0.
Below is a method from jcrop. And some added functionality to get the natural and client width.
$('#target').Jcrop({
onChange : updatePreview,
onSelect : updatePreview,
aspectRatio : xsize / ysize
}, function() {
// Use the API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
// Store the API in the jcrop_api variable
jcrop_api = this;
// Move the preview into the jcrop container for css positioning
$preview.appendTo(jcrop_api.ui.holder);
});
function updatePreview(c) {
$('#xmargin').val(Math.round(c.x));
$('#ymargin').val(Math.round(c.y));
$('#x2').val(Math.round(c.w));
$('#y2').val(Math.round(c.h));
var clientW = document.getElementById("target").clientWidth;
var naturalW = document.getElementById("target").naturalWidth;
var multiply = naturalW/clientW;
$('#multiply1').val(clientW); //Returns 0
$('#multiply2').val(naturalW); //Returns correct value
if (parseInt(c.w) > 0) {
var rx = xsize / c.w;
var ry = ysize / c.h;
$pimg.css({
width : Math.round(rx * boundx) + 'px',
height : Math.round(ry * boundy) + 'px',
marginLeft : '-' + Math.round(rx * c.x) + 'px',
marginTop : '-' + Math.round(ry * c.y) + 'px'
});
}
}