SVG学習 3日目「Javascriptで描画」

2018年8月14日

Javascript テクノロジー プログラミング 特集

SVGって単語の意味知ってますか?
Scalable Vector Graphics
の頭文字です。 拡大縮小できるベクターグラフィックという事なんですね。 これまでは、この技術はFlashが担っていたんですが、スマートフォンをはじめ、ブラウザアプリ全般でFlashを非対応するようになってきたのは、HTML5でSVG対応が決まって、もはやFlashのようなブラウザ標準ではなく、プラグインとしての要素は排除したかっのかもしれませんね。 Flash自体をHTML5で取り込む様な検討はされなかったんでしょうか? 一企業がライセンスを持っている状態だったので、それ自体が邪魔だったのかも・・・WEB業界の闇の様な感じなので、あまり掘り下げない方がいいかも・・・

Javascript描画ライブラリ

前回描画したものをjavascriptで描画してみます。 ;(function(){ var draw = { ns : "http://www.w3.org/2000/svg", /* Base option : { id , class , version , viewBox } */ svg : function(w , h , option){ var svg = document.createElementNS(this.ns , "svg"); svg.setAttribute('width' , w); svg.setAttribute('height' , h); if(option){ if(option.id){ svg.id = option.id; } if(option.class){ svg.className = option.class; } if(option.version){ svg.setAttribute('version' , option.version); } if(option.viewBox){ svg.setAttribute('viewBox' , option.viewBox); } } return svg; }, /* Box option : { id , class , rx , ry , fill , stroke , strokeW , rotate , translate{x,y} } */ rect : function(svg , x , y , w , h , option){ var rect = document.createElementNS(this.ns , "rect"); svg.appendChild(rect); rect.setAttribute("x" , ((x) ? x : 0)); rect.setAttribute("y" , ((y) ? y : 0)); rect.setAttribute("width" , ((w) ? w : 0)); rect.setAttribute("height" , ((h) ? h : 0)); if(option){ var transform = []; if(option.translate){ var tx = (option.translate.x) ? option.translate.x : 0; var ty = (option.translate.y) ? option.translate.y : 0; transform.push("translate("+ tx +" "+ ty +")"); } else{ rect.setAttribute("x" , 0); rect.setAttribute("y" , 0); transform.push("translate("+ x +" "+ y +")"); } if(option.rotate){ transform.push("rotate("+option.rotate+")"); } if(transform.length){ rect.setAttribute("transform" , transform.join(" ")); } if(option.id){ rect.setAttribute("id" , option.id); } if(option.class){ rect.setAttribute("class" , option.class); } if(option.stroke){ rect.setAttribute("stroke" , option.stroke); } if(option.strokeW){ rect.setAttribute("stroke-width" , option.strokeW); } if(option.fill){ rect.setAttribute("fill" , option.fill); } if(option.rx){ rect.setAttribute("rx" , option.rx); } if(option.ry){ rect.setAttribute("ry" , option.ry); } } return rect; }, /* 真円 option : { id , class , fill , stroke , strokeW , rotate , translate{x,y} } */ circle : function(svg , cx , cy , r , option){ var circle = document.createElementNS(this.ns , "circle"); svg.appendChild(circle); circle.setAttribute("cx" , ((cx) ? cx : 0)); circle.setAttribute("cy" , ((cy) ? cy : 0)); circle.setAttribute("r" , ((r) ? r : 0)); if(option){ var transform = []; if(option.translate){ var tx = (option.translate.x) ? option.translate.x : 0; var ty = (option.translate.y) ? option.translate.y : 0; transform.push("translate("+ tx +" "+ ty +")"); } else{ ellipse.setAttribute("cx" , 0); ellipse.setAttribute("cy" , 0); transform.push("translate("+ cx +" "+ cy +")"); } if(option.rotate){ transform.push("rotate("+option.rotate+")"); } if(transform.length){ circle.setAttribute("transform" , transform.join(" ")); } if(option.id){ circle.setAttribute("id" , option.id); } if(option.class){ circle.setAttribute("class" , option.class); } if(option.stroke){ circle.setAttribute("stroke" , option.stroke); } if(option.strokeW){ circle.setAttribute("stroke-width" , option.strokeW); } if(option.fill){ circle.setAttribute("fill" , option.fill); } } return circle; }, /* 楕円 option : { id , class , fill , stroke , strokeW , rotate , translate{x,y} } */ ellipse : function(svg , cx , cy , rx , ry , option){ var ellipse = document.createElementNS(this.ns , "ellipse"); svg.appendChild(ellipse); ellipse.setAttribute("cx" , ((cx) ? cx : 0)); ellipse.setAttribute("cy" , ((cy) ? cy : 0)); ellipse.setAttribute("rx" , ((rx) ? rx : 0)); ellipse.setAttribute("ry" , ((ry) ? ry : 0)); if(option){ var transform = []; if(option.translate){ var tx = (option.translate.x) ? option.translate.x : 0; var ty = (option.translate.y) ? option.translate.y : 0; transform.push("translate("+ tx +" "+ ty +")"); } else{ ellipse.setAttribute("cx" , 0); ellipse.setAttribute("cy" , 0); transform.push("translate("+ cx +" "+ cy +")"); } if(option.rotate){ transform.push("rotate("+option.rotate+")"); } if(transform.length){ ellipse.setAttribute("transform" , transform.join(" ")); } if(option.id){ ellipse.setAttribute("id" , option.id); } if(option.class){ ellipse.setAttribute("class" , option.class); } if(option.stroke){ ellipse.setAttribute("stroke" , option.stroke); } if(option.strokeW){ ellipse.setAttribute("stroke-width" , option.strokeW); } if(option.fill){ ellipse.setAttribute("fill" , option.fill); } } return ellipse; }, /* 線 option : { id , class , stroke , strokeW , rotate , translate{x,y} } */ line : function(svg , x1 , y1 , x2 , y2 , option){ var line = document.createElementNS(this.ns , "line"); svg.appendChild(line); line.setAttribute("x1" , ((x1) ? x1 : 0)); line.setAttribute("y1" , ((y1) ? y1 : 0)); line.setAttribute("x2" , ((x2) ? x2 : 0)); line.setAttribute("y2" , ((y2) ? y2 : 0)); if(option){ var transform = []; if(option.translate){ var tx = (option.translate.x) ? option.translate.x : 0; var ty = (option.translate.y) ? option.translate.y : 0; transform.push("translate("+ tx +" "+ ty +")"); } if(option.rotate){ transform.push("rotate("+option.rotate+")"); } if(transform.length){ line.setAttribute("transform" , transform.join(" ")); } if(option.id){ line.setAttribute("id" , option.id); } if(option.class){ line.setAttribute("class" , option.class); } if(option.stroke){ line.setAttribute("stroke" , option.stroke); } if(option.strokeW){ line.setAttribute("stroke-width" , option.strokeW); } } return line; }, /* 折れ線 points : x1,y1 x2,y2 x3,y3 ... (string) option : { id , class , stroke , strokeW , rotate , translate{x,y} } */ polyline : function(svg , points , option){ var polyline = document.createElementNS(this.ns , "polyline"); svg.appendChild(polyline); polyline.setAttribute("points" , points); if(option){ var transform = []; if(option.translate){ var tx = (option.translate.x) ? option.translate.x : 0; var ty = (option.translate.y) ? option.translate.y : 0; transform.push("translate("+ tx +" "+ ty +")"); } if(option.rotate){ transform.push("rotate("+option.rotate+")"); } if(transform.length){ polyline.setAttribute("transform" , transform.join(" ")); } if(option.id){ polyline.setAttribute("id" , option.id); } if(option.class){ polyline.setAttribute("class" , option.class); } if(option.stroke){ polyline.setAttribute("stroke" , option.stroke); } if(option.strokeW){ polyline.setAttribute("stroke-width" , option.strokeW); } if(option.fill){ polyline.setAttribute("fill" , option.fill); } } return polyline; }, /* ポリゴン points : x1,y1 x2,y2 x3,y3 ... (string) option : { id , class , rotate , stroke , strokeW , rotate , translate{x,y} } */ polygon : function(svg , points , option){ var polygon = document.createElementNS(this.ns , "polygon"); svg.appendChild(polygon); polygon.setAttribute("points" , points); if(option){ var transform = []; if(option.translate){ var tx = (option.translate.x) ? option.translate.x : 0; var ty = (option.translate.y) ? option.translate.y : 0; transform.push("translate("+ tx +" "+ ty +")"); } if(option.rotate){ transform.push("rotate("+option.rotate+")"); } if(transform.length){ polygon.setAttribute("transform" , transform.join(" ")); } if(option.id){ polygon.setAttribute("id" , option.id); } if(option.class){ polygon.setAttribute("class" , option.class); } if(option.stroke){ polygon.setAttribute("stroke" , option.stroke); } if(option.strokeW){ polygon.setAttribute("stroke-width" , option.strokeW); } if(option.fill){ polygon.setAttribute("fill" , option.fill); } } return polygon; } }; var area = document.getElementById("svg"); var svg = draw.svg(600 , 200 , {id : "test_1" , version : "1.1" , viewBox : "0 0 1200 400"}); area.appendChild(svg); draw.rect(svg , 0 , 0 , 160 , 160 , {fill : "skyblue" , stroke : "blue" , strokeW : "4"}); draw.rect(svg , 0 , 0 , 80 , 80 , {fill : "tomato" , rx : 8 , ry : 8 , rotate:45 , translate:{x:80 , y:20}}); draw.circle(svg , 0 , 0 , 80 , {fill : "rgba(255,0,0,0.5)" , translate : {x:250 , y:80}}); draw.ellipse(svg , 0 , 0 , 80 , 40 , {rotate : 0 , fill : "rgba(0,0,255,0.5)" , translate : {x:400 , y:80}}); draw.line(svg , 400,0,480,100,{strokeW:8 , stroke:"lightgreen"}); draw.polyline(svg , "50,375 150,375 150,325 250,325 250,375 350,375 350,250 450,250 450,375 550,375 550,175 650,175 650,375 750,375 750,100 850,100 850,375 950,375 950,25 1050,25 1050,375 1150,375" ,{strokeW:8 , stroke:"blue" , fill:"none"}); draw.polygon(svg , "350,75 379,161 469,161 397,215 423,301 350,250 277,301 303,215 231,161 321,161" ,{strokeW:4 , stroke:"brown" , fill:"yellow" , rotate:5}); })(); <!DOCTYPE html> <html> <head> <title>svg</title> </head> <body> <h1>SVG</h1> <div id="svg"></div> <script src="svg.js"></script> </body> </html> 前回表示したものと同じ画面になっているのがわかります。

簡単解説

前回HTMLタグで記述したものをそのままjavascript関数にして引数で対応しています。 ただし、SVGをjavascriptでタグ作成する時の注意点として"createElement"ではうまく表示されないという事を知っておきましょう。 正しくは、"createElementNS"という命令を使わなければいけません。 NSは"NameSpace"の略のようです。 ソースコード内をみるとわかる様に、下記の様に記述する必要があります。 var svg = document.createElementNS("http://www.w3.org/2000/svg" , "svg"); URL部分はおまじないだと思ってそのまま記述します。 他のrectやcircleなどのタグも同じくcreateElementNSを使って作成します。 属性値については、基本的にoptionとしてobjectで受け渡す事ですべてのシェイプを同じ様な形にしています。 ただし、poly系のpointsや、transformの箇所は少し癖がある書き方なので、細かな箇所を書き込みたい人は、w3cのリファレンスページをご覧ください。

リファレンスページ

https://triple-underscore.github.io/SVG11/index.html

次回予告

上記のソースコードをもう少し効率的にまとめるのと、テキストの書き込みや外部画像ファイルの取り込み表示にTRYしてみたいと思います。 ここまでできたら、表示系の部分に関してはまあまあ好きにいじれるようになると思いますよ。 そして、次回からはjavascriptでの処理を基本として行いますので、付いて来られなくなったという人がいたら、コメントで「ムズイやんけ!」とお知らせください。 でも、HTMLタグのみでよければ、他のサイトでわかりやすいページもいくつかありますよ。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ