POPSブログ

SVG.js matrix()と3D風Carousel

388

  Category:  javascript2016/07/06 pops 

SVG.js matrix()について調べてみます。一部当方独自の方法をも取りますが、一応正常に可動します。何も知らない者が「SVG」を触るのですから大変無謀なことです。

 

SVG.js matrix()のテスト

SVG.js matrix()について調べてみます。マニュアルにサンプル無しなので、大変苦労します。

ご注意、Chrome.Firefox.IE11(一部機能しません)などSVGに対応したブラウザでご覧ください。Chromeを推奨します。
このページのJSは「IE11」では実行出来ません。


SVG.js matrixの説明


SVGのmatrix処理

1. SVGではtransform属性があった場合、「変形」はmatrixで処理されます。(2D)
2. CSSと同じmatrixですが、SVGでは多少違うところもある様です。(詳細は実行しないとわからないようです)
3. 通常SVG.jsでは変形があれば、自動的にmatrix表記されますので意識する必要は有りません。
4. SVG.jsではmatrixの操作が出来るので、matrixでの直接変形、matrixでのアニメも可能ではあるがなじみが薄い。
(まだ規格など統合できていない理由でCSS的なmatrixとも振舞いが違うようだ)
5. matrix変形のアニメは、実行しないと「振る舞い」がわからない。(まだ成り行き任せである)
6 現時点ではSVGはほとんどなじみの薄いものと思います。(時節柄、再度脚光を浴びることと成りそう....)


SVG.jsの図形などの要素は「変形があった場合自動的にmatrixで表記」されます

つまり、SVG.jsでは、意図的にmatrixを操作しなければならない場合を除き、通常のSVG.js処理では必要のないことです。
処理の例、変形があればmatrixが生成されています。


変形無し
var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#CCC','stroke-width':1}).center(320,150)

<rect id="SvgjsRect1009" width="100" height="100" fill="none" stroke="#cccccc" stroke-width="1" x="270" y="100"></rect>

----------------------------

変形あり
var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#CCC','stroke-width':1}).center(320,150).scale(0.5)

<rect id="SvgjsRect1009" width="100" height="100" fill="none" stroke="#cccccc" stroke-width="1" x="270" y="100" transform="matrix(0.5,0,0,0.5,160,75)"></rect>

SVGのmatrix

SVGの変形transformについての基礎知識は下記「svg要素の基本的な使い方まとめ」transform属性:座標軸の変形が参考になります。

【参照】h2.dion.ne.jpの記事 図形の変形: transform属性:座標軸の変形


SVG.jsのmatrix書式

SVGのMatrixはCSS3と同様のmatrixですが、手書きで中の数値を操作するのは難しい。
SVG.jsのマトリックスオブジェクトに対する変形命令(matrix操作メソッド)で中を操作できます。
以下、SVG.jsマニュアルより抜粋。


matrix関数 matrix(a,b,c,d,e,f)

1番目の数値aは、水平方向の縮尺
2番目の数値bは、垂直方向の傾斜率
3番目の数値cは、水平方向の傾斜率
4番目の数値dは、垂直方向の縮尺
5番目の数値eは、水平方向の移動距離
6番目の数値fは、垂直方向の移動距離

--------------------------------------

変形していない場合の値
matrix(1,0,0,1,0,0)

● SVG.Matrixオブジェクトを作る。その後matrix操作メソッドで操作します。
中の(1,0,0,1,0,0)は書かなくとも、SVG.jsが処理してくれる。


どちらでもOK
var matrix=new SVG.Matrix()
var matrix=new SVG.Matrix(1,0,0,1,0,0)

SVG.jsのmatrix操作メソッド

Matrixに対する、SVG.Matrixの変形メソッドです。詳細はマニュアルのMatrixを参照ください。
translate scale rotate等の変形をします。filpはX軸Y軸をMatrix処理上で移動させます。変更すると次元が異なるような動きをします。


Matrixに移動伸縮回転を与えます

translate
matrix.translate(x,y)

scale
matrix.scale(xyスケール同値)
matrix.scale(xスケール値,yスケール値)

matrix.scale(xyスケール同値,cx値,cy値) 以外と安定しない
matrix.scale(xスケール値,yスケール値,cx値,cy値) 安定する、場合により反対もある
状況によりどちらか試す、これ事実です

rotate
matrix.rotate(degrees値)
matrix.rotate(degrees値,cx値,cy値)

------------------------------------------

使い方によっては便利かも知れない
filp
matrix.filp('x',x値)
matrix.filp('y',y値)

------------------------------------------

matrixの中心を補正はわずらわしい
around
matrix.around(cx,cy,matrix)

// cx, cy, matrix
matrix.around(100,150,new SVG.Matrix().skew(0,45))


matrix操作メソッドは他にもありますが、ここでは省略します。


● Matrixの実行
上記のMatrixの変形メソッドはMatrixに対しての処理で、まだインスタンスに対してMatrixの実行はしていません。
Matrixを実行するには、対象インスタンスのタグの transform属性 にMatrixを直接書き込めばよいわけです。


対象インスタンスがある、変形はしていません
<rect id="SvgjsRect1009" width="100" height="100" fill="none" stroke="#cccccc" stroke-width="1" x="270" y="100"></rect>

Matrixを直接書き込めば変形します
<rect id="SvgjsRect1009" width="100" height="100" fill="none" stroke="#cccccc" stroke-width="1" x="270" y="100" transform="matrix(0.5,0,0,0.5,160,75)"></rect>

SVG.jsにはtransform()がありますが、matrixの操作は上手く出来ません(エラーにはならない)。
matrixの実行はSVG.Matrixオブジェクトを文字列化して、attr()で行います。
transform()は主に「g」グループの操作に用いるようです。


これは上手く行きません、ダメ、matrixプロパティを認識しない
インスタンス.transform({'matrix':文字列})

------------------------------------------

attr()はOKですからこちらで処理
インスタンス.attr('transform',文字列)
または
インスタンス.attr({'transform':文字列})

● SVG.Matrixの変形と実行

SVG.Matrixを作り、Matrixのtranslate() scale() rotate()等でマトリックスの変形を適用させます。
面倒なマトリックスの中(a,b,c,d,e,f)をSVG.jsが作ってくれます。

文字形のSVG.Matrixオブジェクトをattr()で設定します。
面倒ですが次の様な流れになります。

詳細はマニュアルのMatrixを参照ください。


SVG.Matrixを作る
var matrix=new SVG.Matrix()
マトリックスに対して変形
.translate(設定値).scale(設定値).rotate(設定値)
マトリックスを文字列に直す
.toString()
インスタンスにattrで処理
インスタンス.attr('transform',マトリックスの文字列)

同じJSに複数の var matrix がある場合は書き方によっては競合する場合がありますので注意ください。
matrixの変数名を変えれば当然問題は有りませんが...


競合する場合がある
var matrix=new SVG.Matrix()
matrix.translate(..).scale(...).rotate(...)

------------------------------------------

競合しない
var matrix=new SVG.Matrix()
.translate(..).scale(...).rotate(...)

実際には、下記サンプル類および別ページの「3D風Carouselデモ」を見て理解ください。


● SVG.Matrixのアニメ

Matrixはattr()形式で実行しますので、当然アニメ-ションも可能な訳です。下記サンプルなど参照


インスタンス.animate().attr('transform',マトリックスの文字列)

● SVG.Matrixと.center(x,y)の組み合わせ

通常レクトなどのインスタンスは、当初から.center()で処理している場合が多いと思います。

Matrixでの中央設定の処理は難しいので(サンプル10番参照)、インスタンスにcenter(x,y)を直接処理したほうが良いようです。
図形などは中心より回転、伸縮しますので.center(x,y)は重要です。但しMatrixには作用させません。インスタンスに対して処理します。matrixの操作ですが、先にインスタンスに対しcenter()を利用したほうが楽です。


center()処理が必要なら先に処理して、その後Matrixを実行する。

//スケール決定
var scale_v=0.5_
//matrix位置決めスケール変更
var matrix=new SVG.Matrix()
.scale(scale_v,scale_v,x,y)
var matrix_v=matrix.toString()
//centerと伸縮
対象インスタンス.center(x,y).attr('transform',matrix_v)

------------------------------------------

理屈として
1. SVG.jsによりcenter(x,y)のマトリックス処理が先に行われる
2. 次に.attr('transform',matrix_v)により、先のマトリックスに修正が行われる
思いついた騙しのテクニックです

Matrixの中央設定の処理はaround()で行えますが、インスタンスの位置が右上.x().y()の必要があります。通常インスタンスは.center()で処理している場合が多いので面倒になり易い。(10番、around rotate変換処理参照)


● stroke幅を一定に保つ場合はvector-effect属性を設定する。


.attr({'fill':image,'stroke':'#FFF','stroke-width':2,'vector-effect':'non-scaling-stroke'})

1番、通常処理GROUP回転アニメ / 2番、matrix()処理外周配置 / 3番、transform処理外周配置

単に外周に図形を配置するならば、1番の様に通常の処理が簡単です。matrix()処理、transform処理は面倒。

2番はmatrix(a,b,c,d,e,f)の形式で態と面倒に表記しています。


1番、GROUP回転アニメの様にグループはtransformで動かせますので、中心指定無くグラフィックの中心より回転できます。またjQueryの様にCSSで固定されませんので注意が必要です。
2番、matrixは個別に「陰影」処理が出来ます。matrix回転はここでは処理していません。

3番は、テスト的に.transform()で処理しました。外周要素に「陰影」は切れますので、グループに「陰影」処理。出来るという事だけで実用性には欠けるでショウ。


サンプルJS


	//対象エレメントID
	var draw=SVG('matrix-1a').size(160,160)

	//TEXT
	var text=draw.text('外周配置位置計算').font({leading:0.8})

	//条件
	var spikes,a,center_x,center_y,radius_v,angle_v
	spikes=8,a=360/spikes,center_x=80,center_y=80,radius_v=50,angle_v=0 //3時方向
	var hit=false//クリック判定
	//GROUP
	var group0=draw.group()

	for (i=0; i < spikes; i++){

		//虹色hsl直接
		var angle_no=Math.floor(i/spikes*360)//0-360
		var color='hsl(' + angle_no + ',100%,50%)'

		var x=center_x+radius_v*Math.cos((i*a+angle_v)*Math.PI/180)
		var y=center_y+radius_v*Math.sin((i*a+angle_v)*Math.PI/180)
		//rect
		var rect=group0.rect(20,20).attr({'fill':color,'stroke':'#FFF','stroke-width':2}).center(x,y).rotate(i*a)
		.attr({'filter':'url(#dropShadow2)'})//陰影

	}

	//ボタン
	var hit_btn0=draw.circle(10).attr({'fill':'#F00','stroke':'#FFF','stroke-width':2}).center(140,10)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	hit_btn0.click(function(e) {
		if(hit){return}
		hit=true
		group0.animate(3000).transform({'rotation':360}).transform({'x':100}).after(function(){
			this.animate(3000).transform({'rotation':0}).transform({'x':-100}).after(function(){
				hit=false
			})
		})
	})

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-1b').size(160,160)

	//TEXT
	var text=draw.text('matrix').font({leading:0.8})

	//条件
	var spikes,a,center_x,center_y,radius_v,angle_v
	spikes=8,a=360/spikes,center_x=80,center_y=80,radius_v=50,angle_v=0 //3時方向

	//GROUP2
	var group2=draw.group()

	for (i=0; i < spikes; i++){

		//虹色hsl直接
		var angle_no=Math.floor(i/spikes*360)//0-360
		var color='hsl(' + angle_no + ',100%,50%)'

		//rect/個別陰影のためcenterを大きくずらす
		var rect=group2.rect(20,20).attr({'fill':color,'stroke':'#FFF','stroke-width':2}).center(20,20)

		//同一径とする
		var x=center_x+radius_v*Math.cos((i*a+angle_v)*Math.PI/180)
		var y=center_y+radius_v*Math.sin((i*a+angle_v)*Math.PI/180)

		//matrix/center補正
		var matrix=new SVG.Matrix({a:1,b:0,c:0,d:1,e:x-20,f:y-20})
		var matrix_v=matrix.toString()
		//attr
		rect.attr('transform',matrix_v)

		//後から回転できる今実行しない、matrixではない
		//rect.rotate(i*a)

		.attr({'filter':'url(#dropShadow2)'})//陰影

	}

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-1c').size(160,160)

	//TEXT
	var text=draw.text('transform').font({leading:0.8})

	//条件
	var spikes,a,center_x,center_y,radius_v,angle_v
	spikes=8,a=360/spikes,center_x=80,center_y=80,radius_v=50,angle_v=0 //3時方向

	//GROUP3
	var group3=draw.group()

	for (i=0; i < spikes; i++){

		//虹色hsl直接
		var angle_no=Math.floor(i/spikes*360)//0-360
		var color='hsl(' + angle_no + ',100%,50%)'

		//rect
		var rect=group3.rect(20,20).attr({'fill':color,'stroke':'#FFF','stroke-width':2}).center(10,10)

		var x=center_x+radius_v*Math.cos((i*a+angle_v)*Math.PI/180)
		var y=center_y+radius_v*Math.sin((i*a+angle_v)*Math.PI/180)

		//transform
		rect.transform({'x':x-10}).transform({'y':y-10}).transform({'rotation':i*a})

		//group
		group3.attr({'filter':'url(#dropShadow2)'})//陰影

	}


matrix処理の利点

直接、要素をmatrix処理する利点は、複数の変形処理が一度で実行出来る面があります。


1 複数の変形処理が一度で実行出来る。(回転を伴う場合は注意)
2 「陰影」処理が切れない。transform()処理は「陰影」が切れる。


matrix処理サンプル

以下、色々なサンプルでテストするが、通常のものとも比較する。結構どちらも問題が多い。
現在NET上にもサンプルなど参考にするものが皆無なため、個人的独断で以下サンプルを作っています。
SVGも進化途上ですから将来的には不具合など解消されると思いますが...


matrix処理サンプル等と、通常処理との比較

● matrix処理サンプルを幾つかテストしてみます。
4番はまだ重ね順の変更は行っていません。5番の処理は不可解です。

4番、matrix処理未完成 / 5番、matrix処理不可解 / 6番、matrix2d画像アニメ処理


サンプルJS


	//対象エレメントID
	var draw=SVG('matrix-2a').size(160,160)

	//TEXT
	var text=draw.text('matrix/3D風配置(未完)').font({leading:0.8})

	//条件
	var spikes,a,center_x,center_y,radius_x,radius_y,angle_v
	spikes=8,a=360/spikes,center_x=80,center_y=80,radius_x=50,radius_y=20,angle_v=0 //3時方向

	//GROUP4
	var group4=draw.group()

	for (i=0; i < spikes; i++){

		//虹色hsl直接
		var angle_no=Math.floor(i/spikes*360)//0-360
		var color='hsl(' + angle_no + ',100%,50%)'

		//rect/個別陰影のためcenterを大きくずらす
		var rect=group4.rect(20,20).attr({'fill':color,'stroke':'#FFF','stroke-width':2}).center(100,100)

		//3D風配置
		var x=center_x+radius_x*Math.cos(((i*a+angle_v)-90)*Math.PI/180)
		var y=center_y+radius_y*Math.sin(((i*a+angle_v)-90)*Math.PI/180)

		//matrixは難しい/center補正
		var matrix=new SVG.Matrix({a:1,b:0,c:0,d:1,e:x-100,f:y-100})
		var matrix_v=matrix.toString()
		//attr
		rect.attr('transform',matrix_v)

		//後から回転できる今実行しない
		//rect.rotate(i*a)

		.attr({'filter':'url(#dropShadow2)'})//陰影

	}

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-2b').size(160,160)

	//TEXT
	var text=draw.text('matrix2d画像').font({leading:0.8})

	//画像表示
	var image=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80)
	//matrix中央配置補正
	var matrix=new SVG.Matrix({a:1,b:0.2,c:0.2,d:1,e:0-16,f:0-16})
	//var matrix=new SVG.Matrix({a:1,b:0.25,c:0.25,d:1,e:0-20,f:0-20})
	var matrix_v=matrix.toString()
	//attr
	image.attr('transform',matrix_v)

	.attr({'filter':'url(#dropShadow2)'})//陰影

	var extract_v=matrix.extract()
	text.text('x/ '+ extract_v.x)


	//-------------

	//対象エレメントID
	var draw=SVG('matrix-2c').size(160,160)

	//TEXT
	var text=draw.text('matrix2d画像アニメ').font({leading:0.8})

	//画像表示2/中央配置補正
	var image2=draw.image('/main/images/testImage102.jpg').size(100,100).center(80,80)
	.attr({'filter':'url(#dropShadow2)'})//陰影

	//ボタン
	var hit_btn=draw.circle(10).attr({'fill':'#F00','stroke':'#FFF','stroke-width':2}).center(140,10)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	hit_btn.click(function(e) {
		this.toggleClass('btn-hit')
		if(this.hasClass('btn-hit')) {
			//変形
			var matrix=new SVG.Matrix({a:1,b:0.2,c:0.2,d:1,e:0-16,f:0-16})
			var matrix_v=matrix.toString()
			image2.animate(1000).attr('transform',matrix_v)
		}else{
			//戻す
			var matrix=new SVG.Matrix({a:1,b:0,c:0,d:1,e:0,f:0})
			var matrix_v=matrix.toString()
			image2.animate(1000).attr('transform',matrix_v)
		}
	})

● translate scale等のmatrix変換。こちらは少し理解できる。

7番、translate 処理 / 8番、scale処理 / 9番、rotate処理


サンプルJS


	//対象エレメントID
	var draw=SVG('matrix-3a').size(160,160)

	//TEXT
	var text=draw.text('画像translate 20 20').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	//画像表示
	var image3=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80)

	//translate移動
	var img_mtx3=new SVG.Matrix()
	.translate(20,20)
	var matrix_v=img_mtx3.toString()
	//attr
	image3.attr('transform',matrix_v)

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-3b').size(160,160)

	//TEXT
	var text=draw.text('画像scale 0.5').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	//画像表示
	var image4=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80)

	//scale変換
	var img_mtx4=new SVG.Matrix()
	.scale(0.5,0.5,80,80)
	var matrix_v=img_mtx4.toString()
	//attr
	image4.attr('transform',matrix_v)

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-3c').size(160,160)

	//TEXT
	var text=draw.text('画像rotate 30').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	//画像表示
	var image5=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80)

	//rotate変換
	var img_mtx5=new SVG.Matrix()
	.rotate(30,80,80)
	var matrix_v=img_mtx5.toString()
	//attr
	image5.attr('transform',matrix_v)


● center表示とmatrix

1番目around処理は少し紛らわしいので、2番目.center()を使用した方が簡単のようです。
3番目、scale(0.5,80,80)は正しく機能しないので、scale(0.5,0.5,80,80)で処理

10番、around rotate変換処理 / 11番、.centerとrotate変換処理 / 12番、Matrix rotate scale変換処理


サンプルJS


	//対象エレメントID
	var draw=SVG('matrix-3d').size(160,160)

	//TEXT
	var text=draw.text('around rotate変換').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	//画像表示
	var image3d=draw.image('/main/images/testImage101.jpg').size(100,100)

	//around rotate変換
	//var mtx3d=new SVG.Matrix()
	//.translate(30,30).rotate(30)//cx cy=0
	var img_mtx3d=new SVG.Matrix()//mtx3d
	.around(50,50,new SVG.Matrix().translate(30,30).rotate(30))

	var matrix_v=img_mtx3d.toString()
	//attr
	image3d.attr('transform',matrix_v)

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-3e').size(160,160)

	//TEXT
	var text=draw.text('.centerとrotate変換').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	//画像表示
	var image3e=draw.image('/main/images/testImage101.jpg').size(100,100)

	//matrix
	var img_mtx3e=new SVG.Matrix()
	.rotate(30,80,80)
	var matrix_v=img_mtx3e.toString()
	//.centerとattr
	image3e.center(80,80).attr('transform',matrix_v)

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-3f').size(160,160)

	//TEXT
	var text=draw.text('Matrix rotate scale変換').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	//画像中央表示
	var image3f=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80)

	//matrix
	var img_mtx3f=new SVG.Matrix()
	.rotate(30,80,80).scale(0.5,0.5,80,80)
	var matrix_v=img_mtx3f.toString()
	//attr
	image3f.attr('transform',matrix_v)


10番around処理のmatrix状況
注意、要素の、rotate()の cx cy は0である。SVG.jsの.center()処理は行っていません。


インスタンスの画像は100x100 原点左上 0 0
下記処理どちらも同じ結果である

//around rotate変換
var mtx3d=new SVG.Matrix()
.translate(30,30).rotate(30)//cx cy=0
var img_mtx3d=new SVG.Matrix()
.around(50,50,mtx3d)
var matrix_v=img_mtx3d.toString()

------------------------------------------

//around rotate変換
var img_mtx3d=new SVG.Matrix()
.around(50,50,new SVG.Matrix().translate(30,30).rotate(30))
var matrix_v=img_mtx3d.toString()

通常インスタンスは.center()で処理している場合が多いので、around()は新たにインスタンスの位置、右上 .x().y() の必要で面倒になり易い。


● 通常の処理で比較してみる

下記13,14番は通常のSVG.jsの処理で生成されるmatrixは、上記9番と同じである。
下記15番は「3D風配置と重ね順補正」であるがmatrix回転で正確になるかは不明。

13番、center rotate処理 / 14番、move rotate処理 /15番、外周配置処理


サンプルJS


	//対象エレメントID
	var draw=SVG('matrix-4a').size(160,160)

	//TEXT
	var text=draw.text('画像rotate 30').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	//画像回転表示
	var image6=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80).rotate(30)

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-4b').size(160,160)

	//TEXT
	var text=draw.text('画像move rotate 30').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	//画像回転表示
	var image7=draw.image('/main/images/testImage101.jpg').size(100,100).move(30,30).rotate(30,80,80)

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-4c').size(160,160)

	//TEXT
	var text=draw.text('3D風配置と重ね順補正').font({leading:0.8})

	//条件
	var spikes,a,center_x,center_y,radius_x,radius_y,angle_v
	spikes=8,a=360/spikes,center_x=80,center_y=80,radius_x=50,radius_y=20,angle_v=0 //3時方向
	var posArr=[]//オブジェクト保存容器

	//GROUP5
	var group5=draw.group()

	for (i=0; i < spikes; i++){

		//虹色hsl直接
		var angle_no=Math.floor(i/spikes*360)//0-360
		var color='hsl(' + angle_no + ',100%,50%)'

		//rect/個別陰影
		var rect=group5.rect(20,20).attr({'fill':color,'stroke':'#FFF','stroke-width':2})

		//3D風配置
		var x=center_x+radius_x*Math.cos(((i*a+angle_v)-90)*Math.PI/180)
		var y=center_y+radius_y*Math.sin(((i*a+angle_v)-90)*Math.PI/180)

		//rect位置決め
		rect.center(x,y)
		//スケール補正とpostion係数保存
		var scale_v=y/center_y
		//postion保存とエレメントをオブジェクトで保存
		posArr.push({'elm':rect, 'postion':scale_v});
		//matrix
		var matrix=new SVG.Matrix()
		.scale(scale_v,scale_v,x,y)
		var matrix_v=matrix.toString()
		rect.attr('transform',matrix_v)

		rect.attr({'filter':'url(#dropShadow2)'})//陰影

	}

	//postion配列をソート/postion昇順にsort
	posArr.sort(function(a,b) {
		var x=a.postion;
		var y=b.postion;
		return x > y ? 1 : -1}
	)
	//重ね変更
	for (var i=0; i < posArr.length; i++){
		//エレメントを取り出す
		var rect=posArr[i].elm
		//エレメントの重ね順補正
		rect.front()
	}


SVG.jsでは「重ね順」を簡単に変更できます。「g」要素である、グループでも「重ね順」を変更できます。


出力されるmatrix状況は共に同じである。
13番のmatrix状況


var image6=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80).rotate(30)

<image id="SvgjsImage1092" xlink:href="/main/images/testImage101.jpg" width="100" height="100" x="30" y="30" transform="matrix(0.8660254037844387,0.49999999999999994,-0.49999999999999994,0.8660254037844387,50.717967697244895,-29.282032302755084)"></image>

14番のmatrix状況


var image7=draw.image('/main/images/testImage101.jpg').size(100,100).move(30,30).rotate(30,80,80)

<image id="SvgjsImage1098" xlink:href="/main/images/testImage101.jpg" width="100" height="100" x="30" y="30" transform="matrix(0.8660254037844387,0.49999999999999994,-0.49999999999999994,0.8660254037844387,50.717967697244895,-29.282032302755084)"></image>

15番、3D風配置と重ね順補正

3D風配置のY位置(係数)を保存して並べ替えて、重ね順を変更している。(より詳細は別途ページCarouselデモ参照)


各要素のY位置を取得して、その大きさ順序に「重ね順」を変更する。
回転する場合はその都度修正しますしダイレクトにインスタンスを参照するため保存しています。


	//postion配列をソート/postion昇順にsort
	posArr.sort(function(a,b) {
		var x=a.postion;
		var y=b.postion;
		return x > y ? 1 : -1}
	)
	//重ね変更
	for (var i=0; i < posArr.length; i++){
		//エレメントを取り出す
		var rect=posArr[i].elm
		//エレメントの重ね順補正
		rect.front()
	}

matrix修正と複合アニメ

画像塗りでは無く通常の画像です。アニメしない場合は結果的なmatrix変形なので状況はわからない。アニメしてみると途中の状況がわかるがmatrix2Dなので意図した動きを作るのが難しい。まだ成り行きまかせの感がある。
但し、2D的なmatrix、アニメは余り見かけないし作る事も少ないのでなじみが薄い。

z軸で回転しながら移動するなどの簡単な複合アニメが同一インスタンス設定で出来ない。(グループ化して2つのアニメ同時進行にすれば出来るが、回転は注意が必要)

16番、通常画像回転縮小 / 17番、matrix画像回転縮小 /18番、matrix回転縮小アニメ


サンプルJS


	//対象エレメントID
	var draw=SVG('matrix-5a').size(160,160)

	//TEXT
	var text=draw.text('通常画像回転縮小').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	//画像回転表示
	var image9=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80)
	.rotate(30).scale(0.5)
	.attr({'filter':'url(#dropShadow2)'})//陰影

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-5b').size(160,160)

	//TEXT
	var text=draw.text('matrix画像回転縮小').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	//matrix画像回転表示
	var image10=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80)
	var matrix=new SVG.Matrix()
	.rotate(30,80,80).scale(0.5,0.5,80,80)//回転縮小
	var matrix_v=matrix.toString()
	//matrix修正実行
	image10.attr('transform',matrix_v)
	.attr({'filter':'url(#dropShadow2)'})//陰影

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-5c').size(160,160)

	//TEXT
	var text=draw.text('matrix回転縮小アニメ').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	var image11=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80)

	//ボタン2
	var hit_btn2=draw.circle(10).attr({'fill':'#F00','stroke':'#FFF','stroke-width':2}).center(140,10)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	hit_btn2.click(function(e) {
		this.toggleClass('btn-hit')
		if(this.hasClass('btn-hit')) {
			//変形
			var matrix=new SVG.Matrix()
			.translate(80,0).rotate(60,80,80).scale(0.5,0.5,80,80)//回転縮小
			var matrix_v=matrix.toString()
			image11.animate(1000).attr('transform',matrix_v)


		}else{
			//戻す
			var matrix=new SVG.Matrix()
			.translate(0,0).rotate(0,80,80).scale(1,1,80,80)//回転縮小
			var matrix_v=matrix.toString()
			image11.animate(1000).attr('transform',matrix_v)

		}
	})


matrixアニメも可能ですが、一度にtranslate,scale,rotate等処理できるが動きに注意、意図する動きにならない場合が多い。


SVG.js アニメーションの振る舞いは下記ページを参照ください。

【参照】当方の記事: SVG.js アニメーション(1)


複合アニメ、同時回転移動は難しい

通常1つのインスタンスに回転を伴う移動アニメは正常に動かないのでグループにして、双方の同時アニメにしている。
かたや、matrixアニメは伸縮回転移動が同時に実行はできるが、matrix2Dの動きになってしまう。

matrix回転アニメはZ軸の回転では無い、少しの設定違いで変になる、90度以下で無ければ難しい。

19番、GROUP画像通常アニメ / 20番、matrix回転アニメ /21番、matrix X軸伸縮


サンプルJS


	//対象エレメントID
	var draw=SVG('matrix-6a').size(160,160)

	//TEXT
	var text=draw.text('GROUP画像通常アニメ').font({leading:0.8})
	//案内ライン
	var line=draw.line(0,80,160,80).attr({'stroke':'#F00','stroke-width':1})

	//GROUP
	var group6=draw.group()
	group6.move(10,50)
	var image6=group6.image('/main/images/testImage101.jpg').size(40,40).center(30,30)
	.attr({'filter':'url(#dropShadow2)'})//陰影

	//ボタン
	var test_btn6=draw.circle(10).attr({'fill':'#FF0000','stroke':'#FFF','stroke-width':2}).center(140,140)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION/360度のこと
	test_btn6.click(function(){
		group6.animate().x(90)
		image6.animate().rotate(360).after(function(){
			group6.animate().x(10)
			this.animate().rotate(0)
		})

	})

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-6b').size(160,160)

	//TEXT
	var text=draw.text('matrix回転アニメ 不可解').font({leading:0.8})
	//案内ライン
	var line=draw.line(0,80,160,80).attr({'stroke':'#F00','stroke-width':1})

	//GROUP
	var group6b=draw.group()
	group6b.move(10,50)
	var image6b=group6b.image('/main/images/testImage101.jpg').size(40,40).center(30,30)
	.attr({'filter':'url(#dropShadow2)'})//陰影

	//変形/Z軸の回転では無い
	var matrix=new SVG.Matrix()
	.translate(80,0).rotate(90,30,30)
	var matrix_v6=matrix.toString()

	//ボタン
	var test_btn6b=draw.circle(10).attr({'fill':'#FF0000','stroke':'#FFF','stroke-width':2}).center(140,140)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION/不可解
	test_btn6b.click(function(){
		image6b.animate().attr('transform',matrix_v6).after(function(){
			//変形
			var matrix=new SVG.Matrix()
			.translate(0,0).rotate(0,30,30)
			var matrix_v6b=matrix.toString()
			this.animate().attr('transform',matrix_v6b)
		})

	})

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-6c').size(160,160)

	//TEXT
	var text=draw.text('matrix X軸伸縮').font({leading:0.8})

	//案内用
	var rect=draw.rect(100,100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	var image20=draw.image('/main/images/testImage101.jpg').size(100,100).center(80,80)

	//ボタン20
	var hit_btn20=draw.circle(10).attr({'fill':'#F00','stroke':'#FFF','stroke-width':2}).center(140,10)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	hit_btn20.click(function(e) {
		this.toggleClass('btn-hit')
		if(this.hasClass('btn-hit')) {
			//変形
			var matrix=new SVG.Matrix()
			//.scale(0,1,30,80)//伸縮
			.flip('x',80)//こちら実行
			var matrix_v=matrix.toString()
			image20.animate(1000).attr('transform',matrix_v)

		}else{
			//戻す
			var matrix=new SVG.Matrix()
			.scale(1,1,30,80)//伸縮
			var matrix_v=matrix.toString()
			image20.animate(1000).attr('transform',matrix_v)

		}
	})


19番の回転移動は通常でも1つのインスタンスで出来ないのでグループとの複合アニメにしている。
20番のmatrix回転はXY軸が回転するので、正面から見れば角度によって見える範囲が狭まり縮小した状態になる。
21番のflip()は便利のようだが、実際作ってみないとわからないし、振る舞いが予測できない。


画像塗りmatrix修正

matrixで在ってもさほど効率的には成らない。画像ロード時にステージの大きさに広げ無ければならない。その後、レクトの位置に移動させます。画像は「完全読み込み済み」のものを使用ください。
画像塗りcarouselは少々面倒だが可能である。(別途ページデモ参照)

3番、center()を使ったのがミソであるが、モット良い方法があるかも知れない。

22番、通常の画像塗り / 23番、画像塗り回転スケール変更 /24番、画像塗りmatrix修正


サンプルJS


	//対象エレメントID
	var draw=SVG('matrix-7a').size(160,160)

	//TEXT
	var text=draw.text('通常の画像塗り').font({leading:0.8})

	//画像塗りmatrix修正/sizeが重要
	var image=draw.image('/main/images/testImage101.jpg').size(160,160).scale(100/160).center(80,80)
	//画像塗り
	var rect=draw.rect(100,100).radius(10).attr({'fill':image,'stroke':'#FFF','stroke-width':2}).center(80,80).rotate(15)
	rect.attr({'filter':'url(#dropShadow2)'})//陰影

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-7b').size(160,160)

	//TEXT
	var text=draw.text('画像塗り回転スケール変更').font({leading:0.8})

	//画像塗りmatrix修正/sizeが重要
	var image=draw.image('/main/images/testImage101.jpg').size(160,160).scale(100/160).center(80,80)
	//画像塗り/centerをあわせる
	var rect=draw.rect(100,100).radius(10).attr({'fill':image,'stroke':'#FFF','stroke-width':2}).center(80,80)
	rect.attr({'filter':'url(#dropShadow2)'})//陰影

	//回転だけはかえられる
	rect.rotate(30).scale(0.5)

	//-------------

	//対象エレメントID
	var draw=SVG('matrix-7c').size(160,160)

	//TEXT
	var text=draw.text('画像塗りmatrix修正').font({leading:0.8})

	//画像塗りmatrix修正/sizeが重要
	var image=draw.image('/main/images/testImage101.jpg').size(160,160)
	var matrix=new SVG.Matrix()
	.scale(100/160,100/160,80,80)
	var matrix_v=matrix.toString()
	//matrix修正実行
	image.center(80,80).attr('transform',matrix_v)
	//画像塗り
	var rect=draw.rect(100,100).radius(10).attr({'fill':image,'stroke':'#FFF','stroke-width':2}).center(80,80).rotate(15)
	rect.attr({'filter':'url(#dropShadow2)'})//陰影


 

レクトと画像の「3D風Carousel」を回転運動する

画像だけの表示であるがIEは処理が遅く少しぐらつく、Chrome、FirefoxはOKである。処理方法が複雑で調整に手間取るがサンプル等は別途ページ参照ください。

SVGはCSSとも若干違い「画像塗りcarousel」の場合は結構面倒なので、サンプルを理解ください。
また、Canvas CSS3 の方が簡単に作れますので、面倒なSVGで作る価値があるか疑問ですし、サンプルは単に「勢い」で作っています。SVGで実用性の有る物を作るには大変かも知れません。


DEMO 3D風Carouselの「デモ」


zu

● デモページは [ jqury-1.9 ] で動作しています。Chromeでの閲覧を推奨します

1 レクトの3D風Carouselとシンボル構成の3D風Carousel

DEMO-041

2 画像の3D風Carousel

DEMO-041b

3 角丸レクトの画像塗り3D風Carousel

DEMO-041c


4 番外、グループ構成の3D風Carousel(matrixでは無い通常処理、スコブル面倒です)

DEMO-041d


 

サンプルJSの全表示

Chromeは文字化けしますのでエンコード(UTF-8)してご覧ください。

● サンプルJSの全表示1(解説ページ用) svg-sample15.js

使用画像

画像は原則使用者が用意ください。デモなどで使用した画像は下記に有ります。

使用画像サンプル

 


 

dropshadowは当方自作の dropshadow-custom.js を使用します。
なおこのページはjQuery1.6.4のため dropshadow-custom-ie.js に成ります。

DropShadowと基本的なことは下記記事を参照ください。

【参照】当方の記事: SVG.js を使用してsvgコンテンツを作り表示します

【参照】当方の記事: SVG.js DropShadowの自作とBlur

CreateJSによるCanvas処理、3D風画像Carouselは下記に有ります。多少SVGより理解し易く画像あわせが楽。

【参照】当方の記事: CreateJS 3D風画像Carousel表示(easeljs-0.8)


独断のサンプルなどですから、モット良い方法があれば考えてください。問題があれば自己解決ください。以上。

 


[ この記事のURL ]


タグ:javascript , SVG

 

ブログ記事一覧



[1]