追記(6月25日)スタイル設定スクリプトと説明を修正
要約:一昨日始めた新しい処理方法のうち、SVG

Contents
- これまで(1)… 全体概要、SQL、JavaScript、HTML
の各ソース データを SVG 出力する SQL について (2)… PostGIS
- JavaScript
で行う処理の概要 - ビューポートの自動設定
- 塗り・線などの
CSS 設定 - 要素の重なり、線の太さ、点の大きさの設定
- 課題
JavaScript で行う処理の概要
下は、(1)に載せたwindow.addEventListener('load', function () { // ページ読み込み後に処理開始 // 最初のOBJECTタグのソースがSVGだと想定し、 // ビューポートとスタイル設定のためのインスタンスを作る var obj = document.getElementsByTagName('object')[0], svg = obj.contentDocument.documentElement, b = new SvgBbox(svg), s = new SvgStyle(svg, b); // ビューポートのオプション設定 // b.width = 500; // 表示横幅. 無指定ならブラウザ横幅 // b.fringe = 10; // 周縁ピクセル数. 無指定ならゼロ // b.vaspOption = 1.3; // 横に対する縦の補正比率. 無指定なら補正なし // カッコ内をIDとする要素を基準に、ビューポート設定 b.calc('border'); // 以下、スタイル設定 // カッコ内をIDとする要素を一番上に持ってくる s.setTop('municipality'); s.setTop('hospitals'); // 後に実行される要素ほど、上に来る .......... .......... // カッコ内をIDとする要素に線幅を設定. 単位はピクセル s.setStrokeWidth('hospitals', 1); .......... .......... // カッコ内をIDとする点データに半径を設定. 単位はピクセル s.setRadius('hospitals', 4); s.setRadius('pubs', 40000, true); // 第三引数が真:ピクセルでなく座標値 // 普通のCSSで、塗り、線色、透明度などを自由に設定 s.css('#border { fill: none; stroke: lightblue }'); .......... .......... });
ビューポートが決まって初めて座標値の単位とピクセルの比率が決まり、クラス
最後の
ビューポートの自動設定
クラス/* coding: utf-8 */ var SvgBbox = function (svg) { this.svg = svg; this.width = document.body.clientWidth; this.height = null; this.fringe = 0; this.scale1px = null; this.vaspOption = 1; }; SvgBbox.prototype.calc = function (id) { var chd = this.svg.getElementById(id).childNodes, aryX = Array(), aryY = Array(); for (var i = 0, len = chd.length; i < len; i++) { var ele = chd[i], tgn = ele.tagName; if (tgn === 'ellipse') { aryX.push(Number(ele.getAttribute('cx'))); aryY.push(Number(ele.getAttribute('cy'))); } else if (tgn === 'text') { aryX.push(Number(ele.getAttribute('x'))); aryY.push(Number(ele.getAttribute('y'))); } else if (tgn === 'path') { var seg = ele.pathSegList; for (var j = 0, len2 = seg.length; j < len2; j++) { var s = seg[j]; if (s.pathSegType === 2 || s.pathSegType === 4) { // only SVGPathSegMovetoAbs or SVGPathSegLinetoAbs aryX.push(s.x); aryY.push(s.y); } } } } var x1 = Math.min.apply(null, aryX), y1 = Math.min.apply(null, aryY), x2 = Math.max.apply(null, aryX), y2 = Math.max.apply(null, aryY), hh = y2 - y1, ww = x2 - x1; this.scale1px = ww / this.width; this.height = hh / this.scale1px; var fgx = this.fringe * this.scale1px, fgy = this.fringe * this.scale1px / this.vaspOption; fg2x = this.fringe * 2, fg2y = this.fringe * 2 / this.vaspOption; this.svg.setAttribute('preserveAspectRatio', 'none'); this.svg.setAttribute('height', this.height * this.vaspOption + fg2y); this.svg.setAttribute('width', this.width + fg2x); this.svg.setAttribute('viewBox', Array( x1 - fgx, y1 - fgy, x2 - x1 + fgx * 2, y2 - y1 + fgy * 2).join(' ')); };
calc
バウンディングボックスの決め方は単純で、全ての子要素が持つ座標(ellipse
path
»
オプション設定がなければ、バウンディングボックスの四隅がそのまま
周縁の大きさ
塗り・線などの CSS 設定
クラス/* coding: utf-8 */ var SvgStyle = function (svg, bbox) { this.svg = svg; this.bb = bbox; }; SvgStyle.prototype.setTop = function (id) { var g = this.svg.getElementById(id), p = g.parentNode; p.removeChild(g); p.appendChild(g); }; SvgStyle.prototype.setStrokeWidth = function (id, num) { var g = this.svg.getElementById(id), chd = g.childNodes, len = chd.length; for (var i = 0; i < len; i++) { chd[i].setAttribute('vector-effect', 'non-scaling-stroke'); } g.setAttribute('stroke-width', num); }; SvgStyle.prototype.setRadius = function (id, num, originalScale) { var els = this.svg.getElementById(id).getElementsByTagName('ellipse'), len = els.length, rx = num, ry = num / this.bb.vaspOption; if (! originalScale) { rx *= this.bb.scale1px; ry *= this.bb.scale1px; } for (var i = 0; i < len; i++) { var e = els[i]; e.setAttribute('rx', rx); e.setAttribute('ry', ry); } }; SvgStyle.prototype.css = function (text) { var ss = this.svg.parentNode.styleSheets; if (ss.length === 0) { this.svg.appendChild(document.createElementNS( 'http://www.w3.org/2000/svg', 'style')); } ss[0].insertRule(text, 0); };
処理内容は
最近のブラウザでは
s.css('#pubs { fill: green; opacity: 0.5 }');

要素の重なり、線の太さ、点の大きさの設定
使うクラスは上と同じ• 要素の重なり …
• 線の太さ …
• 点の大きさ …
要素の重なりは、CSS
線の太さは、指定されたピクセル数をビューポートの座標単位に変換して
まず子要素を全て走査し
»
(修正ここまで)
点の大きさは、ellipse
s.setRadius('pubs', 40000, true);
課題
今回はビューポート設定メソッドは、当初、要素
今後は
明日はブラウザ上での