import { EventojLancilo } from './EventojLancilo.js' EventojLancilo( EventTarget ) // same event handler for everybody String.merge = (ss,...pp)=> [].concat(ss).map( (s,i)=> s+(i in pp?pp[i]:'') ).join('') const logNpass = o=> console.log(o)||o // const ss_pp = (ss,...pp)=> [].concat(ss).map( (s,i)=> s+(i in pp?pp[i]:'') ).join('') // const $ = (ss,...pp)=> document.querySelector( ss_pp(ss,...pp) ) // const $$ = (ss,...pp)=> [...document.querySelectorAll( ss_pp(ss,...pp) )] const DOM = (ss,...pp)=> { let t = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'template' ) t.innerHTML = String.merge(ss,...pp) return t.content } const SVG = (ss,...pp)=> DOM`${String.merge(ss,...pp)}` .children[0].childNodes const CSS = (ss,...pp)=> { let styles = new CSSStyleSheet() styles.replaceSync( String.merge(ss,...pp) ) return styles } const $ = (ss,...pp)=> document.$( ss,...pp ) const $$ = (ss,...pp)=> document.$$( ss,...pp ) Node.prototype.$ = function(ss,...pp) { return this.querySelector( String.merge(ss,...pp) ) } Node.prototype.$$ = function(ss,...pp) { return [...this.querySelectorAll( String.merge(ss,...pp) )] } Node.prototype.add = function( ...args ) { this.append( ...args ) return this } // Node.prototype.on = function(ss,...pp) // { // return (...args)=> ( this.addEventListener( ss_pp(ss,...pp), ...args ), this ) // } Object.defineProperties( SVGRect.prototype, { center: { get(){ return { x: this.x + ( this.width/2 ) , y: this.y + ( this.height/2 ) }} , set( v ){} } }) /** **/ // @see https://cp-algorithms.com/geometry/segment-to-line.html // SVGLineElement.prototype.getCoef = function line() // { // let P = { x: this.x1.baseVal.value, y: this.y1.baseVal.value } // let Q = { x: this.x2.baseVal.value, y: this.y2.baseVal.value } // //console.log(P,Q) // let A = P.y - Q.y // let B = Q.x - P.x // let C = ( -A * P.x ) - ( B * P.y ) // return [A,B,C] // } // // @see https://cp-algorithms.com/geometry/lines-intersection.html // SVGLineElement.prototype.intersect = function intersect( line ) // { // let [ a1,b1,c1 ] = this.getCoef() // // console.log(this.getCoef()) // let [ a2,b2,c2 ] = line.getCoef() // // console.log(line.getCoef()) // let x = - ((c1*b2)-(c2*b1))/((a1*b2)-(a2*b1)) // let y = - ((a1*c2)-(a2*c1))/((a1*b2)-(a2*b1)) // return { x, y } // } //PointProperty('_p1','x1','y1') const PointProperty = ( _, x, y )=> ({ get(){ return this[_] = this[_] || new DOMPoint( this[x].baseVal.value, this[y].baseVal.value )} , set( obj ){ if( 'x' in obj && 'y' in obj ) { const ev = e=> { this.setAttribute( x, obj.x ) this.setAttribute( y, obj.y ) this.dispatchEvent( new Event('move') ) } this[_] && this[_].removeEventListener && this[_].removeEventListener('move', ev) this[_] = obj obj.addEventListener && obj.addEventListener('move', ev) ev() this.dispatchEvent( new Event('pointchange') ) } } }) Object.defineProperties(SVGLineElement.prototype, { p1: PointProperty('_p1','x1','y1') // { // get(){ return this._p1 = this._p1 || new DOMPoint( // this.x1.baseVal.value, // this.y1.baseVal.value // ) // } // , set( obj ){ // if( 'x' in obj && 'y' in obj ) // { // const ev = e=> { // this.setAttribute('x1', obj.x) // this.setAttribute('y1', obj.y) // this.dispatchEvent( new Event('move') ) // } // this._p1 // && this._p1.removeEventListener // && this._p1.removeEventListener('move', ev) // this._p1 = obj // obj.addEventListener && obj.addEventListener('move', ev) // ev() // this.dispatchEvent( new Event('pointchange') ) // } // } // } , p2: PointProperty('_p2','x2','y2') // { // get(){ return this._p2 = this._p2 || new DOMPoint( // this.x2.baseVal.value, // this.y2.baseVal.value // )} // , set( obj ){ // if( 'x' in obj && 'y' in obj ) // { // const ev = e=> { // this.setAttribute('x2', obj.x) // this.setAttribute('y2', obj.y) // this.dispatchEvent( new Event('move') ) // } // this._p2 // && this._p2.removeEventListener // && this._p2.removeEventListener('move', ev) // this._p2 = obj // obj.addEventListener && obj.addEventListener('move', ev) // ev() // this.dispatchEvent( new Event('pointchange') ) // } // } // } }) //@TODO Debounce move event fired twice when changing x and y //@TODO Adapt which attribute is set ( x, cx, x1, transform ), depending on localName ( , , , ... ) Object.defineProperties(SVGElement.prototype, { x: { get(){ return parseFloat((this.attributes.x||this.attributes.cx||this.attributes.x1||{value:0}).value) } , set( v ){ if( !isFinite(v) ) return v if( this.localName == 'g' ) this.setAttribute('transform',`translate(${v},${this.y})`) this.setAttribute('x',v) this.setAttribute('cx',v) this.setAttribute('x1',v) } } , y: { get(){ return parseFloat((this.attributes.y||this.attributes.cy||this.attributes.y1||{value:0}).value) } , set( v ){ if( !isFinite(v) ) return v if( this.localName == 'g' ) this.setAttribute('transform',`translate(${this.x},${v})`) this.setAttribute('y',v) this.setAttribute('cy',v) this.setAttribute('y1',v) } } , moveTo: { value: function({ x, y }){ this.x = x this.y = y this.dispatchEvent( new Event('move') ) return this } } , moveBy: { value: function({ x, y }){ this.x += x this.y += y this.dispatchEvent( new Event('move') ) return this } } }) Object.defineProperties(SVGSVGElement.prototype, { zoom: { get(){ return parseFloat((this.attributes.x||this.attributes.cx||this.attributes.x1||{value:0}).value) } , set( v ){ if( !isFinite(v) ) return v if( this.localName == 'g' ) this.setAttribute('transform',`translate(${v},${this.y})`) this.setAttribute('x',v) this.setAttribute('cx',v) this.setAttribute('x1',v) } } , pan: //PointProperty('_pan','pan-x','pan-y') { get(){ return this._pan = this._pan || new DOMPoint( this.x2.baseVal.value, this.y2.baseVal.value )} , set( obj ){ if( 'x' in obj && 'y' in obj ) { const ev = e=> { this.setAttribute('x2', obj.x) this.setAttribute('y2', obj.y) this.dispatchEvent( new Event('move') ) } this._p2 && this._p2.removeEventListener && this._p2.removeEventListener('move', ev) this._p2 = obj obj.addEventListener && obj.addEventListener('move', ev) ev() this.dispatchEvent( new Event('pointchange') ) } } } , panAndZoom: { value( x, y, z ) { let { x:vx, y:vy, width:vw, height:vh } = this.viewBox.baseVal , vz vz = Math.min( vw, vh ) / 2 vx = vx + ( vw / 2 ) vy = vy + ( vh / 2 ) requestAnimationFrame( ()=> { // this.setAttribute('viewBox', `${typeof x == 'number' ? x-(z||vz) : vx} ${typeof y == 'number' ? y-(z||vz) : vy} ${z ? z*2 : vw} ${z ? z*2 : vh}`) this.setAttribute('viewBox', `${(x||vx)-(z||vz)} ${(y||vy)-(z||vz)} ${(z||vz)*2} ${(z||vz)*2}`) console.log('viewBox', `${(x||vx)-(z||vz)} ${(y||vy)-(z||vz)} ${(z||vz)*2} ${(z||vz)*2}`) // this.setAttribute('pan', `${x} ${y}`) // this.setAttribute('zoom', `${z}`) }) } } }) export { logNpass , DOM , SVG , CSS , $ , $$ }