33

I'm have a heat map application and store I store the x,y coordinates of a click and also the viewport width and height. Real data for 2 clicks:

x,   y,   width, height
433, 343, 1257,  959
331, 823, 1257,  959

The issue is when I resize the screen on the responsive site, the displayed clicks are now all off. I'm coming up empty on my searches but is there a formula or algorithm to recalculate the x and y coordinates for different resolutions. For example, the first click, if the width goes from 1257 to 990 and the height goes from 959 to 400, how to I recalculate the x and y so they line up in the same spot?

EDIT: I added 2 fields to the database, width_percentage and height percentage to store the x percentage of the width and the y percentage of the height. So if x was 433 and the width of the screen was 1257 then x was 35% from the left edge of the screen. I then used the same theory for the height and ran the calculations but it did not scale the click dot to the same spot as I though the percentages would do for scaling resolutions. I testing this by clicking on full resolution 1257 width then reopening at 900 width. See below for code to display click dots at lower resolution.

Ajax PHP

while ($row = mysql_fetch_array($results)) { 
  if( $_GET['w'] < $row['width'] ) {
    $xcorr = $row['width_percentage'] * $_GET['w'];
    $ycorr = $row['y']; 
  }
}

This uses the $_GET variable, passing the width and height of the screen resolution on page load. Then it gets the click dots from the database as $results. Since I only scale the resolution width from 1257 to 900 I did not put in calculation for height and its the same pixel as the initial click. The new width I multiplied by the percentage and set the dot that percentage margin from the left of the screen. Since the percentage is 35% the new x coordinate becomes 900 *.35 = 315px from the left edge. It did not work and I'm still scratching my head on head to keep click in the same spot for responsive sites.

Naterade
  • 2,635
  • 8
  • 34
  • 54
  • 2
    You'll need to show some code. However, the probable solution is to add a `resize` listener to the `document` and do some magic with `element.getBoundingClientRect()`. See the following answer to the question: [Retrieve the position (X,Y) of an HTML element](http://stackoverflow.com/a/11396681/691711) – zero298 Oct 06 '15 at 19:04
  • 3
    Apart from x.y coordinates, save target element of event too. Now keep some resize listener on document and recalculate the x,y coordinate of the saved element on resize event. – Rama Rao M Oct 06 '15 at 19:12
  • 1
    Are you sure you are getting the correct values in `$row`? Try `var_dump($row)`. Also: what do you mean with "It did not work"? What was the result this time? The same as before, or something else? – Daan Wilmer Oct 06 '15 at 19:40
  • 1
    Let me do some dumps and retest and let you know the results. – Naterade Oct 06 '15 at 21:00
  • 1
    Can i have demo where i will debug – Mitul Oct 07 '15 at 05:43
  • 1
    I can't seem to figure out why there needs to be a re-calculation on the `x` & `y` coordinates. Only the width and height might change. But as **coordinates start from the top-left corner** `x` & `y` would always have the same value (except that they should be lower than your width & height). – Goowik Oct 07 '15 at 08:13
  • 1
    I'd have some sort of viewport dimensions to artboard dimensions calculations, and attach all listener points based on that. – josh.chavanne Oct 12 '15 at 23:47
  • You could just bind an event to all of the elements allowing you to know when they were clicked on. And then detect their current position in the window. – Andrew Ice Oct 13 '15 at 14:51

7 Answers7

23

Have you tried this mathematical formula to change the range of a number?

FormulaX

FormulaY

And also instead of storing this:

x,   y,   width, height
433, 343, 1257,  959
331, 823, 1257,  959

You could store it normalized between 0 and 1 so it works for any width/height (calculated by dividing each x by its width and each y by its height):

x,     y
0.344, 0.357
0.263, 0.858

Then you don't need to know the width/height you used when you stored them, and when you want to translate them to the size of the current screen you just multiply each one by the current width/height

Daniel
  • 21,933
  • 14
  • 72
  • 101
10

You can acheive this by jquery:

$( window ).resize(function() {
  //ur code
});

javascript

window.onresize = resize;

function resize()
{
 alert("resize event detected!");
}

if you are working on mobile devices use this one also

$(window).on("orientationchange",function(event){
  alert("Orientation is: " + event.orientation);
});
Arun
  • 1,177
  • 9
  • 15
  • 3
    Careful with the `$(window).resize` binding. Use `debounce` or `throttle` with that, or you will get a really laggy and sluggish interface. `resize` events are triggered throughout the resize action, incessantly, and unless you want to recalculate each 10ms, you would throttle that to 250ms or how often you feel is necessary. Refer to: http://davidwalsh.name/javascript-debounce-function and https://remysharp.com/2010/07/21/throttling-function-calls – Adrian Oprea Oct 12 '15 at 14:41
3

I think you are on the right track with the percentages. Are you including the offset of the map image. I wonder if your algo is working but the visual representation appears wrong because the offset is changing in the viewport.

$(window).resize(function() {
    var offset = yourMap.offset();
    myLeft = offset.left();
    myTop = offset.top();
});

You need to add the offsets every time to get the proper placement.

Joe Johnston
  • 2,794
  • 2
  • 31
  • 54
3

This is what you should do. Sometimes the resize event fires when the document is being parsed. It is a good idea to put the code inside an onload event function. The orientation change function is taken from @Arun answer.

window.onload = function() {

  $(window).on("orientationchange", function(event) {
    alert("Orientation is: " + event.orientation);
  });

  window.onresize = function() {
    alert('window resized; recalculate');
  };

};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
www139
  • 4,960
  • 3
  • 31
  • 56
2

for this you need to do some calculation. Here is the function which will return new x and y potion based on the height and width

function getNewX(xVlaue, oldWidth, newWidth){
   return xVlaue * newWidth / oldWidth;
}
newX = getNewX(10, 150, 100); // Use

You can use the common function for height and width calc.

DEMO

Mitul
  • 3,431
  • 2
  • 22
  • 35
0

The whole question highly depends on the page you want to use this on. Most pages have a centered block and/or some self-resizing (read "responsive") elements. If the page is not very responsive, e.g. having a fixed width, you have an easier job. If the page is centered, you might want to save the cursor's X-position relative to the center of the page. this way the window width doesn't matter. The same also applies to left- and right aligned pages of course - in this case you would save the X-pos relative to the left or right edge of the window respectively.

The following image shows a center-oriented click position. Note that the x- and y properties of the click don't change here if you resize the window.

explanation of center-oriented position

Now to the more generic methods

If you save the window dimensions, the cursor position AND the scroll offsets on every click, you will most probably be able to reproduce it alongside the layout, but you'll need to reproduce it for every unique dimensions set. If you used the trick from above you might be able to overlay all layouts and find a common denominator. For example, if your page is centered in the window, has a max-width, and you saved the X-pos relative to the center of the window, you can overlay all clicks that happened in windows that were at least that width.

You could do some trickery however, and save the clicked elements alongside the informations you already do save. If you also save the click position relative to the element, you can evaluate this data to something like "the submit button is rather pressed on the bottom right side" or "people often click on the far end of that drop-down and sometimes mis-click by a few pixels".

Hubert Grzeskowiak
  • 15,137
  • 5
  • 57
  • 74
0

Try both of the following:

1. Padding and margins might not scale. Use "* {padding:0;margin:0}" at the end of your stylesheet and check if that fixes it.

2. Ensure outer and inner (that means all) elements scale. Any single element failing to scale will make many other elements fall out of place. This generally happens with text inputs. Use "*{border:solid 2}" at the end of your stylesheet to visually observe the effect of scaling on each element.

I'm sure your problem will be resolved.

aanand_ub
  • 71
  • 3