I am sorry, by center of origin I refer to the point that is calculated by setting the CSS "transform-origin: center center" property.
Both the viewport and the image have this property set. However, this get calculatd different points (depending on the width/height respectively). OriginX/Y is difference between both transform-origin. (AS seen here: https://bugzilla.mozilla.org/attachment.cgi?id=795609) Translating by this difference aligns both elements.

Concerning the encapsulation, I rotation has to been done by using "transform-origin: center center" or it is very messy. The same applies for scaling more or less. I opted to promote translation to its own layer to keep it origin at "transform-origin: top left" as assumed by all the calculation in the code. Hence I hardly did any chances to pan() and zoom(). I just parametrized it a bit.

I will move some of the orientation conditionals out of pan() and zoom() as you suggested earlier for clarities sake.