Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
devingfx | a57110514f |
|
@ -0,0 +1,93 @@
|
|||
import { SVG } from './DOM.js'
|
||||
import { makeDraggable } from './Draggable.js'
|
||||
import { Group } from './Group.js'
|
||||
|
||||
const Box = ( title, inputs, outputs )=> {
|
||||
let $dom = makeDraggable( Group('Box') ), $fo, $box
|
||||
|
||||
$dom.append(
|
||||
$fo = SVG`<foreignObject width="180" height="100">
|
||||
<box xmlns="http://www.w3.org/1999/xhtml">
|
||||
<header>${title}</header>
|
||||
${outputs.map( str=> `<socket output>${str}</socket>`).join('')}
|
||||
${inputs.map( str=> `<socket input>${str}</socket>`).join('')}
|
||||
</box>
|
||||
</foreignObject>`[0]
|
||||
)
|
||||
$box = $fo.$`box`
|
||||
$dom.resize = ({ width, height })=> {
|
||||
width && $fo.setAttribute('width', width )
|
||||
height && $fo.setAttribute('height', height )
|
||||
$dom.updateAnchors()
|
||||
}
|
||||
|
||||
let heightInvalidated = false
|
||||
$dom.invalidateHeight = ()=> {
|
||||
heightInvalidated = true
|
||||
requestAnimationFrame( ()=> $dom.resize({height: $box.offsetHeight }) )
|
||||
}
|
||||
let widthInvalidated = false
|
||||
$dom.invalidateWidth = ()=> {
|
||||
widthInvalidated = true
|
||||
requestAnimationFrame( ()=> $dom.resize({width: $box.offsetWidth }) )
|
||||
}
|
||||
|
||||
setTimeout( $dom.invalidateHeight, 1000 )
|
||||
|
||||
|
||||
// Draw anchors
|
||||
$box.$$`socket`.map( sock=> sock.anchor = SVG`<circle class="anchor"/>`[0] )
|
||||
.map( a=> $dom.append(a) )
|
||||
|
||||
$dom.updateAnchors = ()=>
|
||||
$box.$$`socket`
|
||||
.map( sock=>
|
||||
sock.anchor.moveTo({
|
||||
x: sock.hasAttribute('output')
|
||||
? $box.offsetWidth
|
||||
: 0
|
||||
, y: sock.offsetTop + ( sock.offsetHeight / 2 ) + 1
|
||||
})
|
||||
)
|
||||
|
||||
$dom.on`contextmenu`( e=> e.menu = Object.assign(e.menu || {}, {
|
||||
'Box': {
|
||||
'Debug': e=> console.log($dom)
|
||||
, 'Convert to >': {
|
||||
ZigZag: e=> $box.style.setProperty('background','orange')
|
||||
, Flat: e=> $dom.style.setProperty('--wave-color','var(--fl-color)')
|
||||
, Impulsive: e=> $dom.style.setProperty('--wave-color','var(--im-color)')
|
||||
}
|
||||
// 'Convert to ZZ':e=> $dom.style.setProperty('--wave-color','var(--zz-color)')
|
||||
// , ...( $dom.fibos ? {['Toggle fibos']: $dom.toggleFibos} : {} )
|
||||
// , ...( w.isEmpty ? {['Subdivise']: $dom.subdivise} : {} )
|
||||
}
|
||||
}) , {capture:true} )
|
||||
|
||||
return $dom
|
||||
}
|
||||
|
||||
|
||||
|
||||
// class Box extends HTMLElement {
|
||||
|
||||
// static styles = CSS`
|
||||
|
||||
// `
|
||||
|
||||
// constructor()
|
||||
// {
|
||||
// super()
|
||||
// this.$svg =
|
||||
// this.addListeners()
|
||||
|
||||
// }
|
||||
|
||||
// addListeners()
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// customElements.define( 'vp-box', Box )
|
||||
|
||||
export { Box }
|
|
@ -0,0 +1,265 @@
|
|||
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`<svg xmlns="http://www.w3.org/2000/svg">${String.merge(ss,...pp)}</svg>`
|
||||
.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 ){}
|
||||
}
|
||||
})
|
||||
|
||||
/** <line> **/
|
||||
|
||||
// @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 ( <rect>, <circle>, <g>, ... )
|
||||
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
|
||||
, $
|
||||
, $$
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
// const UI = {}
|
||||
|
||||
|
||||
// SVG.Point = ( x, y )=> Object.assign( document.documentElement.createSVGPoint(), {x,y} )
|
||||
|
||||
Symbol.Draggable = Symbol`Draggable`
|
||||
|
||||
var Draggable = obj=> {
|
||||
|
||||
if( Symbol.Draggable in obj ) return obj
|
||||
obj[Symbol.Draggable] = true
|
||||
|
||||
obj.startDrag = e=> {
|
||||
let mouse = new DOMPoint( e.clientX , e.clientY )//.matrixTransform( obj.getCTM().inverse() )
|
||||
mouse.x /= obj.ownerSVGElement.currentScale
|
||||
mouse.y /= obj.ownerSVGElement.currentScale
|
||||
|
||||
obj.drag.offset = new DOMPoint( mouse.x - obj.x, mouse.y - obj.y )
|
||||
obj.setAttribute( 'dragged', true )
|
||||
console.log(e, mouse, obj.drag.offset)
|
||||
}
|
||||
|
||||
obj.drag = function(e)
|
||||
{//debugger;
|
||||
if(e.buttons === 1)
|
||||
{
|
||||
let mouse = new DOMPoint( e.clientX / obj.ownerSVGElement.currentScale, e.clientY / obj.ownerSVGElement.currentScale )//.matrixTransform( obj.getScreenCTM().inverse() )
|
||||
, pos = new DOMPoint( mouse.x - obj.drag.offset.x, mouse.y - obj.drag.offset.y)
|
||||
|
||||
// pos.x /= obj.ownerSVGElement.currentScale
|
||||
// pos.y /= obj.ownerSVGElement.currentScale
|
||||
this.moveTo( pos )
|
||||
this.dispatchEvent( new Event('move') )
|
||||
}
|
||||
}
|
||||
|
||||
obj.stopDrag = e=> obj.removeAttribute('dragged')
|
||||
|
||||
obj.on`mousedown`( obj.startDrag )
|
||||
// ,onmousemove:e=> e.buttons === 1 && e.target.drag(e)
|
||||
//obj.onmouseup = e=> e.currentTarget.setAttribute(' dragged', false )
|
||||
|
||||
return obj
|
||||
}
|
||||
Draggable.startGlobalDrag = e=> e.target.$$`[dragged]`.filter(el=>el.draggable).map( el=> el.drag(e) )
|
||||
Draggable.stopGlobalDrag = e=> e.target.$$`[dragged]`.map( el=> el.removeAttribute('dragged') )
|
||||
|
||||
// $$`[draggable]`
|
||||
// .map( Draggable )
|
||||
|
||||
// document.documentElement.on`mousemove`( e=> $$`[dragged]`.filter(el=>el.draggable).map( el=> el.drag(e) ) , true )
|
||||
// document.documentElement.onmouseup = e=> $$`[dragged]`.map( el=> el.removeAttribute('dragged') )
|
||||
|
||||
|
||||
// Makes an element in an SVG document draggable.
|
||||
// Fires custom `dragstart`, `drag`, and `dragend` events on the
|
||||
// element with the `detail` property of the event carrying XY
|
||||
// coordinates for the location of the element.
|
||||
function makeDraggable(el)
|
||||
{
|
||||
if (!el) return console.error('makeDraggable() needs an element')
|
||||
|
||||
let svg, pt, doc, root
|
||||
//var svg = el;
|
||||
//while (svg && svg.tagName!='svg') svg=svg.parentNode;
|
||||
//if (!svg) return console.error(el,'must be inside an SVG wrapper');
|
||||
//var pt=svg.createSVGPoint(), doc=svg.ownerDocument;
|
||||
|
||||
//var root = doc.rootElement || doc.body || svg;
|
||||
let xlate, txStartX, txStartY, mouseStart
|
||||
let xforms = el.transform.baseVal
|
||||
|
||||
el.addEventListener('mousedown', e=> e.which == 1 && startMove(e), false )
|
||||
|
||||
function startMove(evt)
|
||||
{
|
||||
svg = el.ownerSVGElement
|
||||
pt = svg.createSVGPoint()
|
||||
doc = svg.ownerDocument
|
||||
root = doc.rootElement || doc.body || svg
|
||||
|
||||
// We listen for mousemove/up on the root-most
|
||||
// element in case the mouse is not over el.
|
||||
root.addEventListener('mousemove',handleMove,false)
|
||||
root.addEventListener('mouseup', finishMove,false)
|
||||
|
||||
// Ensure that the first transform is a translate()
|
||||
xlate = xforms.numberOfItems>0 && xforms.getItem(0)
|
||||
if (!xlate || xlate.type != SVGTransform.SVG_TRANSFORM_TRANSLATE){
|
||||
xlate = xforms.createSVGTransformFromMatrix( svg.createSVGMatrix() )
|
||||
xforms.insertItemBefore( xlate, 0 )
|
||||
}
|
||||
txStartX = xlate.matrix.e
|
||||
txStartY = xlate.matrix.f
|
||||
mouseStart = inElementSpace(evt)
|
||||
fireEvent('dragstart')
|
||||
}
|
||||
|
||||
function handleMove(evt)
|
||||
{
|
||||
var point = inElementSpace(evt)
|
||||
xlate.setTranslate(
|
||||
txStartX + point.x - mouseStart.x,
|
||||
txStartY + point.y - mouseStart.y
|
||||
)
|
||||
fireEvent('drag')
|
||||
}
|
||||
|
||||
function finishMove(evt)
|
||||
{
|
||||
root.removeEventListener('mousemove',handleMove,false)
|
||||
root.removeEventListener('mouseup', finishMove,false)
|
||||
fireEvent('dragend')
|
||||
}
|
||||
|
||||
function fireEvent(eventName)
|
||||
{
|
||||
var event = new Event(eventName)
|
||||
event.detail = { x:xlate.matrix.e, y:xlate.matrix.f }
|
||||
return el.dispatchEvent(event)
|
||||
}
|
||||
|
||||
// Convert mouse position from screen space to coordinates of el
|
||||
function inElementSpace(evt)
|
||||
{
|
||||
pt.x = evt.clientX
|
||||
pt.y = evt.clientY
|
||||
return pt.matrixTransform( el.parentNode.getScreenCTM().inverse() )
|
||||
}
|
||||
|
||||
return el
|
||||
}
|
||||
|
||||
|
||||
export { Draggable, makeDraggable }
|
|
@ -0,0 +1,98 @@
|
|||
|
||||
var Event = Event || class Event { constructor(type){this.type=type} }
|
||||
// eventoj lancilo = events launcher
|
||||
var EventojLancilo = function( obj )
|
||||
{
|
||||
obj = this instanceof EventojLancilo ? this : obj
|
||||
obj = obj instanceof Function ? obj.prototype : obj
|
||||
|
||||
let has = {
|
||||
add: obj.addEventListener || obj.on
|
||||
, rem: obj.removeEventListener || obj.off
|
||||
, emit: obj.dispatchEvent || obj.emit || obj.fire || obj.fireEvent
|
||||
}
|
||||
// console.log(has)
|
||||
if( !has.add )
|
||||
obj[Symbol.Eventoj] = {}
|
||||
|
||||
// obj.on = tplOrCall(add) tpl?
|
||||
// obj.on('a',cb) n ok
|
||||
// obj.on('a',cb,opt) n ok
|
||||
// obj.on('a b',cb) n ok
|
||||
// obj.on(['a','b'],cb) y ko
|
||||
// obj.on(['a','b'],cb,opt) n ok
|
||||
// obj.on(['a','b','c'],cb,{}) y ko
|
||||
// obj.on({a:cba,b:cb2,c:cb3}) n ok
|
||||
|
||||
// obj.on('a')(cb) n ko
|
||||
// obj.on(['a'])(cb) y ok
|
||||
|
||||
// obj.on`a`(cb) y ok
|
||||
// obj.on`${str}change`(cb) y ok
|
||||
function tplOrCall( fn )
|
||||
{
|
||||
return function( ss, ...pp )
|
||||
{
|
||||
let isTpl = Array.isArray( ss ) && ss.every( o=> typeof o == 'string' ) && ss.length == pp.length + 1
|
||||
return isTpl
|
||||
? (...a)=> fn.bind(this)( String.merge(ss,...pp), ...a )
|
||||
: fn.bind(this)( ss, ...pp )
|
||||
}
|
||||
}
|
||||
// obj.on(['a','b'],cb,opt)
|
||||
// obj.on({a:cba,b:cb2,c:cb3},opt)
|
||||
// obj.on('a b',cb,opt)
|
||||
function multi( fn )
|
||||
{
|
||||
return ( ev, ...args )=>
|
||||
Array.isArray( ev )
|
||||
? ev.map( e=> fn(e,...args) )
|
||||
: typeof ev == 'object'
|
||||
? Object.keys( ev ).map( e=> fn(e,ev[e],...args) )
|
||||
: fn(ev,...args)
|
||||
}
|
||||
function on( event, handler, options )
|
||||
{
|
||||
let evs = this[Symbol.Eventoj][event] = this[Symbol.Eventoj][event] || []
|
||||
!evs.includes( handler )
|
||||
&& evs.push( handler )
|
||||
return this
|
||||
}
|
||||
function one( event, handler, options )
|
||||
{
|
||||
return on( event, (...args)=> off(handler) && handler(...args) )
|
||||
}
|
||||
function off( event, handler )
|
||||
{
|
||||
let evs = obj[Symbol.Eventoj][event] = obj[Symbol.Eventoj][event] || []
|
||||
evs.includes( handler )
|
||||
&& evs.splice( evs.indexOf(handler), 1 )
|
||||
return obj
|
||||
}
|
||||
function fire( event, ...args )
|
||||
{
|
||||
event = typeof event == 'string'
|
||||
? new Event( event )
|
||||
: event
|
||||
event.target = obj
|
||||
event.details = args
|
||||
event.type in obj[Symbol.Eventoj]
|
||||
&& obj[Symbol.Eventoj][event.type].map( h=> h.call(obj, event, ...args) )
|
||||
return event
|
||||
}
|
||||
Object.defineProperties( obj, {
|
||||
on: { value: tplOrCall(has.add ? has.add : on) }
|
||||
, off: { value: tplOrCall(has.rem ? has.rem : off) }
|
||||
, fire: { value: tplOrCall(has.emit ? has.emit : fire) }
|
||||
, one: { value: tplOrCall(has.add ? has.add : one) }
|
||||
, once: { value: tplOrCall(has.add ? has.add : one) }
|
||||
, addEventListener: { value: tplOrCall(has.add ? has.add : on) }
|
||||
, removeEventListener: { value: tplOrCall(has.rem ? has.rem : off) }
|
||||
, dispatchEvent: { value: tplOrCall(has.emit ? has.emit : fire) }
|
||||
, emit: { value: tplOrCall(has.emit ? has.emit : fire) }
|
||||
})
|
||||
}
|
||||
Symbol.Eventoj = Symbol`Eventoj`
|
||||
|
||||
|
||||
export { Event, EventojLancilo }
|
|
@ -0,0 +1,8 @@
|
|||
import { SVG } from './DOM.js'
|
||||
|
||||
const Group = ( cls )=> {
|
||||
let $dom = SVG`<g${cls ? ` class="${cls}"` : ''}/>`[0]
|
||||
return $dom
|
||||
}
|
||||
|
||||
export { Group }
|
|
@ -0,0 +1,61 @@
|
|||
import { SVG, DOM } from './DOM.js'
|
||||
/**
|
||||
* Context menus globally managed
|
||||
* <node>s that have a contextmenu handler at capture time put their menu
|
||||
* under event.menu property and this final bubble handler on document
|
||||
* creates the menu HTML in a SVG's <foreignObject>.
|
||||
*/
|
||||
document.xxxoncontextmenu = e=> {
|
||||
console.log(e)
|
||||
// console.log(e.path)
|
||||
console.log(e.menu)
|
||||
// let items = e.menu//path.reverse().reduce( (m,n)=> ({...m,...(n.menu?n.menu:{})}),{})
|
||||
// console.log(items, Object.keys(items).length )
|
||||
if( e.menu )
|
||||
{
|
||||
e.preventDefault()
|
||||
// let menu
|
||||
// , layer = UI.Overlay( menu = UI.Menu( items ) )
|
||||
// menu.setAttribute( 'x', e.clientX )
|
||||
// menu.setAttribute( 'y', e.clientY )
|
||||
// menu.style.transform = `translate( ${e.clientX}px, ${e.clientY}px )`
|
||||
// menu.style.position = 'absolute'
|
||||
// document.documentElement.append( layer )
|
||||
document.documentElement.append(
|
||||
Overlay(
|
||||
ContextMenu( e, e.menu )
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
const Overlay = ( ...items )=> {
|
||||
let html = SVG`<foreignObject width="100%" height="100%"/>`[0]
|
||||
html.append( ...items )
|
||||
html.one`click`( e=> /*e.target == html && */html.remove() )
|
||||
return html
|
||||
}
|
||||
const Menu = ( items, label )=> {
|
||||
let html = DOM`<menu xmlns="http://www.w3.org/1999/xhtml"${label ? ` label="${label}"` : ''}></menu>`.children[0]
|
||||
, btn
|
||||
html.append(
|
||||
...Object.keys( items )
|
||||
.map( k=> typeof items[k] == 'object'
|
||||
? Menu( items[k], k )
|
||||
: ( btn = DOM`<button>${k}</button>`.children[0], btn.on`click`( items[k] ), btn )
|
||||
)
|
||||
// ...items.map( item=> DOM`<button>${item.label}</button>`)
|
||||
)
|
||||
return html
|
||||
}
|
||||
const ContextMenu = ( {x,y}, items )=> {
|
||||
let menu = Menu( items )
|
||||
menu.style.transform = `translate( ${x}px, ${y}px )`
|
||||
menu.style.position = 'absolute'
|
||||
return menu
|
||||
}
|
||||
|
||||
export {
|
||||
Overlay
|
||||
, Menu
|
||||
, ContextMenu
|
||||
}
|
|
@ -0,0 +1,393 @@
|
|||
import { DOM, SVG, CSS } from './DOM.js'
|
||||
import { makeDraggable, Draggable } from './Draggable.js'
|
||||
|
||||
class Viewport extends HTMLElement {
|
||||
|
||||
static stylesForSVG = `
|
||||
@namespace html "http://www.w3.org/1999/xhtml";
|
||||
|
||||
/*TitilliumWeb-ExtraLight.ttf*/
|
||||
:root {
|
||||
--canvas-size: 1000000px;
|
||||
background-color: hsl(259 14% 12% / 1);
|
||||
--grid-color-hsl: 256deg 5% 46%;
|
||||
--grid-color: hsl(var(--grid-color-hsl));
|
||||
|
||||
display: inline-flex;
|
||||
}
|
||||
:root([debug]) g.Box foreignObject { border: 1px dashed red; }
|
||||
|
||||
[coordinate] { display: none }
|
||||
:root([grid]) [coordinate] { display: inline }
|
||||
|
||||
[coordinate] [origin],
|
||||
[coordinate] [x-axis],
|
||||
[coordinate] [y-axis] {
|
||||
fill: var(--grid-color);
|
||||
stroke: var(--grid-color);
|
||||
stroke-width: 3px;
|
||||
}
|
||||
[coordinate] [x-axis] {
|
||||
x1: calc(var(--canvas-size) * -1);
|
||||
x2: var(--canvas-size);
|
||||
}
|
||||
[coordinate] [y-axis] {
|
||||
y1: calc(var(--canvas-size) * -1);
|
||||
y2: var(--canvas-size);
|
||||
}
|
||||
[coordinate] [grid] {
|
||||
x: calc(var(--canvas-size) * -1);
|
||||
y: calc(var(--canvas-size) * -1);
|
||||
width: calc(var(--canvas-size) * 2);
|
||||
height: calc(var(--canvas-size) * 2);
|
||||
}
|
||||
|
||||
[mouse] { pointer-events:none }
|
||||
|
||||
[draggable] { cursor: move }
|
||||
|
||||
g.Box { --color: rgb(55, 50, 66); }
|
||||
g.Box foreignObject { font-family: 'Titillium Web', sans-serif; filter: drop-shadow(black 0px 2px 3px) drop-shadow(rgba(0, 0, 0, 0.5) 0px 2px 10px); }
|
||||
g.Box foreignObject * { pointer-events: none; user-select: none }
|
||||
g.Box foreignObject > html|box {
|
||||
display: flex;
|
||||
background: var(--color);
|
||||
border-radius: 5px;
|
||||
padding: 2em .5em .3em;
|
||||
color: white;
|
||||
flex-direction: column;
|
||||
place-items: stretch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
g.Box foreignObject > html|box > html|header {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background: rgba(255,255,255,0.3);
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-radius: 5px 5px 0 0;
|
||||
padding: .3em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
g.Box foreignObject > html|box > html|socket[output] {
|
||||
align-self: flex-end;
|
||||
}
|
||||
g.Box .anchor {
|
||||
r: 5px;
|
||||
fill: rgb(22, 199, 118);
|
||||
stroke: var(--color);
|
||||
stroke-width: 2;
|
||||
}
|
||||
g.Box .anchor.string {
|
||||
fill: chocolate;
|
||||
}
|
||||
`
|
||||
static styles = CSS`
|
||||
|
||||
menu {
|
||||
padding: .2em;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: wheat;
|
||||
background: #FFF1;
|
||||
font-family: sans-serif;
|
||||
font-size: 10px;
|
||||
/* box-shadow: 0 2px 4px black; */
|
||||
}
|
||||
|
||||
menu button {
|
||||
white-space: nowrap;
|
||||
background: transparent;
|
||||
border: none;
|
||||
text-align: start;
|
||||
font-family: sans-serif;
|
||||
color: wheat;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
menu[label]::before {
|
||||
content: attr(label);
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #FFF2;
|
||||
}
|
||||
|
||||
foreignObject > menu {
|
||||
box-shadow: 0 2px 4px black;
|
||||
padding: .3em;
|
||||
background: #131722e0;
|
||||
backdrop-filter: blur(3px);
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
constructor()
|
||||
{
|
||||
super()
|
||||
this.attachShadow({ mode: 'open' })
|
||||
this.shadowRoot.insertBefore()
|
||||
this.shadowRoot.innerHTML =
|
||||
`<svg width="100%" height="100%">
|
||||
<defs>
|
||||
<pattern id="smallGrid" width="10" height="10" patternUnits="userSpaceOnUse">
|
||||
<path d="M 10 0 L 0 0 0 10" fill="none" stroke="var(--grid-color)" stroke-width="0.5"></path>
|
||||
</pattern>
|
||||
<pattern id="grid100" width="100" height="100" patternUnits="userSpaceOnUse">
|
||||
<rect width="100" height="100" fill="url(#smallGrid)"></rect>
|
||||
<path d="M 100 0 L 0 0 0 100" fill="none" stroke="var(--grid-color)" stroke-width="1"></path>
|
||||
</pattern>
|
||||
<pattern id="grid" width="1000" height="1000" patternUnits="userSpaceOnUse">
|
||||
<rect width="1000" height="1000" fill="url(#grid100)"></rect>
|
||||
<path d="M 1000 0 L 0 0 0 1000" fill="none" stroke="var(--grid-color)" stroke-width="2.5"></path>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g canvas coordinate>
|
||||
<rect grid fill="url(#grid)"></rect>
|
||||
<circle origin r=3 />
|
||||
<line y-axis />
|
||||
<line x-axis />
|
||||
</g>
|
||||
<g mouse>
|
||||
<circle fill="red" r=5 />
|
||||
<line y-axis stroke="red" y1="-1000000" y2="1000000" />
|
||||
<line x-axis stroke="red" x1="-1000000" x2="1000000" />
|
||||
</g>
|
||||
</svg>
|
||||
<slot></slot>`
|
||||
// <rect view stroke="red" fill="aliceblue" width=1366 height=663 />
|
||||
this.shadowRoot.adoptedStyleSheets = [Viewport.styles]
|
||||
this.$svg = this.shadowRoot.querySelector('svg')
|
||||
this.$svg.append(
|
||||
DOM`<style>${Viewport.stylesForSVG}</style>`
|
||||
)
|
||||
|
||||
//.ownerDocument.adoptedStyleSheets = [Viewport.stylesForSVG]
|
||||
this.$canvas = this.$svg.querySelector('g[canvas]')
|
||||
this.$mouse = this.$svg.querySelector('g[mouse]')
|
||||
// this.$view = this.$svg.querySelector('rect[view]')
|
||||
// makeDraggable( this.$view )
|
||||
// this.$view.on`drag`( e=> this.$svg.setAttribute('viewBox',`${e.target.transform.baseVal[0].matrix.e} ${e.target.transform.baseVal[0].matrix.f} ${e.target.width.baseVal.value} ${e.target.width.baseVal.value}`) )
|
||||
this.$slot = this.shadowRoot.querySelector('slot')
|
||||
|
||||
}
|
||||
|
||||
connectedCallback()
|
||||
{
|
||||
if( !this.$svg.hasAttribute('viewBox') )
|
||||
this.$svg.setAttribute('viewBox', `0 0 ${this.offsetWidth} ${this.offsetHeight}`)
|
||||
this.addListeners()
|
||||
}
|
||||
|
||||
addListeners()
|
||||
{
|
||||
// Children svg append
|
||||
this.$slot.on`slotchange`( e=>
|
||||
this.$slot.assignedNodes()
|
||||
.filter( node=> node.$svg )
|
||||
.map( node=> this.$canvas.append(node.$svg) )
|
||||
|
||||
)
|
||||
|
||||
// Mouse
|
||||
this.onmousemove = e=> /*console.log('mouse',e.movementX,e.movementY)||*/ requestAnimationFrame( ()=>this.$mouse.moveTo(getMousePosition(e) ) )
|
||||
|
||||
// Zoom
|
||||
//@TODO Disable zoom while panning
|
||||
//@TODO Get min(width,height)
|
||||
this.onmousewheel = e=>
|
||||
this.$svg.panAndZoom( false, false, (this.$svg.viewBox.baseVal.height/2) * ( 1-(e.deltaY/1000) ) )
|
||||
// this.onmousewheel = e=> this.$svg.currentScale *= 1 - ( e.deltaY / 1000 )
|
||||
// this.onmousewheel = e=> this.setView({
|
||||
// width: 1 + ( e.deltaY / 1000 ),
|
||||
// height: 1 + ( e.deltaY / 1000 )
|
||||
// })
|
||||
|
||||
const getMousePosition = e=> {
|
||||
var CTM = this.$svg.getScreenCTM()
|
||||
if (e.touches) { e = e.touches[0] }
|
||||
return {
|
||||
x: (e.x - CTM.e) / CTM.a,
|
||||
y: (e.y - CTM.f) / CTM.d
|
||||
}
|
||||
}
|
||||
|
||||
// Convert mouse position from screen space to coordinates of el
|
||||
const inElementSpace = e=> {
|
||||
var pt = this.$svg.createSVGPoint()
|
||||
pt.x = e.x
|
||||
pt.y = e.y
|
||||
return pt.matrixTransform( this.$svg.getScreenCTM().inverse() )
|
||||
}
|
||||
|
||||
// Pan
|
||||
//@TODO x Change to moving $canvas
|
||||
//@TODO x Get initial CTM when start pan and don't update it while panning
|
||||
this.pan = e=> {
|
||||
|
||||
this._mouseOffset = { x: e.clientX, y: e.clientY }//{ x: this.$mouse.x, y: this.$mouse.y }
|
||||
// this.$svg.dataset.dragX = e.x
|
||||
// this.$svg.dataset.dragY = e.y
|
||||
// this._panStartCTM = this.$svg.getScreenCTM()
|
||||
// let rect = this.$svg.viewBox.baseVal
|
||||
// this.$svg.dataset.curTrX = rect.x + ( rect.width/2 )//this.$svg.currentTranslate.x
|
||||
// this.$svg.dataset.curTrY = rect.y + ( rect.height/2 )//this.$svg.currentTranslate.y
|
||||
// this._startPan = {
|
||||
// x: rect.x + ( rect.width/2 )
|
||||
// , y: rect.y + ( rect.height/2 )
|
||||
// }
|
||||
this._startPan = this.$svg.viewBox.baseVal.center
|
||||
this.addEventListener('mousemove', this.panning )
|
||||
|
||||
}
|
||||
this.panning = e=> {
|
||||
// console.log(e)
|
||||
// this.$svg.currentTranslate.x = this.$svg.dataset.curTrX - ( this.$svg.dataset.dragX - e.x )
|
||||
// this.$svg.currentTranslate.y = this.$svg.dataset.curTrY - ( this.$svg.dataset.dragY - e.y )
|
||||
// let mouse = getMousePosition( e )
|
||||
let _mouseDiff = { x: e.clientX - this._mouseOffset.x, y: e.clientY - this._mouseOffset.y }
|
||||
_mouseDiff.x /= this.$svg.clientHeight / this.$svg.viewBox.baseVal.height
|
||||
_mouseDiff.y /= this.$svg.clientHeight / this.$svg.viewBox.baseVal.height
|
||||
// let _mouseDiffCTM = getMousePosition( _mouseDiff )
|
||||
// let _mouseDiffSpace = inElementSpace( _mouseDiff )
|
||||
// let rect = this.$svg.viewBox.baseVal
|
||||
// let center = this.$svg.viewBox.baseVal.center//{
|
||||
// x: rect.x + ( rect.width/2 )
|
||||
// , y: rect.y + ( rect.height/2 )
|
||||
// }
|
||||
this.$svg.panAndZoom(
|
||||
// this._startPan.x - ( mouse.x - this._mouseOffset.x )
|
||||
// , this._startPan.y - ( mouse.y - this._mouseOffset.y )
|
||||
this._startPan.x - _mouseDiff.x
|
||||
, this._startPan.y - _mouseDiff.y
|
||||
// center.x - ( _mouseDiffCTM.x )
|
||||
// , center.y - ( _mouseDiffCTM.y )
|
||||
)
|
||||
}
|
||||
this.finishPan = e=> this.removeEventListener('mousemove', this.panning )
|
||||
this.cancelPan = e=> console.warn('@TODO')
|
||||
|
||||
this.onmousedown = e=> {
|
||||
if( e.which == 2 )// Wheel click
|
||||
this.pan( e )
|
||||
}
|
||||
this.onmouseup = e=> this.finishPan( e )
|
||||
|
||||
// Draggable stuff
|
||||
Draggable.startGlobalDrag = e=> this.$svg.$$`[dragged]`.filter(el=>el.draggable).map( el=> el.drag(e) )
|
||||
Draggable.stopGlobalDrag = e=> this.$svg.$$`[dragged]`.map( el=> el.removeAttribute('dragged') )
|
||||
|
||||
// Draggable
|
||||
window.on`mousemove`( Draggable.startGlobalDrag , true )
|
||||
window.on`mouseup`( Draggable.stopGlobalDrag )
|
||||
|
||||
|
||||
/**
|
||||
* Context menus globally managed
|
||||
* <node>s that have a contextmenu handler at capture time put their menu
|
||||
* under event.menu property and this final bubble handler on document
|
||||
* creates the menu HTML in a SVG's <foreignObject>.
|
||||
*/
|
||||
this.$svg.oncontextmenu = e=> {
|
||||
console.log(e)
|
||||
// console.log(e.path)
|
||||
console.log(e.menu)
|
||||
// let items = e.menu//path.reverse().reduce( (m,n)=> ({...m,...(n.menu?n.menu:{})}),{})
|
||||
// console.log(items, Object.keys(items).length )
|
||||
if( e.menu )
|
||||
{
|
||||
e.preventDefault()
|
||||
// let menu
|
||||
// , layer = UI.Overlay( menu = UI.Menu( items ) )
|
||||
// menu.setAttribute( 'x', e.clientX )
|
||||
// menu.setAttribute( 'y', e.clientY )
|
||||
// menu.style.transform = `translate( ${e.clientX}px, ${e.clientY}px )`
|
||||
// menu.style.position = 'absolute'
|
||||
// document.documentElement.append( layer )
|
||||
this.$svg.append(
|
||||
Overlay(
|
||||
ContextMenu( e, e.menu )
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newDocument()
|
||||
{
|
||||
let doc = DOM`<svg width="100%" height="100%">
|
||||
<defs>
|
||||
<pattern id="smallGrid" width="10" height="10" patternUnits="userSpaceOnUse">
|
||||
<path d="M 10 0 L 0 0 0 10" fill="none" stroke="var(--grid-color)" stroke-width="0.5"></path>
|
||||
</pattern>
|
||||
<pattern id="grid100" width="100" height="100" patternUnits="userSpaceOnUse">
|
||||
<rect width="100" height="100" fill="url(#smallGrid)"></rect>
|
||||
<path d="M 100 0 L 0 0 0 100" fill="none" stroke="var(--grid-color)" stroke-width="1"></path>
|
||||
</pattern>
|
||||
<pattern id="grid" width="1000" height="1000" patternUnits="userSpaceOnUse">
|
||||
<rect width="1000" height="1000" fill="url(#grid100)"></rect>
|
||||
<path d="M 1000 0 L 0 0 0 1000" fill="none" stroke="var(--grid-color)" stroke-width="2.5"></path>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g canvas coordinate>
|
||||
<rect grid fill="url(#grid)"></rect>
|
||||
<circle origin r=3 />
|
||||
<line y-axis />
|
||||
<line x-axis />
|
||||
</g>
|
||||
<g mouse>
|
||||
<circle fill="red" r=5 />
|
||||
<line y-axis stroke="red" y1="-1000000" y2="1000000" />
|
||||
<line x-axis stroke="red" x1="-1000000" x2="1000000" />
|
||||
</g>
|
||||
</svg>
|
||||
`
|
||||
return doc
|
||||
}
|
||||
|
||||
loadDocument()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
openDocument( doc )
|
||||
{
|
||||
this.sha
|
||||
}
|
||||
|
||||
async saveToFile()
|
||||
{
|
||||
let file = await showSaveFilePicker()
|
||||
, W = await file.createWritable()
|
||||
await W.write( this.toString() )
|
||||
await W.close()
|
||||
}
|
||||
|
||||
toString()
|
||||
{
|
||||
let styles
|
||||
, dolly = this.$svg.cloneNode(true)
|
||||
// dolly.append(
|
||||
// styles = DOM`<style>${
|
||||
// [...Viewport.stylesForSVG.rules]
|
||||
// .map( r=> r.cssText )
|
||||
// .join('\n')
|
||||
// }</style>`
|
||||
// )
|
||||
|
||||
dolly.removeAttribute('width')
|
||||
dolly.removeAttribute('height')
|
||||
|
||||
dolly.setAttribute('xmlns', 'http://www.w3.org/2000/svg' )
|
||||
dolly.setAttribute('xmlns:svg', 'http://www.w3.org/2000/svg' )
|
||||
dolly.setAttribute('xmlns:html', 'http://www.w3.org/1999/xhtml' )
|
||||
|
||||
return dolly.outerHTML
|
||||
}
|
||||
}
|
||||
customElements.define( 'nb-viewport', Viewport )
|
||||
|
||||
|
||||
|
||||
export { Viewport }
|
Binary file not shown.
|
@ -0,0 +1,38 @@
|
|||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Titillium+Web:wght@200&display=swap');
|
||||
html, body, svg, vp-viewport {
|
||||
margin: 0; padding: 0; width: 100%; height: 100%;
|
||||
--grid-color: grey;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="./EventojLancilo.js"></script>
|
||||
<script src="./DOM.js"></script>
|
||||
<script src="./Draggable.js"></script>
|
||||
<script src="./Overlay.js"></script>
|
||||
<script src="./Group.js"></script>
|
||||
<script src="./Box.js"></script>
|
||||
|
||||
<script src="./Viewport.js"></script>
|
||||
|
||||
|
||||
<vp-viewport grid></vp-viewport>
|
||||
|
||||
<!-- <vp-box title="Name tag">
|
||||
<vp-socket output name="output1"></vp-socket>
|
||||
<vp-socket input name="input1"></vp-socket>
|
||||
<vp-socket input name="input2"></vp-socket>
|
||||
</vp-box>
|
||||
</vp-viewport> -->
|
||||
|
||||
<script>
|
||||
const view = $`vp-viewport`.$svg
|
||||
view.append(
|
||||
Box('Name',['aze'],['qsd'])
|
||||
, Box('Other',['float', 'list', 'list', 'list', 'list', 'list', 'list', 'list'],['foo'])
|
||||
, Box('Awesome',['position:Vector3'],['scale:Vector3'])
|
||||
, Box('SVG output',['svg:SVGSvgElement'],[])
|
||||
, Box('String input',[],['string:String'])
|
||||
, Box('Selector',['css:String','root:Node'],['nodes:NodeList'])
|
||||
)
|
||||
</script>
|
|
@ -0,0 +1,75 @@
|
|||
<style>
|
||||
@import url('./fonts/TitilliumWeb/TitilliumWeb.css');
|
||||
html, body, svg, vp-viewport {
|
||||
font-family: 'Titillium Web', sans-serif;
|
||||
margin: 0; padding: 0; width: 100%; height: 100%;
|
||||
--grid-color: grey;
|
||||
}
|
||||
</style>
|
||||
<!--
|
||||
<script src="./EventojLancilo.js"></script>
|
||||
<script src="./DOM.js"></script>
|
||||
<script src="./Draggable.js"></script>
|
||||
<script src="./Overlay.js"></script>
|
||||
<script src="./Group.js"></script>
|
||||
<script src="./Box.js"></script>
|
||||
|
||||
<script src="./Viewport.js"></script>
|
||||
-->
|
||||
<script type="module">
|
||||
import {
|
||||
EventojLancilo
|
||||
, logNpass
|
||||
, DOM
|
||||
, SVG
|
||||
, CSS
|
||||
, $
|
||||
, $$
|
||||
, Draggable
|
||||
, Overlay
|
||||
, Group
|
||||
, Box
|
||||
, Viewport
|
||||
} from "./index.js"
|
||||
|
||||
window.nouilles = {
|
||||
EventojLancilo
|
||||
, logNpass
|
||||
, DOM
|
||||
, SVG
|
||||
, CSS
|
||||
, $
|
||||
, $$
|
||||
, Draggable
|
||||
, Overlay
|
||||
, Group
|
||||
, Box
|
||||
, Viewport
|
||||
}
|
||||
</script>
|
||||
|
||||
<nb-viewport grid></nb-viewport>
|
||||
|
||||
<!-- <vp-box title="Name tag">
|
||||
<vp-socket output name="output1"></vp-socket>
|
||||
<vp-socket input name="input1"></vp-socket>
|
||||
<vp-socket input name="input2"></vp-socket>
|
||||
</vp-box>
|
||||
</vp-viewport> -->
|
||||
|
||||
<script type="module">
|
||||
import { $ } from './DOM.js'
|
||||
import { Box } from './Box.js'
|
||||
|
||||
const view = $`vp-viewport`
|
||||
view.$svg.append(
|
||||
Box('Name',['aze'],['qsd'])
|
||||
, Box('Other',['float', 'list', 'list', 'list', 'list', 'list', 'list', 'list'],['foo'])
|
||||
, Box('Awesome',['position:Vector3'],['scale:Vector3'])
|
||||
, Box('SVG output',['svg:SVGSvgElement'],[])
|
||||
, Box('String input',[],['string:String'])
|
||||
, Box('Selector',['css:String','root:Node'],['nodes:NodeList'])
|
||||
)
|
||||
|
||||
window.view = view
|
||||
</script>
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
export { EventojLancilo } from './EventojLancilo.js'
|
||||
export {
|
||||
logNpass
|
||||
, DOM
|
||||
, SVG
|
||||
, CSS
|
||||
, $
|
||||
, $$
|
||||
} from './DOM.js'
|
||||
export { Draggable, makeDraggable } from './Draggable.js'
|
||||
export { Overlay, Menu } from './Overlay.js'
|
||||
export { Group } from './Group.js'
|
||||
export { Box } from './Box.js'
|
||||
|
||||
export { Viewport } from './Viewport.js'
|
Loading…
Reference in New Issue