トランスフォームについて(CSS Transforms)
トランスフォームについて
■トランスフォームについて
CSS Transforms は、CSS3 世代の機能です。
http://www.w3.org/TR/css3-transforms/ (Working Draft)
エレメントをアフィン変換するには、スタイルの transform を使用します。
■スタイルの transform を設定する関数
スタイルの transform を設定する関数
// ------------------------------------------------------------
// スタイルの transform を設定する関数
// ------------------------------------------------------------
function StyleDeclarationSetTransform(style,value){
var list = [
"transform",
"webkitTransform",
"MozTransform",
"msTransform",
"OTransform"
];
var i;
var num = list.length;
for(i=0;i < num;i++){
if(style[list[i]] !== undefined){
style[list[i]] = value;
return true;
}
}
return false;
}
■指定可能な表記方法
以下の関数表記が可能です。(一部抜粋)
空白で区切って、複数の関数表記を指定する事もできます。
この場合、最後尾から順番に変換(乗算)されます。
表記 | 説明 |
translate(tx,ty) | 位置を設定する。 |
rotate(angle) | 回転を設定する。 |
scale(sx,sy) | 拡大縮小率を設定する。(1.0 で等倍) |
matrix(a,b,c,d,tx,ty) | 2D 用マトリックスを設定する。 |
表記 | 説明 |
translateX(tx) | 水平位置を設定する。 |
translateY(ty) | 垂直位置を設定する。 |
scaleX(sx) | 水平方向の拡大縮小率を設定する。(1.0 で等倍) |
scaleY(sy) | 垂直方向の拡大縮小率を設定する。(1.0 で等倍) |
■トランスフォームの動作について
現在(トランスフォーム適用直前)の姿勢が、原点となります。
自身の存在矩形自体は、デフォルトの場所(原点)にそのまま残ります。
トランスフォームを適用しても、周りのレイアウトが崩れる事はありません。
要素自体は、変換後の見た目通りに動作します。
親がスクロールバーを含む場合、すべて表示されるようにスクロール最大値が補正されます。
■設定例
角度を10度に設定する
// ------------------------------------------------------------
// エレメント
// ------------------------------------------------------------
// エレメントを作成する
var element = document.createElement("div");
// BODY のノードリストに登録する
document.body.appendChild(element);
// ------------------------------------------------------------
// CSSStyleDeclaration オブジェクトを取得
// ------------------------------------------------------------
var style = element.style;
// 基本的なスタイルを設定する
style.cssText = "width:100px; height:100px; border-top:2px solid #f44; border-left:2px solid #44f; background:#ccc;";
// ------------------------------------------------------------
// トランスフォームを設定する
// ------------------------------------------------------------
StyleDeclarationSetTransform(style,"rotate(10deg)");
拡大率を(2,3) → 角度を(10deg) → 位置を(100px,200px) の順番で設定する
// ------------------------------------------------------------
// エレメント
// ------------------------------------------------------------
// エレメントを作成する
var element = document.createElement("div");
// BODY のノードリストに登録する
document.body.appendChild(element);
// ------------------------------------------------------------
// CSSStyleDeclaration オブジェクトを取得
// ------------------------------------------------------------
var style = element.style;
// 基本的なスタイルを設定する
style.cssText = "width:100px; height:100px; border-top:2px solid #f44; border-left:2px solid #44f; background:#ccc;";
// ------------------------------------------------------------
// トランスフォームを設定する
// ------------------------------------------------------------
StyleDeclarationSetTransform(style,"translate(100px,200px) rotate(10deg) scale(2,3)");
トランスフォームの基点について
■トランスフォームの基点について
トランスフォームの基点を変更するには、transform-origin スタイルを使用します。
デフォルトでは、要素の中央が基点となります。
■スタイルの transform-origin を設定する関数
スタイルの transform-origin を設定する関数
// ------------------------------------------------------------
// スタイルの transform-origin を設定する関数
// ------------------------------------------------------------
function StyleDeclarationSetTransformOrigin(style,value){
var list = [
"transformOrigin",
"webkitTransformOrigin",
"MozTransformOrigin",
"msTransformOrigin",
"OTransformOrigin"
];
var i;
var num = list.length;
for(i=0;i < num;i++){
if(style[list[i]] !== undefined){
style[list[i]] = value;
return true;
}
}
return false;
}
■指定可能な表記方法
以下の単位表記が可能です。
表記 | 説明 |
0px 0px | 基点をピクセル値で指定する。(左端,上端) |
50% 50% | 基点をパーセント値で指定する。(左端,上端) |
表記例 | 説明 |
0% 0% | 左端上端を基点に設定する。 |
50% 50% | 中央を基点に設定する。(デフォルト値) |
100% 100% | 右端下端を基点に設定する。 |
■要素の原点について
transform-origin を変更した場合、見た目が変化しない事が優先されます。
この仕様は、原点の方が ( +水平基点, +垂直基点 ) 分ずれる事で実現されます。
■すべての要素の座標系(原点)を統一するには?
デフォルトの状態では、要素ごとに、原点が異なる座標系を持っています。
これにより transform は、グローバル座標系への配置として機能しません。
すべての要素の座標系を統一したい場合、「0px 0px」を指定します。
左上端以外を基点にしたい場合は、行列の乗算順序を工夫して吸収します。
position:absolute; の指定も必要です。
■設定例
トランスフォームの左上を基点に設定する
// ------------------------------------------------------------
// エレメント
// ------------------------------------------------------------
// エレメントを作成する
var element = document.createElement("div");
// BODY のノードリストに登録する
document.body.appendChild(element);
// ------------------------------------------------------------
// CSSStyleDeclaration オブジェクトを取得
// ------------------------------------------------------------
var style = element.style;
// 基本的なスタイルを設定する
style.cssText = "width:100px; height:100px; border-top:2px solid #f44; border-left:2px solid #44f; background:#ccc;";
// ------------------------------------------------------------
// トランスフォームの基点を設定する
// ------------------------------------------------------------
StyleDeclarationSetTransformOrigin(style,"0% 0%");
// ------------------------------------------------------------
// トランスフォームを設定する
// ------------------------------------------------------------
StyleDeclarationSetTransform(style,"rotate(10deg)");
エレメントを移動する
■エレメントを移動する
移動成分に作用する関数表記は、以下の種類があります。
表記 | 説明 |
translate(tx,ty) | 位置を設定する。(水平位置,垂直位置) |
translateX(tx) | 水平位置を設定する。 |
translateY(ty) | 垂直位置を設定する。 |
■単位表記について
単位指定を省略する事はできません。
px(単位:ピクセル値)などを指定します。
■設定例
水平方向に 200px、垂直方向に 100px 移動する
// ------------------------------------------------------------
// エレメント
// ------------------------------------------------------------
// エレメントを作成する
var element = document.createElement("div");
// BODY のノードリストに登録する
document.body.appendChild(element);
// ------------------------------------------------------------
// CSSStyleDeclaration オブジェクトを取得
// ------------------------------------------------------------
var style = element.style;
// 基本的なスタイルを設定する
style.cssText = "width:100px; height:100px; border-top:2px solid #f44; border-left:2px solid #44f; background:#ccc;";
// ------------------------------------------------------------
// トランスフォームを設定する
// ------------------------------------------------------------
StyleDeclarationSetTransform(style,"translate(200px,100px)");
エレメントを回転する
■エレメントを回転する
回転成分に作用する関数表記は、以下の種類があります。
表記 | 説明 |
rotate(angle) | 回転を設定する。 |
■単位表記について
角度(deg)とラジアン(rad)の指定が可能です。
単位指定を省略する事はできません。
表記 | 説明 |
0deg | 度数単位で角度を指定する。(時計回りで正の方向) |
0rad | ラジアン単位で角度を指定する。(時計回りで正の方向) |
■設定例
エレメントを 30 度回転する
// ------------------------------------------------------------
// エレメント
// ------------------------------------------------------------
// エレメントを作成する
var element = document.createElement("div");
// BODY のノードリストに登録する
document.body.appendChild(element);
// ------------------------------------------------------------
// CSSStyleDeclaration オブジェクトを取得
// ------------------------------------------------------------
var style = element.style;
// 基本的なスタイルを設定する
style.cssText = "width:100px; height:100px; border-top:2px solid #f44; border-left:2px solid #44f; background:#ccc;";
// ------------------------------------------------------------
// トランスフォームを設定する
// ------------------------------------------------------------
StyleDeclarationSetTransform(style,"rotate(30deg)");
エレメントを拡大縮小する
■エレメントを拡大縮小する
拡大縮小成分に作用する関数表記は、以下の種類があります。
表記 | 説明 |
scale(sx,sy) | 拡大縮小率を設定する。(1.0 で等倍) |
scaleX(sx) | 水平方向の拡大縮小率を設定する。(1.0 で等倍) |
scaleY(sy) | 垂直方向の拡大縮小率を設定する。(1.0 で等倍) |
■単位表記について
単位の指定は不要です。
1.0 で等倍となります。
■設定例
エレメントを水平方向に 2.0 倍、垂直方向に 0.5 倍拡大する
// ------------------------------------------------------------
// エレメント
// ------------------------------------------------------------
// エレメントを作成する
var element = document.createElement("div");
// BODY のノードリストに登録する
document.body.appendChild(element);
// ------------------------------------------------------------
// CSSStyleDeclaration オブジェクトを取得
// ------------------------------------------------------------
var style = element.style;
// 基本的なスタイルを設定する
style.cssText = "width:100px; height:100px; border-top:2px solid #f44; border-left:2px solid #44f; background:#ccc;";
// ------------------------------------------------------------
// トランスフォームを設定する
// ------------------------------------------------------------
StyleDeclarationSetTransform(style,"scale(2.0,0.5)");
エレメントに2D用の行列を適用する
■エレメントに2D用の行列を適用する
2D用の行列を指定する関数表記は、以下の種類があります。
表記 | 説明 |
matrix(a,b,c,d,tx,ty) | 2D 用マトリックスを設定する。 |
■プロパティについて
赤いベクトルが、 x 軸成分を表しており ( a , b ) ベクトルとなります。
青いベクトルが、 y 軸成分を表しており ( c , d ) ベクトルとなります。
赤と青の2つのベクトルの交わる点は、座標成分を表していて (tx, ty) 位置ベクトルとなります。
a , b , c , d の4つのパラメータの組み合わせにより、回転、拡大、せん断といった要素が決定します。
tx, ty の2つのパラメータにより、位置の要素が決定します。
■単位表記について
単位の指定は不要です。
■2D用の行列を計算するクラス
2D用の行列を計算するクラス
// ------------------------------------------------------------
// 2D用の行列を計算するクラス
// ------------------------------------------------------------
function Matrix32 (a,b,c,d,tx,ty) {
this.a = ((a === undefined) ? 1.0 : a );
this.b = ((b === undefined) ? 0.0 : b );
this.c = ((c === undefined) ? 0.0 : c );
this.d = ((d === undefined) ? 1.0 : d );
this.tx = ((tx === undefined) ? 0.0 : tx);
this.ty = ((ty === undefined) ? 0.0 : ty);
}
Matrix32.prototype = {
// ------------------------------------------------------------
// 単位行列化
// ------------------------------------------------------------
identity:function(){
this.a = 1.0; this.b = 0.0;
this.c = 0.0; this.d = 1.0;
this.tx = 0.0; this.ty = 0.0;
},
// ------------------------------------------------------------
// 移動成分を乗算
// ------------------------------------------------------------
translate:function(tx,ty){
this.tx += tx;
this.ty += ty;
},
// ------------------------------------------------------------
// 回転成分を乗算(ラジアン)
// ------------------------------------------------------------
rotate:function(angle){
var cos = Math.cos(angle);
var sin = Math.sin(angle);
var a = this.a;
var c = this.c;
var tx = this.tx;
this.a = a * cos + this.b * -sin;
this.b = a * sin + this.b * cos;
this.c = c * cos + this.d * -sin;
this.d = c * sin + this.d * cos;
this.tx = tx * cos + this.ty * -sin;
this.ty = tx * sin + this.ty * cos;
},
// ------------------------------------------------------------
// 拡大縮小成分を乗算
// ------------------------------------------------------------
scale:function(sx,sy){
this.a = this.a * sx;
this.b = this.b * sy;
this.c = this.c * sx;
this.d = this.d * sy;
this.tx = this.tx * sx;
this.ty = this.ty * sy;
},
// ------------------------------------------------------------
// 行列を乗算 (this * m)
// ------------------------------------------------------------
multiply:function(m){
var a = this.a;
var c = this.c;
var tx = this.tx;
this.a = a * m.a + this.b * m.c;
this.b = a * m.b + this.b * m.d;
this.c = c * m.a + this.d * m.c;
this.d = c * m.b + this.d * m.d;
this.tx = tx * m.a + this.ty * m.c + m.tx;
this.ty = tx * m.b + this.ty * m.d + m.ty;
},
// ------------------------------------------------------------
// 座標を変換
// ------------------------------------------------------------
transformPosition:function(pos){
return {
x:pos.x * this.a + pos.y * this.c + this.tx,
y:pos.x * this.b + pos.y * this.d + this.ty
};
},
// ------------------------------------------------------------
// ベクトルを変換
// ------------------------------------------------------------
transformVector:function(vec){
return {
x:vec.x * this.a + vec.y * this.c,
y:vec.x * this.b + vec.y * this.d
};
},
// ------------------------------------------------------------
// 逆行列化
// ------------------------------------------------------------
invert: function(){
var a = this.a;
var b = this.b;
var c = this.c;
var d = this.d;
var tx = this.tx;
var ty = this.ty;
this.a = 1.0; this.b = 0.0;
this.c = 0.0; this.d = 1.0;
this.tx = 0.0; this.ty = 0.0;
var b_ = b;
var d_ = d;
var ty_ = ty;
if(a){
this.a /= a;
b_ /= a;
}
d_ -= c * b_;
this.c -= c * this.a;
ty_ -= tx * b_;
this.tx -= tx * this.a;
if(d_){
this.c /= d_;
}
this.tx -= ty_ * this.c;
this.a -= b_ * this.c;
if(a){
this.b /= a;
b /= a;
}
d -= c * b;
this.d -= c * this.b;
ty -= tx * b;
this.ty -= tx * this.b;
if(d){
this.d /= d;
}
this.ty -= ty * this.d;
this.b -= b * this.d;
},
// ------------------------------------------------------------
// 複製
// ------------------------------------------------------------
clone:function(){
return new Matrix32(
this.a, this.b,
this.c, this.d,
this.tx, this.ty
);
},
// ------------------------------------------------------------
// 文字列を取得
// ------------------------------------------------------------
toString:function(){
return "matrix(" +
this.a.toFixed(20) + "," +
this.b.toFixed(20) + "," +
this.c.toFixed(20) + "," +
this.d.toFixed(20) + "," +
this.tx.toFixed(20) + "," +
this.ty.toFixed(20) +
")";
}
};
■使用例
拡大率(2,3) → 角度(10度) → 位置(100,200) の順番で乗算する
// ------------------------------------------------------------
// Matrix32 オブジェクトを作成
// ------------------------------------------------------------
var mtx32 = new Matrix32();
// ------------------------------------------------------------
// 各成分を順番に乗算する
// ------------------------------------------------------------
// 単位行列化
mtx32.identity();
// 拡大縮小成分を乗算
mtx32.scale(2.0,3.0);
// 回転成分を乗算(ラジアン)
mtx32.rotate(10 * Math.PI / 180);
// 移動成分を乗算
mtx32.translate(100,200);
// ------------------------------------------------------------
// 出力テスト
// ------------------------------------------------------------
console.log(mtx32.toString()); // matrix(1.96961,0.34729,-0.52094,2.95442,100,200)
3つの行列を順番に乗算する
// ------------------------------------------------------------
// Matrix32 オブジェクトを作成
// ------------------------------------------------------------
var mtx32_a = new Matrix32(1,0,0,1,0,0);
// 拡大縮小成分
mtx32_a.scale(2.0,3.0);
// ------------------------------------------------------------
// Matrix32 オブジェクトを作成
// ------------------------------------------------------------
var mtx32_b = new Matrix32(1,0,0,1,0,0);
// 回転成分(ラジアン)
mtx32_b.rotate(10 * Math.PI / 180);
// ------------------------------------------------------------
// Matrix32 オブジェクトを作成
// ------------------------------------------------------------
var mtx32_c = new Matrix32(1,0,0,1,0,0);
// 移動成分
mtx32_c.translate(100,200);
// ------------------------------------------------------------
// 行列を順番に乗算 a * b * c
// ------------------------------------------------------------
mtx32_a.multiply(mtx32_b);
mtx32_a.multiply(mtx32_c);
// 出力テスト
console.log(mtx32_a.toString()); // matrix(1.96961,0.34729,-0.52094,2.95442,100,200)
■設定例
拡大率(2,3) → 角度(10度) → 位置(100,200) の順番で乗算した行列を設定する
// ------------------------------------------------------------
// Matrix32 オブジェクトを作成
// ------------------------------------------------------------
var mtx32 = new Matrix32();
// ------------------------------------------------------------
// 各成分を順番に乗算する
// ------------------------------------------------------------
// 単位行列化
mtx32.identity();
// 拡大縮小成分を乗算
mtx32.scale(2.0,3.0);
// 回転成分を乗算(ラジアン)
mtx32.rotate(10 * Math.PI / 180);
// 移動成分を乗算
mtx32.translate(100,200);
// ------------------------------------------------------------
// エレメント
// ------------------------------------------------------------
// エレメントを作成する
var element = document.createElement("div");
// BODY のノードリストに登録する
document.body.appendChild(element);
// ------------------------------------------------------------
// CSSStyleDeclaration オブジェクトを取得
// ------------------------------------------------------------
var style = element.style;
// 基本的なスタイルを設定する
style.cssText = "width:100px; height:100px; border-top:2px solid #f44; border-left:2px solid #44f; background:#ccc;";
// ------------------------------------------------------------
// トランスフォームを設定する
// ------------------------------------------------------------
StyleDeclarationSetTransform(style,mtx32.toString());