How implement independent transforms for translate AND scale?

I am able to translate an image, via a transform, and I can also, independently, change the image size. I would like to make the change in image size also be a transform, but am encountering problems. I have the following tags, to hold and manipulate an image.

<div id="viewPort" class="viewer medium_4_3 pos00_00">
    <img id="img" src="imgURL" class="img_medium"/>
</div>

The viewer class contains all the CSS except size and positioning. The class medium_4_3 is one of several possible that each contain a height and width property. The last class, “pos00_00” is one of a large collection of positioning classes with a range of translation values. An example follows:

.viewer.pos20_60 img {
    transform: translate(-20%, -60%);
    transition: transform 1000;
}

By removing and adding “pos” classes, I translate the image with the following Javascript code fragment (where the desired positioning classes are contained in the variables):

viewPort.classList.remove(posClassToReplace);
viewPort.classList.add(currentPosClass);

To change the size of the image, I am using a series of CSS classes that specify a range of widths:

.img_small 
    width: 300;
    opacity: 0;
}
.img_medium {
    width: 600;
    opacity: 0;
}
.img_large {
    width: 1000;
    opacity: 0;
}

The Javascript that handles the switching for the image similarly removes and adds classes to the classList for img.classList.

Forgot to mention: the opacity values are defaults that are manipulated in Javascript, using a setInterval method for fading in or out.

The changes in the image size are instantaneous. I’d like to make them transition, similar to the way the translation values are transitioned. But so far I’ve been unable to do so. For example, I tried rewriting the CSS for the image sizing classes as follows:

.img_medium {
    transform: scale(4.25);  /* img.jpg: 2550 pixels width, desired: 600 */
    transition: transform 1000;
    opacity: 0;
}

However, this leaves the image on the screen at the full 2550 width, instantaneously, with no transform animation visible.

I clearly am missing something about how to go about this.

Is this a situation where one should instead look at making another setInteraval method (similar for fading in and out) to directly alter the image’s width property? I think I’d rather use transform, if it can be made to work.

Do you mean you want to use transform: scale(4.5) instead of changing the images actual width?

If so then you are already using the translate value so you would need to combine them in the same rule.

E.g. transform: translate(x, y) scale(4.5) ;

You can’t do them individually (yet) as one will overwrite the other.

You could of course translate the parent element instead of the image and then just scale the image

What is that supposed to do. 1000 what?

Why aren’t you animating the opacity in css instead of js? You can use a comma separated list to add more transition properties.

Also you must specify units on your css dimensions otherwise browsers are allowed to consider them as zero.

Yes, an oversight on my part to omit the “s”! I will check that this wasn’t the cause of the code not working. (Also I see it’s in seconds, not millis!)

I think that I was attempting to follow that bit of advice. The div #viewPort is being translated. The image #img held within #viewPort is being scaled.

I will look into this. It would be tricky to explain.

1 Like

Not having success. The new class for the image has a properly designated time value, but the css class is erroring out.

.img_medium {
	transform: scale(0.425);
	transition: transform 1s;		
}

Maybe an additional tag is needed to get the proper parent/child separation you mentioned.

I’m pretty far along with a workable JS solution. I may have to just stick with that. I’m skeptical about combining the translations and scalings. I already have 60 (10 x 6 grid of possible positions) translation classes, and multiplying that by 4 or more possible scaling values seems unwieldy (especially since I could end up with more like 6 or 8 total scaling values).

If this rule is present on the same image :slight_smile:

.viewer.pos20_60 img {
    transform: translate(-20%, -60%);
}

Then this rule will not be applied to that image:

.img_medium {
	transform: scale(0.425);
	transition: transform 1s;		
}

The specificity of the first rule wins out. Even if it did work then the translate would be lost because as mentioned transform properties can only be multiples when combined in the same rule (although that is to change I believe).

Maybe add a span around the image and translate the span but scale the image. It all depends on the set up which I can’t really see without a demo :slight_smile:

More rookie mistakes on my part! Thank you for reminding me that the first rule is acting on the img tag and not the viewport. I managed to get mixed up about that, even though I had written the code that way. Good to also have pointed out the precedence of the transform rules. I very much appreciate your help.

The JS scaling function that I wrote is working satisfactorily. I was able to figure out how to hard code some easing as it transits from one img width to the next (using setInterval). I’m going to take what I learned here about an alternate CSS solution for future work, or possibly use it for refactoring the existing project if the JS ends up causing performance problems.

I’ll try to make time for presenting a demo the next time I have a question. I hope to have something hosted online on this project before the week is out. The goal is a browser-based comic book reader, with the individual panels encoded (server side database, delivered for a given comic book page via Thymeleaf) and with the viewer having the ability to transition through the panels in a helpful way.

2 Likes