POPSブログ

SVG.js TEXT表示とTEXTマスク

378

  Category:  javascript2016/02/12 pops 

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

 

SVG.js テキスト表示とマスクのテスト


zuzu

 

ご注意、Chrome.Firefox.IE11(一部機能しません)などSVGに対応したブラウザでご覧ください。Chromeを推奨します。

 

DEMO テキスト表示とマスク、その他の「デモ」

● デモページは [ jqury-1.9 ] で動作しています。


Chromeでの閲覧を推奨します


DEMO、このページに収容できない、テキスト表示とマスクに関連する「デモ」です。

DEMO-038




 

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


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

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


テキスト表示

標準的なテキストは、「P要素」の様にロゴ文字の様に比較的大きなフォントで表示する方法、「SPAN要素」の様に小さな文字を表示する方法があり、共に1行単位で折り返しはしない。
その他HTMLで文字を表示する方法もある。

フォントの指定は、ブラウザにより登録文字が違い、必ず表示される保障は有りません。
ブラウザ共通にフォント指定するには、Webフォント、googleフォントなどを事前に読み込み表示させる必要があります。



書式

//文字描画/フォント
var text=draw.text('POPSWEB KOUBOU')
.font({
  family:'Arial'
  ,size:50
  ,'font-weight':'bolder'
  ,anchor:'left'
  ,leading:1
})


family		'Arial'、フォントfamilyで指定、初期値は'Helvetica'
size		50、数値指定
font-weight	'bolder' 'bold' 'normal'、boldでも動作した
anchor		'left' 'middle' 'right'、通常'left'
leading		1、line-height属性と同様のようです
-----------------------------------------------------

これ以上の設定が必要な場合は、attr()で設定します

-----------------------------------------------------
次はエラーになります

var text=draw.text()
var text=draw.text

family:''

大きなフォントで表示

以下の様になるが、表示は簡単であるが配置などが面倒であり、特に「IE11」は振る舞いが違い面倒きわまりない。
文字が大きくなるほど、縦方向の誤差がでて面倒である。但し、原因がわかったので修正します。


1.「IE11」のY位置の不具合は、ページ のline-height の影響で、文字の大きさ取得に大幅な違いが出るからです。
2.「IE11」の位置計算にも少し不具合があるようです。
3.「IE11」に対応しない方が賢明です。


● 図の説明/IE11の振る舞い

zudaze

 

1.2番、x y()の設定が無ければ、TEXTの高さに関係なく綺麗に表示される、縦位置は leading で調整可能です。
但しこれはtspan用の設定で移動すれば変化しますので意味は無い。(設定などまだ未設定で起きている現象)
3番、anchor:left 状態で、.x().y() または center() で中央に移動できますが、leading は関係有りません。実際配置時ブラウザにより若干の誤差がでます。
(「IE11」の高さが合わない場合はページ のline-height の影響です)
4番、「IE11」で青の文字の様に、y(0) を実行して、大きな誤差があれば、「IE11」line-height 設定異常ですからCSSで修正します。
anchor:middle で、赤色の様に、中心が左に移動して x=0 の状態になります。


IE11、line-height属性の影響とCSS修正

大きなフォントを設定した場合に、TEXTの高さが大幅に狂う現象に出会います。「IE11」ではページに設定しているline-height属性が影響します。JSでの修正は可能ですが、煩雑で処理を複雑にするだけですので、裏をかいて「line-heightを設定して」TEXTの高さを他のブラウザ値に近づけます。
そのために、DIV容器を作る際にline-heightを設定して修正することにしますが、1では少し高さが大きめに成るので、
1.1-1.15位がよろしいようです。ここでは 1.15 にしています。
IE11以外の、Chrome Firefoxでは影響は有りません。



ここの例では「svg」を生成する「div」に

.svgtext-elm{
line-height:1.15;
width:640px;
height:100px;
margin:0;
padding:0;
border:#000000 1px solid;
overflow:hidden;
}

具体的な表示例

SVG.jsでは多くの位置設定方法がありますので、具体的に表示してみます。実際には「3 center()で移動配置」が便利と思います。一応数例表示してみます。CSS修正していますのでほとんど中央に位置すると思います。
● テスト的にTEXTの大きさをbbox()で取得して表示して見ます。(下記サンプルの青枠が大きさです)

DATA


SAMPLE

1a. x() y()で移動配置

.y(0)を実行した場合に、IE11ではどこに行くか考えればよい。(異常である事には相違ないが)

IE11のみ y() で微調整すれば完全一致する。この例では誤差が少ないのでそのままです。


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-1a').size(640,100)

	//middle参考表示
	var text_mid=draw.text('POPSWEB KOUBOU')
	//フォント
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'middle'
		,leading:1
	})
	text_mid.attr({fill:'#F00','fill-opacity':0.2})

	//文字
	var text=draw.text('POPSWEB KOUBOU')
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//大きさ取得
	var txdata=text.bbox()
	var tw=Math.round(txdata.width)
	var th=Math.round(txdata.height)
	//jQueryで表示
	$('#show-text').text(' W' + tw + ' H' + th)

	var rect=draw.rect(tw,th).attr({'fill':'none','stroke':'#00F','stroke-width':1}).center(320,50)

	var mv_x=(640-tw)/2
	var mv_y=(100-th)/2
	text.attr({fill:'#000'}).x(mv_x).y(mv_y)//.move(mv_x,mv_y)

	var txt=draw.text('1 xy移動').font({leading:0.8})


● 大きさの取得

大きさはbbox()を取得すれば判るが、ブラウザにより値にバラつきが有ります。
例ではjQueryで表示している。「IE11」の値が異常でない事を確認して下さい。

このページ[p要素]には、line-height:150% が設定されているため、テキスト高さ、132.5 になり、原因究明にえらい時間を要した。(line-heightの影響とはわからんかったナ)


//大きさ取得
var txdata=text.bbox()
var tw=txdata.width
var th=txdata.height

//丸めてもたいした違いは無い
var tw=Math.round(txdata.width)
var th=Math.round(txdata.height)

//jQueryで表示
$('#show-text').text(' W' + tw + ' H' + th)

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

Firefox	W493 H59
Chrome	W491.6875 H56
IE11	W492 H58

影響を受けている場合、数値はページにより違いあり
IE11	W491.6999816894531 H132.5

1b. move()で移動します

x() y()、2つを纏めたものがmove()です。個別に設定する場合は、x() y()を使用しますが、move()でも同じに出来ます。

● move()で移動配置


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-1b').size(640,100)

	var rect=draw.rect(tw,th).attr({'fill':'none','stroke':'#00F','stroke-width':1}).center(320,50)

	//文字
	var text=draw.text('POPSWEB KOUBOU')
	//フォント
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//move移動
	text.attr({fill:'#000'}).move(mv_x,mv_y)

	var txt=draw.text('1b move移動').font({leading:0.8})


2 グループ化 x() y()で移動配置

.y()の影響を避けるためにグループ化した。中心から回転可能、テストでドラッグ設定。(かなり特殊な方法といえる、ボタンなどを作る場合には良いかも)


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-1c').size(640,100)

	var rect=draw.rect(tw,th).attr({'fill':'none','stroke':'#00F','stroke-width':1}).center(320,50)

	//Group
	var group=draw.group()
	group.rect(0,0,492,56)

	//文字
	var text2=group.text('POPSWEB KOUBOU')
	//フォント
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:0.9
	})

	//group範囲を決めて処理するとIEでも少し簡単
	var mv_x=(640-492)/2
	var mv_y=(100-56)/2
	text2.attr({fill:'#F00'})
	//dropShadow
	text2.attr({'filter':'url(#dropShadow)'})

	//Group移動/TEXTのxyは絶対指定しないこと
	group.x(mv_x).y(mv_y)
	.style('cursor','default').draggable()

	//Groupでボタンを作る
	var gp_btn=draw.group()
	var btn_base=gp_btn.rect(60,20).radius(5).attr({'fill':'#FFD700','stroke':'#FFF','stroke-width':1}).center(600,80)
	.attr({'filter':'url(#dropShadow2)'})
 	btn_text=gp_btn.text('BUTTON')
	.font({
		family:'Arial'
		,size:12
		,anchor:'left'
		,leading:1
	})
	.attr({'fill':'#FFF'}).center(600,80)
	.attr({'filter':'url(#dropShadow3)'})

	gp_btn.style('cursor','pointer')
	gp_btn.click(function(){
		alert('HIT-BTN')
	
	})

	var txt=draw.text('2 Group移動 drag').font({leading:0.8})


3 center()で移動配置

基本的にcenter()で移動配置が大きさを知る必要が無く簡単なため使用が多い。上の方法は面倒である。

下記画像は、表示展開の例です。故意に大きな画像を使用しています。


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-1d').size(640,100)

	//画像を表示/1000x100
	var image=draw.image('/main/images/line-grad.jpg').size(1000,100)

	var rect=draw.rect(tw,th).attr({'fill':'none','stroke':'#00F','stroke-width':1}).center(320,50)

	//文字
	var text3=draw.text('POPSWEB KOUBOU')
	//フォント
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//center()移動
	text3.attr({fill:'#FFF'}).center(320,50)
	//回転可能
	text2.rotate(-5)
	//dropShadow
	text3.attr({'filter':'url(#dropShadow)'})

	var txt=draw.text('3 center()').font({leading:0.8})


4 グループ化 center()で移動配置、画像塗り

ドラッグなどの場合はグループ化したほうが良い。画像塗りの方が装飾し易い利点がある。


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-1e').size(640,100)

	//画像を表示/1000x100
	var image=draw.image('/main/images/line-grad.jpg').size(1000,100)

	var rect=draw.rect(tw,th).attr({'fill':'none','stroke':'#00F','stroke-width':1}).center(320,50)

	//グループ化
	var logo_group=draw.group()
	//文字
	var text4=logo_group.text('POPSWEB KOUBOU')
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//center()移動
	text4.attr({fill:image,'stroke':'#FFF','stroke-width':1}).center(320,50)
	//dropShadow
	text4.attr({'filter':'url(#dropShadow)'})

	//グループドラッグ
	logo_group.style('cursor','pointer').draggable()

	var txt=draw.text('4 Group center()移動 drag').font({leading:0.8})


5 move()で移動配置

ドラッグで中の画像塗りが動くことに注目ください。画像が固定されていない。この違いを理解ください。


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-1f').size(640,100)

	//画像を表示/1000x100
	var image=draw.image('/main/images/line-grad.jpg').size(1000,100)

	//文字
	var text5=draw.text('POPSWEB KOUBOU')
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'middle'
		,leading:1
	})

	//移動
	text5.attr({fill:image}).move(320,20)
	//dropShadow
	text5.attr({'filter':'url(#dropShadow)'})

	//ドラッグ
	text5.style('cursor','pointer').draggable()

	var txt=draw.text('5 画像塗りmove()移動 drag').font({leading:0.8})


TEXTの変更更新

テキスト内容の更新も行えます。位置、色などは随時変更できます。

TEXT内容の更新

テキスト内容の更新はplain()メソッドまたは、tspan()メソッドで行います。位置設定方法の違いでクリアされる場合も有ります。


サンプルJS


	//6 TEXTの更新
	//エレメントID
	var draw=SVG('svgtext-1g').size(640,100)

	var text_no=0
	//文字
	var before_text=draw.text('POPSWEB KOUBOU')
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//移動
	before_text.attr({fill:'#F00'}).center(320,50)
	//dropShadow
	before_text.attr({'filter':'url(#dropShadow)'})

	//ボタン1
	var test_btn=draw.circle(10).attr({'fill':'#FFD700','stroke':'#FFF','stroke-width':2}).center(620,10)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	test_btn.click(function(){
		//更新
		if(text_no==0){before_text.plain('Diomedea albatrus')}
		if(text_no==1){before_text.plain('POPSWEB KOUBOU')}
		text_no ++
		if(text_no>1){text_no=0}
		before_text.center(320,50)
	})
	//ボタン2
	var test_btn2=draw.circle(10).attr({'fill':'#0000FF','stroke':'#FFF','stroke-width':2}).center(600,90)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	test_btn2.click(function(){
		//色の変更
		before_text.attr({fill:'#0000FF'})
	})
	//ボタン3
	var test_btn3=draw.circle(10).attr({'fill':'#FF0000','stroke':'#FFF','stroke-width':2}).center(620,90)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	test_btn3.click(function(){
		//色の変更
		before_text.attr({fill:'#FF0000'})
	})

	var txt=draw.text('6 右の「黄ボタン」でテキスト内容を更新します(交互)、「赤青」ボタンで色変更').font({leading:0.8})



テキスト内容の更新、center()は大きさが変わるので再設定する

before_text.plain('Diomedea albatrus')
before_text.center(320,50)

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

attr()等はいつでも更新出来る、実行時点で変わる
before_text.attr(.....)

画像塗りの変更

画像を取り替えれば良いのですが、贅沢にも「完全読み込み済み」の画像でなければなりません。
コンナ場合、image.load()が便利です。


サンプルJS


	//画像塗りの更新
	//エレメントID
	var draw=SVG('svgtext-1h').size(640,100)

	//画像を表示/1000x100
	var before_image=draw.image('/main/images/line-grad.jpg').size(1000,100)

	//文字
	var draw_text=draw.text('POPSWEB KOUBOU')
	//フォント
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//画像塗りcenter()移動
	draw_text.attr({fill:before_image}).center(320,50)
	//dropShadow
	draw_text.attr({'filter':'url(#dropShadow2)'})

	//ボタン4
	var test_btn4=draw.circle(10).attr({'fill':'#FF0000','stroke':'#FFF','stroke-width':2}).center(620,10)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	test_btn4.click(function(){
		//画像塗り更新/1000x100
		before_image.load('/main/images/line-grad4.jpg')
	})

	var txt=draw.text('7 画像塗りの更新、ボタンを押してください(1回限り)').font({leading:0.8})


center()処理していますので、同じ大きさの画像にして下さい。

事前にキャッシュしておかなくとも、Load完了後処理してくれるので便利だ。


画像があることが条件です

対象imageインスタンス.load('画像URL')

fillとstrokeを分離して描画する時の注意点

「IE11」でstrokeを描画しないとテキストにズレが出来ます。「IE11」の内部計算が間違っているようです。
fill描画時に透明のstrokeを描き防止可能ですが、結構面倒で、デザインによっては困る場合も出るでしょう。

okoke

 

● IE11でcenter()処理の場合、strokeが右に動きます。

fill描画時に透明のstrokeを描き、テキスト横幅をあわせます。(center()処理のためtranslate()を使用できません)


サンプルJS


	//fill,strokeを分離して描画1
	//エレメントID
	var draw=SVG('svgtext-1i').size(640,100)

	//文字1
	var fill_text=draw.text('POPSWEB KOUBOU')
	//フォント
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})
	//center()移動
	fill_text.attr({fill:'#F00','stroke':'rgba(0,0,0,0)','stroke-width':2}).center(320,50)//IEずれない
	//fill_text.attr({fill:'#F00'}).center(320,50)//IEずれる
	.attr({'filter':'url(#dropShadow)'})

	//文字2
	var stroke_text=draw.text('POPSWEB KOUBOU')
	//フォント
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})
	//center()移動
	stroke_text.attr({fill:'none','stroke':'#FFF','stroke-width':2}).center(320,50)
	.attr({'filter':'url(#dropShadow2)'})

	var txt=draw.text('A fill,strokeを分離して描画、center()処理').font({leading:0.8})



透明のストロークを描く
fill_text.attr({fill:'#F00','stroke':'rgba(0,0,0,0)','stroke-width':2}).center(320,50)//IEずれない
//fill_text.attr({fill:'#F00'}).center(320,50)//IEずれる

● IE11でmove()処理の場合、strokeが下に動きます。

fill描画時に透明のstrokeを描き、テキスト横幅をあわせます。またはtranslate()で移動します。


サンプルJS


	//fill,strokeを分離して描画2
	//エレメントID
	var draw=SVG('svgtext-1j').size(640,100)

	//文字1
	var fill_text=draw.text('POPSWEB KOUBOU')
	//フォント
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})
	//center()移動
	fill_text.attr({fill:'#00F','stroke':'rgba(0,0,0,0.5)','stroke-width':2}).move(80,25)//IEずれない
	//fill_text.attr({fill:'#00F'}).translate(80,25)//IEずれない
	.attr({'filter':'url(#dropShadow)'})

	//文字2
	var stroke_text=draw.text('POPSWEB KOUBOU')
	//フォント
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})
	//center()移動
	stroke_text.attr({fill:'none','stroke':'#FFF','stroke-width':2}).move(80,25)//あわせる
	//stroke_text.attr({fill:'none','stroke':'#FFF','stroke-width':2}).translate(80,25)//あわせる
	.attr({'filter':'url(#dropShadow2)'})

	var txt=draw.text('B fill,strokeを分離して描画、move()処理').font({leading:0.8})



透明のストロークを描く
fill_text.attr({fill:'#00F','stroke':'rgba(0,0,0,0.5)','stroke-width':2}).move(80,25)//IEずれない
-------------------------------------------
translateなら
fill_text.attr({fill:'#00F'}).translate(80,25)//IEずれない
strokeもあわせる
stroke_text.attr({fill:'none','stroke':'#FFF','stroke-width':2}).translate(80,25)//あわせる

カーニングと文字の着色

文字の位置を狭めるカーニングをtspanで行得ます。合わせて文字の色を変えてみます。移動はmove()です。

2つの方法がありますが、詳細はページ下段の記事「カーニングの方法」を参照ください。

● カーニングと文字の着色/虹色

現在は、hsl() で簡単に出来ます。(古いブラウザはこの機能は無い)


サンプルJS


	//カーニング
	//ランダムカラー
	//エレメントID
	var draw=SVG('svgtext-3a').size(640,100)

	//ストリング
	var main_strings="Merry Christmas 2016.dazo"

	//空文字
	var k_text=draw.text('')
	.font({
		family:'Times New Roman'
		,size:65
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//カーニングと着色
	var spikes=main_strings.length
	k_text.text(function(add) {
		for (var i=0; i<spikes;i++){

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

			var tx=main_strings.charAt(i)
			add.tspan(tx).attr({'dx':-10,'fill':color,'stroke':'#FFF','stroke-width':1})
		}
	})

	//move位置移動
	k_text.move(50,15)
	.attr({'filter':'url(#dropShadow)'})

	var txt=draw.text('A カーニングと着色 move位置移動').font({leading:0.8})



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

● カーニングと文字の着色/ランダムカラー

一応可能ですが、文字指定「Times New Roman」は表示の保障はない。(dxはカーニング値)
尚、個別に陰影はFirefox機能せず、全体に陰影処理しています。ランダムカラー着色していますが虹色着色可能です。


サンプルJS


	//ランダムカラー
	//エレメントID
	var draw=SVG('svgtext-3b').size(640,100)

	//ストリング
	var main_strings="Merry Christmas 2016.dazo"

	//空文字
	var k_text2=draw.text('')
	.font({
		family:'Times New Roman'
		,size:65
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//カーニングと着色
	var spikes=main_strings.length
	k_text2.text(function(add) {
		for (var i=0; i<spikes;i++){

			//ランダムカラー
			//var color='rgba('+Math.floor(Math.random()*255)+','+Math.floor(Math.random()*255)+','+Math.floor(Math.random()*255)+',1)'

			//16進カラー形式なら、新しいブラウザ向け
			var color='#'+Math.random().toString(16).slice(-6)

			var tx=main_strings.charAt(i)
			add.tspan(tx).attr({'dx':-10,'fill':color,'stroke':'#FFF','stroke-width':1})
		}
	})

	//move位置移動
	k_text2.move(50,15)
	.attr({'filter':'url(#dropShadow)'})

	var txt=draw.text('B カーニングと着色 move位置移動').font({leading:0.8})



//rgba形式なら、ランダムカラーOK
var color='rgba('+Math.floor(Math.random()*255)+','+Math.floor(Math.random()*255)+','+Math.floor(Math.random()*255)+',1)'

//16進カラー形式なら、新しいブラウザ向け
var color='#'+Math.random().toString(16).slice(-6)

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

ブラウザが古い場合16進カラーOK
var color='#'+('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6)
var color='#'+('00000'+(Math.floor(Math.random()*16777215).toString(16))).slice(-6)
var color='#'+('00000'+(Math.floor(Math.random()*0xFFFFFF).toString(16))).slice(-6)

注意、下記はSVGでは不安定で使えない
var color='#'+Math.floor(Math.random()*16777215).toString(16)

下記のように、tspanは生成されるがaddで処理されている為か、後でインスタンスを特定できない。つまり変更など難しい。方法があると思うが未解決です。誰か考えてください....


<text><tspan></tspan><tspan></tspan>....</text>

● カーニングと文字の着色/2色間の色を補完する


サンプルJS


	//カーニング3
	//エレメントID
	var draw=SVG('svgtext-3c').size(640,100)

	//ストリング
	var main_strings="Merry Christmas 2016.dazo"

	//空文字
	var k_text3=draw.text('')
	.font({
		family:'Times New Roman'
		,size:65
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//開始色と最終色
	var color_v=new SVG.Color('#FF0000').morph('#FFD700')

	//カーニングと着色
	var spikes=main_strings.length
	k_text3.text(function(add) {
		for (var i=0; i<spikes;i++){
			//中間色
			var color=color_v.at(i/spikes).toHex()
			var tx=main_strings.charAt(i)
			add.tspan(tx).attr({'dx':-10,'fill':color,'stroke':'#FFF','stroke-width':1})
		}
	})

	//move位置移動
	k_text3.move(50,15)
	.attr({'filter':'url(#dropShadow)'})

	var txt=draw.text('C カーニングと着色 move位置移動').font({leading:0.8})



//開始色と最終色を入力
var color_v=new SVG.Color('#FF0000').morph('#FFD700')
//中間色を計算する
var color=color_v.at(i/spikes).toHex()

● add()を使用しないで、tspanで記述。(add形式のほうが楽かも)


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-3d').size(640,100)

	//空文字
	var k_text4=draw.text('')
	.font({
		family:'Times New Roman'
		,size:55
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//文字と色
	k_text4.tspan('Merry ').attr({'fill':'#FFD700'})
	.tspan('Christmas ').attr({'fill':'#20B2AA','stroke':'#FFF','stroke-width':1})
	.tspan('2016').attr({'fill':'#9370DB','stroke':'#FFF','stroke-width':0})

	//move移動
	k_text4.move(50,15)
	.attr({'filter':'url(#dropShadow2)'})

	var txt=draw.text('D 着色 move位置移動').font({leading:0.8})


小さなTEXTの表示

小さなTEXTはFONTを省略して記述したほうが便利です。この場合SVG.js初期値で表示されます。
各サンプルに使用していますが位置指定がないので上に表示されます。leadingのみ変更しています。
「複数テキスト表示」はデモページを参照ください。


var txt=draw.text('1b カーニングと着色 move位置移動').font({leading:0.8})
var txt=draw.text('1b カーニングと着色 move位置移動').font({leading:0.8}).move(x値,y値)

指定のない場合は初期値が入る
<text font-family="Helvetica, Arial, sans-serif"><tspan>文章</tspan></text>

 

clipマスクとmaskマスクとタイガーマスク

文字でマスクした場合の例である。通常は「clipマスク」が便利ですが、透過処理させたい場合は「maskマスク」を利用する。マスク材はパス等で構成されたインスタンスです。

 

1 clipマスク

通常のclipマスクではドラッグで中の画像が動くのでグループ化している。そのため陰影も可能です。画像塗りとの違いを知ってください。どちらが良いかは好みの問題ですが。


サンプルJS


	//マスク
	//エレメントID
	var draw=SVG('svgtext-4a').size(640,100)

	var mask_group=draw.group()
	//画像を表示/1000x100
	var mask_image=mask_group.image('/main/images/line-grad2.jpg').size(1000,100)
	//ドラッグのためグループ化
	//文字
	var text6=mask_group.text('POPSWEB KOUBOU')
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//center()移動
	text6.attr({fill:'#000'}).center(320,50)
	//clipマスク
	mask_image.clipWith(text6)

	//グループをドラッグ
	mask_group.style('cursor','pointer').draggable()
	//dropShadow
	mask_group.attr({'filter':'url(#dropShadow)'})

	var txt=draw.text('1 clip画像マスクcenter()移動 drag').font({leading:0.8})



対象インスタンス.clipWith(マスク材)

2 maskマスク

maskマスクのみ、白黒グラデーションで塗れば黒の部分が透過できる利点がある。(白は透過しない、通常の色であれば明度の差に成る)、例では通常のレクトだが画像でも良い。



対象インスタンス.maskWith(マスク材)

サンプルJS


	//エレメントID
	var draw=SVG('svgtext-4b').size(640,100)

	//黒背景
	var back_rect=draw.rect(640,100).attr({'fill':'#000'})
	//マスク本体
	var mask_rect=draw.rect(640,100).attr({'fill':'#F00'}).center(320,50)

	//グラデ
	var gradient=draw.gradient('linear', function(stop) {
		stop.at(0,'#FFF')
		stop.at(0.9,'#000')
	}).size(100,100)
	//gradientの方向
	gradient.from(0,0).to(0,1)

	//文字グラデ塗り
	var text7=draw.text('POPSWEB KOUBOU')
	.font({
		family:'Arial'
		,size:60
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})
	text7.attr({fill:gradient}).center(320,50)
	//マスク
	mask_rect.maskWith(text7)

	var txt=draw.text('2 maskマスクcenter()移動').font({leading:0.8}).attr({'fill':'#FFF'})


● 画像の場合(画像の大きさ、文字サイズを変更してみた)

小さな画像は事前にキャッシュしておかなくともマスク出来る場合が多いが、Firefoxで不安定なので、やはり事前にキャッシュして於く方が良い。大きな画像の場合は「完全読み込み済み」の事。


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-4c').size(640,100)

	//黒背景
	var back_rect=draw.rect(640,100).attr({'fill':'#000'})

	//壁紙70x70
	var image=draw.image('/main/images/wall.gif').size(35,35)
	//マスク本体画像塗り
	var mask_image=draw.rect(640,100).attr({'fill':image})

	//グラデ
	var gradient=draw.gradient('linear', function(stop) {
		stop.at(0,'#FFF')
		stop.at(0.9,'#000')
	}).size(100,100)
	//gradientの方向
	gradient.from(0,0).to(0,1)

	//文字グラデ塗り
	var text8=draw.text('POPSWEB KOUBOU')
	.font({
		family:'Arial'
		,size:100
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})
	text8.attr({fill:gradient}).center(320,50)
	//マスク
	mask_image.maskWith(text8)

	var txt=draw.text('2B maskマスク 画像の場合').font({size:10,leading:0.8}).attr({'fill':'#FFF'})


3 タイガーマスク

説明は不要であろう。タイガージャーをclipマスクしたので「タイガーマスク」だ、象印だったらどうしよう。

通常マスクでは陰影部分もマスクされてカットされますので、陰影が必要な場合はグループ化すれば良い。


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-4d').size(640,100)

	//タイガーボード
	var back_bord=draw.image('/main/images/tigerbrand.jpg')
	//colorize
	back_bord.filter(function(add) {
	add.colorMatrix('matrix',[1.0,0,0,0,0
		, 0,0.5,0,0,0
		, 0,0,0.2,0,0
		, 0,0,0,1.0,0])
	})
	var back=draw.rect(640,100).attr({'fill':back_bord})

	//TEXT
	var tiger_text=draw.text('TigerBord')
	.font({
		family:'Arial'
		,size:150
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})
	tiger_text.attr({fill:'#FFD700'}).center(320,50).rotate(15)

	//画像を表示/100x100
	var tiger_image=draw.image('/main/images/tiger.jpg').size(100,100).center(320,50)
	var mask_circle=draw.circle(100).attr({'fill':'#F00'}).center(320,50)

	//clipタイガーマスク
	tiger_image.clipWith(mask_circle)

	var txt=draw.text('3 タイガーマスク').font({leading:0.8})


背景はタイガーボードで有る。ちなみに「吉野石膏」創業地は同じ市内、吉野地区にある。「吉野商店」の名前の由来である。


4 clipマスクの画像更新

陰影処理のためグループ化している。image.load()が便利です。


サンプルJS


	//clipマスクの画像更新
	//エレメントID
	var draw=SVG('svgtext-4e').size(640,100)

	var mask_group2=draw.group()
	//画像を表示/1000x100
	var mask_image2=mask_group2.image('/main/images/line-grad2.jpg').size(1000,100)
	//グループ化
	//文字
	var text9=mask_group2.text('POPSWEB KOUBOU')
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//center()移動
	text9.attr({fill:'#000'}).center(320,50)
	//clipマスク
	mask_image2.clipWith(text9)

	//dropShadow
	mask_group2.attr({'filter':'url(#dropShadow)'})

	//ボタン5
	var test_btn5=draw.circle(10).attr({'fill':'#FF0000','stroke':'#FFF','stroke-width':2}).center(620,10)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	test_btn5.click(function(){
		//画像塗り更新/1000x100
		mask_image2.load('/main/images/line-grad4.jpg')
	})

	var txt=draw.text('4 画像塗りの更新、ボタンを押してください(1回限り)').font({leading:0.8})


5 clipマスクのマスクにアクセス

clipマスク処理後、マスク対象にも簡単にアクセスできます。中のTEXTを拡大縮小させます。


サンプルJS


	//clipマスクのマスク材にアクセス
	//エレメントID
	var draw=SVG('svgtext-4f').size(640,100)

	var mask_group3=draw.group()
	//画像を表示/1000x100
	var mask_image3=mask_group3.image('/main/images/line-grad4.jpg').size(1000,100)
	//グループ化
	//文字
	var clip_text=mask_group3.text('POPSWEB KOUBOU')
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})

	//center()移動
	clip_text.attr({fill:'#000'}).center(320,50)
	//clipマスク
	mask_image3.clipWith(clip_text)

	//dropShadow
	mask_group3.attr({'filter':'url(#dropShadow)'})

	//ボタン6
	var test_btn6=draw.circle(10).attr({'fill':'#FF0000','stroke':'#FFF','stroke-width':2}).center(620,10)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	test_btn6.click(function(){
		//animate
		clip_text.animate(2000).scale(1.5,1.5).after(function(){
			this.animate(1000).scale(1,1)
		})
	})

	var txt=draw.text('5 TEXT拡大縮小、ボタンを押してください').font({leading:0.8})


6 複数のマスク材はadd()で処理

複数のマスク材はadd()で処理する。RECT、TEXTはマスク材としては余り芳しくない。ほとんどパスを想定した処理が主であるから出来ることが限定される。重なりはadd順。


サンプルJS


	//clipマスクのマスク材にアクセス2
	//エレメントID
	var draw=SVG('svgtext-4g').size(640,100)

	var rect=draw.rect(520,60).radius(10).attr({'fill':'#48D1CC'}).center(320,50)

	//画像/1000x100
	var image=draw.image('/main/images/line-grad4.jpg').size(1000,100)
	var line_rect=draw.rect(520,60).radius(10).attr({'fill':'#000','stroke':'#FFF','stroke-width':4}).center(320,50)
	//文字
	var clip_text2=draw.text('TEKITO MASK DAZE')
	.font({
		family:'Arial'
		,size:50
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})
	//center()移動
	clip_text2.attr({fill:'#FFF'}).center(320,50)
	//.attr({'filter':'url(#dropShadow2)'})
	//複数のマスク材
	var mask=draw.mask().add(line_rect).add(clip_text2)
	image.maskWith(mask)

	//ボタン7
	var test_btn7=draw.circle(10).attr({'fill':'#FF0000','stroke':'#FFF','stroke-width':2}).center(620,10)
	.attr({'filter':'url(#dropShadow2)'})//陰影
	.style('cursor','pointer')
	test_btn7.click(function(){
		//animate
		line_rect.animate(2000).attr({'fill':'#FFF'}).after(function(){
			this.animate(2000).attr({'fill':'#000'})
		})
	})

	var txt=draw.text('6 テキトウマスク').font({leading:0.8})



面白い効果があるが、Firefox陰影処理は黒色のため文字が消える
clip_text2.attr({fill:'#FFF'}).center(320,50)
//.attr({'filter':'url(#dropShadow2)'})

テキストパス (TextPath)

テキストパスに沿ってTEXTを描画します(Chromeの描画が汚い)。
tspanで書きますので、意識的にtspanにして.path()メソッドにパスを記述します。それだけです。
パスは自動的にdefsに収容されますので、use()で表示可能です(サンプルではそうはしていない...)。


//TEXT
var text=draw.text(function(add) {
  	add.tspan('文章などの文字列')
})

//テキストパス設定
text.path('M 50,90 A 800,800 0 0,1 580,90')
//装飾
.attr({'fill':'#48D1CC','stroke':'#CCC','stroke-width':1})

● 弧の例


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-5a').size(640,100)

	//赤ガイドライン表示/削除のこと
	var guide_line=draw.path('M 50,90 A 800,800 0 0,1 580,90').attr({'fill':'none','stroke':'#F00','stroke-width':1})

	//TEXT
	var arc_text=draw.text(function(add) {
  		add.tspan('POPS-WEB KOUBOU DAYO')
	})
	.font({
		family:'Arial'
		,size:40
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})
	//テキストパス
	arc_text.path('M 50,90 A 800,800 0 0,1 580,90')
	.attr({'fill':'#48D1CC','stroke':'#CCC','stroke-width':1})
	.attr({'filter':'url(#dropShadow2)'})

	var txt=draw.text('1 テキストパス').font({leading:0.8})


● 円の例

SVGでは半円を2つ描いて円にします。


サンプルJS


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

	//赤ガイドライン表示/削除のこと
	var circle=draw.circle(100).attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	var text=draw.text(function(add) {
  		add.tspan('POPS WEB KOUBOU POPS WEB KOUBOU')
	})
	text.font({'size':15,'family':'Arial'})
	text.path('M 80 80 m 0 -50 a 50 50 0 1 1 -1 0 h 1')

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

	var text=draw.text('2 TextPathに沿って描画').font({size:10,leading:0.8})

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

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

	//赤ガイドライン表示/削除のこと
	var circle=draw.path('M10 80 Q 45 10, 80 80 T 150 80').attr({'fill':'none','stroke':'#F00','stroke-width':1}).center(80,80)

	var text2=draw.text(function(add) {
  		add.tspan('ISONO NAMIHEI UNERIKURUU')
	})
	text2.font({'size':14,'family':'Arial'})
	text2.path('M10 80 Q 45 10, 80 80 T 150 80')

	.attr({'fill':'#000'})
	.attr({'filter':'url(#dropShadow3)'})//陰影

	var text=draw.text('3 TextPathに沿って描画').font({size:10,leading:0.8})


 

Webフォント

GoogleFont等のWebフォントを利用すれば、確実にフォントを指定出来ます。
ブラウザ側が「フォントを利用」出来るまでの処理時間が結構掛かりますので、「svg」動作までに0.5-1秒遅延したほうが良いと思います。特にFirefoxは厳格ですので注意です。


Webフォントは、原則HTMLの中で使用するためのものですから、「svg」で使用するにはコツがいります。1度表示してしまえば以後問題は有りません。特に表示以外の処理に利用する場合は重要です。

SVG.js処理では、.addClass('クラス名') が確実のようです。


1. HTMLで表示する、「svg」で使用するのだから現実的ではないが...
<p class="OpenSans">DUMMY</p>

2. svgで欄外にダミーで表示する、見えませんが文字は何でも良い
var webtxt=draw.text('A').font({family:'Open Sans',size:10,leading:1}).x(-100)
実際処理に時間が掛かるので(100ミリ秒位かかっているようだ)、その後少し間合いをおく

3. 使用するTEXTインスタンスにクラス名を付ける
//文字描画/'Open Sans'
var google_text=draw.text('GoogleFont Open Sans')
.font({
	family:'Open Sans'
	,size:50
	,anchor:'left'
	,leading:1
})
.addClass('OpenSans')//有効

Webフォントのcenter()での位置決定は困難です

WebフォントTEXTの横幅取得が正確でない。
そのために、center()では位置が大幅に狂います。よって目測で大体の位置を決めて、move()で調整処理しています。システムフォントは問題有りません。

話は違いますが、Canvasの描画では問題有りませんので、将来的には是正されると思いますが、...


Webフォント中央に来ない

//文字描画/GauFontMilkChoco
var web_text=draw.text('POPSWEB KOUBOU')...
web_text.center(320,50)

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

目測でテキトウな位置に移動

web_text.attr({fill:'#000'}).move(10,25)

GoogleFont

指定の書式が表示されますので、ページに埋め込むだけで利用できます。

「WebFontは表示OK状態」でなければ「Firefox」は何も表示しない場合が有ります。

okonai

サンプルJS


	//googleフォント
	//エレメントID
	var draw=SVG('svgtext-6a').size(640,100)

	//文字/'Open Sans'
	var google_text=draw.text('GoogleFont Open Sans')
	.font({
		family:'Open Sans'
		,size:50
		,anchor:'left'
		,leading:1
	})
	.addClass('OpenSans')//有効

	//webFontはcenter()移動ダメ幅計算が狂うmove()で行う
	google_text.attr({fill:'#000'}).move(30,20)

	var txt=draw.text('1 webFont [Open Sans]').font({leading:0.8})


GoogleFontの設定例


HTML
<link href='https://fonts.googleapis.com/css?family=Open+Sans:800' rel='stylesheet' type='text/css'>
CSS
.OpenSans{
font-family:'Open Sans';
}

自作のWebFont

これも、「svg」動作までに0.5-1秒遅延したほうが良いと思います。特にFirefoxは注意です。

この例は画像加工を伴いますので、「画像は完全読み込み済み」「WebFontは表示OK状態」でなければ「Firefox」は何も表示しません。他のブラウザは結構問題無く処理する事が多い。


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-6b').size(640,100)

	//var webtxt=draw.text('A').font({family:'GauFontMilkChoco',size:10,leading:1}).x(-100)

	//画像/1000x100
	var image=mask_group3.image('/main/images/line-grad4.jpg').size(1000,100)

	//文字
	var web_text=draw.text('POPSWEB KOUBOU')
	.font({
		family:'Arial'
		,size:50
		,anchor:'left'
		,leading:1
	})
	.addClass('GauFontMilkChoco')//有効

	//webFontはcenter()移動ダメ幅計算が狂うmove()で行う
	web_text.attr({fill:image}).move(10,25)

	var txt=draw.text('2 webFont [GauFontMilkChoco]').font({leading:0.8})


当方のWebフォントの設定例、(フォント制作元の許可をえて、Webフォント化処理して使用しています)


CSS
@font-face{ 
font-family:'GauFontMilkChoco';
src:url('/main/asset/GAU_Milk_Choco.woff') format('woff');
}
.GauFontMilkChoco {
font-family:'GauFontMilkChoco';
}
----------------------------------------

TEXTにクラス設定ではこちら優先される
.addClass('GauFontMilkChoco')

カーニングの方法

● 文字間隔を狭める。(2つの方法があります、勿論広げることも出来ます、こちら難しいです)


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-6c').size(640,100)

	//var webtxt=draw.text('A').font({family:'GauFontMilkChoco',size:10,leading:1}).x(-100)

	var strings="POPSWEB KOUBOU"
	var dx_str=""
	//Firefox/三項演算子/文字列生成
	for (var i = 0; i < strings.length; i++)
		dx_str=(i<strings.length-1)?dx_str +='-10,':dx_str +='-10'

	//文字
	var text=draw.text(strings)
	.font({
		family:'GauFontMilkChoco'
		,size:50
		,anchor:'left'
		,leading:1
	})

	//IE middleだめ
	text.attr({dx:dx_str,fill:'#FF1493'}).move(80,25)
	.attr({'filter':'url(#dropShadow2)'})

	var txt=draw.text('3 webFont').font({leading:0.8})


● 文字間隔を狭め、個別に色をつける。tspan処理をすれば下記の様に出来ます。(こちらが簡単に理解し易い)

Chromeでのstroke描画が汚いです。


サンプルJS


	//エレメントID
	var draw=SVG('svgtext-6d').size(640,100)

	var strings="POPSWEB KOUBOU"

	//文字
	var text=draw.text('')
	.font({
		family:'GauFontMilkChoco'
		,size:50
		,anchor:'left'
		,leading:1
	})
	.addClass('GauFontMilkChoco')//有効

	var spikes=strings.length
	text.text(function(add) {
		for (var i=0; i<spikes;i++){
			//虹色hsl直接
			var angle_no=Math.floor(i/spikes*360)//0-360
			var color='hsl(' + angle_no + ',100%,50%)'
			var tx=strings.charAt(i)
			add.tspan(tx).attr({'dx':-10,'fill':color,'stroke':'#FFF','stroke-width':1})
			//.attr({'filter':'url(#dropShadow2)'})
		}
	})

	//IE middleだめ
	text.move(80,25).attr({'filter':'url(#dropShadow2)'})

	var txt=draw.text('4 webFont').font({leading:0.8})


zuzudaze

個別にはFirefox機能せず、他に方法があるか不明
add.tspan(tx).attr({'dx':-10,'fill':color,'stroke':'#FFF','stroke-width':1})
.attr({'filter':'url(#dropShadow2)'}

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

全体ならFirefoxもOK
add.tspan(tx).attr({'dx':-10,'fill':color,'stroke':'#FFF','stroke-width':1})
this.attr({'filter':'url(#dropShadow2)'}

但し下記と同等である
text.attr({'filter':'url(#dropShadow2)'}

 


 

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

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

【参照】当方の記事: SVG.js 図形とパスの描画

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

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

 

【参考】mksaver70.blog.jpの記事: JavaScriptでランダムな#RRGGBBカラーを表示・出力させる


コツさえ掴めば結構簡単だが、しごく面倒である。以上。

 


[ この記事のURL ]


タグ:javascript , SVG

 

ブログ記事一覧



[1]