Get correct click position on scaled image - javascript

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/

Related

Zoom image on mouse position without transform/translate

I've found a simple example about zooming a HTML image on mouse wheel. Unfortunately in my case I cannot use CSS "transform/translate" and "transformOrigin" because image's position top/left stays the same, but it has to be changed (for example, when the image becomes large enough and reaches left screen side - 'left' position must be "0", not "500px" as in my example).
My code:
<!doctype html>
<html lang="en">
<head>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
window.onload = function() {
scale = 1; // scale of the image
xLast = 0; // last x location on the screen
yLast = 0; // last y location on the screen
xImage = 0; // last x location on the image
yImage = 0; // last y location on the image
var mousewheelevt=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel" //FF doesn't recognize mousewheel as of FF3.x
if (document.attachEvent) //if IE (and Opera depending on user setting)
document.attachEvent("on"+mousewheelevt, zoomImg)
else if (document.addEventListener) //WC3 browsers
document.addEventListener(mousewheelevt, zoomImg, false)
}
function zoomImg(e){
var evt = window.event || e // equalize event object
var delta = evt.detail? evt.detail*(-120) : evt.wheelDelta // check for detail first so Opera uses that instead of wheelDelta
var imgg = document.getElementById('imgg');
// find current location on screen
var xScreen = e.pageX - imgg.offsetLeft;
var yScreen = e.pageY - imgg.offsetTop;
// find current location on the image at the current scale
xImage = xImage + ((xScreen - xLast) / scale);
yImage = yImage + ((yScreen - yLast) / scale);
// determine the new scale
if (delta > 0)
{
if (scale < 5)
scale += 0.1;
}
else
{
if (scale > 1)
scale -= 0.1;
}
// determine the location on the screen at the new scale
var xNew = (xScreen - xImage) / scale;
var yNew = (yScreen - yImage) / scale;
// save the current screen location
xLast = xScreen;
yLast = yScreen;
imgg.style.transform = 'scale(' + scale + ')' + 'translate(' + xNew + 'px, ' + yNew + 'px' + ')';
imgg.style.transformOrigin = xImage + 'px ' + yImage + 'px';
}
</script>
</head>
<body>
<img id="imgg" src="http://www.baytrail.org/vtour/map4/access/CyteHils/Bayview_Tr_Grn_Hills.JPG" style="position:absolute; top:300px; left:500px;">
</body>
</html>
In my opinion all coefficients are known and I just need to replace these 2 lines to affect position, but I cannot find the right way:
imgg.style.transform = 'scale(' + scale + ')' + 'translate(' + xNew + 'px, ' + yNew + 'px' + ')';
imgg.style.transformOrigin = xImage + 'px ' + yImage + 'px';
How can I do that? If possible, please show an example with CSS "scale" and "zoom" functions.

Calculating positioning of the parent Div

Hi i want to calculate the position of the Div. Pardon me if i am not able to explain it properly but i will try to explain everything in the simplest way. I am creating sidepanel ad and to place the panels i want the position of the width. When i upload the script on my server then i get a small script which we place on the publisher website and where our script runs inside the iframe. I want to get the position of the div which has a class 'content'. Here is the screen shot.
in the above screenshot the yellow highlighted script is calculating the position of the div class="content" which is in red box. My code was working fine but on the publisher site it was not working fine and i was only able to get only two Divs whose id is like ebDiv..... (these divs are above the yellow highlighted js).
Then i found out to read the parentDiv in order to get the content positions.
i wrote this code.
var parentDoc = window;
while (parentDoc !== parentDoc.parent) {
parentDoc = parentDoc.parent;
}
parentDoc = parentDoc.document;
var parentDiv = parentDoc.getElementsByTagName('div');
var divs = [];
for (var i = 0; i < parentDiv.length; i++) {
if (parentDiv[i].className == "content") {
alert(parentDiv[i].offsetWidth);
alert(parentDiv[i].offsetLeft);
}
The width is calcuated as 1010 which is fine but i am just missing left positioning which i am getting using parentDiv[i].offsetLeft is 2.
Above the screenshot has width 1010 which is fine but left positioning is not correct.
i had this code to calculate the width.
function ReadDivPos(selector) {
var _divPos = "";
$(selector).each(function() {
var p = $(this).offset();
var w = $(this).width();
console.log("Top " + p.top) //top
console.log("left " + p.left) //left
console.log("right " + p.left + w) //right
console.log("offsetWidth " + w); //width
_divPos += "Left " + p.left + ",Width " + w + ",Avail Width " + window.screen.availWidth + ",Right " + (p.left + w) + "\\n";
});
return _divPos;
}
console.log(ReadDivPos(".content"));
when i am using the same code to calculate the positioning then it is not working .
var parentDoc = window;
while (parentDoc !== parentDoc.parent) {
parentDoc = parentDoc.parent;
}
parentDoc = parentDoc.document;
var parentDiv = parentDoc.getElementsByTagName('div');
var divs = [];
for (var i = 0; i < parentDiv.length; i++) {
if (parentDiv[i].className == "content") {
$(parentDiv[i]).each(function() {
var p = $(this).offset();
var w = $(this).width();
console.log("Top " + p.top) //top
console.log("left " + p.left) //left
console.log("right " + p.left + w) //right
console.log("offsetWidth " + w); //width
_divPos += "Left " + p.left + ",Width " + w + ",Avail Width " + window.screen.availWidth + ",Right " + (p.left + w) + "\\n";
}
}
Can someone me explain me how to fix this. Jquery/Javascript anythingwould be fine. I am not good in the frontend things so i am sorry if i could not explain it better. Thanks in advance
Here is a function used to get the position on the page of an element:
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 };
}
Used like this:
var pos = getPosition(element);
var x = pos["x"];
var y = pos["y"];
I'm not sure if this is exactly what you need, but if not maybe you can tweak it to fit your situation

select specific area of a div

I made a carousel using 2 divs named "left" and "right" putting mousemove events on them. I wanted to make it go up and down as well so I created a "top" and "bottom" and noticed that I couldn't make them combine to go the way the cursor goes.
I thus thought of targeting a specific area in the container (i.e top half of my container div) instead of creating divs inside triggering a specific direction, this way (I think) I can trigger all these event altogether. However after now hours of research I couldn't find a way to do so.
How should I proceed ? here is the code : http://jsfiddle.net/pool4/vL5g3/3/
var x=0,
y=0,
rateX=0,
rateY=0,
maxspeed=10;
var backdrop = $('.backdrop');
$('.directionx', backdrop).mousemove(function(e){
var $this = $(this);
var left = $this.is('.left');
var right = $this.is('.right');
if (left){
var w = $this.width();
rateX = (w - e.pageX - $this.offset().left + 1)/w;
}
else if (right){
var w = $this.width();
rateX = -(e.pageX - $this.offset().left + 1)/w;
}
});
$('.directiony', backdrop).mousemove(function(e){
var $this = $(this);
var top = $this.is('.top');
var bottom = $this.is('.bottom');
if (top){
var h = $this.height();
rateY = (h - e.pageY - $this.offset().top + 1)/h;
}
else if (bottom) {
var h = $this.height();
rateY = -(e.pageY - $this.offset().top + 1)/h;
}
});
backdrop.hover(
function(){
var scroller = setInterval( moveBackdrop, 30 );
$(this).data('scroller', scroller);
},
function(){
var scroller = $(this).data('scroller');
clearInterval( scroller );
}
);
function moveBackdrop(){
x += maxspeed * rateX;
y += maxspeed * rateY;
var newpos = x+'px '+y+'px';
backdrop.css('background-position',newpos);
}
Your problem is that the divs that control movement up and down are placed over the ones that control left and right, so the latter do not receive the mousemove event ever. Mouse events do not propagate through layers, even if they're transparent. I changed your code and CSS, so each div is in one of the corners. To make things easier, I've used data-* attributes so the direction controlled by each div is set in a declarative way, without the need to change the code. You'll see that the code is much simpler (and it could be simplified even more).
By the way, you could achieve this witout extra divs, just controlling where the cursor is (to the top, right, left or bottom of the center of the div).
backdrop.on('mousemove', '.dir', function(e){
var $this = $(this);
var direction = $(e.target).attr('data-direction');
var left = direction.indexOf('left') > - 1;
var right = direction.indexOf('right') > - 1;
var top = direction.indexOf('up') > - 1;
var bottom = direction.indexOf('down') > - 1;
if (left){
var w = $this.width();
rateX = (w - e.pageX - $this.offset().left + 1)/w;
}
else if (right){
var w = $this.width();
rateX = -(e.pageX - $this.offset().left + 1)/w;
}
if (top){
var h = $this.height();
rateY = (h - e.pageY - $this.offset().top + 1)/h;
}
else if (bottom) {
var h = $this.height();
rateY = -(e.pageY - $this.offset().top + 1)/h;
}
});
I've updated your fiddle.
EDIT In this new fiddle I do it without extra divs:
var w = backdrop.width() / 2;
var h = backdrop.height() / 2;
var center = {
x: backdrop.offset().left + backdrop.width() / 2,
y: backdrop.offset().top + backdrop.height() / 2
};
backdrop.on('mousemove', function(e){
var offsetX = e.pageX - center.x;
var offsetY = e.pageY - center.y;
rateX = -offsetX / w;
rateY = -offsetY / h;
});
backdrop.hover(
function(){
var scroller = $(this).data('scroller');
if (!scroller) {
scroller = setInterval( moveBackdrop, 30 );
$(this).data('scroller', scroller);
}
},
function(){
var scroller = $(this).data('scroller');
if (scroller) {
clearInterval( scroller );
$(this).data('scroller', null);
}
}
);
As you see, the mousmove handler is considerably simpler.
To avoid issue of children losing event could use just the one.
First HTML from 4 child divs to just one
<div class="backdrop">
<div class="direction"></div>
</div>
<div id="pos"></div>
Next Inside the mousemove find your relative position
//Get Relative Position
var relX = e.pageX - $this.offset().left;
var relY = e.pageY - $this.offset().top;
Get Relative Position as a percentage of width and put 50% of it in negative for direction
var w = $this.width();
rateX = ((relX / w) - 0.5) * -1;
var h = $this.height();
rateY = ((relY / h) - 0.5) * -1;
Fiddle

Stop function when pressing ctrl jQuery

So I am making a little game where you have to press Ctrl to stop a div from jumping randomly.
However I can't get it working...
The jumpRandom function works fine, until i put the randomJump(){return false;}; inside the if (event.ctrlKey) {}. What should I do to get it working?
js:
$(document).ready(function() {
function randomFromTo(from, to){
return Math.floor(Math.random() * (to - from + 1) + from);
}
$( "#goal" ).bind('mouseenter keypress', function(event) {
if (event.ctrlKey) {
randomJump(){return false;};
}
});
$('#goal').mouseenter(randomJump);
function randomJump(){
/* get Window position and size
* -- access method : cPos.top and cPos.left*/
var cPos = $('#pageWrap').offset();
var cHeight = $(window).height() - $('header').height() - $('footer').height();
var cWidth = $(window).width();
// get box padding (assume all padding have same value)
var pad = parseInt($('#goal').css('padding-top').replace('px', ''));
// get movable box size
var bHeight = $('#goal').height();
var bWidth = $('#goal').width();
// set maximum position
maxY = cPos.top + cHeight - bHeight - pad;
maxX = cPos.left + cWidth - bWidth - pad;
// set minimum position
minY = cPos.top + pad;
minX = cPos.left + pad;
// set new position
newY = randomFromTo(minY, maxY);
newX = randomFromTo(minX, maxX);
$('#goal').fadeOut(50, function(){
$('#goal').fadeIn(700);
});
$('#goal').animate({
left: newX,
top: newY,
duration: 500
});
}
});
Try this:
$("#goal").bind('mouseenter keypress', function (e) {
randomJump(e);
});
function randomJump(e) {
if (!e.ctrlKey) {
//do normal stuff
} else {
//depending on how permanent you need this to be...
//$("#goal").unbind('mouseenter keypress');
}
return !e.ctrlKey;
}

How to resize a div based on mouse location?

I'm trying to make a div that expands left, right, up, and down depending on where the mouse is. But when I move the mouse, the div just pops up and doesn't do anything. What is wrong in what I'm doing?
(function() {
document.onmousemove = function(e) {
draw(e);
};
function draw(e) {
var method = [
e.pageX ? e.pageX : e.clientX,
e.pageY ? e.pageY : e.clientY
];
var X = method[0],
Y = method[1];
var html = '<div class="box" style="padding-top:' + Y + ';padding-bottom:' + Y + ';padding-left:' + X + ';padding-right:' + X + '"></div>'
;
document.body.innerHTML = html;
}
})();​
You forgot the unit px:
(function() {
document.onmousemove = function(e) {
draw(e);
};
function draw(e) {
var method = [
e.pageX ? e.pageX : e.clientX,
e.pageY ? e.pageY : e.clientY
];
var X = method[0],
Y = method[1];
var html = '<div class="box" style="background-color:red;padding-top:' + Y + 'px;padding-bottom:' + Y + 'px;padding-left:' + X + 'px;padding-right:' + X + 'px"></div>'
;
document.body.innerHTML = html;
}
})();​
(I've also added a red background in order to make the DIV visible)
jsFiddle: http://jsfiddle.net/8LUwp/
X and Y are numbers. CSS lengths require units. Add some px.
CSS length attributes (padding, margin, height, width etc.) require units - px, em etc. So just having:
padding-top:10
is invalid. Instead you need to add units:
padding-top:10px
So in your case the line setting the html should read:
var html = '<div class="box" style="padding-top:' + Y + 'px;padding-bottom:' + Y + 'px;padding-left:' + X + 'px;padding-right:' + X + 'px"></div>';
You were missing px suffix with the x and Y
(function() {
document.onmousemove = function(e) {
draw(e);
};
function draw(e) {
var method = [
e.pageX ? e.pageX : e.clientX,
e.pageY ? e.pageY : e.clientY
];
var X = method[0],
Y = method[1];
var html = '<div class="box" style="padding-top:' + Y +"px" + ';padding-bottom:' + Y +"px" + ';padding-left:' + X +"px" + ';padding-right:' + X +"px" + '"></div>'
;
document.body.innerHTML = html;
}
})();​

Categories