1 2 /** 3 * @name CeL SVG function 4 * @fileoverview 5 * 本檔案包含了 SVG 的 functions。 6 * @since 7 */ 8 9 10 /* 11 TODO 12 對無顯示 SVG 的多一項警告。 13 14 ASCIIsvg.js 15 http://www1.chapman.edu/~jipsen/svg/asciisvg.html 16 */ 17 18 if (typeof CeL === 'function'){ 19 20 /** 21 * 本 module 之 name(id),<span style="text-decoration:line-through;">不設定時會從呼叫時之 path 取得</span>。 22 * @type String 23 * @constant 24 * @inner 25 * @ignore 26 */ 27 var module_name = 'net.SVG'; 28 29 //=================================================== 30 /** 31 * 若欲 include 整個 module 時,需囊括之 code。 32 * @type Function 33 * @param {Function} library_namespace namespace of library 34 * @param load_arguments 呼叫時之 argument(s) 35 * @return 36 * @name CeL.net.SVG 37 * @constant 38 * @inner 39 * @ignore 40 */ 41 var code_for_including = function(library_namespace, load_arguments) { 42 43 // requires 44 if (eval(library_namespace.use_function( 45 'net.web.XML_node,net.web.set_attribute,net.web.remove_all_child,net.web.set_class,data.split_String_to_Object'))) 46 return; 47 48 49 // ============================================================================ 50 // definition of module SVG 51 52 /* 53 54 TODO: 55 animation 56 .add_image 57 */ 58 59 // in 運算子會檢查物件是否有名稱為 property 的屬性。它也會檢查物件的原型,查看 property 是否屬於原型鏈結的一部分。如果 property 是在物件或原型鏈結中,則 in 運算子會傳回 true,否則會傳回 false。 http://msdn2.microsoft.com/zh-tw/library/11e33275(VS.80).aspx 60 61 //g_SVG[generateCode.dLK]='set_attribute,XML_node,remove_all_child';//removeNode 62 63 /** 64 * module SVG 物件之 constructor。<br/> 65 * 設定 SVG document fragment 並將之插入網頁中。 66 67 * @class generation of Scalable Vector Graphics<br/> 68 * 輔助繪圖的基本功能物件,生成 SVG 操作函數。 69 * @since 2006/12/7,10-12 70 * @deprecated Use toolkit listed below instead:<br/> 71 * <a href="http://code.google.com/p/svgweb/" accessdate="2009/11/15 16:34" title="svgweb - Project Hosting on Google Code">svgweb</a><br/> 72 * <a href="https://launchpad.net/scour" accessdate="2009/11/15 16:35" title="Scour - Cleaning SVG Files in Launchpad">Scour</a> 73 74 * @constructor 75 * @param {int} _width width of the canvas 76 * @param {int} _height height of the canvas 77 * @param {color String} [_backgroundColor] background color of the canvas (UNDO) 78 * @requires set_attribute,XML_node,remove_all_child//removeNode 79 * @type CeL.net.SVG 80 * @return {CeL.net.SVG} CeL.net.SVG object created 81 82 * @see <a href="http://www.w3.org/TR/SVG/" accessdate="2009/11/15 16:31">Scalable Vector Graphics (SVG) 1.1 Specification</a><br/> 83 * <a href="http://zvon.org/xxl/svgReference/Output/" accessdate="2009/11/15 16:31">SVG 1.1 reference with examples</a><br/> 84 * <a href="http://www.permadi.com/tutorial/jsFunc/index.html" accessdate="2009/11/15 16:31" title="Introduction and Features of JavaScript "Function" Objects">Introduction and Features of JavaScript "Function" Objects</a><br/> 85 * <a href="http://volity.org/wiki/index.cgi?SVG_Script_Tricks" accessdate="2009/11/15 16:31">Volity Wiki: SVG Script Tricks</a><br/> 86 * <a href="http://pilat.free.fr/english/routines/js_dom.htm" accessdate="2009/11/15 16:31">Javascript SVG et DOM</a> 87 */ 88 CeL.net.SVG 89 = function(_width, _height, _backgroundColor){ 90 var _f = _, _s; 91 /* 92 if(!_f.createENS()){ 93 //alert('Your browser doesn't support SVG!'); 94 return; 95 } 96 */ 97 98 /** 99 * SVG document fragment 100 * @property 101 * @see <a href="http://www.w3.org/TR/SVG/struct.html#NewDocument" accessdate="2009/11/15 16:53">Defining an SVG document fragment: the 'svg' element</a> 102 */ 103 this.svg=_s= // raw 104 arguments.length===1 && arguments[0] && typeof arguments[0]==='object' && arguments[0].tagName.toLowerCase()==='svg' 105 ?arguments[0] 106 :_f.createNode('svg') 107 ; 108 if(!_s)return; // error! 109 110 // http://www.w3.org/TR/SVG/struct.html#DefsElement http://www.svgbasics.com/defs.html 111 _s.appendChild(this.defs=_f.createNode('defs')); // raw 112 113 // 調整大小 114 this.setSize(_width,_height); 115 // set_attribute(_s,{xmlns:_f.NS.SVG}); 116 set_attribute(_s,{xmlns:'http://www.w3.org/2000/svg'}); 117 // may cause error! should use .setAttributeNS()?? 118 _s.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink'); 119 //viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" 120 121 /** 122 * 包含了插入元件的原始資訊。<br/> 123 * Use {@link #addContain} to add contains. 124 * @property 125 * @type Array 126 */ 127 this.contains = []; 128 /** 129 * 所插入之網頁元素 130 * @property 131 */ 132 this.div = null; 133 134 //document.body.appendChild(this.svg); 135 return this;//return this.createNode(_nodeN); 136 }; 137 //_.NS={SVG:'http://www.w3.org/2000/svg',XLink:'http://www.w3.org/1999/xlink'}; 138 _.defaultColor = '#222'; 139 140 CeL.net.SVG 141 . 142 /** 143 * default stroke width. 單位: px 144 * 145 * @unit px 146 * @type Number 147 * @memberOf CeL.net.SVG 148 */ 149 defaultStrokeWidth = .5; 150 151 //_.defaultColor='#444';_.defaultStrokeWidth=1; 152 153 CeL.net.SVG 154 . 155 /** 156 * 所有造出 id 之 prefix 157 * @type string 158 * @memberOf CeL.net.SVG 159 */ 160 idPrefix = 161 // +'_SVG_'; 162 library_namespace.to_module_name(module_name) + '.'; 163 164 // _.bout closure. 165 //_.createENS=document.createElementNS?function(){return document.createElementNS(arguments[0],arguments[1]);}:null; 166 CeL.net.SVG 167 . 168 /** 169 * create SVG document fragment (only for .createNode) 170 * @param _ns namespaceURI 171 * @param _qn qualifiedName 172 * @param _a propertyA 173 * @param _i innerObj 174 * @return 175 * @memberOf CeL.net.SVG 176 * @function 177 * @private 178 */ 179 createENS = function(_ns, _qn, _a, _i) { 180 return ( 181 // document.createElementNS?XML_node(_ns+':'+_qn,_a,0,_i):null; 182 XML_node(_ns + ':' + _qn, _a, 0, _i)); 183 }; 184 185 CeL.net.SVG 186 . 187 /** 188 * create SVG document fragment 元件(component)。<br/> 189 * SVG 之 document fragment 與 HTML 不同 namespace,因此我們需要使用到 <a href="http://www.w3.org/2000/svg">http://www.w3.org/2000/svg</a> 來作為 XML elements 的 namespace。為了未來的兼容性,我們將這個功能獨立出來。 190 * @param _nodeN node/tag name 191 * @param {hash|string}_a attribute/property 192 * @param _i inner object 193 * @return node created or null 194 * @memberOf CeL.net.SVG 195 * @private 196 * @function 197 */ 198 createNode = function(_nodeN,_a,_i){ 199 //return this.createENS?this.createENS('svg',_nodeN||'svg'):null; 200 return _.createENS('svg', _nodeN || 'svg', _a, _i); 201 202 // Error: uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: file:///C:/kanashimi/www/cgi-bin/program/tmp/JavaScript%20Framework/dojo/dojo-0.4.0-ajax/a.htm :: anonymous :: line 29" data: no] 203 // http://www.codingforums.com/archive/index.php?t-94573.html When you do var x = document.getElementById and then x('hello') you are executing the function x in the context of the window object instead of the document object. Gecko probably utilizes the scoping of the document object to access some internal methods to execute getElementById, which the window object doesn't have. 204 // http://developer.mozilla.org/en/docs/Safely_accessing_content_DOM_from_chrome http://developer.mozilla.org/en/docs/Working_around_the_Firefox_1.0.3_DHTML_regression http://www.codingforums.com/archive/index.php?t-68554.html 205 // OK? 206 //return this.createENS?this.createENS.call(document,'svg',_nodeN||'svg'):null; 207 // fault: 208 //return this.createENS===document.createElementNS?document.createElementNS('svg',_nodeN||'svg'):this.createENS?this.createENS('svg',_nodeN||'svg'):null; 209 //return this.createENS?(alert(this.createENS===document.createElementNS),Function.apply(this.createENS,['svg',(_nodeN||'svg')])):null; 210 //return this.createENS?(alert(this.createENS===document.createElementNS),this.createENS.apply(document.createElementNS,['svg',(_nodeN||'svg')])):null; 211 }; 212 /* 213 _.createLink=function(_ref){ 214 return this.createENS('xLink','xlink:href'); 215 }; 216 */ 217 218 CeL.net.SVG 219 . 220 /** 221 * 從 id 獲得 node 222 * @param id id 223 * @return node 224 * @memberOf CeL.net.SVG 225 * @private 226 */ 227 getNodeById = function(id) { 228 // return this.svg.getElementById(_i);//useless? 229 230 // lookupPrefix() 231 return document.getElementById(id); 232 }; 233 234 CeL.net.SVG 235 . 236 /** 237 * get a random ID to use. 238 * @param tag tag name(nodeType) 239 * @return a random ID 240 * @memberOf CeL.net.SVG 241 * @private 242 */ 243 getRandomID = function(tag) { 244 if (typeof tag === 'object') 245 tag = tag.tagName/* nodeType */; 246 var _j; 247 while (_.getNodeById(_j = _.idPrefix + tag + '_' 248 + ('' + Math.random()).slice(2, 6))) 249 ; 250 return _j; 251 }; 252 CeL.net.SVG 253 . 254 /** 255 * give a random ID to the specified node. 256 * @param _n node 257 * @return id of the specified node 258 * @memberOf CeL.net.SVG 259 * @private 260 */ 261 setRandomID = function(_n) { 262 if (_n && typeof _n === 'object') { 263 /** 264 * id of the specified node 265 * @inner 266 * @ignore 267 */ 268 var _i = set_attribute(_n, 'id'); 269 if (!_i) 270 set_attribute(_n, { 271 id : _i = _.getRandomID(_n) 272 }); 273 return _i; 274 } 275 }; 276 277 CeL.net.SVG 278 . 279 /** 280 * 改變 text 281 * @param text_node text object 282 * @param text change to this text 283 * @return 284 * @memberOf CeL.net.SVG 285 * @see 286 * <a href="http://www.w3.org/TR/SVG/text.html" accessdate="2009/12/15 0:2">Text - SVG 1.1 - 20030114</a> 287 * <tref xlink:href="#ReferencedText"/> 288 */ 289 changeText = function(text_node, text) { 290 //if (typeof remove_all_child === 'function') 291 // remove_all_child(text_node); 292 //else throw new Error(1, 'changeText: function remove_all_child is not included!'); 293 remove_all_child(text_node); 294 295 if (text) 296 text_node.appendChild(document.createTextNode(text)); 297 //else removeNode(_textO); 298 }; 299 300 CeL.net.SVG 301 . 302 addTitle = function(_o, _t_d) { 303 if (_t) 304 _o.appendChild(this.createNode('title', 0, _t)); 305 // A more descriptive label should be put in a <desc> child element 306 if (_t) 307 _o.appendChild(this.createNode('desc', 0, _t)); 308 }; 309 310 311 /* transform http://www.w3.org/TR/SVG/coords.html#TransformAttribute http://archive.dojotoolkit.org/nightly/tests/gfx/test_image.html 312 recommend for performance reasons to use transformation matrices whenever possible. http://www.mecxpert.de/svg/transform.html 313 * @memberOf module SVG 314 */ 315 CeL.net.SVG 316 . 317 setTransform = function(_o, _t) { 318 // TODO 319 throw new Error(1, 'setTransform: yet implement!'); 320 set_attribute(_o, { 321 transform : _t 322 }); 323 }; 324 325 // ============================================================================ 326 // definition of module SVG object 327 328 _.prototype={ 329 330 /** 331 * 顯現 this module SVG object 332 * @param _v visible 333 * @return this module SVG object 334 * @memberOf CeL.net.SVG 335 */ 336 show : function(_v) { 337 var _d = this.div; 338 if (this.svg) 339 if (_d) {// _s.parentNode 340 _d.style.display = typeof _v == 'undefined' ? _d.style.display === 'none' ? 'block' 341 : 'none' 342 : _v ? 'block' : 'none'; // block怪怪的 343 } else if (_v || typeof _v == 'undefined') 344 this.div = XML_node('div', 0, [ document.body ], 345 this.svg); 346 return this; 347 }, 348 setAttribute : function() { 349 this.svg && this.svg.setAttribute(arguments); 350 return this; 351 }, 352 //setDimensions 353 /** 354 * 調整 canvas 大小 355 * @unit px 356 * @param {Integer} _width width in px 357 * @param {Integer} _height height in px 358 * @return this module SVG object 359 * @memberOf CeL.net.SVG 360 */ 361 setSize : function(_width, _height) { 362 _width = parseInt(_width) || 0; 363 _height = parseInt(_height) || 0; 364 365 if (_width > 0 && _height > 0) 366 set_attribute(this.svg, { 367 width : _width, 368 height : _height 369 }); 370 371 return this; 372 }, 373 getSize : function() { 374 return set_attribute(this.svg, 'width,height'); 375 }, 376 377 /** 378 * 將本 Object 附在 _n 上(attach to node) 379 * @param _n HTML/SVG object 380 * @return 381 */ 382 attach : function(_n) { 383 if (typeof _n === 'string') 384 _n = _.getNodeById(_n); 385 386 if (!_n) 387 return this; 388 389 var _t = _n.tagName.toLowerCase(); 390 if (_t === 'svg') 391 // TODO: 若不想創建新 node.. 392 return new _(_n); 393 394 if (_t === 'div') { 395 //if(this.div){TODO: 原先已經 attach} 396 this.div = _n; 397 _n.appendChild(this.svg); 398 } 399 400 return this; 401 }, 402 403 get_XML : function() { 404 var _t = document.createElement('div'), _x, _s = this.svg; 405 406 if (!_s) 407 // error! 408 return; 409 410 // TODO: 效率不高! 411 _t.appendChild(_s = _s.cloneNode(true)); 412 _x = _t.innerHTML; 413 _t.removeChild(_s); 414 // 確保在此環境下 create 出來的會被 destory 415 _t = null; 416 // ugly hack 417 // <?xml version="1.0" encoding="UTF-8" standalone="no"?> 418 _x = _x.replace(/(\s)(href=['"])/g, '$1xlink:$2'); 419 420 return _x; 421 }, 422 423 /** 424 * 清除 canvas<br/> 425 * 很可能會出問題! 426 * @return this SVG 427 * @memberOf CeL.net.SVG 428 * @since 2009/12/18 21:17:09 429 */ 430 clean : function() { 431 var s = this.svg; 432 // [0]: <defs> 433 while (s.childNodes.length > 1) 434 //library_namespace.debug(s.childNodes.length + ',' + s.lastChild), 435 s.removeChild(s.lastChild); 436 437 // remove childrens of <defs> 438 //remove_all_child(s.lastChild, 1); 439 s = s.lastChild; 440 while (s.hasChildNodes()) 441 //library_namespace.debug(s.childNodes.length + ',' + s.lastChild), 442 s.removeChild(s.lastChild); 443 444 return this; 445 }, 446 447 /** 448 * 創建本物件之 SVG 群組。<br/> 449 * 利用 SVG 群組我們可以同時操作多個 SVG elements。 450 * @param {hash|string}_a attribute/property 451 * @param _i inner object 452 * @return this SVG 453 * @memberOf CeL.net.SVG 454 */ 455 createGroup : function(_a, _i) { 456 var _g = _.createNode('g', _a, _i); 457 this.group = _g; 458 return this; 459 }, 460 /** 461 * 綁定 SVG elements 至本物件群組。<br/> 462 * 這函數將已存在的 SVG elements 綁定至本物件之群組中。若群組不存在,則創建出一個。 463 * @param _n node 464 * @return this module SVG object 465 * @memberOf CeL.net.SVG 466 */ 467 attachGroup : function(_n) { 468 if (!this.group) 469 this.createGroup(); 470 this.group.appendChild(_n); 471 return this; 472 }, 473 474 createSymbol : function(_a, _i) { 475 var _s = _.createNode('symbol', _a, _i); 476 this.symbol = _s; 477 return this; 478 }, 479 attachSymbol : function(_n) { 480 if (!this.symbol) 481 this.createSymbol(); 482 this.symbol.appendChild(_n); 483 return this; 484 }, 485 486 // TODO 487 setFill:function(){throw new Error(1,'setFill: yet implement!');}, 488 setStroke:function(){throw new Error(1,'setStroke: yet implement!');}, 489 setShape:function(){throw new Error(1,'setShape: yet implement!');}, 490 setTransform:function(){throw new Error(1,'setTransform: yet implement!');}, 491 492 //<animateMotion>,<animateColor> 493 494 /** 495 * 最後一個增加的 instance 496 * @memberOf CeL.net.SVG 497 */ 498 lastAdd: null, 499 /** 500 * 最後一個增加的 definition 501 * @memberOf CeL.net.SVG 502 */ 503 lastAddDefs: null, 504 /** 505 * 增加 SVG element。<br/> 506 * 結合 .prototype.addDefs 與 .prototype.addUse,作完定義後隨即使用之。 507 * @param _n tagName(nodeType) 508 * @param {hash|string} _a attribute/property 509 * @param _i inner object 510 * @return 511 * @memberOf CeL.net.SVG 512 */ 513 addNode : function(_n, _a, _i) { 514 if (typeof _n == 'string') 515 _n = _.createNode(_n, _a, _i); 516 if (_n) { 517 this.addDefs(_n); 518 this.addUse(_n); 519 } 520 return this; 521 }, 522 523 /** 524 * 增加 SVG 定義。<br/> 525 * SVG 規範中聲明,SVG 的 <use> element 不能引用外部文件或其 elements。因此我們在創建實例之前,需要先在本物件中作定義。 526 * @param _n node 527 * @return 528 * @memberOf CeL.net.SVG 529 */ 530 addDefs : function(_n) { 531 // var _d=this.defs; 532 if (_n) { 533 _.setRandomID(_n); 534 this.defs.appendChild(this.lastAddDefs = _n); 535 } 536 return this; 537 }, 538 /** 539 * 增加 SVG 實例。<br/> 540 * 利用本物件中之定義創建實例並增添至本物件中。<br/> 541 * 在裝載 b.svg 時,將 a.svg 中的 defs 中的圖元裝載到 b.svg 中(文件上是兩者是保持獨立的,但在內存中將二者合二為一),這樣就可以在b.svg中直接引用這些圖元了。<br/> 542 * SVG 規範中聲明,SVG 的 <use> element 不能引用外部文件或其 elements。因此我們在創建實例之前,需要先在本物件中作定義。 543 * @param _i id 544 * @param _a 545 * @return 546 * @memberOf CeL.net.SVG 547 */ 548 addUse : function(_i, _a) { 549 var _s = this.svg, _o = _.createNode('use', _a); 550 if (_o && _s && _i) { 551 if (typeof _i == 'object') 552 _i = _.setRandomID(_i); 553 set_attribute(_o, { 554 'xlink:href' : '#' + _i 555 }); 556 _s.appendChild(this.lastAdd = _o); 557 } 558 return this; 559 }, 560 561 /** 562 * 增加插入的元件。<br/> 563 * 應該用 <a href="http://www.w3.org/TR/SVG/struct.html#SymbolElement">symbol</a> 564 * @param _o object reference 565 * @param _type type of this component 566 * @param [propertyO] other properties 567 * @return 568 * @requires split_String_to_Object 569 * @memberOf CeL.net.SVG 570 */ 571 addContain : function(_o, _type, propertyO) { 572 if (_type && this.contains) { 573 if (typeof propertyO === 'string') 574 propertyO = split_String_to_Object(propertyO); 575 if (propertyO.o || propertyO.t) 576 this.contains.push( { 577 o : _o, 578 t : _type, 579 p : propertyO 580 }); 581 else 582 propertyO.o = _o, propertyO.t = _type, this.contains 583 .push(propertyO); 584 } 585 return this; 586 }, 587 588 589 /** 590 * 繪製直線。<br/> 591 * 此函數利用 _.eNode 造出直線元件之後,再用 .prototype.addNode 將之插入本物件中。 592 * @param _left 593 * @param _top 594 * @param _width 595 * @param _height 596 * @param _color 597 * @param _strokeWidth 598 * @return 599 * @memberOf CeL.net.SVG 600 */ 601 addLine : function(_left, _top, _width, _height, _color, 602 _strokeWidth) { 603 var _l = _.createNode('line', { 604 x1 : _top, 605 y1 : _left, 606 x2 : _top + _width, 607 y2 : _left + _height, 608 stroke : _color || this.addLine.defaultColor, 609 'stroke-width' : _strokeWidth || _.defaultStrokeWidth 610 }); 611 if (_l && this.svg) { 612 //this.svg.appendChild(_l); 613 this.addNode(_l); 614 } 615 return this; 616 }, 617 618 619 /** 620 * 繪製曲線路徑。<br/> 621 * 此函數利用 _.eNode 造出路徑元件之後再用 .prototype.addNode 將之插入本物件中。 622 * @param _d 623 * @param _color 624 * @param _strokeWidth 625 * @param _fill 626 * @return 627 * @memberOf CeL.net.SVG 628 */ 629 addPath : function(_d, _color, _strokeWidth, _fill) { 630 var _p = _.createNode('path', { 631 d : _d, 632 stroke : _color || this.addLine.defaultColor, 633 'stroke-width' : _strokeWidth || _.defaultStrokeWidth, 634 fill : _fill || 'none' 635 }); 636 if (_p && this.svg) 637 this.addNode(_p); 638 return this; 639 }, 640 641 642 //xml:space="default|preserve" 643 /** 644 * 添加文字。<br/> 645 * 此函數利用 _.eNode 造出文字元件之後再用 .prototype.addNode 將之插入本物件中。 646 * @param _text 647 * @param _left 648 * @param _baseLine 649 * @param _color 650 * @param _font 651 * @return 652 * @memberOf CeL.net.SVG 653 */ 654 addText : function(_text,_left,_baseLine,_color,_font){ 655 if (_color) 656 this.addText.defaultColor = _color; 657 else 658 _color = this.addText.defaultColor; 659 660 if (_font) 661 this.addText.defaultFont = _font; 662 else 663 _font = this.addText.defaultFont; 664 665 // http://www.w3.org/TR/SVG/text.html <tref xlink:href="#ReferencedText"/> 666 //var _o=document.createTextNode(_text); 667 //var _o=_.createNode('tspan',{x:_left,y:_baseLine,stroke:_color||this.addText.defaultColor,style:_font?'font-family:"'+_font+'"':null},_text); 668 //this.addNode(_.createNode('text',{x:_left,y:_baseLine,stroke:_color||this.addText.defaultColor,style:_font?'font-family:"'+_font+'"':null},_o)); 669 //this.lastAdd=_o; 670 671 // ugly hack: 說是_baseLine,其實還是會再往下一點點。 672 _baseLine -= 2; 673 this.addNode(_.createNode('text', { 674 x : _left, 675 y : _baseLine, 676 stroke : _color || this.addText.defaultColor, 677 style : _font ? 'font-family:"' + _font + '"' : null 678 }, _text)); 679 //(text|g).pointer-events="none": Make text unselectable 680 681 /* 本法為標準,但FF尚未支援。 682 var _s=this.svg,_i=_.getRandomID('text')_.SVG.createNode('text',{id:_i},_text); 683 this.addDefs(this.lastAddDefs=_o); 684 _o=_.createNode('text',{x:_left,y:_baseLine,stroke:_color||this.addText.defaultColor,style:_font?'font-family:"'+_font+'"':null},0,_t=_.createNode('tref')); 685 _t.setAttributeNS('xLink','xlink:href','#'+_i); 686 _o.appendChild(_t); 687 _s.appendChild(this.lastAdd=_o); 688 */ 689 690 return this; 691 }, 692 693 /** 694 * add numbers 695 * @param _text 696 * @param _left 697 * @param _baseLine 698 * @param _tW 699 * @param _color 700 * @param _font 701 * @return 702 * @see 703 * _left: http://www.w3.org/TR/SVG/text.html#TSpanElementXAttribute 704 */ 705 addNum : function(_text, _left, _baseLine, _tW, _color, _font) { 706 if (!isNaN(_text)) { 707 // 說是_baseLine,其實還是會再往下一點點。 708 _baseLine -= 2; 709 //_text=''+_text; 710 _text += ''; 711 712 var _o = [], _i = 0, _s = this.svg; 713 for (; _i < _text.length; _i++) 714 // _text.split('') 715 _o.push(_.createNode('tspan', { 716 x : _left + _i * _tW 717 //, y:_baseLine 718 }, _text.charAt(_i))); 719 720 if (_s) 721 _s.appendChild(this.lastAdd = _.createNode('text', { 722 y : _baseLine, 723 stroke : _color || this.addText.defaultColor, 724 style : _font ? 'font-family:"' + _font + '"' 725 : null 726 }, _o)); 727 } 728 return this; 729 }, 730 731 732 /** 733 * add parallel graph 734 * @param _ds 735 * @param _h 736 * @param _d 737 * @param _us 738 * @param tramA 739 * @return 740 * @since 2006/12/18 0:35 741 */ 742 addParallelG : function(_ds, _h, _d, _us, tramA) { 743 if (_ds && _h) { 744 if (isNaN(_us) || _us === '') 745 _us = _ds; 746 set_attribute(this 747 .addPath('M' + _ds + ',' + _h + ' H0 L' + (_d || 0) 748 + ',0' + (_us ? ' h' + _us : '') + ' z'), { 749 transform : tramA 750 }); // 0=='' 751 } 752 return this; 753 }, 754 755 lastQuadrilateral : null, 756 lastQuadrilateralDefs : null, 757 /** 758 * 畫簡單長方形或平行四邊形、梯形 759 * @param _ds 760 * @param _h 761 * @param _d 762 * @param _us 763 * @param tramA 764 * @return 765 * @see <a href="http://zh.wikipedia.org/wiki/%E5%B9%B3%E8%A1%8C%E5%9B%9B%E8%BE%B9%E5%BD%A2">平行四邊形</a> 766 * @memberOf CeL.net.SVG 767 */ 768 addQuadrilateral:function(_ds,_h,_d,_us,tramA){ // down side,height,upper distance,upper side 769 this.addParallelG(_ds,_h,_d,_us,tramA).addContain(this.lastQuadrilateralDefs=this.lastAddDefs,'quadrilateral',{down_side:_ds,hight:_h,distance:_d,upper_side:_us}); 770 this.lastQuadrilateral=this.lastAdd; // set_attribute(s.lastQuadrilateral,'fill=none'); 771 return this; 772 }, 773 774 lastTriangle : null, 775 lastTriangleDefs : null, 776 /** 777 * 畫簡單三角形 778 * @since 2006/12/17 12:38 779 * @param _ds 780 * @param _h 781 * @param _d 782 * @param tramA 783 * @return 784 * @memberOf CeL.net.SVG 785 */ 786 addTriangle : function(_ds, _h, _d, tramA) { 787 this.addParallelG(_ds, _h, _d, 0, tramA).addContain( 788 this.lastTriangleDefs = this.lastAddDefs, 'triangle', { 789 down_side : _ds, 790 hight : _h, 791 distance : _d 792 }); 793 this.lastTriangle = this.lastAdd; 794 return this; 795 }, 796 797 798 /** 799 * 繪製橢圓曲線。<br/> 800 * 此函數利用 _.eNode 造出橢圓曲線元件之後,再用 .prototype.addNode 將之插入本物件中。 801 * @param _rx 802 * @param _ry 803 * @param _cx 804 * @param _cy 805 * @param _color 806 * @param _strokeWidth 807 * @param _fill 808 * @param tramA 809 * @return 810 * @memberOf CeL.net.SVG 811 */ 812 addEllipsePath : function(_rx, _ry, _cx, _cy, _color, _strokeWidth, 813 _fill, tramA) { 814 if (_rx) { 815 var _e, _p = { 816 rx : _rx, 817 ry : _ry, 818 cx : _cx, 819 cy : _cy, 820 stroke : _color || this.addEllipsePath.defaultColor, 821 'stroke-width' : _strokeWidth || _.defaultStrokeWidth, 822 fill : _fill || 'none', 823 transform : tramA 824 }; 825 826 if (!_ry) 827 _e = 'circle', _p.r = _rx; 828 else 829 _e = 'ellipse', _p.rx = _rx, _p.ry = _ry; 830 831 _e = _.createNode(_e, _p); 832 833 if (_e && this.svg) 834 this.addNode(_e); 835 } 836 return this; 837 }, 838 839 840 lastCircle : null, 841 lastCircleDefs : null, 842 /** 843 * 繪製圓形。<br/> 844 * 此函數利用 _.type.addEllipsePath 來畫簡單圓形。 845 * @param _r 846 * @param _cx 847 * @param _cy 848 * @return 849 * @memberOf CeL.net.SVG 850 */ 851 addCircle : function(_r, _cx, _cy) { 852 if (_r) 853 this.addEllipsePath(_r, '', _cx, _cy).addContain( 854 this.lastCircleDefs = this.lastAddDefs, 'circle', { 855 r : _r 856 }); 857 return this; 858 }, 859 860 lastEllipse : null, 861 lastEllipseDefs : null, 862 /** 863 * 繪製簡單圓形/橢圓。<br/> 864 * 此函數利用 .prototype.addEllipsePath 來畫簡單橢圓。 865 * @param _rx 866 * @param _ry 867 * @param _cx 868 * @param _cy 869 * @return 870 * @memberOf CeL.net.SVG 871 */ 872 addEllipse : function(_rx, _ry, _cx, _cy) { 873 if (_rx) { 874 this.addEllipsePath(_rx, _ry, _cx, _cy).addContain( 875 this.lastEllipseDefs = this.lastAddDefs, 'ellipse', 876 { 877 rx : _rx, 878 ry : _ry 879 }); 880 this.lastEllipse = this.lastAdd; 881 } 882 return this; 883 }, 884 885 886 /** 887 * 繪製矩形。<br/> 888 * 此函數利用 _.eNode 造出矩形路徑元件之後,再用 .prototype.addNode 將之插入本物件中。 889 * @param _w 890 * @param _h 891 * @param _x 892 * @param _y 893 * @param _color 894 * @param _strokeWidth 895 * @param _fill 896 * @param tramA 897 * @return 898 * @memberOf CeL.net.SVG 899 */ 900 addRect : function(_w, _h, _x, _y, _color, _strokeWidth, _fill, 901 tramA) { 902 this.addNode(_.createNode('rect', { 903 width : _w, 904 height : _h, 905 x : _x, 906 y : _y, 907 stroke : _color || this.addRect.defaultColor, 908 'stroke-width' : _strokeWidth || _.defaultStrokeWidth, 909 fill : _fill || 'none', 910 transform : tramA 911 })); 912 return this; 913 }, 914 915 916 /** 917 * 繪製多邊形。<br/> 918 * 此函數利用 _.eNode 造出多邊形路徑元件之後再用 .prototype.addNode 將之插入本物件中。 919 * @param {int array} _pA [x1,y1,x2,y2,x3,y3,..] 920 * @param _color 921 * @param _strokeWidth 922 * @param _fill 923 * @param tramA 924 * @return 925 * @memberOf CeL.net.SVG 926 */ 927 addPolyline : function(_pA, _color, _strokeWidth, _fill, tramA) { 928 var _i = 0, _p = []; 929 while (_i < _pA.length) 930 _p.push(_pA[_i++] + ',' + _pA[_i++]); 931 this.addNode(_.createNode('polyline', { 932 points : _p.join(' '), 933 stroke : _color || this.addRect.defaultColor, 934 'stroke-width' : _strokeWidth || _.defaultStrokeWidth, 935 fill : _fill || 'none', 936 transform : tramA 937 })); 938 return this; 939 }, 940 941 942 addImage : function() { 943 // TODO 944 throw new Error(1, 'addImage: yet implement!'); 945 }, 946 947 /** 948 * 功能正常嗎? 949 * @return {Boolean} 功能正常 950 */ 951 status_OK : function() { 952 // !!: dual-unary operator 953 return !!this.svg; 954 } 955 956 }; // _.prototype={ 957 958 959 // other manual setting 960 with (_.prototype) { 961 addLine.defaultColor = _.defaultColor; 962 addPath.defaultColor = _.defaultColor; 963 addText.defaultColor = _.defaultColor; 964 addText.defaultFont = null; 965 addEllipsePath.defaultColor = _.defaultColor; 966 addRect.defaultColor = _.defaultColor; 967 addPolyline.defaultColor = _.defaultColor; 968 969 } 970 971 // ↑definition of module SVG object 972 973 // ↑definition of module SVG 974 // ============================================================================ 975 976 977 /**#@+ 978 * @description use {@link CeL.net.SVG} to draw: 979 */ 980 981 /* 982 draw_circle[generateCode.dLK] 983 =draw_ellipse[generateCode.dLK] 984 =draw_triangle[generateCode.dLK] 985 =draw_quadrilateral[generateCode.dLK] 986 ='g_SVG'; 987 */ 988 989 CeL.net.SVG 990 . 991 /** 992 * 繪製圓形。 993 * @since 2006/12/19 18:05 994 * @param _r 995 * @param svgO 996 * @param _color 997 * @param _fill 998 * @return module SVG object 999 * @memberOf CeL.net.SVG 1000 */ 1001 draw_circle = function(_r, svgO, _color, _fill) { 1002 var g_SVG = library_namespace.net.SVG; 1003 if (_r 1004 && (svgO || (svgO = new g_SVG( 1005 (_r + g_SVG.defaultStrokeWidth) * 2, 1006 (_r + g_SVG.defaultStrokeWidth) * 2).show())) 1007 && svgO.status_OK()) { 1008 svgO.addCircle(_r, _r + g_SVG.defaultStrokeWidth, _r 1009 + g_SVG.defaultStrokeWidth); 1010 return svgO; 1011 } 1012 }; 1013 CeL.net.SVG 1014 . 1015 /** 1016 * 繪製橢圓。 1017 * @param _rx 1018 * @param _ry 1019 * @param svgO 1020 * @param _color 1021 * @param _fill 1022 * @return module SVG object 1023 * @memberOf CeL.net.SVG 1024 */ 1025 draw_ellipse = function(_rx, _ry, svgO, _color, _fill) { 1026 var g_SVG = library_namespace.net.SVG; 1027 if (_rx 1028 && _ry 1029 && (svgO || (svgO = new g_SVG( 1030 (_rx + g_SVG.defaultStrokeWidth) * 2, 1031 (_ry + g_SVG.defaultStrokeWidth) * 2).show())) 1032 && svgO.status_OK()) { 1033 svgO.addEllipse(_rx, _ry, _rx + g_SVG.defaultStrokeWidth, _ry 1034 + g_SVG.defaultStrokeWidth); 1035 return svgO; 1036 } 1037 }; 1038 1039 1040 CeL.net.SVG 1041 . 1042 /** 1043 * 畫簡單梯形。 1044 * @since 2006/12/17 12:38 1045 * @requires split_String_to_Object,set_attribute,XML_node,removeNode,remove_all_child,g_SVG,draw_quadrilateral 1046 * @param _ds 1047 * @param _h 1048 * @param _d 1049 * @param _us 1050 * @param svgO 1051 * @param _color 1052 * @param _fill 1053 * @return module SVG object 1054 * @memberOf CeL.net.SVG 1055 */ 1056 draw_quadrilateral = function(_ds, _h, _d, _us, svgO, _color, _fill) { 1057 var g_SVG = library_namespace.net.SVG; 1058 if (isNaN(_us) || _us === '') 1059 _us = _ds; 1060 if (_ds 1061 && _h 1062 && (svgO || (svgO = new g_SVG((_ds > _d + _us ? _ds : _d 1063 + _us) 1064 + g_SVG.defaultStrokeWidth, _h 1065 + g_SVG.defaultStrokeWidth).show())) 1066 && svgO.status_OK()) { 1067 set_attribute(svgO.addQuadrilateral(_ds, _h, _d, _us).lastQuadrilateral, 1068 { 1069 stroke : _color, 1070 fill : _fill 1071 }); 1072 return svgO; 1073 } 1074 }; 1075 1076 CeL.net.SVG 1077 . 1078 /** 1079 * 畫簡單三角形。 1080 * @since 2006/12/17 12:38 1081 * @requires split_String_to_Object,set_attribute,XML_node,removeNode,remove_all_child,g_SVG,draw_triangle 1082 * @param _ds 1083 * @param _h 1084 * @param _d 1085 * @param svgO 1086 * @param _color 1087 * @param _fill 1088 * @return module SVG object 1089 * @memberOf CeL.net.SVG 1090 */ 1091 draw_triangle = function(_ds, _h, _d, svgO, _color, _fill) { 1092 var g_SVG = library_namespace.net.SVG; 1093 if (_ds 1094 && _h 1095 && (svgO || (svgO = new g_SVG((_ds > _d ? _ds : _d) 1096 + g_SVG.defaultStrokeWidth, _h 1097 + g_SVG.defaultStrokeWidth).show())) 1098 && svgO.status_OK()) { 1099 set_attribute(svgO.addTriangle(_ds, _h, _d).lastTriangleDefs, { 1100 stroke : _color, 1101 fill : _fill 1102 }); 1103 return svgO; 1104 } 1105 }; 1106 1107 /* 1108 draw_addition[generateCode.dLK] 1109 =draw_multiplication[generateCode.dLK] 1110 =draw_long_division[generateCode.dLK] 1111 ='g_SVG,draw_scale'; 1112 */ 1113 1114 /** 1115 * default 畫筆。 1116 * @inner 1117 * @private 1118 */ 1119 var draw_scale = { 1120 /** 1121 * text width 1122 * @inner 1123 * @private 1124 */ 1125 tW : 10, 1126 /** 1127 * text height 1128 * @inner 1129 * @private 1130 */ 1131 tH : 2 * (10/* tW */- 2), 1132 /** 1133 * decimal separator, 小數點 1134 * @see 1135 * <a href="http://en.wikipedia.org/wiki/Decimal_separator" accessdate="2010/1/20 18:29">Decimal separator</a> 1136 */ 1137 ds : '.', 1138 /** 1139 * width of decimal separator 1140 */ 1141 dsw : 4, 1142 /** 1143 * line height 1144 * @inner 1145 * @private 1146 */ 1147 lH : 4, 1148 /** 1149 * margin left 1150 * @inner 1151 * @private 1152 */ 1153 mL : 0, 1154 /** 1155 * margin top 1156 * @inner 1157 * @private 1158 */ 1159 mT : 0, 1160 /** 1161 * 根號寬, squire width 1162 * @inner 1163 * @private 1164 */ 1165 sW : 10 1166 }; 1167 //draw_scale.tH=22,draw_scale.tW=12; // for print 1168 CeL.net.SVG 1169 . 1170 /** 1171 * 利用 module SVG 物件來演示直式加法。 1172 * @since 2006/12/26 17:47 1173 * @param num1 1174 * @param num2 1175 * @param svgO 1176 * @param _color 1177 * @param _font 1178 * @return module SVG object 1179 * @memberOf CeL.net.SVG 1180 */ 1181 draw_addition=function(num1, num2, svgO, _color, _font) { 1182 if (!num1 && !num2) 1183 return; 1184 var g_SVG = library_namespace.net.SVG; 1185 var _op = '+'; 1186 if (num2 < 0) 1187 _op = '-', num2 = -num2; 1188 1189 var _a = _op == '+' ? (num1 - 0) + (num2 - 0) : num1 - num2, 1190 _h = 3, 1191 _w = (num2 += '').length + 2, 1192 tW = draw_scale.tW, 1193 tH = draw_scale.tH, 1194 lH = draw_scale.lH, 1195 mL = draw_scale.mL, 1196 mT = draw_scale.mT; 1197 1198 if ((_a += '').length + 1 > _w) 1199 _w = _a.length + 1; 1200 if ((num1 += '').length + 1 > _w) 1201 _w = num1.length + 1; 1202 _h = _h * tH + 2 * lH + 2 * mT; 1203 _w = (2 + _w) * tW + 2 * mL; 1204 1205 if (svgO && svgO.status_OK()) 1206 svgO.clean(); 1207 else if (!(svgO = new g_SVG).show().status_OK()) 1208 return null; 1209 1210 svgO.setSize(_w, _h); 1211 1212 _w -= mL + tW; 1213 1214 // TODO: 讓 IE8 顯示起來像 111+111=222, 而非 +111111222 1215 svgO 1216 .addNum(num1, _w - num1.length * tW, mT + tH, tW, _color, _font) 1217 .addNum(num2, _w - num2.length * tW, mT + 2 * tH, tW, _color, _font) 1218 .addText(_op, mL + tW, mT + 2 * tH, _color, _font) 1219 .addPath('M' + mL + ',' + (mT + 2 * tH + lH / 2) + ' H' + (_w + tW)) 1220 .addNum(_a, _w - _a.length * tW, mT + 3 * tH + lH, tW, _color, _font); 1221 1222 return svgO; 1223 }; 1224 //draw_subtraction[generateCode.dLK]='draw_addition'; 1225 CeL.net.SVG 1226 . 1227 /** 1228 * 呼叫 draw_subtraction 來演示直式減法。因為直式加減法的運算與機制過程非常相似,因此我們以 draw_addition 來一併的處理這兩個相似的運算過程。 1229 * @since 2006/12/26 17:47 1230 * @param num1 1231 * @param num2 1232 * @param svgO 1233 * @param _color 1234 * @param _font 1235 * @return module SVG object 1236 * @memberOf CeL.net.SVG 1237 */ 1238 draw_subtraction = function(num1, num2, svgO, _color, _font) { 1239 return _.draw_addition.call(this, num1, -num2, svgO, _color, _font); 1240 }; 1241 1242 CeL.net.SVG 1243 . 1244 /** 1245 * 利用 module SVG 物件來演示直式乘法。<br/> 1246 * TODO: 小數的乘法 1247 * @since 2006/12/26 17:47 1248 * @param num1 1249 * @param num2 1250 * @param svgO 1251 * @param _color 1252 * @param _font 1253 * @return module SVG object 1254 * @memberOf CeL.net.SVG 1255 * @see 1256 * <a href="http://203.71.239.19/math/courses/cs04/M4_6.php" accessdate="2010/1/20 18:5">小數篇:小數的乘法</a> 1257 */ 1258 draw_multiplication=function(num1, num2, svgO, _color, _font) { 1259 if (!num1 && !num2) 1260 return; 1261 1262 var g_SVG = library_namespace.net.SVG; 1263 var _op = '×', _j, _C = 1, _a = num1 * num2, _h = 0, _w = (num2 += '').length + 2, tW = draw_scale.tW, tH = draw_scale.tH, lH = draw_scale.lH, mL = draw_scale.mL, mT = draw_scale.mT; 1264 if ((_a += '').length > _w) 1265 _w = _a.length; 1266 if ((num1 += '').length > _w) 1267 _w = num1.length; 1268 for (_j = 0; _j < num2.length; _j++) 1269 if (num2.charAt(_j) - 0) 1270 _h++; 1271 if (_h == 1) 1272 _h = 0, _C = 0; 1273 _h = (3 + _h) * tH + 2 * lH + 2 * mT; 1274 _w = (2 + _w) * tW + 2 * mL; 1275 1276 if (svgO && svgO.status_OK()) 1277 svgO.clean(); 1278 else if (!(svgO = new g_SVG).show().status_OK()) 1279 return null; 1280 1281 svgO.setSize(_w, _h); 1282 1283 _w -= mL + tW; 1284 1285 svgO 1286 .addNum(num1, _w - num1.length * tW, mT + tH, tW, _color, _font) 1287 .addNum(num2, _w - num2.length * tW, mT + 2 * tH, tW, _color, _font) 1288 .addText(_op, mL + tW, mT + 2 * tH, _color, _font) 1289 .addPath('M' + mL + ',' + (_h = mT + 2 * tH + lH / 2) + ' H' + (_w + tW)); 1290 1291 _op = ''; 1292 _h += lH / 2; 1293 var _w2 = _w, _n; 1294 if (_C) { 1295 for (_j = num2.length - 1; _j >= 0; _j--) 1296 if (_n = num2.charAt(_j) - 0) 1297 svgO.addNum(_n = (num1 * _n) + _op, _w2 - _n.length 1298 * tW, _h += tH, tW, _color, _font), _w2 -= tW 1299 * (_op.length + 1), _op = ''; 1300 else 1301 _op += '0'; 1302 svgO 1303 .addPath('M' + mL + ',' + (_h += lH / 2) + ' H' 1304 + (_w + tW)); 1305 } 1306 1307 svgO.addNum(_a, _w - _a.length * tW, _h + lH / 2 + tH, tW, _color, _font); 1308 1309 return svgO; 1310 }; 1311 1312 /* 1313 TODO: 1314 小數 1315 換基底 1316 */ 1317 //draw_long_division[generateCode.dLK]='g_SVG,set_class';//split_String_to_Object,set_attribute,XML_node,removeNode,remove_all_child,g_SVG,draw_long_division 1318 CeL.net.SVG 1319 . 1320 /** 1321 * 利用 module SVG 物件來展示<a href="http://en.wikipedia.org/wiki/Long_division" title="long division">直式除法</a>。<br/> 1322 * !! 尚有許多 bug<br/> 1323 * @since 2006/12/11-12 11:36 1324 * @param dividend 1325 * @param divisor 1326 * @param digits_after TODO: 小數直式除法: 小數點後位數, how many digits after the decimal separator 1327 * @param svgO 1328 * @param _color 1329 * @param _font 1330 * @return module SVG object 1331 * @example 1332 * // include module 1333 * CeL.use('net.SVG'); 1334 * 1335 * // way 1 1336 * var SVG_object = new CeL.SVG; 1337 * SVG_object.attach('panel_for_SVG').show(1); 1338 * CeL.draw_long_division(452, 34, SVG_object); 1339 * // You can also put here. 1340 * //SVG_object.attach('panel_for_SVG').show(1); 1341 * 1342 * // way 2 1343 * var SVG_object = CeL.draw_long_division(100000, 7); 1344 * SVG_object.attach('panel_for_SVG').show(1); 1345 * 1346 * // 另一次顯示 1347 * CeL.draw_long_division(100, 7, SVG_object); 1348 * @memberOf CeL.net.SVG 1349 */ 1350 draw_long_division = function(dividend, divisor, svgO, _color, _font) { 1351 if (isNaN(dividend) || isNaN(divisor) || !divisor) 1352 return; 1353 1354 var g_SVG = library_namespace.net.SVG; 1355 /** 1356 * 餘數 remainder 1357 * @inner 1358 * @ignore 1359 */ 1360 var remainder; 1361 /** 1362 * 商 quotient 1363 * @inner 1364 * @ignore 1365 */ 1366 var quotient = '' + Math.floor(dividend / divisor), 1367 tW = draw_scale.tW, 1368 tH = draw_scale.tH, 1369 lH = draw_scale.lH, 1370 mL = draw_scale.mL, 1371 mT = draw_scale.mT, 1372 sW = draw_scale.sW, 1373 bx = mL + ('' + divisor).length * tW + sW, 1374 by = mT + lH + 2 * tH; 1375 1376 dividend += ''; 1377 if (svgO && svgO.status_OK()) 1378 svgO.clean(); 1379 else if (!(svgO = new g_SVG).show().status_OK()) 1380 return null; 1381 1382 svgO 1383 //.show(1) 1384 // 調整大小 1385 .setSize( 1386 2 1387 * mL 1388 + (('' + divisor).length + dividend.length + 2) 1389 * tW + sW, 1390 2 * mT + by + quotient.length * (tH * 2 + lH)) 1391 // 除數 divisor 1392 .addNum(divisor, mL, by, tW, _color, _font) 1393 // 商 quotient 1394 .addNum(quotient, 1395 bx + (dividend.length - quotient.length) * tW, 1396 mT + tH, tW, _color, _font) 1397 // 被除數 dividend 1398 .addNum(dividend, bx, by, tW, _color, _font) 1399 // .addNode('path',{d:'M'+(bx+(dividend.length+1)*tW)+','+(by-lH/2-tH)+' 1400 // H'+(bx-tW)+' a'+tW/2+','+(lH+tH)+' 0 0,1 1401 // -'+tW/2+','+(lH+tH),stroke:'#000',style:'fill:none;'}) 1402 .addPath( 1403 'M' + (bx - (tW + sW) / 2) + ',' + (by + lH / 2) 1404 + ' a' + tW / 2 + ',' + (lH + tH) 1405 + ' 0 0,0 ' + tW / 2 + ',-' + (lH + tH) 1406 + ' h' + (dividend.length + 2) * tW); 1407 1408 svgO.addDefs(g_SVG.createNode('line', { 1409 x1 : 0, 1410 y1 : 0, 1411 x2 : (dividend.length + 1) * tW, 1412 y2 : 0, 1413 // 'stroke-width':'1px', 1414 stroke : svgO.addLine.defaultColor 1415 })); 1416 1417 if (svgO.div) 1418 // svgO.div.className='long_division'; 1419 set_class(svgO.div, 'long_division'); 1420 1421 // 用 symbol?? 1422 svgO.addContain(0, 'long_division', { 1423 dividend : dividend, 1424 divisor : divisor 1425 }); 1426 1427 var _k = 0, a, b, l = svgO.lastAddDefs, 1428 /** 1429 * 被除數處理到第幾位 1430 * @inner 1431 * @ignore 1432 */ 1433 dt = 1; 1434 remainder = dividend.charAt(0); 1435 for (; _k < quotient.length;) { 1436 a = quotient.charAt(_k); 1437 // if(!a)continue; 1438 a = '' + a * divisor, b = dividend.length 1439 - quotient.length + _k + 1; 1440 1441 svgO.addUse(l, { 1442 x : bx, 1443 y : (by + tH + lH / 2) 1444 }).addNum(a, bx + (b - a.length) * tW, by + tH, tW, _color, 1445 _font); 1446 1447 // 以下..ugly hack 1448 // 先算出餘數 1449 while ((a == 0 || remainder - a < 0) && dt < dividend.length) 1450 remainder += dividend.charAt(dt++); 1451 remainder -= a; 1452 if (!remainder) 1453 remainder = ''; 1454 //alert(remainder+','+quotient.charAt(_k+1)+'\n'+(i<quotient.length)) 1455 // 再添加到夠減的位數 1456 while (quotient.charAt(++_k) == 0 && _k < quotient.length) { 1457 b++; 1458 if (remainder || dividend.charAt(dt) > 0) 1459 remainder += dividend.charAt(dt); 1460 dt++; 1461 } 1462 // 顯示位數微調 1463 if (dt < dividend.length) { 1464 b++; 1465 // 加一位 1466 remainder += dividend.charAt(dt++); 1467 } else if (!remainder) 1468 b--; 1469 //alert(remainder+','+a+','+dt+'\n'+(remainder<a)); 1470 svgO.addNum(remainder || 0, bx + (b - ('' + remainder).length) 1471 * tW, by += 2 * tH + lH, tW, _color, _font); 1472 } 1473 1474 return svgO; 1475 }; 1476 1477 1478 /**#@-*/ 1479 // ↑@memberOf module SVG 1480 1481 1482 1483 1484 return ( 1485 CeL.net.SVG 1486 ); 1487 }; 1488 1489 //=================================================== 1490 1491 CeL.setup_module(module_name, code_for_including); 1492 1493 }; 1494