POPSブログ

SVG.js を使用してsvgコンテンツを作り表示します

375

  Category:  javascript2016/01/26 pops 

SVG.js を使用してみましたが、使用法の解説サンプルなども現在皆無に近く、全て手探りで使用法、問題点などを洗い出してみます。SVG.jsに興味を持ち何も知らない者が「SVG」を触るのですから大変無謀なことです。

 

SVG.js を使用してsvgコンテンツを作り表示するテスト


SVGを利用すればHTMLでベクターのパスが利用できますので、SVG.js を使用してみたいと思います。


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


下図、は本文とは直接関係有りません。CSSで図形フォントの表現には現在限りがありますが、「SVG」を利用すればデザイン表現の幅が広がります。単にそれだけの理由です。

zu

 

手抜き目次


SVG.js 使用の基本的な説明
1. SVG.js構築の注意点 SAMPLEとデモのJSについて
2. 描画処理を行う基本
3. 画像表示と画像塗り
4. DropShadowとBlur
5. Groupについて ページ容量の都合で詳細は次ページで説明
6. ドラッグ
7. その他の「デモ」など

 

DEMO その他の「デモ」など

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


Chromeでの閲覧を推奨します


DEMO、ページ容量の問題で、このページに収容できない「デモ」です。

DEMO-036




 

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


下記のJSおよびプラグインが必要になります。

SVG.js 配布サイト svgjs.com Downloadsよりsvg.js 1.0.1、svg.min.js 1.0.1が取得できます。

filterプラグイン svg.filter.jsフィルター処理用のJSです。

draggableプラグイン svg.draggable.jsドラッグ用のJSです。

ドキュメント 英字ドキュメント英字のマニュアル説明です。


filterプラグインは2年前のもので、DropShadow処理でエラーがでるので、DropShadowのみカスタムのJSを作り別の方法で対処します。Blur処理などで一応必要になります。
svg.jsは意外と頻繁に更新されていますが、古いバージョンの取得はできませんので、時間経過と共に記事の内容と異なる事が発生するかも知れません。マニュアル記載の例文が多いので結構助かります。(英文は判りませんが適当に解釈しまして...)
このページでは、version 2.2.5、BUILT:Mon Jan 11現在のsvg.jsを使用しています。


SVG.js構築の注意点


SVG.jsには多くのメソッドが有り、色々な構造に作ることが可能になっていますが、
SVG.jsのネット上の資料などは非常に少なく、配布サイトのサンプルも表示作動しないものが多いのでコードを確認すらできない(この辺理解し難い、SVG界は「勝手にどうぞ」の世界のようです)。
つまり、当方の独自解釈などで構築している面が多い事を念頭に読んでください。

SVG.jsは多機能ですから結構評価は高いようですが、「苦悶式」です。使用例がほとんど見つからないフシギなJS。
尚、SVG.jsコードの記述部分には「 ; 」を使用しませんので注意ください。

 

SAMPLEとデモのJSについて

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


私の習性として「角丸陰影」はこだわりの絶対条件、且つ、陰影をつけると「ブラウザ」の問題点が出やすいので随所に利用します。問題があれば「ゴマカシ」で乗り切っていますので、ご理解ください。


基本的なSAMPLE

基本的なSAMPLEと共に、JSを掲示しますので感覚的にとらえてください。ページの制約上、他にデモページにも別途有ります。振る舞いなどは今日時点の現象で、時間経過ブラウザバージョンにより違いが出るかも知れません。


SAMPLE、sample-1a, sample-1b, sample-1c

 

サンプルJS


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

	var rect=draw.rect(100,100).attr({'fill':'#FFD700'}).center(80,80)

	var text=draw.text('1 rect表示').font({leading:0.8})

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

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

	//1
	var rect=draw.rect(100,100).attr({'fill':'#FFD700','stroke':'#FFF','stroke-width':2}).center(80,80)
	//オリジナルdropShadow
	.attr({'filter':'url(#dropShadow2)'})
	//2
	var rect=draw.rect(80,80).attr({'fill':'#DAA520'}).center(80,80)
	//3
	var rect=draw.rect(60,60).attr({'fill':'#B8860B'}).center(80,80)

	var text=draw.text('2 rect表示陰影処理').font({leading:0.8})

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

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

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

	var text=draw.text('3 画像表示と回転').font({leading:0.8})


画像は別物です

3 画像表示と回転に注目ください。他のrectなどのgraphic要素は意図的に cx cy で回転軸を中央に設定していますが、
「画像」は最初から画像の回転軸が中央に有ります。

画像はrectなどのgraphic要素とは別物として扱う事が大事なようです。


対象HTML要素とCSS

中身の空のHTML要素を用意します。は生成された「SVG」の中に描画されますので通常「はみ出し」はないのですが、IEで「はみ出す」から、CSSは overflow:hidden; を設定します。


対象HTML要素
<div id="sample-1a" class="graphic-elm"></div>

CSS
.graphic-elm{
width:160px;
height:160px;
margin:0;
padding:0;
border:#000000 1px solid;
overflow:hidden;
}

描画処理を行う基本

「ID」を指定して、draw.rect()を実行すると四角形が描画されます。

SVG.jsの処理部分では「 ; 」を使用しないで、記述しますので注意が必要です。
また私の場合 .attr({'fill':'#FFD700'}) と記述しています。色「#FFD700」は、SVG.jsで「#ffd700」と変換されます。


テキトウな名前のオブジェクトのようなものを生成します。ステージ的な意味合いです。このメソッドを実行すると「埋め込み対象のID」に「svg」が生成されます。よってブラウザが実行表示します。
「svg」はブラウザのデベロッパーツールで「埋め込み対象のID」の箇所のエレメントをコピーすれば確認できます。
以後、サンプルでは「draw」とします。


var ステージのオブジェクト=SVG('埋め込み対象のID').size(生成するsvgの大きさ)


var draw=SVG('sample-1a').size(160,160)
var rect=draw.rect(100,100).attr({'fill':'#FFD700'}).center(80,80)

同じ
var rect=draw.rect(100,100).attr({fill:'#FFD700'}).center(80,80)

該当DIVには下記の様にSVGが生成されます。defsは必要なくとも自動で付属します。
主に path filter が収容されます。


<svg id="SvgjsSvg1000" 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="SvgjsDefs1001"></defs>
<rect id="SvgjsRect1007" width="100" height="100" fill="#ffd700" x="30" y="30"></rect>
</svg>

● ここでの「draw」はステージ名などと同様で、名称は何でも構いません。
(例、draw paper canvas stage drawbox goromaru ....)
その後に処理は rect() 等と、メソッドの形態で記載するのがSVG.js通常の書き方です。


対象IDに生成する、svgの大きさを指定して
var draw=SVG('sample-1a').size(160,160)

名称は自由
var canvas=SVG('sample-1a').size(160,160)

rectを描画する
var rect=draw.rect(100,100).attr({'fill':'#FFD700'}).center(80,80)

インスタンス名(オブジェクト)なども自由ですし、書き方も色々あります
var rect=draw.rect(100,100).fill({'#FFD700'}).move(30,30).cx(50).cy(50)
名前は何でも良い、cx() cy()を決めないと回転軸は左上ですから注意
var sikaku=draw.rect(100,100).fill({'#FFD700'}).move(30,30)

● .center()は、表示位置と回転位置の指定を一括で出来る便利な機能です。(但し画像の場合は少し違います)


左上位置を指定してから、回転位置を決める
.move(30,30).cx(50).cy(50)
同じです
.x(30).y(30).cx(50).cy(50)

これを1回で決めるのが
.center(80,80)

fillとstrokeと着色

fillは図形(パスで閉ざされた内側)を指定色などで染めます。strokeは外側のアウトラインで幅などを指定できますが、CSSと違ってstrokeの中心がfillの外形線に成ります(Canvasと同じ)。
つまり、陰影など処理する場合は上下左右にそれなりの余裕が無ければ、途切れてしまいます。


指定色などで染めますが、指定できる形式は多彩です。事前に gradient、pattern のデータを用意すれば Gradient、Pattern 塗りが可能であり、画像でも染めることが可能です。

SAMPLE、sample-1d, sample-1e, sample-1f

 

サンプルJS



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

	//fill-stroke
	var rect=draw.rect(100,100).radius(10).attr({'fill':'#FFD700','stroke':'#FFF','stroke-width':6}).center(80,80)
	//オリジナルdropShadow
	.attr({'filter':'url(#dropShadow2)'})
	//説明用ライン破線
	var outline=draw.rect(100,100).radius(10).attr({'fill':'none','stroke':'#F00','stroke-width':1,'stroke-dasharray':3}).center(80,80)

	var text=draw.text('4 stroke説明').font({leading:0.8})

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

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

	//fill-stroke
	var rect=draw.rect(100,100).radius(10).attr({'fill':'rgba(0,0,0,0.2)','stroke':'red','stroke-width':2}).center(80,80)
	//オリジナルdropShadow
	.attr({'filter':'url(#dropShadow)'})

	var text=draw.text('5 fill stroke説明').font({leading:0.8})

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

	//stroke画像塗り
	//対象エレメントID
	var draw=SVG('sample-1f').size(160,160)

	var backrect=draw.rect(150,150).attr({'fill':'#EEEEEE'}).center(80,80)
	//オリジナルdropShadow
	.attr({'filter':'url(#dropShadow)'})

	//image 200x200
	var image=draw.image('/main/images/grad_200.jpg').size(200,200)

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

	//rect
	var rect=draw.rect(100,100).attr({
		'fill':gradient
		,'stroke':image
		,'stroke-width':4
	})
	.radius(10)
	.center(80,80)
	//オリジナルdropShadow2
	rect.attr({'filter':'url(#dropShadow2)'})

	var text=draw.text('5 stroke画像塗りとグラデ').font({leading:0.8})



色々指定出来ます
var rect=draw.rect(100,100).attr({'fill':'#ffd700'})
var rect=draw.rect(100,100).attr({'fill':'#fff'})
var rect=draw.rect(100,100).attr({'fill':'red'})
var rect=draw.rect(100,100).attr({'fill':'rgb(0,0,0)'})
var rect=draw.rect(100,100).attr({'fill':'rgba(0,0,0,0.5)'})
var rect=draw.rect(100,100).attr({'fill':'hsl(0.5,100%,50%)'})
var rect=draw.rect(100,100).attr({'fill':image})
var rect=draw.rect(100,100).attr({'fill':gradient})
var rect=draw.rect(100,100).attr({'fill':pattern})

塗らないはfillのみ、strokeは記述しなければよい
var rect=draw.rect(100,100).attr({'fill':'none'})

注意、現在、strokeにpatternは有りません

描画順と重なり

描画命令順に上に重なりますが、z-indexの仕組みを持ちませんので、重なり順序を変えるのは困難です。
カンバス(canvas)同じで、同じ変数で重ねていけますが、「SVG」ではChild要素として区別、あとで指定して変更など行える違いは有ります。


3段重ねになる、勿論、その都度名前を変えても結構ですが
var rect=draw.rect(100,100).attr({'fill':'#FFD700','stroke':'#FFF','stroke-width':2}).center(80,80)
var rect=draw.rect(80,80).attr({'fill':'#DAA520'}).center(80,80)
var rect=draw.rect(60,60).attr({'fill':'#B8860B'}).center(80,80)

attrの書き方は次の様に見やすくなるように書くのが推奨されています。

特に注意が必要なのは「stroke-width」などの場合、「strokeWidth」とは書きません。文字型で指定ください。


var rect=draw.rect(100,100).attr({
  fill:'#FFD700'
 ,stroke:'#FFF'
 ,'stroke-width':2
})
.center(80,80)

fillを描かない場合は none です。strokeを描かない場合は stroke を設定しない。


var rect=draw.rect(100,100).attr({
  fill:'none'
 ,stroke:'#FFF'
 ,'stroke-width':2
})
.center(80,80)

attr()については、それぞれのブラウザの実装状態により異なりますが、あらかた機能すると思います。
詳細は「SVG」を手書きで実装に関する記事などを参照ください。fill stroke 以外でも同様です。


標準的なgraphicの描画

角形、円形、多角形など標準で簡単に描画できます。

SAMPLE、sample-2a, sample-2b, sample-2c

 

サンプルJS


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

	//roundrect
	var roundrect=draw.rect(100,100).attr({
		'fill':'#FFD700'
		,'stroke':'#FFF'
		,'stroke-width':4
	})
	.radius(20)
	.center(80,80)
	//オリジナルdropShadow
	.attr({'filter':'url(#dropShadow)'})

	var text=draw.text('1 角丸四角形').font({leading:0.8})

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

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

	//circle
	var circle=draw.circle(100).attr({
		'fill':'#FFD700'
		,'stroke':'#FFF'
		,'stroke-width':4
	})
	.center(80,80)
	//オリジナルdropShadow
	.attr({'filter':'url(#dropShadow)'})

	var text=draw.text('2 円形').font({leading:0.8})

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

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

	//ellipse
	var ellipse=draw.ellipse(120,80).attr({
		'fill':'#FFD700'
		,'stroke':'#FFF'
		,'stroke-width':4
	})
	.center(80,80)
	//オリジナルdropShadow
	.attr({'filter':'url(#dropShadow)'})

	var text=draw.text('2 楕円形').font({leading:0.8})


下記はドキュメント記載のものを表示しています。Circle Ellipseも.radius()で描画できますが半径設定になります。
ここにないものは、path()を利用して自作することになります。Polyline Polygonは主にグラフ描画に用いると便利なようです。


Rect
var rect=draw.rect(100,100)

RoundRect
rect.radius(10)
rect.radius(10,20)

Circle
var circle=draw.circle(100)
rect.radius(75)

Ellipse
var ellipse=draw.ellipse(200,100)
rect.radius(75,50)

Line
var line=draw.line(0,0,100,150).stroke({width:1})

Polyline
//polyline('x,y x,y x,y')
var polyline=draw.polyline('0,0 100,50 50,100').fill('none').stroke({width:1})

Polygon
//polygon('x,y x,y x,y')
var polygon=draw.polygon('0,0 100,50 50,100').fill('none').stroke({width:1})

属性スタイルの指定(シンタックスシュガー)

rect等の図形描画の設定形式です。attr()を使うかは使用者の好みですが、私の場合はほとんどattr()を使用しています。

fill stroke で画像も塗れるが注意が必要です。これは問題があるので「別途に説明」します。


下記はドキュメント記載のものを表示しています。極標準的な機能で有りますので、これ以外の設定はattr()で行う事になります。(attr()のpropertyはSVG規格に順次ます)

下記はSVG.js独自の書式ですから、fill、strokeは、attr()表記に出来るものも有ります。書き方は個人的な好みです。


fill
rect.fill({ color: '#f06', opacity: 0.6 })
attr()表記なら
rect.attr({fill:'#f06','fill-opacity':0.6})

画像も塗れるが注意が必要です
rect.fill('images/shade.jpg')
rect.fill(draw.image('images/shade.jpg', 20, 20))

stroke
rect.stroke({ color: '#f06', opacity: 0.6, width: 5 })
attr()表記なら
rect.attr({stroke:'#f06','stroke-opacity':0.6,'stroke-width':5})

画像も塗れるが注意が必要です
rect.stroke('images/shade.jpg')

opacity
rect.opacity(0.5)

rotate
rect.rotate(45)
回転の中心 cx cy も設定する場合
rect.rotate(45, 50, 50)

skew
rect.skew(0, 45)

scale
rect.scale(0.5, -1)
rect.translate(0.5, -1)

radius
rect.radius(10)
rect.radius(10, 20)

ドキュメント記載以外のpropertyを使用の場合はブラウザ毎の確認が必要になります。
ブラウザによっては実装されていない場合も有ります。


strokeが半透明の破線になる

var rect=draw.rect(100,100).attr({
  fill:'#FFD700'
 ,stroke:'#FFF'
 ,'stroke-width':2
 ,'stroke-opacity':0.5
 ,'stroke-dasharray':4
})
.center(80,80)

SVG documentより抜粋、ドキュメントの最後、Contributing に次の記載があります。
変数はともかく、ループ処理は大変になりますので、エラーにならず確実に実行するように「各自工夫」して下さい。

【参照】documentup.comドキュメント: SVG.jsドキュメントContributing

その他はドキュメントを参照ください。(結構大変です、とても守れません)


要素の操作

rectなどの要素を画面に配置する場合に、数多くの命令(メソッド)が用意されていますし、また記述方法も数多くありますので、個人的に統一して使用したほうが良いと思います。
特にcenter()は便利な機能です。特に多用するものだけいくつか挙げてみますが、詳細はドキュメントの「Manipulating elements」を参照ください。

● attr()

私の場合、x y 値などは別途 x() y() などを使用するようにしています。あくまでも fill stroke 等の記載に使用しています。
attr()の中では fill-opacity stroke-opacity と個別に透明度を設定できます。fill-opacityの様に間に-が入るものは
「SVG」の書式どおり、文字形 'fill-opacity' で記載します。fillOpacityとは書きません、これは無効。


シングル設定
rect.attr('x',50)
同じです
rect.attr({'x':50})

複数項目の設定
rect.attr({
  fill:'#f06'
 ,'fill-opacity':0.3
 ,stroke:'#000'
 ,'stroke-opacity':0.8
 ,'stroke-width':10
})

● x() y() move()


要素の左上の位置 x y 値です
rect.x(10).y(20)

まとめて書けば
rect.move(10,20)

● cx() cy()

回転軸の位置です。rectなどgraphic要素は通常左上ですが、これを任意の位置に移動します。graphicの中央にすることが多いと思います。
但し、この場合にはgraphic要素の大きさを事前に知っている必要が有ります。


rect(100,100)
rect.cx(50).cy(50)

● center()

move() cx() cy() を一括にしたメソッドで大変便利です。「graphic要素の大きさを調べなくとも」自動的に計算して指定位置を「graphicの中央」にして配置してくれます。


親である、draw 160x160の大きさとすれば
rect.center(80,80)

これを別に書けば、draw 160x160、 rect 100x100 と仮定すれば
rect.move(30,30).cx(50).cy(50)

● rotate()

center()、(cx cy)を指定している場合と、指定していない場合の2通りの設定が有ります。上手く使い別けます。

center()が便利なので設定の場合が多いから、回転はrotate()の角度だけ変更が多いと思う。


回転値だけ、デグリー値です
rect.rotate(30)

回転値と cx cy の指定
rect.rotate(30,50,50)

● transform()

transform()は、主に、group()設定なされたelement等に対するメソッドですので、rectなど「graphic要素」に実行しますと事前の設定が解除されたり、また位置が変更されstrokeが切れたりの弊害が発生します。
複数同時設定はできないようです、シングル表記の羅列となります。ここでの詳細は省略します。


//グループを動かす
group.transform({cx:50,cy:50}).transform({x:30,y:30}).transform({rotation:30})

● size

生成する大きさ width height を設定します。attr()でもできますが、勤めてこちらを使用する場合が多い。


draw.size(160,160)
image.size(100,100)

● style()

CSSでの設定が必要な場合です。必ずCSSが機能するとは限りませんのでブラウザ毎の確認が必要です。
下記はドラッグなどで、cursor の変更が必要な場合の例です。
ちなみに、hide() show() はstyleでdisplayの表示非表示を操作しているだけです。


rect.style('cursor','pointer')
rect.style({cursor:'pointer',fill:'#f03'})

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

rect.style('display','none')
は rect.hide() と同等です

● addClass()

Class名の追加などの必要な場合ですが、SVG.jsでは生成されたエレメント(タグなど)に「固有のID」が付けられますので、jQuery操作が必要な場合はClass名でアクセスします。(SVG.jsでは少しコードの変更があれば「固有のID」も簡単に変更になりますのでIDでのアクセスは得策では有りません)


必要ならクラスを付けられます
rect.addClass('pink-flower')

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

クラスを付ける
var draw=SVG('drawing')
var rect=draw.rect(100,100).addClass('my-element')
jQueryでクラスにアクセス
$('#drawing .my-element')....

画像表示と画像塗り

画像表示する場合です(画像塗りでは有りません)。次の様にすれば表示します。

画像の場合は他のrectなどと違い、画像を<image>でロードして、大きさを設定した時点で自動的に cx() cy() が画像中心に決められますのでmove()で位置を決めてやればよい訳です。


DIVの大きさが160x160だからこれで中央に回転軸の中心がセットされる
var image=draw.image('/main/images/testImage108.jpg').size(100,100).move(30,30)

これは間違い、右下にずれ込む
var image=draw.image('/main/images/testImage108.jpg').size(100,100).center(80,80)

上記コードは画像の加工が無いため、読み込み次第表示されます。


fill stroke の画像塗り

fill、stroke、の「画像塗り」が出来ることは「大変に便利」ですが注意が必要になります。
塗る際には、画像が「完全読み込み」の状態でなければ上手く処理してはくれません。特にFirefoxでは厳密ですからマスクの際であっても注意ください。
画像は<image>で読み込まれますから、画像そのものではなく必要なのは「画像URL」です。画像を表示するだけならば問題は少ない。


1. 原則、画像塗りの場合は「完全読み込み」の状態でなければ成らない。
(同じドメインで小さな画像なっらChromeは表示しますが、Firefoxはだめ)
2. 画像ローダーまたは事前に new Image() で画像をキャッシュしておき、画像塗りを実行するのが確実です。
3. 画像をマスクする場合も、Firefoxは「完全読み込み」の状態でなければマスクしてくれない。
4. 画像の大きさを設定しないと処理出来ない場合が大半ですから、大きさを設定しましょう。


画像ローダーが確実ではあるが、new Image() で画像を簡単にキャッシュ処理して、少々遅延してJSを実行すれば、ほぼ処理します。(当然確認は必要です、キャッシュのオブジェクトを直接利用はしません、ブラウザに事前にキャッシュさせるだけ)
JSのメインSVG.js処理に行く前に、簡単にキャッシュする。setTimeoutの時間を調整します。


    //画像キャッシュ
    var image1=new Image()
    image1.src="/main/images/line-grad.jpg"
    var image2=new Image()
    image2.src="/main/images/line-grad2.jpg"
    var image3=new Image()
    image3.src="/main/images/line-grad3.jpg"

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

画像塗りの実際

次に処理の実際を掲示します。、回転させても塗り位置が動いていないのを確認できます。

SAMPLE、sample-3a, sample-3b, sample-3c

 

サンプルJS


	//画像塗り
	//対象エレメントID
	var draw=SVG('sample-3a').size(160,160)

	//image 100x100
	var image=draw.image('/main/images/testImage108.jpg').size(160,160).center(80,80).scale(100/160)
	//rect
	var rect=draw.rect(100,100).attr({'fill':image}).radius(10).center(80,80).rotate(30)
	//オリジナルdropShadow2
	rect.attr({'filter':'url(#dropShadow2)'})

	var text=draw.text('1 画像塗りdropShadow2').font({leading:0.8})

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

	//画像塗り失敗
	//対象エレメントID
	var draw=SVG('sample-3b').size(160,160)

	//image 100x100
	var image=draw.image('/main/images/testImage108.jpg').size(100,100)
	//rect
	var rect=draw.rect(100,100).attr({'fill':image}).radius(10).center(80,80)//.rotate(30)
	//オリジナルdropShadow2
	rect.attr({'filter':'url(#dropShadow2)'})
	//drag
	rect.draggable()

	var text=draw.text('2 画像塗り失敗例 drag').font({leading:0.8})

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

	//stroke画像塗り
	//対象エレメントID
	var draw=SVG('sample-3c').size(160,160)

	//image 200x200
	var image=draw.image('/main/images/grad_200.jpg').size(200,200)
	//rect
	var rect=draw.rect(100,100).attr({
		'fill':'#FFEFD5'
		,'stroke':image
		,'stroke-width':4
	})
	.radius(10)
	.center(80,80).rotate(30)
	//オリジナルdropShadow2
	rect.attr({'filter':'url(#dropShadow2)'})

	var text=draw.text('3 stroke画像塗り 無修正').font({leading:0.8})


イワユル、ゴマカシ手法で有ります。画像の中心合わせとgraphicの中心あわせの手法が違うため単に fill:image では上手く塗りが実行されません。下記が修正方法です。
画像は「完全読み込み」の状態であることが処理の条件です。一番の利点はマスクなどの必要は無く graphic1層で移動アニメなど出来ることです。


1. 塗りの対象であるrect(graphic)は「svg」の中央にあると仮定します。
2. 画像は通常、画像の有る場所の「svg」にリピートされた状態で取り込まれますので、位置あわせの調整が必要。
3. 画像の大きさを「svg」の大きさに拡大しますと「svg」の中心に画像中心が移ります。次にgraphicの大きさに合うように縮小すると合わせる事ができます。
4. 画像にもcenter()設定するのは自由に移動させるためです。
5. 1度塗りで収まった画像は回転してもgraphicを移動しても塗り位置は固定されたままです。
6. 画像(模様壁紙など)によってはリピートした方が良い場合も有ります。


2 画像塗り失敗例にドラッグを設定していますので、画像がリピートされているのが確認できます。画像の作りによってはこのような状態でもそれなりの効果を出せる場合もあります。

 

画像塗りの実際2

画像の縦横比率の違う場合と壁紙。(赤線は説明用の線です)

1). 横長画像の場合、塗りもOKです。(赤線は説明用の線です)
2). 縦長画像の場合、塗りもOKです。
3). シームレス壁紙の場合は中央を気にせずとも良い。塗りは画像がリピートする。


SAMPLE、sample-3d, sample-3e, sample-3f

 

サンプルJS


	//横長画像
	//対象エレメントID
	var draw=SVG('sample-3d').size(160,160)

	//image 260x150/ゴマカシcenter()処理
	var image=draw.image('/main/images/pops_lady.jpg').size(160,92).center(80,80).scale(130/160)

	//rect暫定表示
	var rect=draw.rect(130,75).attr({'fill':'none','stroke':'#F00','stroke-width':1,'stroke-dasharray':4}).center(80,80)

	var text=draw.text('4 横長画像center処理').font({leading:0.8})

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

	//縦長画像
	//対象エレメントID
	var draw=SVG('sample-3e').size(160,160)

	//image 100x120/ゴマカシcenter()処理
	var image=draw.image('/main/images/toyota05s.jpg').size(133,160).center(80,80).scale(100/160)

	//rect暫定表示
	var rect=draw.rect(100,120).attr({'fill':'none','stroke':'#F00','stroke-width':1,'stroke-dasharray':4}).center(80,80)

	var text=draw.text('5 縦長画像center処理').font({leading:0.8})

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

	//シームレス壁紙
	//対象エレメントID
	var draw=SVG('sample-3f').size(160,160)
	
	//image 255x255
	var image=draw.image('/main/images/patn-img03.png').size(50,50)

	//rect壁紙ぬり
	var rect=draw.rect(100,100).radius(10).attr({'fill':image,'stroke':'#FFF','stroke-width':2}).center(80,80).rotate(30)
	.attr({'filter':'url(#dropShadow2)'})

	var text=draw.text('6 壁紙を縮小して塗り').font({leading:0.8})


画像塗りの実際3

画像塗りはリピートするので、基本的には四方連続、シームレスな壁紙の使用の用途です。
1). スケール変更の画像塗り以外にtranslateを使用して固定できるが、stroke、dropShadowが切れる。(但し、角形のみで角丸などには出来ない、その後の移動もtranslateでなければならない)
2).3). は壁紙をそのまま塗りこんだもので、ドラッグすれば状況がわかる。画像塗りはまだ規定が策定出来ていないものと思う。

SAMPLE、sample-3g, sample-3h, sample-3i

 

サンプルJS


	//画像translate塗り/stroke角丸NG
	//対象エレメントID
	var draw=SVG('sample-3g').size(160,160)
	
	//image 100x100
	var image=draw.image('/main/images/testImage108.jpg').size(100,100)

	//rect画像塗り
	var rect=draw.rect(100,100).attr({'fill':image})
	rect.translate(30,30).rotate(30,50,50)
	.attr({'filter':'url(#dropShadow)'})

	var text=draw.text('7 画像translate塗りNG').font({leading:0.8})

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

	//連続壁紙
	//対象エレメントID
	var draw=SVG('sample-3h').size(160,160)
	
	//image 93x78
	var image=draw.image('/main/images/h4gr02.gif').size(93,78)

	//rect画像塗り
	var rect=draw.rect(100,100).radius(10).attr({'fill':image,'stroke':'#FFF','stroke-width':2}).center(80,80).rotate(30)
	.attr({'filter':'url(#dropShadow2)'})

	var text=draw.text('8 壁紙塗り').font({leading:0.8})

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

	//連続壁紙
	//対象エレメントID
	var draw=SVG('sample-3i').size(160,160)
	
	//wall.gif 70x70
	var image=draw.image('/main/images/wall.gif').size(70,70)

	//rect画像塗り
	var rect=draw.rect(100,100).radius(10).attr({'fill':image,'stroke':'#FFF','stroke-width':2}).center(80,80).rotate(30)
	.attr({'filter':'url(#dropShadow2)'})
	.draggable()

	var text=draw.text('9 壁紙塗り drag').font({leading:0.8})


DropShadowとBlur

DropShadowが問題です。SVG.jsのプラグイン svg.filter.jsにDropShadowがあるのですがエラーで機能しません。
よって自作のDropShadowを使用します。ページ容量の事情で、詳細は「前ページ」の記事を参照ください。

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

 

dropshadow-custom.jsの使用例

● 私なりに調整した3種類を使用していますが、違うdropShadowを登録して使用するなどは自由です。

1.#dropShadow、一般的なdropShadowであるが余りずらしてはいない。
2.#dropShadow2、周囲にdropShadowが掛かる。
3.#dropShadow3、文字用途にズレを調整したもの。
このページは、jQuery-1.6.4のためdropshadow-custom-ie.jsを読み込んでいます。

DropShadow SAMPLE、sample-4a, sample-4b, sample-4c

 

サンプルJS


	//画像塗りオリジナルdropShadow
	//対象エレメントID
	var draw=SVG('sample-4a').size(160,160)

	//image 100x100
	var image=draw.image('/main/images/testImage108.jpg').size(160,160).center(80,80).scale(100/160)
	//rect
	var rect=draw.rect(100,100).attr({
		'fill':image
		,'stroke':'#FFF'
		,'stroke-width':2
	})
	.radius(10).center(80,80).rotate(30)
	//オリジナルdropShadow
	.attr({'filter':'url(#dropShadow)'})

	var text=draw.text('1 dropShadow').font({leading:0.8})

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

	//画像塗り
	//対象エレメントID
	var draw=SVG('sample-4b').size(160,160)

	//image 100x100
	var image=draw.image('/main/images/slice_img07b.jpg').size(160,160).center(80,80).scale(100/160)
	//rect
	var rect=draw.rect(100,100).attr({
		'fill':image
	})
	.radius(10)
	.center(80,80).rotate(30)
	//オリジナルdropShadow
	rect.attr({'filter':'url(#dropShadow2)'})

	var outline=draw.rect(100,100).attr({
		'fill':'none'
		,'stroke':'#FFF'
		,'stroke-width':2
	})
	.radius(10)
	.center(80,80).rotate(30)
	//オリジナルdropShadow
	outline.attr({'filter':'url(#dropShadow2)'})

	var text=draw.text('2 dropShadow').font({leading:0.8})

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

	//group画像塗り/drag OK
	//対象エレメントID
	var draw=SVG('sample-4c').size(160,160)

	var group=draw.group()
	group.rect()
	//image 100x100
	var image=group.image('/main/images/testImage108.jpg').size(160,160).center(80,80).scale(100/160)
	//rect
	var rect=group.rect(100,100).attr({
		'fill':image
		,'stroke':'#FFF'
		,'stroke-width':2
	})
	.radius(10)
	.center(80,80)
	//オリジナルdropShadow
	rect.attr({'filter':'url(#dropShadow2)'})

	//フォント文字
	var text=group.text('POPS').attr({'fill':'#FFF'}).center(65,80)
	text.font({
		family:'Arial'
		,size:24
		,'font-weight':'bolder'
		,anchor:'left'
		,leading:1
	})
	//オリジナルdropShadow
	.attr({'filter':'url(#dropShadow3)'})
	//groupdrag
	group.draggable()

	var text=draw.text('3 dropShadow group drag').font({leading:0.8})


● Blurはプラグインで正常に機能しますから、Blurの設定は自由です。また陰影用のインスタンスを下に配置してdropShadowを作る事も可能ですが、場合によっては構造を変えねばならないので、通常の#dropShadowが簡単です。

3番は画像の場合ですが、x y 方向別々の大きさにBlurも可能です。必要であれば範囲を調整します。

Blur SAMPLE、sample-4d, sample-4e, sample-4f

 

サンプルJS


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

	//back
	var rectback=draw.rect(100,100).attr({
		'fill':'#000'
	})
	.radius(10)
	.center(90,90)//ずらす
	//blur
	.filter(function(add) {
  		add.gaussianBlur(2)
	})

	//roundrect2
	var roundrect2=draw.rect(100,100).attr({
		'fill':'#FFD700'
	})
	.radius(10)
	.center(80,80)

	var text=draw.text('4 draw層でblur').font({leading:0.8})

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

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

	//base
	var base_rect=draw.rect(160,160).attr({'fill':'#000'})
	var group=draw.group()
	//back
	var rectback=group.rect(100,100).attr({
		'fill':'#00BFFF'
	})
	.radius(10)
	.center(80,80)
	//オリジナルcustomBlur
	.attr({'filter':'url(#customBlur)'})

	//roundrect2
	var roundrect2=group.rect(98,98).attr({
		'fill':'#9370DB'
	})
	.radius(10)
	.center(80,80)

	var text=draw.text('5 group層でblur').font({leading:0.8}).attr({'fill':'#FFF'})

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

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

	var image=draw.image('/main/images/testImage108.jpg').size(100,100).move(30,30)
	.filter(function(add) {
  		add.gaussianBlur(3)
	})

	var text=draw.text('6 画像Blur表示').font({leading:0.8})


Blurの範囲は初期時は縦横10%です

1番はインスタンスが小さいのでBlurが中途半端です。Blurの範囲は初期時は縦横10%ですから範囲を広げれば直ります。大きいものは範囲が広いので正常にBlur処理なされています。
2番は範囲を広げて修正しています。
3番は透過部分のドラッグはどうなるかのテストです。fill部分 none でないならドラッグ有効ですから、透明にすれば良い。

Blur SAMPLE、sample-4g, sample-4h, sample-4i

 

サンプルJS


	//ループのBlur品質悪し
	//対象エレメントID
	var draw=SVG('sample-4g').size(160,160)

	//test-rect
	var test_back=draw.rect(100,100).attr({'fill':'#000'}).center(80,80)
	.filter(function(add) {
		add.gaussianBlur(3)
	})

	//円周配置の図形
	var rects=[],spikes=8,a=360/spikes,point_x=80,point_y=80,radius_v=50,
	angle12=-90 //12時補正
	//rect配置描画/12時補正
	for (i=0; i < spikes; i++){

		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)

		var back=draw.rect(22,22).attr({'fill':'#000'}).center(x,y).rotate(i*a)
		.filter(function(add) {
			add.gaussianBlur(3)
		})

		//指定色
		var rect=draw.rect(20,20).attr({'fill':'#D2B4BC','stroke':'#FFF','stroke-width':2}).center(x,y).rotate(i*a)

	}

	var text=draw.text('1 Blur品質悪し 悪い見本').font({leading:0.8})

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

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

	//円周配置の図形
	var rects=[],spikes=8,a=360/spikes,point_x=80,point_y=80,radius_v=50,
	angle12=-90 //12時補正
	//rect配置描画/12時補正
	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)

		var back=draw.rect(22,22).attr({'fill':'#000'}).center(x,y).rotate(i*a)
		.filter(function(add) {
			add.gaussianBlur(3)
			this.size('200%','200%').move('-50%','-50%')
		})

		//rect虹色
		var rect=draw.rect(20,20).attr({'fill':color,'stroke':'#FFF','stroke-width':2}).center(x,y).rotate(i*a)

	}

	var text=draw.text('2 Blur品質 補正').font({leading:0.8})

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

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

	var group=draw.group()
	group.rect()//範囲0重要

	//stroke
	var back=group.rect(100,100).attr({'fill':'none','stroke':'#000','stroke-width':2}).center(80,80)
	.filter(function(add) {
		add.gaussianBlur(3)
	})
	//rect-stroke/fill部分noneでないならドラッグ有効
	var rect=group.rect(100,100).attr({'fill':'#ff0','stroke':'#FFF','stroke-width':2,'fill-opacity':0}).center(80,80)
	//var rect=group.rect(100,100).attr({'fill':'rgba(0,0,0,0)','stroke':'#FFF','stroke-width':2}).center(80,80)

	//drag
	group.draggable()

	var text=draw.text('3 グループ透明部分 drag').font({leading:0.8})


小さいインスタンスは必要に応じて処理エリアを広げる。(標準では上下左右10%までで、バグでは有りません)

 

zuzu

 

Groupについて

原則、複数のパスで構成されたインスタンス、例えばパスで描かれたイラストなどを、1つにグルーピングする目的で利用します。
勿論、他のインスタンスと区別する、あるいは単なるレーヤー的な利用も可能です。
ページ容量の都合で詳細は「次ページ」で説明します。


Group化するには、add()で纏めるが、直接に記載も出来るようです。またドラッグ設定などで不具合があるならGroup化してGroupにドラッグ設定すれば上手く機能するようです。問題も有りますので記事参照ください。


draw層のインスタンス
var rect1=draw.rect(100,100).attr({'fill':'#FF0'}).center(80,80)
var rect2=draw.rect(80,80).attr({'fill':'#F0F'}).center(80,80)

Group化し移動する
var group=draw.group()
group.add(rect1).add(rect2)


Groupに直接記載
var group=draw.group()
var rect1=group.rect(100,100).attr({'fill':'#FF0','stroke':'#FFF','stroke-width':2}).center(80,80)
var rect2=group.rect(80,80).attr({'fill':'#F0F','stroke':'#FFF','stroke-width':2}).center(80,80)

 

ドラッグ

ドラッグさせるには、draggableプラグイン svg.draggable.jsドラッグ用のJSが必要です。ここでドラッグの詳細な説明は省略しますが、ページで使用していますので、簡単に記述しておきます。
対象インスタンスに.draggable()とするだけです、範囲の設定も可能ですが、ここでは省略します。
グループにも設定できますが、回転させると斜め方向のドラッグが上手くできない。修正できないか探っているがまだ解決できない。


簡単
rect.draggable()

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

グループにもできますが、回転させると斜め方向のドラッグが上手くできない
group.rotate(30)
group.draggable()

 

最後に

問題はありますが、コツさえ掴めば結構簡単に構成、操作できます。私としては満足です。
まだ時期早尚と思いますが、早めに取り組みたいものです。問題がでましたら自己解決ください。


以下の記事を参考にしました。

【参考】dion.ne.jpの記事: svg要素の基本的な使い方まとめ

【参考】dion.ne.jpの記事: Snap.svgの使い方まとめ

【参考】atmarkit.co.jpの記事: 10分でわかるSVG 基礎編 (1/5)

【参考】ascii.jpの記事: いまさら聞けないSVG Web制作に便利な3つの理由

DropShadowの詳細は「前ページ」の記事を参照ください。

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


コツさえ掴めば結構簡単だ。以上「苦悶式」イイカゲンなお話でした。

 


[ この記事のURL ]


タグ:SVG , javascript

 

ブログ記事一覧

年別アーカイブ一覧



[1]