transform:skewの仕組みを理解する。

〽️反対の軸が傾斜。 〽️傾斜の方向。 〽️大きさが変わらないので大きくなる。 〽️90°以上を考える。 〽️XYskewのとき。 〽️座標変換につながる思考。





⬆︎CSSアニメーションについてのまとめページはこちら。




こんにちは、「ふ」です。

CSSアニメーション、transform編。前回transform:skewについて取り上げたのですが、なんとも予測不能な動きをしていました。

これ⬆︎は要素にskewX(1〜360°)を指定した場合の様子です。
transform:skewは他のtransform関数と違い、いまいち「直感的ではない」動きをします。

 ・どういう仕組みで傾斜しているの?
 ・X/Yで傾斜方向が違う?
 ・なぜ大きくなるのか?
 ・180°ごとにループする理由は?

skewを操作していると、さまざまな疑問にぶち当たります💧

そこで今回はtransform:skewの根本的な仕組みについて説明していきたいと思います。
仕組みを知ることである程度の結果を予想することができ、予想外の事態を回避しやすくなるでしょう。

反対の軸が傾斜。


幅100px、高さ100pxの要素があったとします。
これを座標空間で見たとき。

web要素における座標はX軸が右から左、Y軸が上から下へと伸びています。
原点を要素の左上とするとこの要素の成分は、

 X成分は「+方向に100px」
 Y成分は「+方向に100px」

と考えることができます。

ここにskewXを指定すると、内部的にどのように処理されているのでしょうか。
html要素のtransform-origin(変形の基準)は初期値が「center」となっています。記事内では要素のXY成分と座標の原点を一致した方がプレビューしやすいため、左上に指定しておきます。

#element { transform-origin:「「4left top」」; transform:「「1skewX(20deg)」」; }

見た目の結果がこちら。
ここにさっきのXY成分を割り当ててみます。

XY成分の矢印を配置すると、このように。

おや? 「skewX」としたのに、角度がついているのはY成分のほうです。
そうです、transform:skewXとすると、変形するのはX軸ではなく垂直に交わっているY軸に角度がつけられているんです。



transform:skewでは、指定した方向と交差している成分が傾斜している。

傾斜の方向。


transform:skewを指定すると、skewXの場合は反時計回りに、skewYの場合は時計回りに要素が傾斜します。
なぜそのような現象になるのか?それは先程のX成分、Y成分の動きで説明がつきます。

transform:skewX「「1(20deg)」」;

skewXに正の値20°を指定しました。このとき内部的には直交するY成分が変形します。「正の値」が与えられているので、Y成分もx軸の「+」の方向(左から右)に向かって傾斜します。

この動きに要素を当てはめると、半時計周りに歪んでいく状態に。

指定角度をマイナスの値にしてみます。

transform:skewX「「1(-20deg)」」;

角度にマイナスの値を指定したので、今度はY成分がx軸に対して逆方向に傾斜します。したがって要素も時計回りにskewします。

今度はskewYで試します。 web上の座標定義では、y軸は下が正の方向でした。

transform:skewY(20deg);

skewYでは、X成分が傾斜します。角度を「プラス20°」としているので、その方向はy軸の正の方向、下向きです。

X成分の傾斜にともない、要素は時計回りに歪みました。角度にマイナスの値に指定すると、逆方向に歪みます。

成分の歪み方向は軸のプラス方向に向いているため、skewX/Yで要素の傾斜方向が逆になるのです。



直交成分の傾斜の方向はskewの指定方向に準ずる。これが時計/半時計周りの原因。

大きさが変わらないので大きくなる。


次なる疑問。
skewにおいて、角度が90°に近づくにつれてなんだか要素全体がでっかくなってしまします。
「傾斜」させたかっただけなのに、なぜこのようなことが起こるのでしょうか?

先程の100px*100pxの要素で考えてみましょう。
skewする前のX成分に注目。
X成分自身の大きさは、「+方向に100px」です。

Y方向に45°傾斜させてみます。

#element { tranform:skewY(45deg); }

先の章で検証したように、skewYのときには指定方向の交差成分、つまりX成分が傾斜します。

そしてこのとき、⬆︎のようにはなりません。
skewの性質を知る上でのカギがここにあります。

X成分は、もともとのX値(+方向に100px)を保持したまま傾斜していきます。

となると、45°傾斜したときには成分自体の長さは拡大される、ということに成増。

要素を当てはめてみました。
X成分の長さが伸びていく。結果それに伴うことで要素も大きくなっていくのです。
これが「傾斜がつくほど要素が大きくなる」理由です。



傾斜する成分は、自身のX値またはY値を保持したまま変形していく。

90°以上を考える。


ここまでは傾斜が90°より小さい場合の動きを見てきました。
skewの値を90°以上にした場合、どのような現象となるのか、見ていきます。

#sample { transform:skewX(45deg); }

現在要素はX方向に45°傾斜しています。
傾斜角度を大きくしてみましょう。

transform:skewX(90deg);

「skewX」なのでY成分がどんどん傾斜していきます。
そして90°に達したとき。要素は「限りなく細長い平行4辺形」となるため、存在はしているのですが見えなくなってしまいます。

そして角度が90°を超えたとき、成分を表す矢印はどのような状態になるのでしょうか?

transform:skewX(135deg);

現在skew135°。
XY成分の状態、フツーに考えるとこう⬆︎なるのかと。



違います。

これではルール違反になってしまうのです。

この状態のY成分のY値は、「マイナス方向に100px」となってしまっています。
前のセクションの「傾斜するY成分は、自身のY値を保持したまま変形していく」という決まりにのっとれば、「プラス方向に100pxを保持したままで傾斜をとる」必要があります。

「プラス方向に100pxで傾斜135°」にするとしたら。。

Y成分の位置はこの⬆︎ように。
傾斜角が90°を超えた場合、「プラス方向に100px」を維持すべく、要素は対角上に回り込んでしまうのです。

現在のXY成分に要素を当てはめると、反対側に傾斜していることがわかります。

90°前後における、Y成分の動きです。
0~90°までは「傾斜の量が増えていく」状態でしたが、90°を過ぎてからは「傾斜の量が減っていく」ように進んでいきます。
skew90°は、「正の方向に傾斜しきった状態」であり、また「負の方向に傾斜しきった状態」でもあるのです。

これがskewXを0°から180°まで変化させた様子です。90°をすぎると反対方向から傾斜の量が減っていき、180°で傾斜がまったくない状態 = 最初の状態に戻ります。

さらに、180°〜270°の範囲も考えてみましょう。
skewのルールを考えずに角度を付けた場合、Y成分は左上の範囲で変化するのですが、

やはり「プラス方向に100px」を維持すべく、Y成分は対角に回り込みます。
そして270°〜360°に関してはフツーに「プラス100px」を維持できるので、そのままの領域で傾斜することができます。

あれ?

これって、0〜180°の時と同じ傾斜範囲ですよね?
そうです。0〜180°の変化と180〜360の変化は同じ状態に成増。
つまり、transform:skewは180°ごとに変化がループするということです。

■ transform:skewは、90°〜270°の間は傾斜成分が対角に回り込み、半周ごとに現象がループします。

XYskewのとき。


ここからはX、Y両方の成分をskewさせた場合の動きを見てみましょう。
ここでも不思議な結果が出ることがあります。

傾斜したX成分の角度をxdeg、Y成分のydeg、2つの成分がなす角度をθとします。

ここまでの結果から、X、Y成分の行動範囲は座標上で⬆︎のように表すことができます。
2つの成分がなす角度θは、0〜270°の範囲で変化するということになるのですが、θの状態により、要素の状態が大別されます。1つずつみていきましょう。

以下、θの状態別に挙動を示していきます。
ただしxdeg、ydegのいずれかが90°/270°であれば、 θの状態にかかわらず無限に膨張されてしまい、表示されません。「それ以外の状態」であることを前提に話を進めていきます。

 ■ θ = 0°

transform:skew(30deg,60deg);

xdegとydegの合計が90°や270°となるとき、2つの成分は重なってしまいます。θ = 0の状態です。
要素が完全につぶれてしまうため、何も表示されません。

 ■ 0°<θ< 180°

transform:skew(-30deg,-15deg);

2つの成分の角度が0°と180°の間であれば、自然なskewの結果と成増。

結果は想像どおりですね。

 ■ θ = 90°

transform:skew(45deg,-45deg);

先ほどの0°と180°の間において、θが90°になる時があります。
この場合2つの成分は直交しているので、要素の傾斜は起こりません。

ただし各成分の傾斜の深さによって、要素が膨張する度合いも変わってきます。

 ■ θ = 180°

transform:skew(150deg,-60deg);

X、Y成分が1直線上になってしまった状態です。
お察しのとおり、要素が完全につぶれてしまって表示されません。

 ■ 180°<θ< 270°

transform:skew(-60deg,-60deg);

2つの成分のなす角度が180°を超えてしまった場合、どうなってしまうのか。

本来要素はX、Y成分の成すL字型に囲まれるように配置されるのですが、θが180°以上の場合には、L字型の関係が反転してしまっています。

結果。X/Y成分の反転に伴い、要素自体も反転します。
あくまで2つの成分の作る「内角側」に要素は描画されるのですね。

X/Y成分の反転は、両者の共通の行動範囲である⬆︎の部分でも起こり得ます。
xdegとydegの合計が90°を超える場合です。



transform:skew(60deg,60deg);

X/Y成分の位置関係が逆転してしまっています。

成分の逆転により、要素も反転しました。

座標変換につながる思考。


transform:skewの内容をここでまとめておきます。
この5つで、skew全ての現象に説明がつきます

① 指定した方向と交差している成分が傾斜する。
② 成分の傾斜方向は指定方向の軸の向きとおなじ。
③ 傾斜成分は、自身のX値またはY値を保持したままというルールを持っている。
④ 90°〜270°の間は傾斜成分が対角に回り込む。
⑤ XY両方を傾斜したときは、2つの成分の角度によって状態が変化する。

最後までお読みくださり、ありがとうございました。
長々と説明を続けてきましたが、今回skewの説明に使ったお話は、「座標変換」という考え方です。
CSSを学習中の方なら、transform:matrixというものを聞いたことがあるでしょうか?
ここでの内容は、matrix(座標変換)に通ずるものがあります。興味をお持ちでしたら、是非チャレンジしてみてください。

ではまた〜 ♩

transform:matrixを理解する。

2021.06.14
行列計算は必要なし。











「ふ」です。

swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。