POPSブログ

SVG.js siblings()とposition()

387

  Category:  javascript2016/06/12 pops 

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

 

【記事更新のお知らせ】
家族が認知症のため介護の必要が生じ、よって今後、記事の更新などが思うように捗りませんのでご理解ください。届出と雑用などが多くこの記事も2ヶ月ぶりの記事になります。


SVG.js siblings positionのテスト

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

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


SVG.js 使用の基本的な説明


基本的な説明下記ページ参照ください。
【参照】当方の記事: SVG.js を使用してsvgコンテンツを作り表示します

このページとデモページにサンプルと共にJSを記載しています。余り説明などしていませんので、感覚的に違いなど理解ください。
Chrome.Firefox.IE11で確認しながら進めますが、その他のブラウザは未確認です。

 

SVG.jsのDropShadowはエラーで機能しません。カスタムDropShadowは独自のもので、4個をdropshadow-custom.jsで設定している。

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


SVG.js siblings()について

jQueryのsiblingsとは違いますので注意ください。(ID名のArrayです)
参考のため、前ページのchildren()の記事をも理解ください。


1. siblings()はID名の配列です。(children()と同様なのでこちらを使用しても良い)
2. ドラッグなどで重ね順を変更すれば、siblings()の内容も変わりますからポジション値はも変わります。(clickで押されたインスタンス特定に便利です)
3. each処理で簡単にインスタンス特定が可能です。(複数のボタンを並べる場合に便利です)
4. 公式なサンプルなど有りませんので、テストで試しています。
6. 構造次第では上手くポジション値が取得できない場合もあります。(問題があれば自己解決)
7. ついでに next prev もテストしてみます。


SVG.js siblings()書式

SVG.jsでは、前ページの説明の如くインスタンス(要素)を表示する毎に siblings children として管理されているので(siblings() children() はArrayです、注意ください)あとでインスタンスを特定したい時など調べられるし、each()メソッドで一括変更処理できる仕組みもある。


SVG.jsでは、インスタンス要素を表示する度に固有のID名が付けられ、表示順序に、ID名が siblings、children 配列に収容されます。ドラッグなどで重ね順を変更すれば、配列中の順序も変わります。



childrenのget値の取得
インスタンス.get()

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

siblingsのposition値の取得
インスタンス.position()

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

each処理の場合インスタンスはthisで特定できるので便利
group層にボタンがならんでいる場合などは
group.each(function(i){
	this.click(function() {
		//position番号
		var no=this.position()
	})
})

siblings()もchildren()と同様にID名のArrayです。また、childrenと似通っても目的はちがいますし、
jQueryのsiblingsとは少々違いがある様です。つまり使用方法に戸惑う。
ページ下段のサンプル「11番、クロスフエード2、load()処理」を参照すれば理解できます。


SVG.js マニュアル Arranging elements 記載より


siblings()

The arrange.js module brings some additional methods. To get all siblings of rect, including rect itself:
rect.siblings()

returns: array

siblings()のサンプル等も有りませんので、下記の如くテストして様子を伺います。正常に処理されていれば、ほぼ正しいと想像するだけで確証は有りませんので、問題があれば自己解決ください。


レクト要素などをグループに画像を表示する例

下記HTMLは、サンプル1番のSVG.jsで生成されたhtmlである。ブラウザのデベロッパーツールで確認できます。
ID名はSVG.js固有の名前が付けられます。

そのため、SVG.jsの中でjQueryを使用する場合はクラス名でアクセスするよう推奨されています。


<div id="arranging-1a" class="graphic-elm">
<svg id="SvgjsSvg1026" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" width="160" height="160">
<defs id="SvgjsDefs1027"></defs>
<text id="SvgjsText1028" font-family="Helvetica, Arial, sans-serif"><tspan id="SvgjsTspan1029" dy="12.8" x="0">drag</tspan></text>
<g id="SvgjsG1030">
<rect id="SvgjsRect1031" width="60" height="60" fill="#ff0000" x="10" y="50" filter="url(#dropShadow2)"></rect>
<rect id="SvgjsRect1032" width="60" height="60" fill="#0000ff" x="50" y="50" filter="url(#dropShadow2)"></rect>
<rect id="SvgjsRect1033" width="60" height="60" fill="#00ffff" x="90" y="50" filter="url(#dropShadow2)"></rect>
</g>
</svg>
</div>

グループの中のRECT要素にsiblings()が自動で与えられる。
ID名は、SvgjsRect1031,SvgjsRect1032,SvgjsRect1033、に成る。
ポジション番号は 0,1,2 を取得可能です。


siblings関連のサンプルと簡単な説明

比較的使用されると思われる、next()、previous()、等はマニュアル通りであり余り説明はしない。

● next()、previous()
現在のアクセスされているインスタンスの next または prev を目指します。
使用方法などはサンプル参照ください。


● forward() backward() front() back()
現在のアクセスされているインスタンスの 構成順序(重ね順)を変えます。
当然、siblings() children() の内部順序も変わります。SVGにはz-indexの概念が無いから「重ね順」を変えるのに便利。
使用方法などはサンプル2-3番を参照ください。


実際の処理サンプル

1番、のsiblings()の内容を文字列にして下記に表示してみます。最初に自動生成されたdefsがあるのがわかる。
下記にsiblings()の内容を表示。(固有のID名になります)


DATA


● position番号取得

siblings()は自動で生成されていますので、対象インスタンス.position()で値を取得できます。
クリック、ドラッグで保存されたのsiblings()のposition番号を取得してみます。(コード参照)


1番、siblings()の内容表示 / 2番、ドラッグで重ね順変更/ 3番、クリックで保存番号表示とforward移動

3番、forward移動ですから、複数回クリックすれば1番上に移動します。


1番、ドラッグのみですからsiblings()の順序は変わりません。(position値は一定)


2番、ドラッグで重ね順変更した場合はsiblings()の順序も変わります。処理に時間が掛かるのでドラッグ後に表示しています。
下記に表示のID名も外周のレクトをドラッグ(クリック)すれば位置も変わります。
ドラッグ時front()を実行していますので常時一番手前に移動します。

position()値はドラッグで一番上に移動するためサンプルでは、常時 7 の値になっています。


DATA




children()値と同じである

重ね順をかえればドラッグ中、正確なposition値は取得できないので注意
ドラッグ終了時で在れば正確なposition値が取れるようである

クリックで使う様にすれば、常時関連のposition() siblings()が取れるので有効である
this.position()

どこでもsiblings()が取れるが値は同じである、確認のため取得しているが実際利用はあまりない
this.siblings()

3番、forward backward で位置重ね順等を変更した場合は、エレメントの構成順序を変えますので、children位置 position値 も変わります。
元の番号などは事前に書き込んでおくと識別が容易になります。(個人により考えは異なるかも知れませんが)



固有の識別番号をエレメントに書き込んでおく
var rect=group2.rect(60,60).attr({'fill':base_colors[i]}).center(i*40+40,80)
.attr({'no':i})

識別番号をattrで取り出す
var no=this.attr('no')

サンプルJS


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

	var bb_txt=draw.text('drag/position値表示').font({leading:0.8})

	base_colors=['#F00','#00F','#0FF']
	//GROUP
	var group=draw.group()
	//group.rect(0,0,160,160)//範囲

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

		var rect=group.rect(60,60).attr({'fill':base_colors[i]}).center(i*40+40,80)
		.attr({'filter':'url(#dropShadow2)'})//陰影
		.draggable(function(x,y){

			//一番手前に
			//動かしたら正確なposition値は取得できない
			//this.front()

			return {x:x,y:y}
		})
		.on('dragstart.namespace', function(event){
			//position値
			var no=this.position()
			bb_txt.text('pos-no ' + no)
		})

	}


	//jQuery処理削除ください
	//var str=rect.siblings().toString()
	//$('#showtext').text(str)

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

	//対象エレメントID
	var draw=SVG('arranging-1b').size(160,160)
	//TEXT
	var d_txt=draw.text('drag').font({leading:0.8})
	var pos_txt

	//角度補正は行わないこと
	var spikes,a,point_x,point_y,radius_v,angle12
	spikes=8,a=360/spikes,point_x=250,point_y=250,radius_v=50,angle12=0 //3時方向

	//GROUP
	var drag_group=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=point_x+radius_v*Math.cos((i*a+angle12)*Math.PI/180)
		var y=point_y+radius_v*Math.sin((i*a+angle12)*Math.PI/180)
		//rect
		var rect=drag_group.rect(40,40).attr({'fill':color,'stroke':'#FFF','stroke-width':2}).center(x,y).rotate(i*a)
		.attr({'no':i+1})
		.attr({'filter':'url(#dropShadow2)'})//陰影
		.draggable(function(x,y){

			//必要な処理も書ける/一番上に
			this.front()

			//識別番号
			var no=this.attr('no')
			d_txt.text('drag-no ' + no)

			return {x:x,y:y}
		})
		rect.on('dragstart.namespace', function(event){
			//index値
			var index_v=drag_group.index(this)
		})
		rect.on('dragend.namespace', function(event){
			//ポジション番号/一番手前に移動なので変わらない
			var pos=this.position()
			pos_txt.text('pos ' + pos)

			//jQuery処理削除ください
			//siblings文字列
			//var str=this.siblings().toString()
			//ID表示
			//$('#showtext2').text(str)
		})

	}

	drag_group.x(-170).y(-170)
	//TEXT
	pos_txt=draw.text('-').font({leading:0.8}).y(145)

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

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

	var bb_txt2=draw.text('click/1つ手前に移動').font({leading:0.8})

	base_colors=['#F00','#00F','#0FF']
	//GROUP
	var group2=draw.group()

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

		var rect=group2.rect(60,60).attr({'fill':base_colors[i]}).center(i*40+40,80)
		.attr({'no':i})
		.attr({'filter':'url(#dropShadow2)'})//陰影
		.click(function() {

			//識別番号
			var no=this.attr('no')
			//ポジション
			var pos=this.position()
			//表示
			bb_txt2.text('no ' + no + ' / pos ' + pos)
			//手前に
			this.forward()
		})
	}


next previousで画像の切り替え表示

画像の切り替えには画像を重ねて、指定の画像を表示させる方法が簡単なので良く用いられる手法である。
next() previous()を使用して画像を切り替えて見ます。


一般的なjQuery処理の構造

<div><img /><img /><img /></div>

htmlのIMGでは良く利用されるが、SVGでは一般的に普及していないので現時点では疑問は残る。
一応、次のサンプルの様に切り替え表示は可能である。

クロスフエードの場合は最後の「クロスフエード処理サンプル(番外)」を参照ください。処理が簡単です。


4番、next表示 / 5番、next表示2 / 6番、next prev 表示(非公式なグループ化)

画像切り替えは簡単だが、きれいに見せるなら構造などを変えねば成らない。


TESTでは単純な画像切り替えです。重なり順を上手く変えながら作る手法もあると思いますが、ここでは省略します。
サンプル6番、7番はグループ化した場合ですが、7番の様にadd()でグループ化するのが正式な手法になります。この場合ポジション番号の違いが出ることに注意が必要です。


サンプルJS


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

	var txt_x=draw.text('next').font({leading:0.8})

	//GROUP
	var group3=draw.group()
	group3.rect(0,0,160,160)//範囲

	//画像非表示
	var image=group3.image('/main/images/testImage101.jpg').size(100,100).move(30,30).hide()
	var image=group3.image('/main/images/testImage102.jpg').size(100,100).move(30,30).hide()
	var image=group3.image('/main/images/testImage103.jpg').size(100,100).move(30,30).hide()

	//1番画像表示
	group3.get(1).show()
	var image_no=1

	//ボタン
	var click_btn=draw.circle(10).attr({'fill':'#FF0000','stroke':'#FFF','stroke-width':2}).center(145,145)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	click_btn.click(function() {

		for (i=0; i < 4; i++){
			group3.get(i).hide()
		}

		group3.get(image_no).next().show()
		txt_x.text('no '+image_no)

		image_no ++
		if(image_no>2){image_no=0}

	})

	//var txt=draw.text('next').font({leading:0.8})

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

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

	var txt_x2=draw.text('next.first').font({leading:0.8})

	//GROUP/範囲無し
	var group4=draw.group()

	//画像非表示
	var image2=group4.image('/main/images/testImage101.jpg').size(100,100).move(30,30).hide()
	var image2=group4.image('/main/images/testImage102.jpg').size(100,100).move(30,30).hide()
	var image2=group4.image('/main/images/testImage103.jpg').size(100,100).move(30,30).hide()
	var image2=group4.image('/main/images/testImage104.jpg').size(100,100).move(30,30).hide()
	var image2=group4.image('/main/images/testImage105.jpg').size(100,100).move(30,30).hide()

	//0番画像表示
	group4.get(0).show()
	var image_no2=0
	//数
	var len=group4.index(image2)+1

	txt_x2.text('next.first'+' /len '+len)

	//ボタン
	var click_btn2=draw.circle(10).attr({'fill':'#FF0000','stroke':'#FFF','stroke-width':2}).center(145,145)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	click_btn2.click(function() {

		//for (i=0; i < len; i++){
			//group4.get(i).hide()
		//}

		group4.each(function(i,children){
			this.hide()
		})

		image_no2 ++
		if(image_no2>len-1){image_no2=0}

		//GROUP範囲無し
		if(image_no2>0){
			//1-
			group4.get(image_no2).show()
		}else{
			//0
			group4.first().show()
		}

		txt_x2.text('no '+image_no2)

	})

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

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

	var img_urls=['testImage101.jpg','testImage102.jpg','testImage103.jpg','testImage104.jpg','testImage105.jpg']
	var image_max=5

	var group5=draw.group()
	for (i=0; i < image_max; i++){
		var inner_image=draw.image('/main/images/' + img_urls[i]).size(160,160).center(80,80).scale(100/160)
		var image_rect=group5.rect(100,100).radius(10).attr({'fill':inner_image,'stroke':'#FFF','stroke-width':2}).center(80,80)
		.hide()
	}
	group5.attr({'filter':'url(#dropShadow2)'})

	//0番画像表示
	group5.get(0).show()
	var imageNo=0

	var data_tx=draw.text(''+imageNo).center(80,145)

	//NEXT
	var nextbtn_group=draw.group()
	var circle=nextbtn_group.circle(16).attr({'fill':'#FFF'}).center(20,145)
	var tagl_path=nextbtn_group.path('M 4,-6 L 14,0 4,6 Z').attr({'fill':'#00F'}).center(21,145)
	nextbtn_group.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	nextbtn_group.click(function() {

		group5.each(function(i,children){
			this.hide()
		})

		imageNo ++
		if(imageNo>image_max-1){imageNo=0}

		//GROUP範囲無し
		if(imageNo>0){
			//1-
			group5.get(imageNo).show()
		}else{
			//0
			group5.get(0).show()
		}

		data_tx.text(''+imageNo)

	})

	//PREV
	var prevbtn_group=draw.group()
	var circle=prevbtn_group.circle(16).attr({'fill':'#FFF'}).center(140,145).rotate(180)
	var tagl_path2=prevbtn_group.path('M 4,-6 L 14,0 4,6 Z').attr({'fill':'#00F'}).center(139,145).rotate(180)
	prevbtn_group.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	prevbtn_group.click(function() {

		group5.each(function(i,children){
			this.hide()
		})

		imageNo --
		if(imageNo<0){imageNo=image_max-1}

		//GROUP範囲無し
		if(imageNo>-1){
			//0-
			group5.get(imageNo).show()
		}else{
			//max
			group5.get(image_max-1).show()
		}

		data_tx.text(''+imageNo)

	})

	var txt=draw.text('next prev').font({leading:0.8})


サムネールボタンを作る場合は注意が必要

画像塗りのサムネールボタンを作る場合は注意が必要に成ります。ボタンはgroupで処理することが多いが、構造次第では get() position() の取得値が違う場合が発生します。下記の例を参考にして下さい。
よってサンプル(クロスフエード処理サンプル)では単純に処理するために「画像のみ」で処理しています。


groupで、first() last()を利用する場合には「レクトの画像塗り」には注意が必要になります。構造次第では正確な値が取得できない場合がある。グループで、レクト、画像それぞれ個別にchildrenとしてカウントされる。



groupに画像塗りレクト配置、画像が1番目、レクトが2番目になる

var group=draw.group()
var image1=group.image('/main/images/testImage101.jpg').size(100,100)
var rect=group.rect(100,100).attr({'fill':image1,'stroke':'#FFF','stroke-width':2})

一旦、draw層にレクトと画像を配置し、その後指定のgroupにadd()するなら first() last() が使用できる。この場合はグループで画像はchildrenとしてカウントされない。(addは正式の処理方法である)



一旦、draw層に配置して画像塗り
var image1=draw.image('/main/images/testImage101.jpg').size(100,100)
var rect1=draw.rect(100,100).attr({'fill':image1,'stroke':'#FFF','stroke-width':2})

groupにレクトをadd()で移動配置、画像塗りレクトが1番目になる
var group=draw.group()
group.add(rect1)

siblings処理

マニュアルにはないが、siblingsのeach処理も可能のようです(サンプル無しなのであくまでも可能のよう...)。構造次第では間違い易いかも知れない。(8番、基準が全体のdrawに対してのeach処理なため)


siblingsを関連付けた処理

マニュアルにはないが、9番の様にすればボタングループ層のボタン位置が取得でき、処理が容易になるようです。

● each処理はchildren()と同様に出来る様だが間違い易いので注意かも知れません。サンプル8番、9番参照。
ボタンを並べるには有効な手段と思います。


7番、next prev 表示(正式なグループ化) / 8番、each処理 / 9番、groupのeach処理、完全な振る舞いは未確認

特に、9番、group-each処理に注目ください。(下の灰色RECTは正確なポジション取得をおこなうか確認のダミーです)


9番、group-each処理はレクト要素などを描画した後なら処理できる様です。マニュアルなどには記載はありませんが、一応機能するようです。資料サンプルなどが無く、工夫が必要になりますが、正しい方法であるかは判りません。
これとload()処理を組み合わせたものが、下記2番のロスフエードサンプルになります。


サンプルJS



	//7 add形式はfirst() last() が使用できる
	//対象エレメントID
	var draw=SVG('arranging-1g').size(160,160)

	var img_urls2=['testImage101.jpg','testImage102.jpg','testImage103.jpg','testImage104.jpg','testImage105.jpg']
	var image_max2=5

	var group6=draw.group()
	for (i=0; i < image_max2; i++){
		//draw層に画像とレクトはいち
		var inner_image=draw.image('/main/images/' + img_urls2[i]).size(160,160).center(80,80).scale(100/160)
		var image_rect2=draw.rect(100,100).radius(10).attr({'fill':inner_image,'stroke':'#FFF','stroke-width':2}).center(80,80)
		.hide()
		//groupにaddで配置処理
		group6.add(image_rect2)
	}
	group6.attr({'filter':'url(#dropShadow2)'})

	//0番画像表示
	group6.get(0).show()
	var imageNo2=0

	var data_tx6=draw.text(''+imageNo2).center(80,145)

	//NEXT
	var nextbtn_group2=draw.group()
	var circle=nextbtn_group2.circle(16).attr({'fill':'#FFF'}).center(20,145)
	var tagl_path=nextbtn_group2.path('M 4,-6 L 14,0 4,6 Z').attr({'fill':'#00F'}).center(21,145)
	nextbtn_group2.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	nextbtn_group2.click(function() {

		group6.each(function(i,children){
			this.hide()
		})

		imageNo2 ++
		if(imageNo2>image_max2-1){imageNo2=0}

		//GROUP範囲無し
		if(imageNo2>0){
			//1-
			group6.get(imageNo2).show()
		}else{
			//0
			//group6.get(0).show()
			group6.first().show()
		}

		data_tx6.text(''+imageNo2)

	})

	//PREV
	var prevbtn_group2=draw.group()
	var circle=prevbtn_group2.circle(16).attr({'fill':'#FFF'}).center(140,145).rotate(180)
	var tagl_path=prevbtn_group2.path('M 4,-6 L 14,0 4,6 Z').attr({'fill':'#00F'}).center(139,145).rotate(180)
	prevbtn_group2.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	prevbtn_group2.click(function() {

		group6.each(function(i,children){
			this.hide()
		})

		imageNo2 --
		if(imageNo2<0){imageNo2=image_max2-1}

		//GROUP範囲無し
		if(imageNo2>-1){
			//0-
			group6.get(imageNo2).show()
		}else{
			//max
			//group6.get(image_max2-1).show()
			group6.last().show()
		}

		data_tx6.text(''+imageNo2)

	})

	var txt=draw.text('next prev / add group').font({leading:0.8})

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

	//対象エレメントID
	var draw_v=SVG('arranging-1h').size(160,160)

	var bb_txt8=draw_v.text('siblings-each処理/click').font({leading:0.8})

	base_colors8=['#F00','#00F','#0FF']
	//GROUP8
	var group8=draw_v.group()

	//draw-each処理
	draw_v.each(function(i){

		//
		var rect_v=group8.rect(60,60).attr({'fill':base_colors8[i]}).center(i*40+40,80)
		.attr({'filter':'url(#dropShadow2)'})//陰影
		.click(function() {

			//position番号
			var no=this.position()
			bb_txt8.text('no ' + no)

		})

	})

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

	//9 each処理出来る様だが間違い易いので注意かも
	//対象エレメントID
	var draw_v2=SVG('arranging-1i').size(160,160)

	//グループが正常かBackを描画して確認
	var rect_back=draw_v2.rect(156,156).attr({'fill':'#CCC'}).x(2).y(2)
	var bb_txt9=draw_v2.text('group-each処理/click').font({leading:0.8})

	base_colors9=['#F00','#00F','#0FF']
	//GROUP9描画
	var group9=draw_v2.group()
	for (i=0; i < 3; i++){
		var rect_v2=group9.rect(60,60).attr({'fill':base_colors9[i]}).center(i*40+40,80)
		.attr({'filter':'url(#dropShadow2)'})//陰影
	}

	//描画してからならばgroupにeach処理可能
	//group-each処理
	group9.each(function(i){
		this.click(function() {

			//position番号
			var no=this.position()
			bb_txt9.text('no ' + no)

		})
	})


つまり、下記の様に、最初にグラフイックをグループ層に描画して、group-each処理すればposition値が得られる。
一応、正確な値を得られるので機能しているものと思います。


eachの中では、各インスタンスは this に成るので処理し易い。this.position()で位置番号の値が取得できる


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

	//GROUP描画して先にボタンを配置する
	var group=draw.group()
	for (i=0; i < 3; i++){
		var rect=group.rect(10,10).attr({'fill':'#FFF'}).center(i*20+40,80)
	}

	//描画してからならばgroupのeach処理可能
	//group-each処理
	group.each(function(i){
		this.click(function() {

			//position番号
			var no=this.position()

		})
	})

下記の様に書いても処理するようですが、余り意味が無いと思います。正式にはchildrenだと思います。


	//group-each処理
	group.each(function(i,siblings){
		this.click(function() {

			//position番号
			var no=this.position()

		})
	})

画像のキャッシュとJS構造

単に画像を表示するのではなく、画像塗り等の加工を行う場合は、事前に画像を読み込み、完全読み込みの状態で処理します。(ブラウザによりエラーになるので注意)
また変数等が影響しないように構成することも重要です。ここではjQueryの形式で作っていますが書き方などは自由です。



(function($){

  $(function(){

    function init(){

	//SVG.jsの処理を書く

    }

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

    //画像キャッシュ
    var image1=new Image()
    image1.src="/main/images/testImage101.jpg"
    var image2=new Image()
    image2.src="/main/images/testImage102.jpg"
    var image3=new Image()
    image3.src="/main/images/testImage103.jpg"
    var image4=new Image()
    image4.src="/main/images/testImage104.jpg"
    var image5=new Image()
    image5.src="/main/images/testImage105.jpg"

    setTimeout(function() {
      //start
      init()
    },1000);

  });

})(jQuery);


 

クロスフエード処理サンプル (番外)

画像層2つの、クロスフエード処理サンプル。構造次第で場合には返って面倒になる場合がある。以下2つ例を示す。

クロスフエード処理等はSVG.jsのload()を利用するのも便利であるが、エラー処理しないので注意が必要です(11-12番)。
処理内容はスクリプトを参照ください。
大変面倒なため、SVGでクロスフエード処理するかは疑問ですが。...


サンプル10番はsiblingsを使用せずボタンを配列に保存して、対応する画像をnwe Image()処理で表示させています。よって画像のエラーにも対処可能ですし複雑な構造にも対応できます。


他方、サンプル11-12番はsiblingsのeach処理ですが、ボタン部分の構造が単純なものに限定されますしエラーに対処出来ません。どのようにするかは意見の分かれる所です。どちらにしろ充分テストして完動する事を確認してください。
但し下記サンプル11-12番は、previous() next() first() last()等は使用していない。

サンプル12番、サムネール処理は画像のみ配置、赤の目印は下にレクトを描画して移動している。(画像塗りだと処理が煩雑になるので止めた、そのため画像は角丸には出来ず四角形のみになります)


● SVG.jsのload()処理

画像インスタンスに動的に画像を効率的にLoad表示します。URLが間違っていれば当然表示しません。レクト要素などに画像塗りの場合は、画像の方にload()処理します。画像の大きさは同一でなければなりません。


load()
Loading another image can be done with the load() method:
image.load('/path/to/another/image.jpg')

10番、クロスフエード1、new Image()処理 / 11番、クロスフエード2、load()処理 / 11番、クロスフエード3、サムネール処理

フエード中はボタンが機能しません。完全にフエード終了後に次のボタンを押してください。


サンプルJS


//クロスフエード処理サンプル (番外)
(function($){

  $(function(){

    function init2(){

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

	//coment
	var coment=draw.text('番外 画像CROSSFADE').font({leading:0.8}).move(10,0)

	var loadimgUrl,img_no=0,hit_btn=[],gl_no
	,image_urls2=['/main/images/testImage108.jpg','/main/images/testImage107.jpg','/main/images/testImage106.jpg','/main/images/testImage105.jpg']

	var back2=draw.rect(100,100).attr({'fill':'#000'}).radius(10).center(80,80)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	//image 100x100
	var top_image2=draw.image(image_urls2[img_no]).size(160,160).center(80,80).scale(100/160)
	var btm_image2=draw.image(image_urls2[img_no]).size(160,160).center(80,80).scale(100/160)

	//下層btm_box画像セット
	var btm_box=draw.rect(100,100).attr({'fill':btm_image2}).radius(10).center(80,80)
	//上層top_box画像セット
	var top_box=draw.rect(100,100).attr({'fill':top_image2}).radius(10).center(80,80)
	.attr({'fill-opacity':0})

	//max
	var image_max=image_urls2.length

	//CROSSFADE
	function crossFade2(no){

		//画像番号
		img_no=no
		//TEXT
		coment.text('' + (img_no+1) + '番目の画像を表示')

		//ボタン色変更
		for (i=0; i < image_urls2.length; i++){
			hit_btn[i].attr({'fill':'#888888'})
			hit_btn[img_no].attr({'fill':'#FF0000'})
		}

		//上層に画像セット透明度0
		top_image2.load(image_urls2[no])
		top_box.attr({'fill-opacity':0})
		//FADE
		top_box.animate(1000).attr({'fill-opacity':1}).after(function(){

			//下層画像セット
			btm_image2.load(image_urls2[no])
			btm_box.attr({'fill-opacity':1})
			btm_image.load(image_urls[no]).attr({'fill-opacity':1})
			//Firefoxちらつき防止対策
			setTimeout(function() {
				//上層消す
				this.attr({'fill-opacity':0})
			},200)
		})
	}

	//画像Loader
	function load_image(no){

		//画像Loader
		var imageLoader=new Image()
		imageLoader.onload=function(){
			//OKロード完了
			crossFade2(no)
		}
		imageLoader.onerror=function(){
			//NG
			coment.text('LoadingError')
		}
		//URL-SET
		imageLoader.src=image_urls2[no]

	}

	//ボタン/受け渡し番号で設定
	for (i=0; i < image_urls2.length; i++){
		hit_btn[i]=draw.circle(10).attr({'fill':'#888888','stroke':'#FFF','stroke-width':2}).center(i*20+50,145)
		.attr({'no':i})//受け渡し番号no
		.attr({'filter':'url(#dropShadow2)'})//陰影
		.style('cursor','pointer')
		hit_btn[i].click(function(){
			//こうしないと番号がわたらない
			var no=this.attr('no')

			load_image(no)
		})
	}

	//最初を赤色に
	hit_btn[img_no].attr({'fill':'#FF0000'})


	//NEXT
	var nextbtn_group=draw.group()
	var circle=nextbtn_group.circle(16).attr({'fill':'#FFF'}).center(20,145)
	var tagl_path=nextbtn_group.path('M 4,-6 L 14,0 4,6 Z').attr({'fill':'#00F'}).center(21,145)
	nextbtn_group.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	nextbtn_group.click(function() {
		img_no ++
		if(img_no>image_max-1){img_no=0}
		load_image(img_no)
	})

	//PREV
	var prevbtn_group=draw.group()
	var circle=prevbtn_group.circle(16).attr({'fill':'#FFF'}).center(140,145).rotate(180)
	var tagl_path=prevbtn_group.path('M 4,-6 L 14,0 4,6 Z').attr({'fill':'#00F'}).center(139,145).rotate(180)
	prevbtn_group.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	//CLICK-ACTION
	prevbtn_group.click(function() {
		img_no --
		if(img_no<0){img_no=image_max-1}
		load_image(img_no)
	})

  }

  //start
  init2()

 });

})(jQuery);

//-------------------------------------------------------------
//クロスフエード処理サンプル (番外)2
(function($){

  $(function(){

    function init3(){

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

	//coment
	var coment=draw.text('SVG load()処理').font({leading:0.8}).move(10,0)

	var loadimgUrl,img_no=0,hit_btn=[],gl_no
	,image_urls2=['/main/images/testImage108.jpg','/main/images/testImage107.jpg','/main/images/testImage106.jpg','/main/images/testImage105.jpg']

	var back2=draw.rect(100,100).attr({'fill':'#000'}).radius(10).center(80,80)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	//image 100x100
	var top_image2=draw.image(image_urls2[img_no]).size(160,160).center(80,80).scale(100/160)
	var btm_image2=draw.image(image_urls2[img_no]).size(160,160).center(80,80).scale(100/160)

	//下層btm_box画像セット
	var btm_box=draw.rect(100,100).attr({'fill':btm_image2}).radius(10).center(80,80)
	//上層top_box画像セット
	var top_box=draw.rect(100,100).attr({'fill':top_image2}).radius(10).center(80,80)
	.attr({'fill-opacity':0})

	//max
	var image_max=image_urls2.length
	//Loadflag
	var loadflag=false

	//CROSSFADE
	function crossFade(no){
		//処理中
		loadflag=true
		coment.text('position番号 ' + no)
		//ボタン処理
		btngroup.each(function(i,siblings){
			this.attr({'fill':'#888888'})
			if(i==no){this.attr({'fill':'#FF0000'})}
		})

		//上層透明度0
		top_box.attr({'fill-opacity':0})
		//FADE
		top_box.animate(1000).attr({'fill-opacity':1}).after(function(){

			//下層画像セット
			btm_image2.load(image_urls2[no]).attr({'fill-opacity':1})
			//Firefoxちらつき防止対策
			setTimeout(function() {
				//上層消す/thisはダメ
				top_box.attr({'fill-opacity':0})
				//処理終了
				loadflag=false
			},200)
		})
	}
	//画像Load
	function load_image(no){
		//FADE処理中は戻る
		if(loadflag){retrun}
		//上層に画像ロード
		top_image2.load(image_urls2[no])
		//直ぐ画像ロード完了前提
		crossFade(no)
	}

	//ボタングループ
	var btngroup=draw.group()
	//ボタン/受け渡し番号で設定
	for (i=0; i < image_urls2.length; i++){
		//BTN
		hit_btn[i]=btngroup.circle(10).attr({'fill':'#888888','stroke':'#FFF','stroke-width':2}).center(i*20+50,145)
		.attr({'no':i})//受け渡し番号no
		.attr({'filter':'url(#dropShadow2)'})//陰影
		.style('cursor','pointer')

	}

	//描画してからならばgroupに可能
	//group-each処理
	btngroup.each(function(i){
		this.click(function() {

			//position番号
			var no=this.position()
			load_image(no)

		})
	})

	//最初を赤色に
	hit_btn[img_no].attr({'fill':'#FF0000'})

  }

  //start
  init3()

 });

})(jQuery);

//-------------------------------------------------------------
//クロスフエード処理サンプル (番外)3
(function($){

  $(function(){

    function init4(){

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

	//coment
	var coment=draw.text('SVG load()処理').font({leading:0.8}).move(10,0)

	var loadimgUrl,img_no=0,hit_btn=[],gl_no
	,image_urls2=['/main/images/testImage108.jpg','/main/images/testImage107.jpg','/main/images/testImage106.jpg','/main/images/testImage105.jpg']

	var back2=draw.rect(100,100).attr({'fill':'#000'}).radius(10).center(80,70)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	//image 100x100
	var top_image2=draw.image(image_urls2[img_no]).size(160,160).center(80,70).scale(100/160)
	var btm_image2=draw.image(image_urls2[img_no]).size(160,160).center(80,70).scale(100/160)

	//下層btm_box画像セット
	var btm_box=draw.rect(100,100).attr({'fill':btm_image2}).radius(10).center(80,70)
	//上層top_box画像セット
	var top_box=draw.rect(100,100).attr({'fill':top_image2}).radius(10).center(80,70)
	.attr({'fill-opacity':0})

//目印ラインBOX
linebox=draw.rect(20,20).attr({'fill':'none','stroke':'#F00','stroke-width':2}).move(25,135)

	//max
	var image_max=image_urls2.length
	//Loadflag
	var loadflag=false

	//CROSSFADE
	function crossFade(no){
		//処理中
		loadflag=true
		coment.text('position番号 ' + no)
		//ボタン処理
		btngroup.each(function(i,siblings){
			if(i==no){
				//サムネール位置取得
				var box_x=this.x()
				//目印ラインBOX移動
				linebox.move(box_x,135)
			}
		})

		//上層透明度0
		top_box.attr({'fill-opacity':0})
		//FADE
		top_box.animate(1000).attr({'fill-opacity':1}).after(function(){

			//下層画像セット
			btm_image2.load(image_urls2[no]).attr({'fill-opacity':1})
			//Firefoxちらつき防止対策
			setTimeout(function() {
				//上層消す/thisはダメ
				top_box.attr({'fill-opacity':0})
				//処理終了
				loadflag=false
			},200)
		})
	}
	//画像Load
	function load_image(no){
		//FADE処理中は戻る
		if(loadflag){retrun}
		//上層に画像ロード
		top_image2.load(image_urls2[no])
		//直ぐ画像ロード完了前提
		crossFade(no)
	}

	//ボタングループ
	var btngroup=draw.group()
	//ボタン/受け渡し番号で設定
	for (i=0; i < image_urls2.length; i++){
		//サムネール
		var image=btngroup.image(image_urls2[i]).size(20,20).move(i*30+25,135)
		.attr({'no':i})//受け渡し番号no
		.attr({'filter':'url(#dropShadow2)'})//陰影
		.style('cursor','pointer')

	}

	//描画してからならばgroupに可能
	//group-each処理
	btngroup.each(function(i){
		this.click(function() {

			//position番号
			var no=this.position()
			load_image(no)

		})
	})

  }

  //start
  init4()

 });

})(jQuery);


グループのボタンを特定する

グループのボタンを特定するには、構造が単純で無いと間違う場合がありますが、上記サンプル2番を例にしますと、
first() get() でも処理できます。(必ず確認ください)


//最初を赤色にする

インスタンスを配列に保存して処理
hit_btn[img_no].attr({'fill':'#FF0000'})

----------------------
firstで処理
btngroup.first().attr({'fill':'#FF0000'})

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

getで処理
btngroup.get(0).attr({'fill':'#FF0000'})


サンプルJSの全表示

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

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

使用画像

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

使用画像サンプル

 


 

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

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

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

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

SVG.js children getの記事は前ページにあります。似通っていますので参考ください。

【参照】当方の記事: SVG.js children() get()


モット良い方法があれば考えてください。問題があれば自己解決ください。以上。

 


[ この記事のURL ]


タグ:javascript , SVG

 

ブログ記事一覧



[1]