1 // svgcanvas.js 2 // SVG 動的生成サポートライブラリ 3 // 4 // 簡単な使い方: 5 // 6 // (1) SVGCanvas オブジェクトを生成 7 // var canvas = new SVGCanvas(width, height); 8 // (2) SVGLayer オブジェクトを生成 9 // var layer = new SVGLayer(id); 10 // (3) レイヤに描画 11 // layer.fillColor = "black"; 12 // layer.text("Hello, world!", 0, 0); // <canvas> プギャー 13 // (4) キャンバスにレイヤを追加 14 // canvas.addLayer(layer); 15 // (5) 要素にキャンバスを追加 16 // canvas.appendTo(document.body); 17 // 18 // * <canvas>なんてウンコは使ってられないぜ 19 // * SVGAnchor を使えばリンクも設定できるぜ 20 // * 細かい属性は思いっきり端折ってやったぜ 21 // 22 23 24 /** 25 * @fileOverview SVG の動的生成を補助するライブラリです。 26 */ 27 28 /** 29 * svg 要素を管理します。 30 * @class 31 * @param {Number} width 幅 32 * @param {Number} height 高さ 33 */ 34 function SVGCanvas() { 35 this.initialise.apply(this, arguments); 36 } 37 SVGCanvas.prototype = { 38 SVG_NS: 'http://www.w3.org/2000/svg', 39 XLink_NS: 'http://www.w3.org/1999/xlink', 40 /** svg 要素 41 * @type element 42 */ 43 svg: null, 44 /** 幅 45 * @type Number 46 */ 47 width: null, 48 /** 高さ 49 * @type Number 50 */ 51 height: null, 52 /** コンストラクタから自動的に呼ばれ、初期化処理を行います。 */ 53 initialise: function(width, height) { 54 this.svg = document.createElementNS(this.SVG_NS, "svg"); 55 //this.svg.setAttributeNS(null, "xmlns:xlink", this.XLink_NS); 56 this.svg.setAttributeNS(null, "width", width); 57 this.svg.setAttributeNS(null, "height", height); 58 this.width = width; 59 this.height = height; 60 }, 61 /** 指定された要素に子要素として追加します。 62 * @param {element} x 親要素 63 */ 64 appendTo: function(x) { 65 x.appendChild(this.svg); 66 }, 67 /** 指定された要素から削除します。 68 * @param {element} x 親要素 69 */ 70 removeFrom: function(x) { 71 x.removeChild(this.svg); 72 }, 73 /** 子要素を追加します。 74 * @param {Object} x 親要素 75 */ 76 add: function(x) { 77 this.svg.appendChild(x.element); 78 }, 79 /** 子要素を削除します。 80 * @param {Object} x 親要素 81 */ 82 remove: function(x) { 83 this.svg.removeChild(x.element); 84 } 85 }; 86 87 /** 88 * SVG の各種子要素を管理します。 89 * @class 90 * @param {Number} width 幅 91 * @param {Number} height 高さ 92 * @property {String} id ID 93 * @property {String} strokeColor ストロークの色 94 * @property {Number} strokeWidth ストロークの幅 95 * @property {Number} strokeOpacity ストロークの透明度 96 * @property {String} fillColor 塗りつぶしの色 97 * @property {Number} fillOpacity 塗りつぶしの透明度 98 */ 99 function SVGElement() { 100 this.initialise.apply(this, arguments); 101 } 102 SVGElement.prototype = { 103 SVG_NS: 'http://www.w3.org/2000/svg', 104 XLink_NS: 'http://www.w3.org/1999/xlink', 105 /** 要素 106 * @type element 107 */ 108 element: null, 109 /** 要素名 110 * @type String 111 */ 112 name: null, 113 _id: null, 114 _strokeWidth: null, 115 _strokeColor: null, 116 _strokeOpacity: null, 117 _fillColor: null, 118 _fillOpacity: null, 119 get id() { return this._id; }, 120 set id(x) { this.element.setAttributeNS(null, "id", x); this._id = x; }, 121 get strokeColor() { return this._strokeColor }, 122 set strokeColor(x) { this.element.setAttributeNS(null, "stroke", x); this._strokeColor = x; }, 123 get strokeWidth() { return this._strokeWidth }, 124 set strokeWidth(x) { this.element.setAttributeNS(null, "stroke-width", x); this._strokeWidth = x; }, 125 get strokeOpacity() { return this._strokeOpacity }, 126 set strokeOpacity(x) { this.element.setAttributeNS(null, "stroke-opacity", x); this._strokeOpacity = x; }, 127 get fillColor() { return this._fillColor }, 128 set fillColor(x) { this.element.setAttributeNS(null, "fill", x); this._fillColor = x; }, 129 get fillOpacity() { return this._fillOpacity }, 130 set fillOpacity(x) { this.element.setAttributeNS(null, "fill-opacity", x); this._fillOpacity = x; }, 131 /* 132 _onClick: null, 133 _onMouseDown: null, 134 _onMouseUp: null, 135 _onMouseMove: null, 136 _onMouseOut: null, 137 _onMouseOver: null, 138 _onActivate: null, 139 get onClick() { return this._onClick }, 140 set onClick(x) { this.element.setAttributeNS(null, "onclick", x); this._onClick = x; }, 141 get onMouseDown() { return this._onMouseDown }, 142 set onMouseDown(x) { this.element.setAttributeNS(null, "onmousedown", x); this._onMouseDown = x; }, 143 get onMouseUp() { return this._onMouseUp }, 144 set onMouseUp(x) { this.element.setAttributeNS(null, "onmouseup", x); this._onMouseUp = x; }, 145 get onMouseMove() { return this._onMouseMove }, 146 set onMouseMove(x) { this.element.setAttributeNS(null, "onmousemove", x); this._onMouseMove = x; }, 147 get onMouseOut() { return this._onMouseOut }, 148 set onMouseOut(x) { this.element.setAttributeNS(null, "onmouseout", x); this._onMouseOut = x; }, 149 get onMouseOver() { return this._onMouseOver }, 150 set onMouseOver(x) { this.element.setAttributeNS(null, "onmouseover", x); this._onMouseOver = x; }, 151 get onActivate() { return this._onActivate }, 152 set onActivate(x) { this.element.setAttributeNS(null, "onactivate", x); this._onActivate = x; }, 153 */ 154 /** コンストラクタから自動的に呼ばれ、初期化処理を行います。 */ 155 initialise: function(name, layer, stroke, fill) { 156 this.name = name; 157 this.element = document.createElementNS(this.SVG_NS, name); 158 if (stroke) { 159 this.strokeColor = layer.strokeColor ? layer.strokeColor : "none" 160 this.strokeWidth = layer.strokeWidth ? layer.strokeWidth : "1" 161 this.strokeOpacity = layer.strokeOpacity ? layer.strokeOpacity : "1" 162 } 163 if (fill) { 164 this.fillColor = layer.fillColor ? layer.fillColor : "none" 165 this.fillOpacity = layer.fillOpacity ? layer.fillOpacity : "1" 166 } 167 }, 168 /** 属性の値を取得します。 169 * @param {String} name 属性名 170 * @return {undefined} 値 171 */ 172 getAttribute: function(name) { 173 this.element.getAttributeNS(null, name); 174 }, 175 /** 属性に値を設定します。 176 * @param {String} name 属性名 177 * @param {undefined} value 値 178 */ 179 setAttribute: function(name, value) { 180 this.element.setAttributeNS(null, name, value); 181 } 182 }; 183 184 /** 185 * SVG のa 要素を管理します。 186 * @class 187 * @param {String} href URI 188 * @param {String} id ID 189 */ 190 function SVGAnchor() { 191 this.initialise.apply(this, arguments); 192 } 193 SVGAnchor.prototype = { 194 SVG_NS: 'http://www.w3.org/2000/svg', 195 XLink_NS: 'http://www.w3.org/1999/xlink', 196 /** 要素 197 * @type element 198 */ 199 element: null, 200 /** ID 201 * @type String 202 */ 203 id: null, 204 /** コンストラクタから自動的に呼ばれ、初期化処理を行います。 */ 205 initialise: function(href, id) { 206 this.element = document.createElementNS(this.SVG_NS, "a"); 207 this.element.setAttributeNS(this.XLink_NS, "xlink:href", href); 208 this.element.setAttributeNS(null, "id", id); 209 this.id = id; 210 }, 211 /** 要素を追加します。 212 * @param {Object} x 要素 213 */ 214 add: function(x) { 215 this.element.appendChild(x.element); 216 }, 217 /** 要素を削除します。 218 * @param {Object} x 要素 219 */ 220 remove: function(x) { 221 this.element.removeChild(x.element); 222 } 223 }; 224 225 /** 226 * SVG の g 要素を管理します。 227 * @class 228 * @param {String} id ID 229 */ 230 function SVGLayer() { 231 this.initialise.apply(this, arguments); 232 } 233 SVGLayer.prototype = { 234 SVG_NS: 'http://www.w3.org/2000/svg', 235 XLink_NS: 'http://www.w3.org/1999/xlink', 236 /** 要素 237 * @type element 238 */ 239 element: null, 240 /** ID 241 * @type String 242 */ 243 id: null, 244 /* ストロークの幅 245 * @type Number 246 */ 247 strokeWidth: null, 248 /* ストロークの色 249 * @type String 250 */ 251 strokeColor: null, 252 /* ストロークの透明度 253 * @type Number 254 */ 255 strokeOpacity: null, 256 /* 塗りつぶしの色 257 * @type String 258 */ 259 fillColor: null, 260 /* 塗りつぶしの透明度 261 * @type Number 262 */ 263 fillOpacity: null, 264 /** コンストラクタから自動的に呼ばれ、初期化処理を行います。 */ 265 initialise: function(id) { 266 this.element = document.createElementNS(this.SVG_NS, "g"); 267 this.element.setAttributeNS(null, "id", id); 268 this.id = id; 269 return this.element; 270 }, 271 /** 配列からカンマ区切りの座標リストへ変換します。 272 * @param {Array} x 配列 273 * @return {String} 文字列 274 */ 275 arrayToPoints: function(x) { 276 var p = []; 277 for (var i = 0; i < x.length; i++) 278 p[i] = x[i].join(" "); 279 return p.join(","); 280 }, 281 /** 要素を追加します。 282 * @param {Object} x 要素 283 */ 284 add: function(x) { 285 this.element.appendChild(x.element); 286 }, 287 /** 要素を削除します。 288 * @param {Object} x 要素 289 */ 290 remove: function(x) { 291 this.element.removeChild(x.element); 292 }, 293 /* 294 createSVGElement: function(name, stroke, fill) { 295 var element = document.createElementNS(this.SVG_NS, name); 296 if (stroke) { 297 element.setAttributeNS(null, "stroke", this.strokeColor ? this.strokeColor : "none"); 298 element.setAttributeNS(null, "stroke-width", this.strokeWidth ? this.strokeWidth : "1"); 299 element.setAttributeNS(null, "stroke-opacity", this.strokeOpacity ? this.strokeOpacity : "1"); 300 } 301 if (fill) { 302 element.setAttributeNS(null, "fill", this.fillColor ? this.fillColor : "none"); 303 element.setAttributeNS(null, "fill-opacity", this.fillOpacity ? this.fillOpacity : "1"); 304 } 305 return element; 306 }, 307 */ 308 /** 四角形を作成します。 309 * @param {Number} x X 座標 310 * @param {Number} y Y 座標 311 * @param {Number} width 幅 312 * @param {Number} height 高さ 313 * @return {SVGElement} SVGElement オブジェクト 314 */ 315 rect: function(x, y, width, height) { 316 //var rect = this.createSVGElement("rect", true, true); 317 var rect = new SVGElement("rect", this, true, true); 318 rect.element.setAttributeNS(null, "x", x); 319 rect.element.setAttributeNS(null, "y", y); 320 rect.element.setAttributeNS(null, "width", width); 321 rect.element.setAttributeNS(null, "height", height); 322 this.element.appendChild(rect.element); 323 return rect; 324 }, 325 /** 円を作成します。 326 * @param {Number} cx 中心の X 座標 327 * @param {Number} cy 中心の Y 座標 328 * @param {Number} r 半径 329 * @return {SVGElement} SVGElement オブジェクト 330 */ 331 circle: function(cx, cy, r) { 332 var circle = new SVGElement("circle", this, true, true); 333 circle.element.setAttributeNS(null, "cx", cx); 334 circle.element.setAttributeNS(null, "cy", cy); 335 circle.element.setAttributeNS(null, "r", r); 336 this.element.appendChild(circle.element); 337 return circle; 338 }, 339 /** 楕円を作成します。 340 * @param {Number} cx 中心の X 座標 341 * @param {Number} cy 中心の Y 座標 342 * @param {Number} rx X 軸方向の半径 343 * @param {Number} ry Y 軸方向の半径 344 * @return {SVGElement} SVGElement オブジェクト 345 */ 346 ellipse: function(cx, cy, rx, ry) { 347 var ellipse = new SVGElement("ellipse", this, true, true); 348 ellipse.element.setAttributeNS(null, "cx", cx); 349 ellipse.element.setAttributeNS(null, "cy", cy); 350 ellipse.element.setAttributeNS(null, "rx", rx); 351 ellipse.element.setAttributeNS(null, "ry", ry); 352 this.element.appendChild(ellipse.element); 353 return ellipse; 354 }, 355 /** 直線を作成します。 356 * @param {Number} x1 始点の X 座標 357 * @param {Number} y1 始点の Y 座標 358 * @param {Number} x2 始点の X 座標 359 * @param {Number} y2 終点の Y 座標 360 * @return {SVGElement} SVGElement オブジェクト 361 */ 362 line: function(x1, y1, x2, y2) { 363 var line = new SVGElement("line", this, true, false); 364 line.element.setAttributeNS(null, "x1", x1); 365 line.element.setAttributeNS(null, "y1", y1); 366 line.element.setAttributeNS(null, "x2", x2); 367 line.element.setAttributeNS(null, "y2", y2); 368 this.element.appendChild(line.element); 369 return line; 370 }, 371 /** 折れ線を作成します。 372 * @param {Array/String} points 座標のリスト 373 * @return {SVGElement} SVGElement オブジェクト 374 */ 375 polyline: function(points) { 376 //var polyline = new SVGElement("polyline", this, true, false); 377 var polyline = new SVGElement("polyline", this, true, true); 378 polyline.element.setAttributeNS(null, "points", (points instanceof Array) ? this.arrayToPoints(points) : points); 379 this.element.appendChild(polyline.element); 380 return polyline; 381 }, 382 /** 多角形を作成します。 383 * @param {Array/String} points 座標のリスト 384 * @return {SVGElement} SVGElement オブジェクト 385 */ 386 polygon: function(points) { 387 var polygon = new SVGElement("polygon", this, true, true); 388 polygon.element.setAttributeNS(null, "points", (points instanceof Array) ? this.arrayToPoints(points) : points); 389 this.element.appendChild(polygon.element); 390 return polygon; 391 }, 392 /** 文字列を作成します。 393 * @param {String} str 文字列 394 * @param {Number} x X 座標 395 * @param {Number} y Y 座標 396 * @return {SVGElement} SVGElement オブジェクト 397 */ 398 text: function(str, x, y) { 399 var text = new SVGElement("text", this, true, true); 400 text.element.setAttributeNS(null, "x", x); 401 text.element.setAttributeNS(null, "y", y); 402 text.element.appendChild(document.createTextNode(str)); 403 this.element.appendChild(text.element); 404 return text; 405 }, 406 /** 画像を作成します。 407 * @param {String} src URI 408 * @param {Number} x X 座標 409 * @param {Number} y Y 座標 410 * @param {Number} width 幅 411 * @param {Number} height 高さ 412 * @return {SVGElement} SVGElement オブジェクト 413 */ 414 image: function(src, x, y, width, height) { 415 var image = new SVGElement("image", this, false, false); 416 image.element.setAttributeNS(this.XLink_NS, "xlink:href", src); 417 if (x) image.element.setAttributeNS(null, "x", x); 418 if (y) image.element.setAttributeNS(null, "y", y); 419 if (width) image.element.setAttributeNS(null, "width", width); 420 if (height) image.element.setAttributeNS(null, "height", height); 421 this.element.appendChild(image.element); 422 return image; 423 }, 424 }; 425 426 /** 427 * SVG の defs 要素を管理します。 428 * @class 429 */ 430 function SVGDefinitions() { 431 this.initialise.apply(this, arguments); 432 } 433 SVGDefinitions.prototype = { 434 SVG_NS: 'http://www.w3.org/2000/svg', 435 XLink_NS: 'http://www.w3.org/1999/xlink', 436 /** 要素 437 * @type element 438 */ 439 element: null, 440 /** コンストラクタから自動的に呼ばれ、初期化処理を行います。 */ 441 initialise: function() { 442 this.element = document.createElementNS(this.SVG_NS, "defs"); 443 return this.element; 444 }, 445 /** 要素を追加します。 446 * @param {Object} x 要素 447 */ 448 add: function(x) { 449 this.element.appendChild(x.element); 450 }, 451 /** 要素を削除します。 452 * @param {Object} x 要素 453 */ 454 remove: function(x) { 455 this.element.removeChild(x.element); 456 } 457 }; 458 459 /** 460 * SVG の filter 要素を管理します。 461 * @param {String} id ID 462 * @param {Number} x X 座標 463 * @param {Number} y Y 座標 464 * @param {Number} width 幅 465 * @param {Number} height 高さ 466 * @class 467 */ 468 function SVGFilter() { 469 this.initialise.apply(this, arguments); 470 } 471 SVGFilter.prototype = { 472 SVG_NS: 'http://www.w3.org/2000/svg', 473 XLink_NS: 'http://www.w3.org/1999/xlink', 474 /** 要素 475 * @type element 476 */ 477 element: null, 478 /** ID 479 * @type String 480 */ 481 id: null, 482 /** X 座標 483 * @type Number 484 */ 485 x: 0, 486 /** Y 座標 487 * @type Number 488 */ 489 y: 0, 490 /** 幅 491 * @type Number 492 */ 493 width: 0, 494 /** 高さ 495 * @type Number 496 */ 497 height: 0, 498 effects: [], 499 /** コンストラクタから自動的に呼ばれ、初期化処理を行います。 */ 500 initialise: function(id, x, y, width, height) { 501 this.element = document.createElementNS(this.SVG_NS, "filter"); 502 this.element.setAttributeNS(null, "id", id); 503 this.id = id; 504 if (x) this.element.setAttributeNS(null, "x", x); 505 if (y) this.element.setAttributeNS(null, "y", y); 506 if (width) this.element.setAttributeNS(null, "width", width); 507 if (height) this.element.setAttributeNS(null, "height", height); 508 return this.element; 509 }, 510 /** 要素を追加します。 511 * @param {Object} x 要素 512 */ 513 add: function(x) { 514 this.element.appendChild(x.element); 515 }, 516 /** 要素を削除します。 517 * @param {Object} x 要素 518 */ 519 remove: function(x) { 520 this.element.removeChild(x.element); 521 } 522 }; 523 524 /** 525 * SVG の 原始フィルタを提供します。 526 * @static 527 */ 528 var SVGFilterPrimitives = { 529 SVG_NS: 'http://www.w3.org/2000/svg', 530 XLink_NS: 'http://www.w3.org/1999/xlink', 531 /** 原始フィルタを作成します。 532 * @param {String} name フィルタ名 533 * @param {String} [x] X 座標 534 * @param {String} [y] Y 座標 535 * @param {String} [input] 入力 536 * @param {String} [result] 出力 537 */ 538 create: function(name, x, y, input, result) { 539 var element = document.createElementNS(this.SVG_NS, name); 540 if (x) element.setAttributeNS(null, "x", x); 541 if (y) element.setAttributeNS(null, "y", y); 542 if (input) element.setAttributeNS(null, "in", input); 543 if (result) element.setAttributeNS(null, "result", result); 544 return element; 545 } 546 }; 547 /** 548 * SVG の feGaussianBlur 要素を管理します。 549 * @class 550 * @param {Number} stdDeviation 標準偏差 551 * @param {String} [x] X 座標 552 * @param {String} [y] Y 座標 553 * @param {String} [input] 入力 554 * @param {String} [result] 出力 555 */ 556 SVGFilterPrimitives.GaussianBlur = function() { 557 this.initialise.apply(this, arguments); 558 } 559 SVGFilterPrimitives.GaussianBlur.prototype = { 560 /** 要素 561 * @type element 562 */ 563 element: null, 564 /** コンストラクタから自動的に呼ばれ、初期化処理を行います。 */ 565 initialise: function(stdDeviation, x, y, input, result) { 566 this.element = SVGFilterPrimitives.create("feGaussianBlur", x, y, input, result); 567 this.element.setAttributeNS(null, "stdDeviation", stdDeviation); 568 } 569 }