ruby で svg を作成(その1)

初めての ruby-svg

http://ruby-svg.sourceforge.jp/ をつかって,ruby で svg を吐き出すスクリプトを作ったので,メモ.

とりあえずこんな感じ.

require 'svg/svg';

svg = SVG.new('4in 4in', '0 0 640 480')
st = SVG::Style.new() {self.style.stroke = '#ff0000' }
svg << SVG::Rect.new(x,y,width,height) { self.Style =  st }
svg << SVG::Line.new(x0,y0,x1,y1) { self.Style =  st }
svg << SVG::Text.new(x,y,string) { self.Style =  st }

svg.to_s

SVG.new()の引数は,svg/core.rb を読むと

<svg width=4in height=4in viewBox="0 0 640 480"> 

と,展開される模様. SVGの仕様書の日本語訳*1によると,widthとheightはビューポートの幅と高さをあらわし,viewboxはそのビューポート内に表示する領域を指定するものらしい.

さらに,座標指定時には4inのように単位を指定できる.省略した場合は"px"でピクセル単位となる.よって,上記の例では 4inch*4inch の枠に 640*480画素のグラフィックを適当にスケール変換して描画するということになる.ああ,アスペクト比が変わってしまう悪い例だったらしい(汗).

ruby-svgにパッチを当てる

また,ruby-svg-1.0.3 を使って生成した svgファイルはfirefox-1.5では表示できなかった.どうも,ruby-svgの出力するsvgは,厳密にはsvgの仕様を満たしておらず,firefoxの律儀なパーサーは受け付けてくれないみたい.

とりあえず svg/core.rb を強引に修正することで,この問題は回避することに成功.

--- core.rb~    2006-02-19 20:57:18.000000000 +0900
+++ core.rb     2006-02-19 21:20:00.000000000 +0900
@@ -48,7 +48,8 @@
       text  = %|<?xml version="1.0" standalone="no"?>\n|
       text << %|<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\n|
       text << %|<svg width="#{@width}" height="#{@height}"|
-      text << %| viewBox="#{@view_box}"| if @view_box
+      text << %| viewBox="#{@view_box}"\n| if @view_box
+      text << %|xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"\n|
       text << %|>\n|
 
       @scripts.each { |script|

ruby-svg 覚書

実はsvg自体をよく知らなかったこともあるので,とりあえずruby-svgを使っていて必要になったSVGの基礎知識をメモ.

  • 色の指定
    • '#RRGGBB' 形式など html と同じ記法
    • 透明色 'none'
  • スタイルの属性
    • svg/style.rb に一覧がある.主に使いそうなのをメモ,
      • stroke
      • stroke-width
      • fill
      • fill-opacity
      • font-size
      • opacity
  • レイヤの作成方法
  • svg的にはグループというらしく, でくくればそのブロックがグループとなる.illustratorで微調整する際に便利かも,
  • ruby-svg的には
svg = SVG.new('4in 4in', '0 0 640 480')
g = SVG::Group.new()
g << SVG::Line.new(x,y,x1,y1)
svg << g 
svg.to_s

なんて感じ.