Panzoom: Zoom-in is blurry in webkit-based browsers

Created on 27 Mar 2014  ·  21Comments  ·  Source: timmywil/panzoom

I think the title explains itself. In Firefox and IE, the issue doesn't occur.

Most helpful comment

I found a trick that works also on mobile for me (chrome and native android browser).
Just put these lines in css:

.panzoom {
-webkit-backface-visibility: initial !important;
-webkit-transform-origin: 50% 50%;
}

All 21 comments

This can't be fixed by panzoom. It is a webkit issue

Weird SVGPan doesn't seem to have this issue: http://www.cyberz.org/projects/SVGPan/tiger.svg

I double-checked and neither does panzoom if setting transforms on a group element in SVG.

Hiya guys
I've been using panzoom since yesterday and am still checking with our designer if SVG is the way to handle our current task. I'd like to use panzoom to zoom on different parts of the SVG image, but in Chrome it becomes blurry, as you guys discuss here. Can I do anything about it? @timmywil you write that "setting transforms on a group element in SVG" should help, but how do I do it? Any help would be appreciated.
Here's the piece of code I use:

var $map = $('.customers-map');
if ($map.length > 0)
{
    var $panzoom = $map.find('.panzoom').panzoom();
    $panzoom.parent().on('mousewheel.focal', function (e)
    {
        e.preventDefault();
        var delta = e.delta || e.originalEvent.wheelDelta;
        var zoomOut = delta ? delta < 0 : e.originalEvent.deltaY > 0;
        $panzoom.panzoom('zoom', zoomOut, {
            increment: 0.1,
            animate: false,
            focal: e
        });
    });
}

and my html is:

<div class="customers-map">
    <div class="panzoom">
        <img src="images/customers/customers-map.svg">
    </div>
</div>

Found a workaround. I flip between -webkit-perspective 1 and 0 on every panzoomzoom.

I'm doing something like this:
var flag = true;
function doThisOnEveryPanzoomzoom(){
$('#mypanzoom').css({
'-webkit-perspective': (flag?1:0)
});
flag = !flag;
}

@tlimited Interesting trick. I'll look into this.

v1.12.4 is last working version with chrome desktop and mobile. Newer versions will work on ios safari and ios chrome only.

Workaround by tlimited will work on desktop chrome but not on mobile. I noticed that in desktop chrome when the image is blurry, if you use chrome inspector and highlight any element on page, the image become sharp again. Repaint problem? (that perpective change triggers repaint, i assume)

I found a trick that works also on mobile for me (chrome and native android browser).
Just put these lines in css:

.panzoom {
-webkit-backface-visibility: initial !important;
-webkit-transform-origin: 50% 50%;
}

EDIT: This seems to work,
Thanks

I found that the gius80's fix worked, but that it slowed down performance on tablets quite a bit.

Instead, I added a panzoom onEnd callback which zooms in ever so slightly after the user has finished their action. This seems to cause panzoom to re-render with no blurriness. I'm sure there is a better way to get to the root of the problem, but this solution seems to work on Chrome desktop and Android at least.

$el.panzoom({
    onEnd: function(){
        $el.panzoom( 'zoom', {increment: .01});
    }
});

This is a catch-22. The webkit issue is explained well in this article. Panzoom is using -webkit-backface-visibility: hidden to promote the element to its own composite layer to take advantage of hardware acceleration. This has improved the performance of animations across devices. That said, webkit doesn't animate hardware-accelerated layers without blurring when any part of the animation happens to fall on a half-pixel. Panzoom can't provide a reliable, universal fix for this.

So, the question is, do we want faster animations that are sometimes blurry in webkit until webkit addresses the issue, or do we want to drop hardware acceleration?

BTW, even if Panzoom doesn't force the separate layer, it will happen sometimes anyway. Webkit will automatically create separate layers under certain circumstances (e.g. animating opacity).

"when any part of the animation happens to fall on a half-pixel"
Maybe the zoom level can be forced to full pixels with Math.floor or Math.ceil?

It's not the zoom level. From the article, it seems the element dimensions must start out divisible by 2, which is not appropriate for Panzoom to enforce (especially on responsive pages).

Fixed blurry is comment lin 821 //'backface-visibility': 'hidden',

gius80 your trick works, thanks a lot.

.panzoom {
     -webkit-backface-visibility: initial !important;
     -webkit-transform-origin: 50% 50%;
 }

I am working on a related problem where the initial rendering of a downscaled image gets extremely pixelated when panzoom is enabled. This does not occur in Firefox, but does occur in Chrome and IE. When applying the suggestion from @gius80 it renders correctly in Chrome. Still testing IE and failing at least in IE9. Thanks for bringing me one step closer!

@jdonahue82 does it work for you in Safari as well? No solutions works in Safari for me.

@marcelboettcher I agree. None of the solutions are working for Safari

According to my experience with a custom zoom (not jquery.panzoom) implementation:

Mobile Safari and Chrome get blurry once you have multiple elements using CSS transform laying over another using CSS position.

I guess this is a general issue with multiple layers that get hardware accelerated.

Maybe this is helpful for solving the problem.

Found another workaround!

You can force a redraw using this code on panzoomzoom.

This is the same as backface-visibility: initial, though, super slow. So you can debounce the function by 100ms. I used lodash for this, but you can manually debounce.

Here's the code:

$('#panzoom-el').on('panzoomzoom', _.debounce( function () {
    this.style.display='none';
    this.offsetHeight;
    this.style.display='';
}, 100));

Hope this helps :)

Was this page helpful?
0 / 5 - 0 ratings