18

If you have an element with many values for transform how do you change just one of those values without changing the other values?

You could rewrite them every time but in some situations that means you will have to parse apart the css for the transform into its different parts. For example:

-webkit-transform:rotateY(45deg) rotate(45deg);

you would have to get the property and value for rotate and rotateY. Isn't there a way to get and set just rotate without changing the value for rotateY?

The problem is illustrated here.

user1873073
  • 3,580
  • 5
  • 46
  • 81

6 Answers6

11

There is no way to directly modify a single component of the transform. Sadly, the various possible transforms were implemented as values on the transform attribute, rather than attributes themselves. There is no object model for CSS attribute values - attribute values are always just a string, as far as JavaScript is concerned. It would've been nice if transform was treated as a shorthand attribute for, eg, transform-rotate-y, transform-*, etc, the same way that background is a shorthand attribute for all the background-* attributes. This would've allowed us direct access to the values via JavaScript, but it was not implemented that way, so we are out of luck.

Edit: The simplest way to accomplish this (without studying the spec and doing a bunch of math) would be to nest your elements, applying different transformations to each. If you apply several transformations that won't change, go ahead and combine those on to one element. Any transformation that you do want to change, use a separate element:

Works here: jsfiddle.net/mkTKH/15


Edit: My original solution below won't work. In testing it out I discovered that getComputedStyle() converts the transform into a matrix(). An early draft of the spec says:

The transform property of the style object returned by getComputedStyle contains a single CSSTransformValue with a type of CSS_MATRIX. The 6 parameters represent the 3x2 matrix that is the result of applying the individual functions listed in the transform property.


So, you have to parse it. If you want to change just one portion of an attribute value, you can use a regular expression to parse the value:

var rotateY = "rotateY(" + deg + "deg)";
var transform = el.style.webkitTransform.replace(/\brotateY([^)]+)\b/, rotateY);
el.style.webkitTransform = transform;

I'd create a reusable function:

function setTransformValue(el, name, value) {
    var currentValue = new RegExp(name + "([^)]+)");
    var style = window.getComputedStyle ? getComputedStyle(el) : el.currentStyle;
    var currentTransform = style.transform ||
                           style.webkitTransform ||
                           style.MozTransform ||
                           style.msTransform ||
                           style.OTransform;
    var transform;
    if (currentValue.test(currentTransform )) {
        transform = currentTransform.replace(currentValue, name + "(" + value + ")");
    }
    else {
        transform = currentTransform + " " + name + "(" + value + ")";
    }
    el.style.transform = transform;
}

Untested.

gilly3
  • 87,962
  • 25
  • 144
  • 176
5

So @gilly3 was right that you can't really do it, but here's how you can kind of fake it.

  1. Remember the current value in an object
  2. Modify one part of the value in that object.
  3. Have a function that converts the object to a string.
  4. Apply the string.
Code Example
var el = document.getElementById('blablabla');
var transform = {
     rotate: 45,
     rotateY: 45
}

function getTransform() {
    var str = '':
    for (var key in transform) {
        str += key + '(' + transform[key] + 'deg)'
    }
    return str;
}

function applyTransform() {
    var transform = getTransform();
    el.style.webkitTransform = el.style.mozTransform = el.style.transform = transform;
}

function rotateABit() {
    transform.rotate += 20;
    applyTransform();
}
Jamund Ferguson
  • 16,721
  • 3
  • 42
  • 50
1

This is what I did and it worked plus it is very simple:

1. convert transformation property of object to a string

var currentTransformation = String(myobject.style.transform);

2. replace the the value that you want transformed

var finalTransformation = currentTransformation.replace("translateZ(100px)", "translateZ(YOURVALUEpx)");

3. assign new transformation

myobject.style.transform = finalTransformation;

Done!

Garret Kaye
  • 2,412
  • 4
  • 21
  • 45
0

I have best experience with this jQuery plugin.

Here is an example.

And even here is an example using in jQuery animation function.

Lin
  • 497
  • 5
  • 15
0

It is possible!

This topic is a bit old, and the author is inactive so he can't accept new answers. Though I've found a solution which I hope will be usfull for new readers. As posted above it is very hard to 'delete' previous value, but you can append to it. Apparently transform values can be 'stacked'! meaning you can add mulitpile rotations one after the other. So we can simply append text without complex replacing and long strings.

So assuming you just want to add rotation without over-writing previuos transitions, you can use this asnwer, which is the shortest solution I found:

The Solution - Without Text Manipulations:

let el = document.getElementsByTagName("div")[0];

// first, sync JS transform with current transform style:
const originalMatrix = window.getComputedStyle(el).transform
if(!el.style.transform){
        el.style.transform = originalMatrix 
}

// Then apply as much transforms as you whish
let myTransform = " rotate(45deg)"
el.style.transform += myTransform
el.style.transform += myTransform

This will rotate your element 90 deg from its original rotation. From here on you can just add transitions as you whish, and they won't over-write existing ones.

Note that for that to work the element must have some transform declatation beforehand (one can use * {"transform: scale(1)"} in the style sheet)

Originally posted here. Check out full explanation & working example in original post

Question's Fiddle - Working Version

window.onload = () =>{

var input = document.getElementById("input");
const box = document.getElementsByClassName("box")[0];
const para = document.getElementsByTagName("p")[0];
const originalMatrix = window.getComputedStyle(box).transform

input.addEventListener("change", () => {
    var transformVal = input.value;
    box.innerHTML = transformVal;
    
    // First, revert JS transform style:
    box.style.transform = originalMatrix
    // Then revert back rotate to 0 deg
    box.style.transform += " rotate(-45deg)"

     // Then append new transform
    box.style.transform += " rotate("+transformVal+"deg)"
    
    let transformText = "rotateY(45deg) rotate(" + transformVal + "deg)";
    para.innerHTML = transformText
});

}
body {
   padding:20px;   
}
.box {
    box-shadow: inset 0 0 15px red, 0px 0px 30px red;
    border-radius:4px;
    height:100px;
    width:100px;
    margin: 50px 50px;
    background: -webkit-linear-gradient(top, rgba(110,110,110,1) 0%,rgba(90,90,90,1) 100%);
    line-height:100px;
    text-align:center;
    color:rgba(220, 220, 220, 1);
    text-shadow:-2px -2px rgba(0, 0, 0, .2);
    font-size:50px;
    
    transform:rotateY(45deg) rotate(45deg);
}
<input type="range" min="0" max="360" value ="45" id="input"/>
<br />
<p>rotateY(45deg) rotate(45deg)</p>
<div class="stage">
    <div class="box">45</div>
</div>
lior bakalo
  • 440
  • 2
  • 9
-1

fiddle

var spinner = (function transform() {
    var rotateX = 0;
    var rotateY = 0;
    var rotateZ = 0;

    var translateX = 0;
    var translateY = 0;
    var translateZ = 0;

    var scaleX = 1;
    var scaleY = 1;
    var scaleZ = 1;

    function transform(props) {
        rotateX = props.rotateX ? props.rotateX : rotateX;
        rotateY = props.rotateY ? props.rotateY : rotateY;
        rotateZ = props.rotateZ ? props.rotateZ : rotateZ;

        translateX = props.translateX ? props.translateX : translateX;
        translateY = props.translateY ? props.translateY : translateY;
        translateZ = props.translateZ ? props.translateZ : translateZ;

        scaleX = props.scaleX ? props.scaleX : scaleX;
        scaleY = props.scaleY ? props.scaleY : scaleY;
        scaleZ = props.scaleZ ? props.scaleZ : scaleZ;

        var css = "";
        css += "rotateX(" + rotateX + "deg) ";
        css += "rotateY(" + rotateY + "deg) ";
        css += "rotateZ(" + rotateZ + "deg) ";
        css += "translateX(" + translateX + "px) ";
        css += "translateY(" + translateY + "px) ";
        css += "translateZ(" + translateZ + "px) ";
        css += "scaleX(" + scaleX + ") ";
        css += "scaleY(" + scaleY + ") ";
        css += "scaleZ(" + scaleZ + ") ";

        spinner.Spinner.css("-webkit-transform", css);
    }
    return {
        Spinner: $("#spinner"),
        Transform: transform
    }
})();
user1873073
  • 3,580
  • 5
  • 46
  • 81