Logo address

Mask

2012/11/11
2012/11/12

例1

次の図は mask の効果を示す。例は簡単でしかも mask の効果が分かりやすいものにした。

あなたのブラウザは SVG をサポートしていません。最新のブラウザをお使いください。

透明度を設定できる、様々な形のフィルタで、図形をマスクできる。

この SVG ファイルを生成する Python のコードは

#encoding: utf-8
import svg

c = svg.Canvas(0,0,400,300,map=(-1.4,1.3,1.4,-1.3))
d = c.define()
m = d.mask(-0.8,-1.1,0.8,1.1,id="M")
c.rect(-0.8,-1.1,0.8,1.1)
c.text(0,-1.1,text="masking region",anchor="N",font="size:12")

c.rect(-1,-1,1,1,stroke="green")
c.text(-1,1,text="masked region",anchor="S",font="size:12")

m.polygon(-1,-1,-1,1,1,1,stroke="black;width:4",fill="grey")
m.polygon(-1,-1,1,-1,1,1,stroke="black;width:4",fill="white")
d.end()

g = c.group(mask="url(#M)")
g.rect(-1,-1,1,1,fill="red",stroke="red")
g.text(0,0,text="abc",id="T",font="size:60",anchor="C",stroke="black",fill="none")
c.close()

特定の色だけをマスクできれば面白いのだが、特定の色だけをマスクできない。
(透明度だけが設定できる)

白色のストライプが入ったのは

stroke="black;width:4"
のせいである。幅を0にするか、stroke="none" を指定すれば、このストライプは出ない。

なお、text

stroke="black",fill="none"
を指定するとアウトライン的なテキストになる。

例2

あなたのブラウザは SVG をサポートしていません。最新のブラウザをお使いください。

マスクされた同じ絵をいくつも描きたいのであれば use が便利である。その場合には次のようになる。

#encoding: utf-8
import svg

c = svg.Canvas(0,0,400,300,map=(-1.4,1.3,1.4,-1.3))
d = c.define()
g = d.group(id="T",scale=0.5)
m = g.mask(-0.8,-1.1,0.8,1.1,id="M")
m.polygon(-1,-1,-1,1,1,1,stroke="black;width:4",fill="grey")
m.polygon(-1,-1,1,-1,1,1,stroke="black;width:4",fill="white")
h = g.group(mask="url(#M)")
h.rect(-1,-1,1,1,fill="red",stroke="red")
h.text(0,0,text="abc",id="T",font="size:60",anchor="C",stroke="black",fill="none")
d.end()

c.use(-0.5,0.5,ref="T")
c.use(0.5,0.5,ref="T")
c.use(-0.5,-0.5,ref="T")
c.use(0.5,-0.5,ref="T")
c.close()

例3

次の図は少し複雑なフィターを使った mask の効果を示す。

あなたのブラウザは SVG をサポートしていません。最新のブラウザをお使いください。

この SVG ファイルを生成する Python のコードは

#encoding: utf-8
import svg

c = svg.Canvas(0,0,400,300,map=(-1.4,1.3,1.4,-1.3))
d = c.define()

d.svgout("linearGradient","""id="G" gradientUnits="userSpaceOnUse"
x1="-100" y1="-100" x2="100" y2="100" """,
"""<stop offset="0" stop-color="white" stop-opacity="0" />
<stop offset="0.7" stop-color="white" stop-opacity="1" />"""
)
m = d.mask(-0.8,-1.1,0.8,1.1,id="M")
c.rect(-0.8,-1.1,0.8,1.1)
c.text(0,-1.1,text="masking region",anchor="N",font="size:12")

c.rect(-1,-1,1,1,stroke="green")
c.text(-1,1,text="masked region",anchor="S",font="size:12")

m.rect(-1,-1,1,1,stroke="black;width:2",fill="url(#G)")
g = d.group(id="T")
g.rect(-1,-1,1,1,fill="red",stroke="red")
g.text(0,0,text="abc",id="T",font="size:60",anchor="C",stroke="black",fill="none")
d.end()

c.use(ref="T",mask="url(#M)")
c.close()

マスクされた領域の中に着目すると、左上から右下に向かって透明度が高くなっている。これは linearGradient の中の

x1="-100" y1="-100" x2="100" y2="100"
によって実現されている。2つの座標によって、透明度が変化する向きを、開始点と終了点で与えているのである。

svgout メソッドを使った場合には、SVG の生の座標系を使わなくてはならないと言う分かりにくさがある。問題の軽減のために、次のようにライブラリの内部で使用されている関数 svgxy を使う事ができる。この関数は、map で与えた論理座標を、SVG の座標系に変換する。

d.svgout("linearGradient","""id="G" gradientUnits="userSpaceOnUse"
x1="%s" y1="%s" x2="%s" y2="%s" """%c.svgxy(-1,1,1,-1),
"""<stop offset="0" stop-color="white" stop-opacity="0" />
<stop offset="0.7" stop-color="white" stop-opacity="1" />"""
)