correct resize/remeasure after css3-transform?

Page: 1

Author Post
Member
Registered: Feb 2011
Posts: 61
This is a very special issue concerning a problem, when manipulating fb-content with css3-transform. Floatbox keeps the original measured width/height of the content and does not adjust its parameters:

When having an image or div opened in floatbox and adjusting this fb-content (i.e. fb.topInstance.fbContent) with css-transform afterwards (e.g. from some kind of rotation-script), obviously the actual width and height of the visible content alters, but fb's viewport and image-dragging-data within zoom-mode stays with the "old values" and therefor ist not accurate ("of course", one might say...).

The magical question is: Is there a possibility to either
- force fb with new parameters concerning the actual content size after transformation (fb.resize does not cover that, as far as I know), or
- make fb (re-)calculate the "real" optical dimensions on screen after transformation, or
- adjust this problem with some kind of dirty and more complex js-hacks that I haven't thought of, yet?
Administrator
Registered: Aug 2008
Posts: 3382
When you say "fb.resize does not cover that, as far as I know", have you tried it? My guess is that a call of fb.topInstance.resize() would do the trick.
Member
Registered: Feb 2011
Posts: 61
fb.resize() definitely doesn't do the job, it's only re-adjusting the box without considering the transformed content.

To reproduce the issue:
- Goto FB-Demo-page: http://floatboxjs.com/demo
- Open wide picture in floatbox (e.g. "Double Beach On Koh Tab")
- inspect floatbox picture-element
- add element-style transform-css (e.g. in Chrome '-webkit-transform: rotate(90deg)'

you'll see that the rotated image is cropped (old width and height handling)

When applying fb.topInstance.resize() or fb.resize(), nothing changes.
Administrator
Registered: Aug 2008
Posts: 3382
You will have to manually specify the new dimensions. A transformed element does not report its changed dimensions, but continues to report the original dimensions for offsetWidth, offsetHeight and getBoundingClientRect (at least in WebKit). So there's no way for fb.resize to measure the transformed contents.

For example, the "dusk dip" image on the demo page is 480x640. Set '-webkit-transform: rotate(90deg) scale(0.75, 1.3333)' on the 'fbContent' img element. (Without the scaling, the image will be distorted.) Check the metrics of the transformed img and note that it is still 480x640. Now a call of fb.resize(640, 480) will produce a box that fits the transformed image. But note that the box metrics no longer match the img metrics, so a click-to-resize is available which will return the box to its original size.
« Last edit by admin on Tue Feb 05, 2013 3:15 am. »
Member
Registered: Feb 2011
Posts: 61
Thank you, this is helpful!

Quote
But note that the box metrics no longer match the img metrics, so a click-to-resize is available which will return the box to its original size.

This is the main-problem. It would be more practical to "tell" floatbox the new dimensions manually and let floatbox recalculate the image with manually given dimensions, without auto-measurement. could there be some kind of function, hook or 'dirty js-hack' where this would be possible:

- disabling or overwriting auto content-width/-height measurement
- or manually define content dimensions (especially for images)

?
Administrator
Registered: Aug 2008
Posts: 3382
You can 'tell' floatbox the desired dimensions by using the width and height options. You can also disable image resizing by setting enableImageResize:false.
Member
Registered: Feb 2011
Posts: 61
Of course, but this approach is very unsatisfying and far too complex, especially if some more fancy transformations (like free rotations-angles) apply.

Quote
A transformed element does not report its changed dimensions, but continues to report the original dimensions for offsetWidth, offsetHeight and getBoundingClientRect (at least in WebKit)


That's not true for getBoundingClientRect as far as I have tested (with Chrome), getBoundingClientRect() does this job perfectly accurate and cross-browser compatible.
« Last edit by JK2011 on Wed Feb 06, 2013 12:14 am. »
Administrator
Registered: Aug 2008
Posts: 3382
I'm not sure if this thread is a feature request to add auto-sizing on css transform changes or is a request for my participation in making your unique use case work. If a feature request, it's not going to happen. In my best judgement there is no demand (nor need) for it and it would likely be impossible to make it work well across all generic use cases and browsers. If its a request for my participation, that goes as far as pointing out what aspects of Floatbox might be helpful.

So you're actually rotating images, and not html content? I assumed html and that you were referencing the demo page image just for convenience. The fb.resize function uses getBoundingClientRect internally for html content. For image content, it uses the images native size as reported when it was loaded. The fb.resize function is intended primarily for html content after that content has been modified. For images, without provided width and height parameters it will simply return the floatbox to the images native size. If it did not, then it would do nothing if invoked against a resized image. getBoundingClientRect does indeed return transformed dimensions for the images, but it returns pretty whacky numbers for transformed html content. If you're transforming images, feel free to call getBCR to retrieve the width and height parameters to pass to fb.resize.

If I was showing images in Floatbox and wanted to give my site visitors the opportunity to view those images sideways and upside down, I would create 4 versions of the images, bundle them in a gallery set, and use the fb.showItem() function to display the desired orientation in response to a user clicking on "rotate this CW". This may not match what you are doing, but I really have no idea what you're up to.
Member
Registered: Feb 2011
Posts: 61
admin wrote
I'm not sure if this thread is a feature request to add auto-sizing on css transform changes or is a request for my participation in making your unique use case work.

It seems to be alittle bit of everything :D

This task for transforming images goes back to point 2) of my feature requests already two years ago. I managed this with a jquery-rotation plugin, which uses css-transform (or specific browser-methods like -webkit-transform) on modern browsers and also rotation by VML for older MSIE to maximize the usability.

First problem ist the scaling by css-transform, since this does not work on legacy browsers that do not support this css3-spec. Second problem is the reloading or resizing with enabling and disabling autoImageResize on opened floatboxes, which is more complicated and less usable than it "could" be.

As you've explained, getBoundingClientRect is NOT used for image-content. If it would be used by floatbox, everything just would be fine and very easy to handle. So this is why this topic here is indeed some personal problem-telling for my current needs, but also a kind of general "bug-report" because width & height of transformed images of any kind are not measured correctly.
« Last edit by JK2011 on Thu Feb 07, 2013 3:54 pm. »
Administrator
Registered: Aug 2008
Posts: 3382
Sorry, no bug here to report or fix.

Floatbox supports upright, rectangular content, thus covering 99.99% of the content people want to present with it. Floatbox does not support css-transformed images. I understand your feature enhancement request but for a variety of reasons will not be implementing such an enhancement.

fb.resize() without width and height provided is intended to measure and set html content. It needs to provide a rational result if invoked against image or video content. That result is to return a resized floatbox to it's original or native dimensions. Your proposal to measure current image state would cause fb.resize() to do nothing for resized images and videos. It would simply set the floatbox dimensions to whatever they currently are, thus breaking current behaviour for supported content.

To use fb.resize on css-transformed content, you will need to pass in the desired new width and height dimensions. If you want to determine what width and height to use by measuring transformed content, that's easy to do with one line of code. I would suggest using Floatbox's fb.getLayout() function for the measuring, passing in fb.fbContent or something similar as the element to measure. fb.getLayout uses getBoundingClientRect internally but has a couple of advantages to using that directly. It returns width and height values directly and it will return some sort of usable values in browsers that don't support getBoundingClientRect (very old Firefox and Safari, iOS 3 on the original iPhone, some Blackberries).

I have thrown you one small bone in the next release. If you pass new width and height for images or videos in fb.resize(), subsequent floatbox resizing will be based on these new values rather than the original native size. I caution you that you won't be happy with the results. As you know, you will need to scale rotated images that aren't square. Subsequent resizing of these images that have css-transform scaling is distorted and problematic. This is not a Floatbox characteristic but is the result of the transformed images css width and height values conflicting with the css-transform values.

In my opinion, you've entered a world of hurt and likely failure by pursuing the css-transform approach. I've already suggested simply having 4 versions of an image available and organizing the presentation of those. If that's too simple, you may want to consider using canvas to rotate those images. Canvas is standardized across browsers whereas css-transforms are not, it's much more versatile, and canvas elements would likely respond to manipulation such as proportional resizing much better.

I've used up all the time I'm willing to spend on this case. You're on your own now. Good luck, and have fun.
Member
Registered: Feb 2011
Posts: 61
Many many many many thanks for all these hints and tipps.

This is extremely helpful and much much much more than I ever could have expected.

Now I'll have to check how much pain I'm able to take, thank you for making this 'world of hurt' a little bit more friendly :D

Page: 1