JavaScript プログラミング講座

 

SVGMatrix について

 


■ SVGMatrix について

 
Scalable Vector Graphics (SVG) の機能の1つです。
 
http://www.w3.org/TR/SVG11/coords.html#InterfaceSVGMatrix
 
SVGMatrix は、3行2列のマトリックスです。
 
2D用のアフィン行列を表現できます。
 
■プロパティについて
 
プロパティ名説明番地
aNumberx 軸成分の x 座標[0][0]
bNumberx 軸成分の y 座標[1][0]
cNumbery 軸成分の x 座標[0][1]
dNumbery 軸成分の y 座標[1][1]
eNumber座標成分の x 座標[0][2]
fNumber座標成分の y 座標[1][2]
 
■行列の並びについて
 
行列の並びは、OpenGL と同等です。
 
行列の並び方

var mtx33 = [
	[ a , c , e ],
	[ b , d , f ],
	[ 0 , 0 , 1 ]
];
 
■各プロパティを確認する
 
赤色のベクトル (a , b) が、x 軸成分です。
 
青色のベクトル (c , d) が、y 軸成分です。
 
赤と青ベクトルの交差位置 (e , f) は、座標成分です。
 
 
■行列の合成(乗算)順序について
 
乗算順序を入れ替えると、合成結果は変化します。
 
自身の行列は、2通りのアプローチで、少しずつ姿勢を変更できます。
 
以下の順序で乗算した場合、差分はグローバル座標系に作用します。
 
(自身の行列) = (新しい差分) * (自身の行列)
 
以下の順序で乗算した場合、差分はローカル座標系に作用します。
 
(自身の行列) = (自身の行列) * (新しい差分)
 


 

SVGMatrix オブジェクトを作成する

 


■SVGMatrix オブジェクトを作成する

 
SVGSVGElementcreateSVGMatrix() メソッドを使用します。
 
デフォルトの状態で、単位行列です。
 
SVGSVGElement.createSVGMatrix ( ) :SVGMatrix
引数 Voidなし。
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■ SVGMatrix オブジェクトを作成する関数
 
SVGMatrix オブジェクトを作成する関数

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する関数
// ------------------------------------------------------------
function SVGMatrixCreate(a,b,c,d,e,f){
	var svg = document.createElementNS("http://www.w3.org/2000/svg","svg");
	var mtx = svg.createSVGMatrix();
	if(a !== undefined) mtx.a = a;
	if(b !== undefined) mtx.b = b;
	if(c !== undefined) mtx.c = c;
	if(d !== undefined) mtx.d = d;
	if(e !== undefined) mtx.e = e;
	if(f !== undefined) mtx.f = f;
	return mtx;
}
 
■使用例
 
SVGMatrix オブジェクトを作成する

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する(単位行列)
// ------------------------------------------------------------
var mtx = SVGMatrixCreate();

// 出力テスト
console.log(mtx); // a:1 , b:0 , c:0 , d:1 , e:0 , f:0
 


 

SVGMatrix の計算について

 
 


■SVGMatrix の機能一覧

 
■平行移動メソッド
 
メソッド説明
translate()並行移動成分を合成する
 
■回転メソッド
 
メソッド説明
rotate()回転成分を合成する(角度指定)
rotateFromVector()回転成分を合成する(ベクトル指定)
 
■拡大縮小メソッド
 
メソッド説明
scaleNonUniform()拡大縮小成分を合成する(軸ごとに指定)
scale()拡大縮小成分を合成する(全体指定)
flipX()水平方向に反転する
flipY()垂直方向に反転する
 
■せん断メソッド
 
メソッド説明
skewX()せん断成分を合成する(y 軸を傾ける)
skewY()せん断成分を合成する(x 軸を傾ける)
 
■乗算メソッド
 
メソッド説明
multiply()行列を合成する(乗算する)
 
■逆行列メソッド
 
メソッド説明
inverse()逆行列を計算する
 

■並行移動成分を合成する

 
■並行移動成分を合成する
 
translate() メソッドを使用します。
 
以下の順番で乗算されます。
 
(新しい行列) = (自身の行列) * (並行移動成分)
 
平行移動成分は、ローカル座標系に作用します。
 
SVGMatrix.translate ( x , y ) :SVGMatrix
第01引数 Numberx 座標を指定。
第02引数 Numbery 座標を指定。
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■使用例
 
並行移動成分を合成する

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する(単位行列)
// ------------------------------------------------------------
var mtx = SVGMatrixCreate();

// ------------------------------------------------------------
// 並行移動成分を合成する
// ------------------------------------------------------------
mtx = mtx.translate(100,200);

// 出力テスト
console.log(mtx); // a:1 , b:0 , c:0 , d:1 , e:100 , f:200
 

■回転成分を合成する(角度指定)

 
■回転成分を合成する(角度指定)
 
rotate() メソッドを使用します。
 
以下の順番で乗算されます。
 
(新しい行列) = (自身の行列) * (回転成分)
 
回転成分は、ローカル座標系に作用します。
 
SVGMatrix.rotate ( angle ) :SVGMatrix
第01引数 Number角度を指定。(単位はデグリー)
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■使用例
 
回転成分を合成する

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する(単位行列)
// ------------------------------------------------------------
var mtx = SVGMatrixCreate();

// ------------------------------------------------------------
// 回転成分を合成する
// ------------------------------------------------------------
mtx = mtx.rotate(30);

// 出力テスト
console.log(mtx); // a:0.866 , b:0.499 , c:-0.499 , d:0.866 , e:0 , f:0
 

■回転成分を合成する(ベクトル指定)

 
■回転成分を合成する(ベクトル指定)
 
rotateFromVector() メソッドを使用します。
 
以下の順番で乗算されます。
 
(新しい行列) = (自身の行列) * (回転成分)
 
回転成分は、ローカル座標系に作用します。
 
SVGMatrix.rotateFromVector ( x , y ) :SVGMatrix
第01引数 Numberベクトルの x 成分を指定。(0.0 指定は不可)
第02引数 Numberベクトルの y 成分を指定。(0.0 指定は不可)
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■エラーが発生する場合
 
引数に 0 を指定すると、エラーが発生します。
 
(0 , 0) の場合に限って発生すべきですが、片方が 0 なら発生します。
 
これにより、rotate() メソッドを使った方が安全です。
 
■ラジアンからベクトルを計算する
 
(x) = Math.cos( ラジアン )
 
(y) = Math.sin( ラジアン )
 
ラジアンからベクトルに変換する

// 角度
var deg = 30;

// ラジアンに変換
var rad = (deg) * (Math.PI / 180);

// ベクトルに変換
var x = Math.cos(rad);
var y = Math.sin(rad);
 
■ベクトルからラジアンを計算する
 
(ラジアン) = Math.atan2( y , x )
 
ベクトルの長さが 0 である場合、ラジアンの計算は不可能です。
 
ベクトルからラジアンに変換する

// ベクトル
var x = 1.0;
var y = 0.0;

// ラジアンに変換
var rad = Math.atan2(y , x);

// 角度に変換
var deg = (rad) * (180 / Math.PI);
 
■使用例
 
回転成分を合成する(ベクトル指定)

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する(単位行列)
// ------------------------------------------------------------
var mtx = SVGMatrixCreate();

// ------------------------------------------------------------
// ベクトルを用意する
// ------------------------------------------------------------
// ラジアン
var rad = (30) * (Math.PI / 180);
// ベクトルに変換
var vec_x = Math.cos(rad);
var vec_y = Math.sin(rad);

// ------------------------------------------------------------
// 回転成分を合成する(ベクトル指定)
// ------------------------------------------------------------
mtx = mtx.rotateFromVector(vec_x , vec_y);

// 出力テスト
console.log(mtx); // a:0.866 , b:0.499 , c:-0.499 , d:0.866 , e:0 , f:0
 

■拡大縮小成分を合成する(軸ごとに指定)

 
■拡大縮小成分を合成する
 
scaleNonUniform() メソッドを使用します。
 
以下の順番で乗算されます。
 
(新しい行列) = (自身の行列) * (拡大縮小成分)
 
拡大縮小成分は、ローカル座標系に作用します。
 
SVGMatrix.scaleNonUniform ( x , y ) :SVGMatrix
第01引数 Numberx 軸方向の拡大率を指定。(1.0 で等倍)
第02引数 Numbery 軸方向の拡大率を指定。(1.0 で等倍)
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■使用例
 
拡大縮小成分を合成する(軸ごとに指定)

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する(単位行列)
// ------------------------------------------------------------
var mtx = SVGMatrixCreate();

// ------------------------------------------------------------
// 拡大縮小成分を合成する(軸ごとに指定)
// ------------------------------------------------------------
mtx = mtx.scaleNonUniform(3 , 0.5);

// 出力テスト
console.log(mtx); // a:3 , b:0 , c:0 , d:0.5 , e:0 , f:0
 

■拡大縮小成分を合成する(全体指定)

 
■拡大縮小成分を合成する
 
scale() メソッドを使用します。
 
以下の順番で乗算されます。
 
(新しい行列) = (自身の行列) * (拡大縮小成分)
 
拡大縮小成分は、ローカル座標系に作用します。
 
SVGMatrix.scale ( scaleFactor ) :SVGMatrix
第01引数 Number全体の拡大率を指定。(1.0 で等倍)
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■使用例
 
拡大縮小成分を合成する(全体指定)

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する(単位行列)
// ------------------------------------------------------------
var mtx = SVGMatrixCreate();

// ------------------------------------------------------------
// 拡大縮小成分を合成する(全体指定)
// ------------------------------------------------------------
mtx = mtx.scale(2.5);

// 出力テスト
console.log(mtx); // a:2.5 , b:0 , c:0 , d:2.5 , e:0 , f:0
 

■水平方向に反転する

 
■水平方向に反転する
 
flipX() メソッドを使用します。
 
以下の行列の乗算と、結果は同等です。
 
(a:-1 , b:0 , c:0 , d:1 , e:0 , f:0)
 
反転は、ローカル座標系に作用します。
 
SVGMatrix.flipX ( ) :SVGMatrix
引数 Voidなし
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■使用例
 
水平方向に反転する

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する
// ------------------------------------------------------------
var mtx = SVGMatrixCreate( 2 , 0 , 0 , 4 , 0 , 0 );

// ------------------------------------------------------------
// 水平方向に反転する
// ------------------------------------------------------------
mtx = mtx.flipX();

// 出力テスト
console.log(mtx); // a:-2 , b:0 , c:0 , d:4 , e:0 , f:0
 

■垂直方向に反転する

 
■垂直方向に反転する
 
flipY() メソッドを使用します。
 
以下の行列の乗算と、結果は同等です。
 
(a:1 , b:0 , c:0 , d:-1 , e:0 , f:0)
 
反転は、ローカル座標系に作用します。
 
SVGMatrix.flipY ( ) :SVGMatrix
引数 Voidなし
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■使用例
 
垂直方向に反転する

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する
// ------------------------------------------------------------
var mtx = SVGMatrixCreate( 2 , 0 , 0 , 4 , 0 , 0 );

// ------------------------------------------------------------
// 垂直方向に反転する
// ------------------------------------------------------------
mtx = mtx.flipY();

// 出力テスト
console.log(mtx); // a:2 , b:0 , c:0 , d:-4 , e:0 , f:0
 

■せん断成分を合成する(y 軸を傾ける)

 
■せん断成分を合成する(y 軸を傾ける)
 
skewX() メソッドを使用します。
 
以下の順番で乗算されます。
 
(新しい行列) = (自身の行列) * (せん断成分)
 
せん断成分は、ローカル座標系に作用します。
 
SVGMatrix.skewX ( angle ) :SVGMatrix
第01引数 Number角度(-90 ~ 90)を指定。(単位はデグリー)
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■せん断行列について
 
y 軸の x 成分のみが変化します。
 
(cプロパティ) = Math.tan(angle * (Math.PI / 180));
 
■使用例
 
せん断成分を合成する(y 軸を傾ける)

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する(単位行列)
// ------------------------------------------------------------
var mtx = SVGMatrixCreate();

// ------------------------------------------------------------
// せん断成分を合成する(y 軸を傾ける)
// ------------------------------------------------------------
mtx = mtx.skewX(30);

// 出力テスト
console.log(mtx); // a:1 , b:0 , c:0.577 , d:1 , e:0 , f:0
 

■せん断成分を合成する(x 軸を傾ける)

 
■せん断成分を合成する(x 軸を傾ける)
 
skewY() メソッドを使用します。
 
以下の順番で乗算されます。
 
(新しい行列) = (自身の行列) * (せん断成分)
 
せん断成分は、ローカル座標系に作用します。
 
SVGMatrix.skewY ( angle ) :SVGMatrix
第01引数 Number角度(-90 ~ 90)を指定。(単位はデグリー)
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■せん断行列について
 
x 軸の y 成分のみのみが変化します。
 
(bプロパティ) = Math.tan(angle * (Math.PI / 180));
 
■使用例
 
せん断成分を合成する(x 軸を傾ける)

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する(単位行列)
// ------------------------------------------------------------
var mtx = SVGMatrixCreate();

// ------------------------------------------------------------
// せん断成分を合成する(x 軸を傾ける)
// ------------------------------------------------------------
mtx = mtx.skewY(30);

// 出力テスト
console.log(mtx); // a:1 , b:0.577 , c:0 , d:1 , e:0 , f:0
 

■行列を合成する(乗算する)

 
■行列を合成する(乗算する)
 
multiply() メソッドを使用します。
 
以下の順番で乗算されます。
 
(新しい行列) = (自身の行列) * (引数の行列)
 
引数で指定した行列は、ローカル座標系に作用します。
 
SVGMatrix.multiply ( second ) :SVGMatrix
第01引数 SVGMatrix2つ目の SVGMatrix オブジェクトを指定。
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■使用例
 
複数の行列を合成する

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する(単位行列)
// ------------------------------------------------------------
var mtx = SVGMatrixCreate();

// ------------------------------------------------------------
// 位置(100,200) ← 角度(10度) ← 拡大率(2,3) の順番で合成
// ------------------------------------------------------------
// 並行移動成分を合成
mtx = mtx.translate( 100.0 , 200.0 );

// 回転成分を合成
mtx = mtx.rotate( 10.0 );

// 拡大縮小成分を合成
mtx = mtx.scaleNonUniform( 2.0 , 3.0 );

// 出力テスト
console.log(mtx); // a:1.969 , b:0.347 , c:-0.520 , d:2.954 , e:100 , f:200


// ------------------------------------------------------------
// 各行列を作成する
// ------------------------------------------------------------
// 単位行列を作成
mtx = SVGMatrixCreate();

// 並行移動行列を作成
var mtx0 = mtx.translate( 100.0 , 200.0 );

// 回転行列を作成
var mtx1 = mtx.rotate( 10.0 );

// 拡大縮小行列を作成
var mtx2 = mtx.scaleNonUniform( 2.0 , 3.0 );

// ------------------------------------------------------------
// 各行列を順番に合成 (移動 ← 回転 ← 拡大)
// ------------------------------------------------------------
mtx = mtx.multiply( mtx0 );
mtx = mtx.multiply( mtx1 );
mtx = mtx.multiply( mtx2 );

// 出力テスト
console.log(mtx); // a:1.969 , b:0.347 , c:-0.520 , d:2.954 , e:100 , f:200
 

■逆行列を計算する

 
■逆行列を計算する
 
inverse() メソッドを使用します。
 
SVGMatrix.inverse ( ) :SVGMatrix
引数 Voidなし。
戻り値 SVGMatrix新しい SVGMatrix オブジェクトが得られる。
 
■使用例
 
逆行列を計算する

// ------------------------------------------------------------
// SVGMatrix オブジェクトを作成する
// ------------------------------------------------------------
var mtx = SVGMatrixCreate();
mtx.a = Math.random() * 2 - 1;
mtx.b = Math.random() * 2 - 1;
mtx.c = Math.random() * 2 - 1;
mtx.d = Math.random() * 2 - 1;
mtx.e = Math.random() * 2 - 1;
mtx.f = Math.random() * 2 - 1;

// ------------------------------------------------------------
// 逆行列を計算する
// ------------------------------------------------------------
var invert_mtx = mtx.inverse();

// ------------------------------------------------------------
// 行列を乗算する
// ------------------------------------------------------------
mtx = mtx.multiply( invert_mtx );

// 出力テスト
console.log(mtx); // a:1 , b:0 , c:0 , d:1 , e:0 , f:0
 

■座標を変換する

 
■座標を変換する関数
 
座標を変換する関数

// ------------------------------------------------------------
// 座標を変換する関数
// ------------------------------------------------------------
function SVGMatrixTransformPosition(matrix,x,y){
	return {
		x:x * matrix.a + y * matrix.c + matrix.e,
		y:x * matrix.b + y * matrix.d + matrix.f
	};
}
 

■ベクトルを変換する

 
■ベクトルを変換する関数
 
ベクトルを変換する関数

// ------------------------------------------------------------
// ベクトルを変換する関数
// ------------------------------------------------------------
function SVGMatrixTransformVector(matrix,x,y){
	return {
		x:x * matrix.a + y * matrix.c,
		y:x * matrix.b + y * matrix.d
	};
}
 


 

SVGMatrix を反映する

 
 


■ CSS 2D Transforms に反映する

 
■ CSS Transforms について
 
CSS Transforms については、こちらで解説しています。
 
■ CSS 2D Transform 用の文字列を出力する関数
 
CSS 2D Transform 用の文字列を出力する関数

// ------------------------------------------------------------
// SVGMatrix から CSS 2D Transform 用の文字列を出力する関数
// ------------------------------------------------------------
function SVGMatrix_ToString_CSSTransform(svg_matrix){
	return "matrix(" +
		svg_matrix.a.toFixed(20) + "," +
		svg_matrix.b.toFixed(20) + "," +
		svg_matrix.c.toFixed(20) + "," +
		svg_matrix.d.toFixed(20) + "," +
		svg_matrix.e.toFixed(20) + "," +
		svg_matrix.f.toFixed(20) + 
	")";
}
 

■ Canvas 2D Context に反映する

 
■ Canvas 2D Context について
 
Canvas 2D Context については、こちらで解説しています。
 
■ Context2D に SVGMatrix をセットする関数
 
Context2D に SVGMatrix をセットする関数

// ------------------------------------------------------------
// Context2D に SVGMatrix をセットする関数
// ------------------------------------------------------------
function Context2D_Set_SVGMatrix(context , matrix){
	context.setTransform(matrix.a,matrix.b,matrix.c,matrix.d,matrix.e,matrix.f);
}