10
votes

I'm trying to compute the viewport geometric center on a webpage, rendered with Tablet devices (iOS and Android), ie the actual CENTER of the viewport (what you see) according to current translation and current zoom level - don't want the center of the document itself, I want the center of the screen what I'm viewing.

The problem is that this calculation is does not take into account any kind of zoom (an then) translation.

On iOS, I've tried with some of these answers, on the question detecting pinch to zoom on iOS, I was able to catch the event "OnZoom" but didn't get any value, though.

On Android, I can't even catch any event related to zoom. I'm aware of touchmove and touchstart events, but how can I distinguish then in order to get zoom (and zoom value)

I'm using jQuery 1.7.2 library.

3
your question is confusing. what do u mean by "viewport geometric center".. plz explain.Neji
This may sound a bit odd, but did you try a hidden, absolutely positioned div, stretched to fill (left:0; right:0; top:0; bottom:0;) and inside that div a centered single pixel image, and then getting the image's coordinates using .position();?c_kick
Wouldn't that image be as big as the whole document? If it would the stretched the center won't be according to the viewport center, I think ...jose
This is what I meant: jsfiddle.net/c_kick/BCPxR/2. You can then hide all this by adding the css .stretched, .center_pixel { visibility: hidden; } (display: none; will break the code, because then the elements are not there)c_kick
Sorry, misread you. The above fiddle won't work when you zoom in or pan the document. Maybe this one will work, where the container div is stretched to percentage: jsfiddle.net/c_kick/m22MZc_kick

3 Answers

2
votes

I have made a demo page which is confirmed to work on iPhone iPad, Samsung Galaxy Tab 10. I have only attached the click event on a huge div, so tap on the screen after zooming to update the display.

The calculation is very simple, use screen.width/window.innerWidth to get the zoom level. screen.width will always be in device pixels and window.innerWidth is always in css pixels, which also take the zoom into account.

Further calculation is simple math:

// round the result down to avoid "half pixels" for odd zoom levels
Math.floor(window.scrollY + window.innerHeight/2);
Math.floor(window.scrollX + window.innerWidth/2);

To check whether the user is zooming, attach the listener to window.resize and window.scroll which will fire after orientationchange hiding the address bar and zooming.

Here's my demo JavaScript:

var dot = document.getElementById("dot");
document.getElementById("main").addEventListener("click", function(e) {
    var zoom = screen.width / window.innerWidth;
    alert("zoom: " + zoom + "\n" + "ScrollY: " + window.scrollY);

    dot.style.top = Math.floor(window.scrollY + window.innerHeight/2 - 5) + "px";
    dot.style.left = Math.floor(window.scrollX + window.innerWidth/2 - 5) + "px";

}, false);
1
votes

Setting up a simple HTML page, I can get pretty close to center.

With the code below, I'm just checking the width and height of a fixed div, and then combining that with the document offset and some simple maths to figure out the center, and place a single black dot there. I can get it pretty close, but it varies on my iPhone 4S.

Haven't tried on Android devices.

I don't think this would work on iOS <= 4, as they don't support fixed-positioning.

<style>
#fixed{
position: fixed;
left: 0; right: 0; top: 0; bottom: 0;
background: orange; opacity: 0.25;
}
.black{
  position: absolute;
  top:0;left:0;
  width: 1px; height: 1px;
  background: black;
}
</style>

<body>
<div id="fixed"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script>
jQuery(function($){
setInterval(function(){
var top = ($("#fixed").height()/2) + $("#fixed").offset().top;
var left = ($("#fixed").width()/2) + $("#fixed").offset().left;
$("body").append('<div class="black" style="top: '+top+'px; left: '+left+'px;" />');
}, 1500)

});
</script>
</body>
1
votes

I had a client request a page zoom detection method in javascript a couple years ago.

In my case, he wanted it to work on a facebook app. Through the iframe canvas/viewport.

I used Max and Min functions

function getDocHeight() {
    var D = document;
    return Math.max(
        Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
        Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
        Math.max(D.body.clientHeight, D.documentElement.clientHeight)
    );
}
function getDocWidth() {
    var D = document;
    return Math.max(
        Math.max(D.body.scrollWidth, D.documentElement.scrollWidth),
        Math.max(D.body.offsetWidth, D.documentElement.offsetWidth),
        Math.max(D.body.clientWidth, D.documentElement.clientWidth)
    );
}

function getMinHeight(h) {
return Math.min(viewport.currentHeight, getDocHeight(), h);
}

getMinWidth was similar, but I had to apply browser-based tweaks to it.

I created an object called viewport which stored the properties of a fixed position div, specifically currentHeight and currentWidth were the offsetHeight and offsetWidth of the div element.

I ended up initializing a window.intervalTimer to run checks on the state of that div, comparedTo the stored values within the viewport object.