UNPKG

uil

Version:

JavaScript gui library

1,763 lines (1,156 loc) 240 kB
/** * @author lth / https://github.com/lo-th */ const REVISION = '4.4.0'; // INTENAL FUNCTION /*const observer = new IntersectionObserver((entries) => { for (const entry of entries) { console.log(entry) //const bounds = entry.boundingClientRect; entry.target.bounds = entry.boundingClientRect; } observer.disconnect(); })*/ const R = { ui: [], debug:false, dom:null, ID: null, lock:false, wlock:false, current:-1, needReZone: true, needResize:false, forceZone:false, isEventsInit: false, isLeave:false, downTime:0, prevTime:0, //prevDefault: ['contextmenu', 'wheel'], prevDefault: ['contextmenu'], pointerEvent: ['pointerdown', 'pointermove', 'pointerup'], eventOut: ['pointercancel', 'pointerout', 'pointerleave'], xmlserializer: null, tmpTime: null, tmpImage: null, oldCursor:'auto', input: null, parent: null, firstImput: true, hiddenImput:null, hiddenSizer:null, hasFocus:false, startInput:false, inputRange : [0,0], cursorId : 0, str:'', pos:0, startX:-1, moveX:-1, debugInput:false, isLoop: false, listens: [], e:{ type:null, clientX:0, clientY:0, keyCode:NaN, key:null, delta:0, }, isMobile: false, now: null, injectCss (css, styleName, parent) { const CSS_ID = styleName || 'codeflask-style'; const PARENT = parent || document.head; if (!css) return false if (document.getElementById(CSS_ID)) return true const style = document.createElement('style'); style.innerHTML = css; style.id = CSS_ID; PARENT.appendChild(style); return true }, getTime: function() { return ( self.performance && self.performance.now ) ? self.performance.now.bind( performance ) : Date.now; }, testMobile: function () { let n = navigator.userAgent; if (n.match(/Android/i) || n.match(/webOS/i) || n.match(/iPhone/i) || n.match(/iPad/i) || n.match(/iPod/i) || n.match(/BlackBerry/i) || n.match(/Windows Phone/i)) return true; else return false; }, // ---------------------- // ADD / REMOVE // ---------------------- add: function ( o ) { R.ui.push( o ); R.getZone( o ); if( !R.isEventsInit ) R.initEvents(); }, remove: function ( o ) { let i = R.ui.indexOf( o ); if ( i !== -1 ) { R.removeListen( o ); R.ui.splice( i, 1 ); } if( R.ui.length === 0 ){ R.removeEvents(); } //console.log('remove:', R.ui.length) }, // ---------------------- // EVENTS // ---------------------- initEvents: function () { if( R.isEventsInit ) return; let dom = document.body; R.isMobile = R.testMobile(); R.now = R.getTime(); if(!R.isMobile){ dom.addEventListener( 'wheel', R, { passive: false } ); } else { dom.style.touchAction = 'none'; } dom.addEventListener( 'pointercancel', R ); dom.addEventListener( 'pointerleave', R ); //dom.addEventListener( 'pointerout', R ) dom.addEventListener( 'pointermove', R ); dom.addEventListener( 'pointerdown', R ); dom.addEventListener( 'pointerup', R ); dom.addEventListener( 'keydown', R, false ); dom.addEventListener( 'keyup', R, false ); window.addEventListener( 'resize', R.resize , false ); //window.onblur = R.out; //window.onfocus = R.in; R.isEventsInit = true; R.dom = dom; //console.log('event is add !') }, removeEvents: function () { if( !R.isEventsInit ) return; let dom = document.body; if(!R.isMobile){ dom.removeEventListener( 'wheel', R ); } dom.removeEventListener( 'pointercancel', R ); dom.removeEventListener( 'pointerleave', R ); //dom.removeEventListener( 'pointerout', R ); dom.removeEventListener( 'pointermove', R ); dom.removeEventListener( 'pointerdown', R ); dom.removeEventListener( 'pointerup', R ); dom.removeEventListener( 'keydown', R ); dom.removeEventListener( 'keyup', R ); window.removeEventListener( 'resize', R.resize ); R.isEventsInit = false; //console.log('event is remove !') }, resize: function () { //console.log('resize !!') let i = R.ui.length, u; while( i-- ){ u = R.ui[i]; if( u.isGui && !u.isCanvasOnly && u.autoResize ) u.calc(); } R.needReZone = true; R.needResize = false; }, out: function () { console.log('im am out'); R.clearOldID(); }, in: function () { console.log('im am in'); // R.clearOldID(); }, // ---------------------- // HANDLE EVENTS // ---------------------- fakeUp: function(){ this.handleEvent( {type:'pointerup'} ); }, handleEvent: function ( event ) { //if(!event.type) return; //if( R.prevDefault.indexOf( event.type ) !== -1 ) event.preventDefault(); if( R.needResize ) R.resize(); R.findZone( R.forceZone ); let e = R.e; let leave = false; if( event.type === 'keydown') R.keydown( event ); if( event.type === 'keyup') R.keyup( event ); if( event.type === 'wheel' ) e.delta = event.deltaY > 0 ? 1 : -1; else e.delta = 0; let ptype = event.pointerType; // mouse, pen, touch e.clientX = ( ptype === 'touch' ? event.pageX : event.clientX ) || 0; e.clientY = ( ptype === 'touch' ? event.pageY : event.clientY ) || 0; e.type = event.type; if( R.eventOut.indexOf( event.type ) !== -1 ){ leave = true; e.type = 'mouseup'; } if( event.type === 'pointerleave') R.isLeave = true; if( event.type === 'pointerdown') e.type = 'mousedown'; if( event.type === 'pointerup') e.type = 'mouseup'; if( event.type === 'pointermove'){ if( R.isLeave ){ // if user resize outside this document R.isLeave = false; R.resize(); } e.type = 'mousemove'; } // double click test if( e.type === 'mousedown' ) { R.downTime = R.now(); let time = R.downTime - R.prevTime; // double click on imput if( time < 200 ) { R.selectAll(); return false } R.prevTime = R.downTime; R.forceZone = false; } // for imput if( e.type === 'mousedown' ) R.clearInput(); // mouse lock if( e.type === 'mousedown' ) R.lock = true; if( e.type === 'mouseup' ) R.lock = false; //if( R.current !== null && R.current.neverlock ) R.lock = false; /*if( e.type === 'mousedown' && event.button === 1){ R.cursor() e.preventDefault(); e.stopPropagation(); }*/ if( R.isMobile && e.type === 'mousedown' ) R.findID( e ); if( e.type === 'mousemove' && !R.lock ) R.findID( e ); if( R.ID !== null ){ if( R.ID.isCanvasOnly ) { e.clientX = R.ID.mouse.x; e.clientY = R.ID.mouse.y; } //if( R.ID.marginDiv ) e.clientY -= R.ID.margin * 0.5 R.ID.handleEvent( e ); } if( R.isMobile && e.type === 'mouseup' ) R.clearOldID(); if( leave ) R.clearOldID(); }, // ---------------------- // ID // ---------------------- findID: function ( e ) { let i = R.ui.length, next = -1, u, x, y; while( i-- ){ u = R.ui[i]; if( u.isCanvasOnly ) { x = u.mouse.x; y = u.mouse.y; } else { x = e.clientX; y = e.clientY; } if( R.onZone( u, x, y ) ){ next = i; if( next !== R.current ){ R.clearOldID(); R.current = next; R.ID = u; } break; } } if( next === -1 ) R.clearOldID(); }, clearOldID: function () { if( !R.ID ) return; R.current = -1; R.ID.reset(); R.ID = null; R.cursor(); }, // ---------------------- // GUI / GROUP FUNCTION // need update if zone change !! // ---------------------- calcUis: ( uis, zone, py, group = false ) => { if( R.debug ) console.log('calc_uis !!'); let i = uis.length, u, px = 0, n = 0, tw; let height = 0; while( i-- ){ u = uis[n]; n++; if( !group && u.isGroup ) u.calcUis(); let m = u.margin || 0; u.zone.w = u.w; u.zone.h = u.h + m; if( !u.autoWidth ){ if( px === 0 ) height += u.h + m; u.zone.x = zone.x + px; u.zone.y = py;// + u.mtop //if(div) u.zone.y += m * 0.5 tw = R.getWidth(u); if( tw ) u.zone.w = u.w = tw; else if( u.fw ) u.zone.w = u.w = u.fw; px += u.zone.w; if( px >= zone.w ) { py += u.h + m; //if(div) py += m * 0.5 px = 0; } } else { px = 0; u.zone.x = zone.x + u.dx; u.zone.y = py; py += u.h + m; height += (u.h + m); //-0.5;// ??? } } return height }, findTarget: function ( uis, e ) { let i = uis.length; while( i-- ){ if( R.onZone( uis[i], e.clientX, e.clientY ) ) return i } return -1; }, // ---------------------- // ZONE // ---------------------- findZone: function ( force = false ) { if( force ) R.needReZone = force; if( !R.needReZone ) return; let i = R.ui.length, u; while( i-- ){ u = R.ui[i]; R.getZone( u ); // TODO need for group open at start !!! if( u.isGui ) u.calcUis(); } R.needReZone = false; }, onZone: function ( o, x, y ) { //console.log(o, x, y) if( x === undefined || y === undefined ) return false; let z = o.zone; let mx = x - z.x;// - o.dx; let my = y - z.y; //if( this.marginDiv ) e.clientY -= this.margin * 0.5 //if( o.group && o.group.marginDiv ) my += o.group.margin * 0.5 //if( o.group !== null ) mx -= o.dx let over = ( mx >= 0 ) && ( my >= 0 ) && ( mx <= z.w ) && ( my <= z.h ); //if( o.marginDiv ) my -= o.margin * 0.5 if( over ) o.local.set( mx, my ); else o.local.neg(); return over; }, getWidth: function ( o ) { //return o.getDom().offsetWidth return o.getDom().clientWidth; //let r = o.getDom().getBoundingClientRect(); //return (r.width) //return Math.floor(r.width) }, getZone: function ( o ) { if( o.isCanvasOnly ) return; if( o.isEmpty ) return; const element = o.getDom(); const r = element.getBoundingClientRect(); o.zone = { x:r.left, y:r.top, w:r.width, h:r.height }; if( o.isBottom ) o.zone.y = o.realTop; }, // ---------------------- // CURSOR // ---------------------- cursor: function ( name ) { name = name ? name : 'auto'; if( name !== R.oldCursor ){ document.body.style.cursor = name; R.oldCursor = name; } }, // ---------------------- // CANVAS // ---------------------- toCanvas: function ( o, w, h, force ) { if( !R.xmlserializer ) R.xmlserializer = new XMLSerializer(); // prevent exesive redraw if( force && R.tmpTime !== null ) { clearTimeout(R.tmpTime); R.tmpTime = null; } if( R.tmpTime !== null ) return; if( R.lock ) R.tmpTime = setTimeout( function(){ R.tmpTime = null; }, 10 ); /// let isNewSize = false; if( w !== o.canvas.width || h !== o.canvas.height ) isNewSize = true; if( R.tmpImage === null ) R.tmpImage = new Image(); let img = R.tmpImage; //new Image(); let htmlString = R.xmlserializer.serializeToString( o.content ); let svg = '<svg xmlns="http://www.w3.org/2000/svg" width="'+w+'" height="'+h+'"><foreignObject style="pointer-events: none; left:0;" width="100%" height="100%">'+ htmlString +'</foreignObject></svg>'; img.onload = function() { let ctx = o.canvas.getContext("2d"); if( isNewSize ){ o.canvas.width = w; o.canvas.height = h; }else { ctx.clearRect( 0, 0, w, h ); } ctx.drawImage( this, 0, 0 ); o.onDraw(); }; img.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg); //img.src = 'data:image/svg+xml;base64,'+ window.btoa( svg ); img.crossOrigin = ''; }, // ---------------------- // INPUT // ---------------------- setHidden: function () { if( R.hiddenImput === null ){ //let css = R.parent.css.txtselect + 'padding:0; width:auto; height:auto; ' //let css = R.parent.css.txt + 'padding:0; width:auto; height:auto; text-shadow:none;' //css += 'left:10px; top:auto; border:none; color:#FFF; background:#000;' + hide; R.hiddenImput = document.createElement('input'); R.hiddenImput.type = 'text'; //R.hiddenImput.style.cssText = css + 'bottom:30px;' + (R.debugInput ? '' : 'transform:scale(0);'); R.hiddenSizer = document.createElement('div'); //R.hiddenSizer.style.cssText = css + 'bottom:60px;'; document.body.appendChild( R.hiddenImput ); document.body.appendChild( R.hiddenSizer ); } let hide = R.debugInput ? '' : 'opacity:0; zIndex:0;'; let css = R.parent.css.txtselect + 'padding:0; width:auto; height:auto; left:10px; top:auto; color:#FFF; background:#000;'+ hide; R.hiddenImput.style.cssText = css + 'bottom:10px;' + (R.debugInput ? '' : 'transform:scale(0);'); R.hiddenSizer.style.cssText = css + 'bottom:40px;'; R.hiddenImput.style.width = R.input.clientWidth + 'px'; R.hiddenImput.value = R.str; R.hiddenSizer.innerHTML = R.str; R.hasFocus = true; }, clearHidden: function ( p ) { if( R.hiddenImput === null ) return; R.hasFocus = false; }, clickPos: function( x ){ let i = R.str.length, l = 0, n = 0; while( i-- ){ l += R.textWidth( R.str[n] ); if( l >= x ) break; n++; } return n; }, upInput: function ( x, down ) { if( R.parent === null ) return false; let up = false; if( down ){ let id = R.clickPos( x ); R.moveX = id; if( R.startX === -1 ){ R.startX = id; R.cursorId = id; R.inputRange = [ R.startX, R.startX ]; } else { let isSelection = R.moveX !== R.startX; if( isSelection ){ if( R.startX > R.moveX ) R.inputRange = [ R.moveX, R.startX ]; else R.inputRange = [ R.startX, R.moveX ]; } } up = true; } else { if( R.startX !== -1 ){ R.hasFocus = true; R.hiddenImput.focus(); R.hiddenImput.selectionStart = R.inputRange[0]; R.hiddenImput.selectionEnd = R.inputRange[1]; R.startX = -1; up = true; } } if( up ) R.selectParent(); return up; }, selectAll: function (){ if(!R.parent) return R.str = R.input.textContent; R.inputRange = [0, R.str.length ]; R.hasFocus = true; R.hiddenImput.focus(); R.hiddenImput.selectionStart = R.inputRange[0]; R.hiddenImput.selectionEnd = R.inputRange[1]; R.cursorId = R.inputRange[1]; R.selectParent(); }, selectParent: function (){ var c = R.textWidth( R.str.substring( 0, R.cursorId )); var e = R.textWidth( R.str.substring( 0, R.inputRange[0] )); var s = R.textWidth( R.str.substring( R.inputRange[0], R.inputRange[1] )); R.parent.select( c, e, s, R.hiddenSizer.innerHTML ); }, textWidth: function ( text ){ if( R.hiddenSizer === null ) return 0; text = text.replace(/ /g, '&nbsp;'); R.hiddenSizer.innerHTML = text; return R.hiddenSizer.clientWidth; }, clearInput: function () { if( R.parent === null ) return; if( !R.firstImput ) R.parent.validate( true ); R.clearHidden(); R.parent.unselect(); //R.input.style.background = 'none'; R.input.style.background = R.parent.colors.back; R.input.style.borderColor = R.parent.colors.border; //R.input.style.color = R.parent.colors.text; R.parent.isEdit = false; R.input = null; R.parent = null; R.str = '', R.firstImput = true; }, setInput: function ( Input, parent ) { R.clearInput(); R.input = Input; R.parent = parent; R.input.style.background = R.parent.colors.backoff; R.input.style.borderColor = R.parent.colors.select; //R.input.style.color = R.parent.colors.textSelect; R.str = R.input.textContent; R.setHidden(); }, keydown: function ( e ) { if( R.parent === null ) return; let keyCode = e.which; e.shiftKey; //console.log( keyCode ) R.firstImput = false; if (R.hasFocus) { // hack to fix touch event bug in iOS Safari window.focus(); R.hiddenImput.focus(); } R.parent.isEdit = true; // e.preventDefault(); // add support for Ctrl/Cmd+A selection //if ( keyCode === 65 && (e.ctrlKey || e.metaKey )) { //R.selectText(); //e.preventDefault(); //return self.render(); //} if( keyCode === 13 ){ //enter R.clearInput(); //} else if( keyCode === 9 ){ //tab key // R.input.textContent = ''; } else { if( R.input.isNum ){ if ( ((e.keyCode > 47) && (e.keyCode < 58)) || ((e.keyCode > 95) && (e.keyCode < 106)) || e.keyCode === 190 || e.keyCode === 110 || e.keyCode === 8 || e.keyCode === 109 ){ R.hiddenImput.readOnly = false; } else { R.hiddenImput.readOnly = true; } } else { R.hiddenImput.readOnly = false; } } }, keyup: function ( e ) { if( R.parent === null ) return; R.str = R.hiddenImput.value; if( R.parent.allEqual ) R.parent.sameStr( R.str );// numeric samùe value else R.input.textContent = R.str; R.cursorId = R.hiddenImput.selectionStart; R.inputRange = [ R.hiddenImput.selectionStart, R.hiddenImput.selectionEnd ]; R.selectParent(); //if( R.parent.allway ) R.parent.validate(); }, // ---------------------- // // LISTENING // // ---------------------- loop: function () { if( R.isLoop ) requestAnimationFrame( R.loop ); R.update(); }, update: function () { let i = R.listens.length; while( i-- ) R.listens[i].listening(); }, removeListen: function ( proto ) { let id = R.listens.indexOf( proto ); if( id !== -1 ) R.listens.splice(id, 1); if( R.listens.length === 0 ) R.isLoop = false; }, addListen: function ( proto ) { let id = R.listens.indexOf( proto ); if( id !== -1 ) return false; R.listens.push( proto ); if( !R.isLoop ){ R.isLoop = true; R.loop(); } return true; }, }; const Roots = R; /** * @author lth / https://github.com/lo-th */ //import { PixelFont } from './PixelFont.js'; const T = { size: { w:320, h:24, p:30, s:8 }, // three reference class texture: null, transition: 0.1, frag: document.createDocumentFragment(), colorRing: null, joystick_0: null, joystick_1: null, circular: null, knob: null, pad2d: null, svgns: "http://www.w3.org/2000/svg", links: "http://www.w3.org/1999/xlink", htmls: "http://www.w3.org/1999/xhtml", DOM_SIZE: [ 'height', 'width', 'top', 'left', 'bottom', 'right', 'margin-left', 'margin-right', 'margin-top', 'margin-bottom'], SVG_TYPE_D: [ 'pattern', 'defs', 'transform', 'stop', 'animate', 'radialGradient', 'linearGradient', 'animateMotion', 'use', 'filter', 'feColorMatrix' ], SVG_TYPE_G: [ 'svg', 'rect', 'circle', 'path', 'polygon', 'text', 'g', 'line', 'foreignObject' ], PI: Math.PI, TwoPI: Math.PI*2, pi90: Math.PI * 0.5, pi60: Math.PI/3, torad: Math.PI / 180, todeg: 180 / Math.PI, clamp: ( v, min, max ) => { v = v < min ? min : v; v = v > max ? max : v; return v; }, isDivid: ( v ) => ( v*0.5 === Math.floor(v*0.5) ), // ---------------------- // COLOR // ---------------------- defineColor: ( o, cc = T.colors ) => { //Roots.injectCss(PixelFont, null) let color = { ...cc }; let textChange = ['fontFamily', 'fontWeight', 'fontShadow', 'fontSize' ]; let changeText = false; if( o.font ) o.fontFamily = o.font; if( o.shadow ) o.fontShadow = o.shadow; if( o.weight ) o.fontWeight = o.weight; if( o.fontColor ) o.text = o.fontColor; if( o.color ) o.text = o.color; if( o.text ){ color.text = o.text; if( !o.fontColor && !o.color ){ color.title = T.ColorLuma( o.text, -0.25 ); color.titleoff = T.ColorLuma( o.text, -0.5 ); } color.textOver = T.ColorLuma( o.text, 0.25 ); color.textSelect = T.ColorLuma( o.text, 0.5 ); } if( o.button ){ color.button = o.button; color.border = T.ColorLuma( o.button, 0.1 ); color.overoff = T.ColorLuma( o.button, 0.2 ); } if( o.select ){ color.select = o.select; color.over = T.ColorLuma( o.select, -0.1 ); } if( o.itemBg ) o.back = o.itemBg; if( o.back ){ color.back = o.back; color.backoff = T.ColorLuma( o.back, -0.1 ); } if( o.fontSelect ) color.textSelect = o.fontSelect; if( o.groupBorder ) color.gborder = o.groupBorder; //if( o.transparent ) o.bg = 'none' //if( o.bg ) color.background = color.backgroundOver = o.bg if( o.bgOver ) color.backgroundOver = o.bgOver; for( let m in color ){ if(o[m]!==undefined) color[m] = o[m]; } for( let m in o ){ if( textChange.indexOf(m) !== -1 ) changeText = true; } if( changeText ) T.defineText( color ); return color }, colors: { sx: 4,//4 sy: 0,//2 radius:6,//2 showOver : 1, //groupOver : 1, content:'#37383d',//#28292e',//'none', background: '#28292e',//'rgba(30,30,30,0)', backgroundOver: 'rgba(40,40,40,0)', title : '#CCC', titleoff : '#BBB', text : '#DDD', textOver : '#EEE', textSelect : '#FFF', back:'rgba(0,0,0,0.2)', backoff:'rgba(0,0,0,0.3)', // input and button border border : '#4c4c4c', borderSize : 1, gborder : 'none', groups : 'none', button : '#3c3c3c', overoff : '#5c5c5c', over : '#024699', select : '#308AFF', action: '#FF3300', //fontFamily: 'Tahoma', //fontFamily: 'Consolas, monospace', //fontFamily:"'SegoeUI', 'Segoe UI', 'Helvetica Neue', -apple-system, BlinkMacSystemFont, Roboto, Oxygen-Sans, Ubuntu, Cantarell, sans-serif", fontFamily:"Roboto Mono, Source Code Pro, Menlo, Courier, monospace", //fontFamily: "'Roboto Mono', 'Source Code Pro', Menlo, Courier, monospace", fontWeight: 'normal', fontShadow: 'none',//'#000', fontSize:11, joyOver:'rgba(48,138,255,0.25)', joyOut: 'rgba(100,100,100,0.5)', joySelect: '#308AFF', hide: 'rgba(0,0,0,0)', }, // style css css : { basic: 'position:absolute; pointer-events:none; box-sizing:border-box; margin:0; padding:0; overflow:hidden; ' + '-o-user-select:none; -ms-user-select:none; -khtml-user-select:none; -webkit-user-select:none; -moz-user-select:none;', button:'display:flex; align-items:center; justify-content:center; text-align:center;', middle:'display:flex; align-items:center; justify-content:left; text-align:left; flex-direction: row-reverse;' }, // svg path svgs: { g1:'M 6 4 L 0 4 0 6 6 6 6 4 M 6 0 L 0 0 0 2 6 2 6 0 Z', g2:'M 6 0 L 4 0 4 6 6 6 6 0 M 2 0 L 0 0 0 6 2 6 2 0 Z', group:'M 7 7 L 7 8 8 8 8 7 7 7 M 5 7 L 5 8 6 8 6 7 5 7 M 3 7 L 3 8 4 8 4 7 3 7 M 7 5 L 7 6 8 6 8 5 7 5 M 6 6 L 6 5 5 5 5 6 6 6 M 7 3 L 7 4 8 4 8 3 7 3 M 6 4 L 6 3 5 3 5 4 6 4 M 3 5 L 3 6 4 6 4 5 3 5 M 3 3 L 3 4 4 4 4 3 3 3 Z', arrow:'M 3 8 L 8 5 3 2 3 8 Z', arrowDown:'M 5 8 L 8 3 2 3 5 8 Z', arrowUp:'M 5 2 L 2 7 8 7 5 2 Z', solid:'M 13 10 L 13 1 4 1 1 4 1 13 10 13 13 10 M 11 3 L 11 9 9 11 3 11 3 5 5 3 11 3 Z', body:'M 13 10 L 13 1 4 1 1 4 1 13 10 13 13 10 M 11 3 L 11 9 9 11 3 11 3 5 5 3 11 3 M 5 4 L 4 5 4 10 9 10 10 9 10 4 5 4 Z', vehicle:'M 13 6 L 11 1 3 1 1 6 1 13 3 13 3 11 11 11 11 13 13 13 13 6 M 2.4 6 L 4 2 10 2 11.6 6 2.4 6 M 12 8 L 12 10 10 10 10 8 12 8 M 4 8 L 4 10 2 10 2 8 4 8 Z', articulation:'M 13 9 L 12 9 9 2 9 1 5 1 5 2 2 9 1 9 1 13 5 13 5 9 4 9 6 5 8 5 10 9 9 9 9 13 13 13 13 9 Z', character:'M 13 4 L 12 3 9 4 5 4 2 3 1 4 5 6 5 8 4 13 6 13 7 9 8 13 10 13 9 8 9 6 13 4 M 6 1 L 6 3 8 3 8 1 6 1 Z', terrain:'M 13 8 L 12 7 Q 9.06 -3.67 5.95 4.85 4.04 3.27 2 7 L 1 8 7 13 13 8 M 3 8 Q 3.78 5.420 5.4 6.6 5.20 7.25 5 8 L 7 8 Q 8.39 -0.16 11 8 L 7 11 3 8 Z', joint:'M 7.7 7.7 Q 8 7.45 8 7 8 6.6 7.7 6.3 7.45 6 7 6 6.6 6 6.3 6.3 6 6.6 6 7 6 7.45 6.3 7.7 6.6 8 7 8 7.45 8 7.7 7.7 M 3.35 8.65 L 1 11 3 13 5.35 10.65 Q 6.1 11 7 11 8.28 11 9.25 10.25 L 7.8 8.8 Q 7.45 9 7 9 6.15 9 5.55 8.4 5 7.85 5 7 5 6.54 5.15 6.15 L 3.7 4.7 Q 3 5.712 3 7 3 7.9 3.35 8.65 M 10.25 9.25 Q 11 8.28 11 7 11 6.1 10.65 5.35 L 13 3 11 1 8.65 3.35 Q 7.9 3 7 3 5.7 3 4.7 3.7 L 6.15 5.15 Q 6.54 5 7 5 7.85 5 8.4 5.55 9 6.15 9 7 9 7.45 8.8 7.8 L 10.25 9.25 Z', ray:'M 9 11 L 5 11 5 12 9 12 9 11 M 12 5 L 11 5 11 9 12 9 12 5 M 11.5 10 Q 10.9 10 10.45 10.45 10 10.9 10 11.5 10 12.2 10.45 12.55 10.9 13 11.5 13 12.2 13 12.55 12.55 13 12.2 13 11.5 13 10.9 12.55 10.45 12.2 10 11.5 10 M 9 10 L 10 9 2 1 1 2 9 10 Z', collision:'M 11 12 L 13 10 10 7 13 4 11 2 7.5 5.5 9 7 7.5 8.5 11 12 M 3 2 L 1 4 4 7 1 10 3 12 8 7 3 2 Z', map:'M 13 1 L 1 1 1 13 13 13 13 1 M 12 2 L 12 7 7 7 7 12 2 12 2 7 7 7 7 2 12 2 Z', material:'M 13 1 L 1 1 1 13 13 13 13 1 M 12 2 L 12 7 7 7 7 12 2 12 2 7 7 7 7 2 12 2 Z', texture:'M 13 4 L 13 1 1 1 1 4 5 4 5 13 9 13 9 4 13 4 Z', object:'M 10 1 L 7 4 4 1 1 1 1 13 4 13 4 5 7 8 10 5 10 13 13 13 13 1 10 1 Z', none:'M 9 5 L 5 5 5 9 9 9 9 5 Z', cursor:'M 4 7 L 1 10 1 12 2 13 4 13 7 10 9 14 14 0 0 5 4 7 Z', load:'M 13 8 L 11.5 6.5 9 9 9 3 5 3 5 9 2.5 6.5 1 8 7 14 13 8 M 9 2 L 9 0 5 0 5 2 9 2 Z', save:'M 9 12 L 5 12 5 14 9 14 9 12 M 11.5 7.5 L 13 6 7 0 1 6 2.5 7.5 5 5 5 11 9 11 9 5 11.5 7.5 Z', extern:'M 14 14 L 14 0 0 0 0 14 14 14 M 12 6 L 12 12 2 12 2 6 12 6 M 12 2 L 12 4 2 4 2 2 12 2 Z', }, setDebug ( v ) { Roots.debug = v; }, rezone () { Roots.needReZone = true; }, getImput: function(){ return Roots.input ? true : false }, setStyle : function ( data ){ for ( var o in data ){ if( T.colors[o] ) T.colors[o] = data[o]; } T.setText(); }, // ---------------------- // custom text // ---------------------- defineText: function( o ){ T.setText( o.fontSize, o.text, o.fontFamily, o.fontShadow, o.fontWeight ); }, setText: function( size, color, font, shadow, weight ){ let cc = T.colors; if( font === undefined ) font = cc.fontFamily; if( size === undefined ) size = cc.fontSize; if( shadow === undefined ) shadow = cc.fontShadow; if( weight === undefined ) weight = cc.fontWeight; if( color === undefined ) color = cc.text; if( isNaN(size) ){ if( size.search('em')===-1 ) size += 'px';} else size += 'px'; //let align = 'display:flex; justify-content:left; align-items:center; text-align:left;' T.css.txt = T.css.basic + T.css.middle + ' font-family:'+ font +'; font-weight:'+weight+'; font-size:'+size+'; color:'+cc.text+'; padding:0px 8px; left:0; top:2px; height:16px; width:100px; overflow:hidden; white-space: nowrap; letter-spacing:normal;';//letter-spacing: normal; if( shadow !== 'none' ) T.css.txt += ' text-shadow: 1px 1px 1px '+shadow+';'; T.css.txtselect = T.css.txt + 'padding:0px 4px; border:1px dashed ' + cc.border + ';'; T.css.item = T.css.txt + 'padding:0px 4px; position:relative; margin-bottom:1px; '; }, // note //https://developer.mozilla.org/fr/docs/Web/CSS/css_flexible_box_layout/aligning_items_in_a_flex_container /*cloneColor: function () { let cc = Object.assign({}, T.colors ); return cc; },*/ // intern function cloneCss: function () { //let cc = Object.assign({}, T.css ); return { ...T.css }; }, clone: function ( o ) { return o.cloneNode( true ); }, setSvg: function( dom, type, value, id, id2 ){ if( id === -1 ) dom.setAttributeNS( null, type, value ); else if( id2 !== undefined ) dom.childNodes[ id || 0 ].childNodes[ id2 || 0 ].setAttributeNS( null, type, value ); else dom.childNodes[ id || 0 ].setAttributeNS( null, type, value ); }, setCss: function( dom, css ){ for( let r in css ){ if( T.DOM_SIZE.indexOf(r) !== -1 ) dom.style[r] = css[r] + 'px'; else dom.style[r] = css[r]; } }, set: function( g, o ){ for( let att in o ){ if( att === 'txt' ) g.textContent = o[ att ]; if( att === 'link' ) g.setAttributeNS( T.links, 'xlink:href', o[ att ] ); else g.setAttributeNS( null, att, o[ att ] ); } }, get: function( dom, id ){ if( id === undefined ) return dom; // root else if( !isNaN( id ) ) return dom.childNodes[ id ]; // first child else if( id instanceof Array ){ if(id.length === 2) return dom.childNodes[ id[0] ].childNodes[ id[1] ]; if(id.length === 3) return dom.childNodes[ id[0] ].childNodes[ id[1] ].childNodes[ id[2] ]; } }, dom : function ( type, css, obj, dom, id ) { type = type || 'div'; if( T.SVG_TYPE_D.indexOf(type) !== -1 || T.SVG_TYPE_G.indexOf(type) !== -1 ){ // is svg element if( type ==='svg' ){ dom = document.createElementNS( T.svgns, 'svg' ); T.set( dom, obj ); /* } else if ( type === 'use' ) { dom = document.createElementNS( T.svgns, 'use' ); T.set( dom, obj ); */ } else { // create new svg if not def if( dom === undefined ) dom = document.createElementNS( T.svgns, 'svg' ); T.addAttributes( dom, type, obj, id ); } } else { // is html element if( dom === undefined ) dom = document.createElementNS( T.htmls, type ); else dom = dom.appendChild( document.createElementNS( T.htmls, type ) ); } if( css ) dom.style.cssText = css; if( id === undefined ) return dom; else return dom.childNodes[ id || 0 ]; }, addAttributes : function( dom, type, o, id ){ let g = document.createElementNS( T.svgns, type ); T.set( g, o ); T.get( dom, id ).appendChild( g ); if( T.SVG_TYPE_G.indexOf(type) !== -1 ) g.style.pointerEvents = 'none'; return g; }, clear : function( dom ){ T.purge( dom ); while (dom.firstChild) { if ( dom.firstChild.firstChild ) T.clear( dom.firstChild ); dom.removeChild( dom.firstChild ); } }, purge : function ( dom ) { let a = dom.attributes, i, n; if (a) { i = a.length; while(i--){ n = a[i].name; if (typeof dom[n] === 'function') dom[n] = null; } } a = dom.childNodes; if (a) { i = a.length; while(i--){ T.purge( dom.childNodes[i] ); } } }, // ---------------------- // SVG Effects function // ---------------------- addSVGGlowEffect: function () { if ( document.getElementById( 'UILGlow') !== null ) return; let svgFilter = T.initUILEffects(); let filter = T.addAttributes( svgFilter, 'filter', { id: 'UILGlow', x: '-20%', y: '-20%', width: '140%', height: '140%' } ); T.addAttributes( filter, 'feGaussianBlur', { in: 'SourceGraphic', stdDeviation: '3', result: 'uilBlur' } ); let feMerge = T.addAttributes( filter, 'feMerge', { } ); for( let i = 0; i <= 3; i++ ) { T.addAttributes( feMerge, 'feMergeNode', { in: 'uilBlur' } ); } T.addAttributes( feMerge, 'feMergeNode', { in: 'SourceGraphic' } ); }, initUILEffects: function () { let svgFilter = document.getElementById( 'UILSVGEffects'); if ( svgFilter === null ) { svgFilter = T.dom( 'svg', undefined , { id: 'UILSVGEffects', width: '0', height: '0' } ); document.body.appendChild( svgFilter ); } return svgFilter; }, // ---------------------- // Color function // ---------------------- ColorLuma : function ( hex, l ) { //if( hex.substring(0, 3) === 'rgba' ) hex = '#000'; if( hex === 'n' ) hex = '#000'; // validate hex string hex = String(hex).replace(/[^0-9a-f]/gi, ''); if (hex.length < 6) { hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2]; } l = l || 0; // convert to decimal and change luminosity let rgb = "#", c, i; for (i = 0; i < 3; i++) { c = parseInt(hex.substr(i*2,2), 16); c = Math.round(Math.min(Math.max(0, c + (c * l)), 255)).toString(16); rgb += ("00"+c).substr(c.length); } return rgb; }, findDeepInver: function ( c ) { return (c[0] * 0.3 + c[1] * .59 + c[2] * .11) <= 0.6; }, lerpColor: function( c1, c2, factor ) { let newColor = {}; for ( let i = 0; i < 3; i++ ) { newColor[i] = c1[ i ] + ( c2[ i ] - c1[ i ] ) * factor; } return newColor; }, hexToHtml: function ( v ) { v = v === undefined ? 0x000000 : v; return "#" + ("000000" + v.toString(16)).substr(-6); }, htmlToHex: function ( v ) { return v.toUpperCase().replace("#", "0x"); }, u255: function (c, i) { return parseInt(c.substring(i, i + 2), 16) / 255; }, u16: function ( c, i ) { return parseInt(c.substring(i, i + 1), 16) / 15; }, unpack: function( c ){ if (c.length == 7) return [ T.u255(c, 1), T.u255(c, 3), T.u255(c, 5) ]; else if (c.length == 4) return [ T.u16(c,1), T.u16(c,2), T.u16(c,3) ]; }, p255: function ( c ) { let h = Math.round( ( c * 255 ) ).toString( 16 ); if ( h.length < 2 ) h = '0' + h; return h; }, pack: function ( c ) { return '#' + T.p255( c[ 0 ] ) + T.p255( c[ 1 ] ) + T.p255( c[ 2 ] ); }, htmlRgba: function( c, a ){ c = T.unpack(c); return 'rgba(' + Math.round(c[0] * 255) + ','+ Math.round(c[1] * 255) + ','+ Math.round(c[2] * 255) + ','+ a + ')'; }, htmlRgb: function( c, a ){ return 'rgb(' + Math.round(c[0] * 255) + ','+ Math.round(c[1] * 255) + ','+ Math.round(c[2] * 255) + ')'; }, pad: function( n ){ if(n.length == 1)n = '0' + n; return n; }, rgbToHex : function( c ){ let r = Math.round(c[0] * 255).toString(16); let g = Math.round(c[1] * 255).toString(16); let b = Math.round(c[2] * 255).toString(16); return '#' + T.pad(r) + T.pad(g) + T.pad(b); // return '#' + ( '000000' + ( ( c[0] * 255 ) << 16 ^ ( c[1] * 255 ) << 8 ^ ( c[2] * 255 ) << 0 ).toString( 16 ) ).slice( - 6 ); }, hueToRgb: function( p, q, t ){ if ( t < 0 ) t += 1; if ( t > 1 ) t -= 1; if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; if ( t < 1 / 2 ) return q; if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); return p; }, rgbToHsl: function ( c ) { let r = c[0], g = c[1], b = c[2], min = Math.min(r, g, b), max = Math.max(r, g, b), delta = max - min, h = 0, s = 0, l = (min + max) / 2; if (l > 0 && l < 1) s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l)); if (delta > 0) { if (max == r && max != g) h += (g - b) / delta; if (max == g && max != b) h += (2 + (b - r) / delta); if (max == b && max != r) h += (4 + (r - g) / delta); h /= 6; } return [ h, s, l ]; }, hslToRgb: function ( c ) { let p, q, h = c[0], s = c[1], l = c[2]; if ( s === 0 ) return [ l, l, l ]; else { q = l <= 0.5 ? l * (s + 1) : l + s - ( l * s ); p = l * 2 - q; return [ T.hueToRgb(p, q, h + 0.33333), T.hueToRgb(p, q, h), T.hueToRgb(p, q, h - 0.33333) ]; } }, // ---------------------- // SVG MODEL // ---------------------- makeGradiant: function ( type, settings, parent, colors ) { T.dom( type, null, settings, parent, 0 ); let n = parent.childNodes[0].childNodes.length - 1, c; for( let i = 0; i < colors.length; i++ ){ c = colors[i]; //T.dom( 'stop', null, { offset:c[0]+'%', style:'stop-color:'+c[1]+'; stop-opacity:'+c[2]+';' }, parent, [0,n] ); T.dom( 'stop', null, { offset:c[0]+'%', 'stop-color':c[1], 'stop-opacity':c[2] }, parent, [0,n] ); } }, /*makeGraph: function () { let w = 128; let radius = 34; let svg = T.dom( 'svg', T.css.basic , { viewBox:'0 0 '+w+' '+w, width:w, height:w, preserveAspectRatio:'none' } ); T.dom( 'path', '', { d:'', stroke:T.colors.text, 'stroke-width':4, fill:'none', 'stroke-linecap':'butt' }, svg );//0 //T.dom( 'rect', '', { x:10, y:10, width:108, height:108, stroke:'rgba(0,0,0,0.3)', 'stroke-width':2 , fill:'none'}, svg );//1 //T.dom( 'circle', '', { cx:64, cy:64, r:radius, fill:T.colors.button, stroke:'rgba(0,0,0,0.3)', 'stroke-width':8 }, svg );//0 //T.dom( 'circle', '', { cx:64, cy:64, r:radius+7, stroke:'rgba(0,0,0,0.3)', 'stroke-width':7 , fill:'none'}, svg );//2 //T.dom( 'path', '', { d:'', stroke:'rgba(255,255,255,0.3)', 'stroke-width':2, fill:'none', 'stroke-linecap':'round', 'stroke-opacity':0.5 }, svg );//3 T.graph = svg; },*/ makePad: function ( model ) { let ww = 256; let svg = T.dom( 'svg', T.css.basic + 'position:relative;', { viewBox:'0 0 '+ww+' '+ww, width:ww, height:ww, preserveAspectRatio:'none' } ); let w = 200; let d = (ww-w)*0.5, m = 20; Tools.dom( 'rect', '', { x: d, y: d, width: w, height: w, fill:T.colors.back }, svg ); // 0 Tools.dom( 'rect', '', { x: d+m*0.5, y: d+m*0.5, width: w - m , height: w - m, fill:T.colors.button }, svg ); // 1 // Pointer Tools.dom( 'line', '', { x1: d+(m*0.5), y1: ww *0.5, x2: d+(w-m*0.5), y2: ww * 0.5, stroke:T.colors.back, 'stroke-width': 2 }, svg ); // 2 Tools.dom( 'line', '', { x1: ww * 0.5, x2: ww * 0.5, y1: d+(m*0.5), y2: d+(w-m*0.5), stroke:T.colors.back, 'stroke-width': 2 }, svg ); // 3 Tools.dom( 'circle', '', { cx: ww * 0.5, cy: ww * 0.5, r:5, stroke: T.colors.text, 'stroke-width': 5, fill:'none' }, svg ); // 4 T.pad2d = svg; }, makeKnob: function ( model ) { let w = 128; let radius = 34; let svg = T.dom( 'svg', T.css.basic + 'position:relative;', { viewBox:'0 0 '+w+' '+w, width:w, height:w, preserveAspectRatio:'none' } ); T.dom( 'circle', '', { cx:64, cy:64, r:radius, fill:T.colors.button, stroke:'rgba(0,0,0,0.3)', 'stroke-width':8 }, svg );//0 T.dom( 'path', '', { d:'', stroke:T.colors.text, 'stroke-width':4, fill:'none', 'stroke-linecap':'round' }, svg );//1 T.dom( 'circle', '', { cx:64, cy:64, r:radius+7, stroke:'rgba(0,0,0,0.1)', 'stroke-width':7 , fill:'none'}, svg );//2 T.dom( 'path', '', { d:'', stroke:'rgba(255,255,255,0.3)', 'stroke-width':2, fill:'none', 'stroke-linecap':'round', 'stroke-opacity':0.5 }, svg );//3 T.knob = svg; }, makeCircular: function ( model ) { let w = 128; let radius = 40; let svg = T.dom( 'svg', T.css.basic + 'position:relative;', { viewBox:'0 0 '+w+' '+w, width:w, height:w, preserveAspectRatio:'none' } ); T.dom( 'circle', '', { cx:64, cy:64, r:radius, stroke:'rgba(0,0,0,0.1)', 'stroke-width':10, fill:'none' }, svg );//0 T.dom( 'path', '', { d:'', stroke:T.colors.text, 'stroke-width':7, fill:'none', 'stroke-linecap':'butt' }, svg );//1 T.circular = svg; }, makeJoystick: function ( model ) { //+' background:#f00;' let w = 128, ccc; let radius = Math.floor((w-30)*0.5); let innerRadius = Math.floor(radius*0.6); let svg = T.dom( 'svg', T.css.basic + 'position:relative;', { viewBox:'0 0 '+w+' '+w, width:w, height:w, preserveAspectRatio:'none' } ); T.dom( 'defs', null, {}, svg ); T.dom( 'g', null, {}, svg ); if( model === 0 ){ // gradian background ccc = [ [40, 'rgb(0,0,0)', 0.3], [80, 'rgb(0,0,0)', 0], [90, 'rgb(50,50,50)', 0.4], [100, 'rgb(50,50,50)', 0] ]; T.makeGradiant( 'radialGradient', { id:'grad', cx:'50%', cy:'50%', r:'50%', fx:'50%', fy:'50%' }, svg, ccc ); // gradian shadow ccc = [ [60, 'rgb(0,0,0)', 0.5], [100, 'rgb(0,0,0)', 0] ]; T.makeGradiant( 'radialGradient', { id:'gradS', cx:'50%', cy:'50%', r:'50%', fx:'50%', fy:'50%' }, svg, ccc ); // gradian stick let cc0 = ['rgb(40,40,40)', 'rgb(48,48,48)', 'rgb(30,30,30)']; let cc1 = ['rgb(1,90,197)', 'rgb(3,95,207)', 'rgb(0,65,167)']; ccc = [ [30, cc0[0], 1], [60, cc0[1], 1], [80, cc0[1], 1], [100, cc0[2], 1] ]; T.makeGradiant( 'radialGradient', { id:'gradIn', cx:'50%', cy:'50%', r:'50%', fx:'50%', fy:'50%' }, svg, ccc ); ccc = [ [30, cc1[0], 1], [60, cc1[1], 1], [80, cc1[1], 1], [100, cc1[2], 1] ]; T.makeGradiant( 'radialGradient', { id:'gradIn2', cx:'50%', cy:'50%', r:'50%', fx:'50%', fy:'50%' }, svg, ccc ); // graph T.dom( 'circle', '', { cx:64, cy:64, r:radius, fill:'url(#grad)' }, svg );//2 T.dom( 'circle', '', { cx:64+5, cy:64+10, r:innerRadius+10, fill:'url(#gradS)' }, svg );//3 T.dom( 'circle', '', { cx:64, cy:64, r:innerRadius, fill:'url(#gradIn)' }, svg );//4 T.joystick_0 = svg; } else { // gradian shadow ccc = [ [69, 'rgb(0,0,0)', 0],[70, 'rgb(0,0,0)', 0.3], [100, 'rgb(0,0,0)', 0] ]; T.makeGradiant( 'radialGradient', { id:'gradX', cx:'50%', cy:'50%', r:'50%', fx:'50%', fy:'50%' }, svg, ccc ); T.dom( 'circle', '', { cx:64, cy:64, r:radius, fill:'none', stroke:'rgba(100,100,100,0.25)', 'stroke-width':'4' }, svg );//2 T.dom( 'circle', '', { cx:64, cy:64, r:innerRadius+14, fill:'url(#gradX)' }, svg );//3 T.dom( 'circle', '', { cx:64, cy:64, r:innerRadius, fill:'none', stroke:'rgb(100,100,100)', 'stroke-width':'4' }, svg );//4 T.joystick_1 = svg; } }, makeColorRing: function () { let w = 256; let svg = T.dom( 'svg', T.css.basic + 'position:relative;', { viewBox:'0 0 '+w+' '+w, width:w, height:w, preserveAspectRatio:'none' } ); T.dom( 'defs', null, {}, svg ); T.dom( 'g', null, {}, svg ); let s = 30;//stroke let r =( w-s )*0.5; let mid = w*0.5; let n = 24, nudge = 8 / r / n * Math.PI, a1 = 0; let am, tan, d2, a2, ar, i, j, path, ccc; let color = []; for ( i = 0; i <= n; ++i) { d2 = i / n; a2 = d2 * T.TwoPI; am = (a1 + a2) * 0.5; tan = 1 / Math.cos((a2 - a1) * 0.5); ar = [ Math.sin(a1), -Math.cos(a1), Math.sin(am) * tan, -Math.cos(am) * tan, Math.sin(a2), -Math.cos(a2) ]; color[1] = T.rgbToHex( T.hslToRgb([d2, 1, 0.5]) ); if (i > 0) { j = 6; while(j--){ ar[j] = ((ar[j]*r)+mid).toFixed(2); } path = ' M' + ar[0] + ' ' + ar[1] + ' Q' + ar[2] + ' ' + ar[3] + ' ' + ar[4] + ' ' + ar[5]; ccc = [ [0,color[0],1], [100,color[1],1] ]; T.makeGradiant( 'linearGradient', { id:'G'+i, x1:ar[0], y1:ar[1], x2:ar[4], y2:ar[5], gradientUnits:"userSpaceOnUse" }, svg, ccc ); T.dom( 'path', '', { d:path, 'stroke-width':s, stroke:'url(#G'+i+')', 'stroke-linecap':"butt" }, svg, 1 ); } a1 = a2 - nudge; color[0] = color[1]; } let tw = 84.90; // black / white ccc = [ [0, '#FFFFFF', 1], [50, '#FFFFFF', 0], [50, '#000000', 0], [100, '#000000', 1] ]; T.makeGradiant( 'linearGradient', { id:'GL0', x1:0, y1:mid-tw, x2:0, y2:mid+tw, gradientUnits:"userSpaceOnUse" }, svg, ccc ); ccc = [ [0, '#7f7f7f', 1], [50, '#7f7f7f', 0.5], [100, '#7f7f7f', 0] ]; T.makeGradiant( 'linearGradient', { id:'GL1', x1:mid-49.05, y1:0, x2:mid+98, y2:0, gradientUnits:"userSpaceOnUse" }, svg, ccc ); T.dom( 'g', null, { 'transform-origin': '128px 128px', 'transform':'rotate(0)' }, svg );//2 T.dom( 'polygon', '', { points:'78.95 43.1 78.95 212.85 226 128', fill:'red' }, svg, 2 );// 2,0 T.dom( 'polygon', '', { points:'78.95 43.1 78.95 212.85 226 128', fill:'url(#GL1)','stroke-width':1, stroke:'url(#GL1)' }, svg, 2 );//2,1 T.dom( 'polygon', '', { points:'78.95 43.1 78.95 212.85 226 128', fill:'url(#GL0)','stroke-width':1, stroke:'url(#GL0)' }, svg, 2 );//2,2 T.dom( 'path', '', { d:'M 255.75 136.5 Q 256 132.3 256 128 256 123.7 255.75 119.5 L 241 128 255.75 136.5 Z', fill:'none','stroke-width':2, stroke:'#000' }, svg, 2 );//2,3 //T.dom( 'circle', '', { cx:128+113, cy:128, r:6, 'stroke-width':3, stroke:'#000', fill:'none' }, svg, 2 );//2.3 T.dom( 'circle', '', { cx:128, cy:128, r:6, 'stroke-width':2, stroke:'#000', fill:'none' }, svg );//3 T.colorRing = svg; }, icon: function ( type, color, w ){ w = w || 40; //color = color || '#DEDEDE'; let viewBox = '0 0 256 256'; //let viewBox = '0 0 '+ w +' '+ w; let t = ["<svg xmlns='"+T.svgns+"' version='1.1' xmlns:xlink='"+T.htmls+"' style='pointer-events:none;' preserveAspectRatio='xMinYMax meet' x='0px' y='0px' width='"+w+"px' height='"+w+"px' viewBox='"+viewBox+"'><g>"]; switch(type){ case 'logo': t[1]="<path id='logoin' fill='"+color+"' stroke='none' d='"+T.logoFill_d+"'/>"; break; case 'donate': t[1]="<path id='logoin' fill='"+color+"' stroke='none' d='"+T.logo_donate+"'/>"; break; case 'neo': t[1]="<path id='logoin' fill='"+color+"' stroke='none' d='"+