CSS 如何使用Javascript精确设置动态样式转换?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19675997/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 00:52:05  来源:igfitidea点击:

How to exact set a dynamic style transform using Javascript?

javascriptcsstransformcss-transforms

提问by Tychio

I know method of setting transform, but I want to set the rotate and to keep others such as scale and skew.

我知道设置变换的方法,但我想设置旋转并保留其他的,例如缩放和倾斜。

Perhaps, we can write a function as:

也许,我们可以写一个函数:

// A variable of element, not parameter. separate out it make more clear.
var el = document.getElementById('el');
function setTransform (p_name, p_value) {
  // how to write some code to set the el transform style...
}

Moreover, I have a element:

此外,我有一个元素:

<div id="el" style="transform: rotate(45deg) skew(45deg);"></div>

And to us our function setTransform:

对我们来说,我们的函数 setTransform:

setTransform('rotate', '30deg');

I hope the element is this:

我希望元素是这样的:

<div id="el" style="transform: rotate(30deg) skew(45deg);"></div>

So my question is how to write content of the function setTransform?

所以我的问题是如何写函数setTransform的内容?

回答by thisiate

Note: you should use skewX and/or skewY instead of skew. See the MDN info here.

注意:您应该使用 skewX 和/或 skewY 而不是 skew。在此处查看MDN 信息

It would be easier to keep track of the transforms in a variable:

跟踪变量中的转换会更容易:

var elRot,    // the rotation 'counter' for the element 'el'
    elScale,  // the scale 'counter' for the element 'el'
    elSkewX,  // the skewX 'counter' for the element 'el'
    elSkewY;  // the skewY 'counter' for the element 'el'

// initialize values
elRot = 0;
elScale = 1;
elSkewX = 0;
elSkewY = 0;

or an object:

或一个对象:

var elTranform = {
    rot: 0,   // the rotation 'counter' for the element 'el'
    sca: 1,   // the scale 'counter' for the element 'el'
    skx: 0,   // the skewX 'counter' for the element 'el'
    sky: 0    // the skewY 'counter' for the element 'el'
};

So now you can start with the function (you will still use var el for the element), the first step is getting the values, so you change the arguments given to the function:

所以现在您可以从函数开始(您仍将使用 var el 作为元素),第一步是获取值,因此您可以更改提供给函数的参数:

// use this with separate vars
function setTransform (element, rotationArg, scaleArg, skewXArg, skewYArg) {
    // how to write some code to set the el transform style...
}

// use this with the object
function setTransform (element, elTransformArg) {
    // how to write some code to set the el transform style...
}

Next you have re-specify any other transforms that are 'staying', in the example you give, the skewX remains 45deg:

接下来,您必须重新指定“停留”的任何其他变换,在您给出的示例中,skewX 保持 45 度:

function setTransform (element, rotationArg, scaleArg, skewXArg, skewYArg) {
    // the brackets cause the string to be evaluated before being assigned
    element.style.transform = ("rotate() scale() skewX() skewY()");
}

or

或者

function setTransform (element, elTransformArg) {
    element.style.transform = ("rotate() scale() skewX() skewY()");
}

Now you have to put the arguments into the string:

现在您必须将参数放入字符串中:

function setTransform (element, rotationArg, scaleArg, skewXArg, skewYArg) {
    element.style.transform = ("rotate(" + rotationArg + "deg ) scale(" + scaleArg
        + ") skewX(" + skewXArg + "deg ) skewY(" + skewYArg + "deg )");
}

or

或者

function setTransform (element, elTransformArg) {
    element.style.transform = ("rotate(" + elTransformArg.rot + "deg ) scale("
        + elTransformArg.sca + ") skewX(" + elTransformArg.skx + "deg ) skewY("
        + elTransformArg.sky + "deg )");
}

A bit messy, so put that string in a variable (this will be beneficial for the prefixes):

有点乱,所以把这个字符串放在一个变量中(这对前缀有益):

function setTransform (element, rotationArg, scaleArg, skewXArg, skewYArg) {
    var transfromString = ("rotate(" + rotationArg + "deg ) scale(" + scaleArg
        + ") skewX(" + skewXArg + "deg ) skewY(" + skewYArg + "deg )");

    // now attach that variable to each prefixed style
    element.style.webkitTransform = transfromString;
    element.style.MozTransform = transfromString;
    element.style.msTransform = transfromString;
    element.style.OTransform = transfromString;
    element.style.transform = transfromString;
}

or

或者

function setTransform (element, elTransformArg) {
    var transfromString = ("rotate(" + elTransformArg.rot + "deg ) scale("
        + elTransformArg.sca + ") skewX(" + elTransformArg.skx + "deg ) skewY("
        + elTransformArg.sky + "deg )");

    // now attach that variable to each prefixed style
    element.style.webkitTransform = transfromString;
    element.style.MozTransform = transfromString;
    element.style.msTransform = transfromString;
    element.style.OTransform = transfromString;
    element.style.transform = transfromString;
}

Now call the function:

现在调用函数:

setTransform(el, elRot, elScale, elSkewX, elSkewY);

or

或者

setTransform(el, elTransform);

To change values, change the variables or object values and call:

要更改值,请更改变量或对象值并调用:

elRot = 45;
elSkewX = 30;
setTransform(el, elRot, elScale, elSkewX, elSkewY);

or

或者

elTransform.rot = 45;
elTransform.skx = 30;
setTransform(el, elTransform);

This way you only have to change the 'counter' values for each transform, and call the function to apply the transform. As mentioned above, it is important to keep any transforms that are not changed as this simply replaces the previous CSS value for the transform with the new one. Giving multiple values means only the last one is used (the C part of CSS).

这样,您只需更改每个转换的“计数器”值,并调用函数来应用转换。如上所述,保留任何未更改的转换很重要,因为这只是用新的转换替换了先前的 CSS 值。给出多个值意味着只使用最后一个(CSS 的 C 部分)。

回答by nik

May be following will help you...

可能以下会帮助你...

el.style.webkitTransform = "";
el.style.MozTransform = "";
el.style.msTransform = "";
el.style.OTransform = "";
el.style.transform = "";

回答by David Lapointe

The absolute best answer here would be a real API that allows us to affect any existing value of computed style without having to parse values. Such a thing exists in some abandonned and non-cross-browser form with the WebkitCSSMatrix APIand the W3C "official" equivalent DOMMatrix. I've seen talks of reformatting and consolidating those two APIs, but they don't seem to agree on implementation. Here's a shim to make it work cross-browser : CSSMatrix class from github user arian.

这里绝对最好的答案是一个真正的 API,它允许我们影响计算样式的任何现有值,而无需解析值。这样的东西存在于WebkitCSSMatrix API和 W3C“官方”等效DOMMatrix 的一些废弃和非跨浏览器形式中。我已经看到有关重新格式化和合并这两个 API 的讨论,但他们似乎在实现上没有达成一致。这是一个使其跨浏览器工作的垫片:来自 github 用户 arian 的 CSSMatrix 类

How this works is that you can pass it the computed transform string (ex.: "translsate3d(0px, 0px, 100px) scale(1.2) skew(2)") and it returns an object that you can manipulate with rotate, transform, translate, skew functions. Every functions return an existing instance of itself with the newly manipulated value and you can simply re-apply its "toString" value to the element style property.

这是如何工作的,您可以将计算出的变换字符串(例如:)传递给它,"translsate3d(0px, 0px, 100px) scale(1.2) skew(2)"并返回一个对象,您可以使用旋转、变换、平移、倾斜函数来操作该对象。每个函数都使用新操作的值返回自身的现有实例,您可以简单地将其“toString”值重新应用于元素样式属性。

A lot of words, but here's an example (Chrome and Safari only because of the WebkitCSSMatrix usage) :

很多话,但这里有一个例子(Chrome 和 Safari 只是因为 WebkitCSSMatrix 的使用):

var computedStyle = window.getComputedStyle(document.querySelector('.btn'));
var matrix = new WebKitCSSMatrix(computedStyle.transform);

// Every second, we add +6 degrees of rotation, no need to read the initial value since WebkitCSSMatrix has parsed it for us
window.setInterval(function(){
  matrix = matrix.rotate(6);
  // matrix = matrix.translate(2, 0, 0);
  // matrix = matrix.scale(1.8);
  document.querySelector('.btn').style.transform = matrix.toString();
}, 1000);
body{
   padding-top: 100px;
   text-align: center;
  }

  .btn{
   text-transform: uppercase;
   border-radius:200%;
   border:1px solid #000;
   width: 2em;
   height: 2em;
   display: inline-block;
   text-align: center;
   line-height: 2em;
   text-decoration: none;
   font-family: sans-serif;
   color: #000;
      
      // It is already rotated and scaled
   transition: transform 1000ms cubic-bezier(.28,.73,.31,1);
      transform: rotate(45deg);
      -webkit-transform: rotate(45deg);
  }

  .btn:hover{
   background:#000;
   color:#fff;
      
      transform: rotate(0deg) scale(1.5);
  }
<a class="btn" href="#">|</a>