drawsocket

Drawsocket API

Each key type has a slightly different API based on the needs of the objects created in the browser.

Note: Please see the Message Format and Addressing the Client Browser sections in the overview page for an introduction to the general drawsocket message syntax and server setup.

svg

The svg key specifies that the val objects will be used to create or modify SVG elements, which will be placed by default in the webpage’s main SVG element.

The object(s) set to the client via the val field predominantly consist of attributes that configure the created object, as specified by the SVG specification, available online in many places. See the Mozilla SVG documentation for information about the basic SVG object types.

Object attributes may be set as members of the val object, as demonstrated above.

In addition there are several keywords used by drawsocket to handle special cases.

style

A sub-bundle labeled style may optionally be included which will set inline CSS style properties for the created node, which will be applied by the browser, depending on the SVG specification, and the browser’s implementation.

For example:

/* : {
    /key : "svg",
    /val : {
        /new : "path",
        /id : "bar",
        /d : "M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80",
        /style : {
            /stroke : "red",
            /stroke-width : 2
        }
    }
}

A note on CSS styles and inheritance

There are three levels of inheritance with SVG CSS styling:

  1. presentation attributes, set within the element, as demonstrated above in the context of SVG object attributes.
  2. stylesheet definitions, set in an attached CSS stylesheet, or within an <style> element in the HTML page (settable via the “css” key detailed below).
  3. inline styling, a set of CSS rules included as part of an element’s style attribute. In drawsocket we set these values via the /style sub-bundle.

Each is overridden by the next: stylesheets override presentation attributes, and inline styles override all the others.

See the online CSS documentation for more information.

SVG Layers

SVG elements are drawn in the order they are created via the new keyword (and remain in layer order if updated after creation).

Sometimes it is useful to separate groups of objects in specific drawing layer order to maintain background, mid, and foreground layers. The can be achieved using the SVG group element.

For example, we can first create three layers that we will name “back”, “main”, and “overlay”, using an array of objects.

/* : {
   /key : "svg",
   /val : [{
      /new : "g",
      /id : "back"
   }, {
      /new : "g",
      /id : "main"
   }, {
      /new : "g",
      /id : "overlay"
   }]
}

Note that the array specifies the order of the objects in the message, so “back” will be drawn first, then “main”, then “overlay”.

When objects are added to any of these groups, they will be appended to the end of the stack of child nodes within the group, however, all objects in the “back” group will appear behind the “main” and “overlay” layers; while objects added to the “overlay” layer will always be above the other layers, and so on.

Referencing SVG Elements

Preexisting object maybe reused with the use SVG element, which uses the id of another SVG object by reference, set by the href attribute.

There are two approaches recommended for reusing SVG elements:

defs

The SVG specification provides a special storage element within the SVG object called defs (see the online documentation for more details). Objects stored in the defs are not drawn to the screen, but are stored as prototypes of objects that can be drawn with the use tag. The defs can be used in this way for storing a library of objects. To add an object to the defs group, you can use the parent keyword to tell the client to add a new object (or group of objects) to the defs, for example:

/* : {
    /key : "svg",
    /val : {
        /parent : "defs",
        /new : "rect",
        /id : "squarePrototype",
        /x : 50,
        /y : 50,
        /width : 20,
        /height : 20
    }
}

use

To use our new defs object, we refer to it by id in the use element’s href attribute, prefixed by the id selector #:

/* : {
    /key : "svg",
    /val : {
        /new : "use",
        /id : "sq",
        /href : "#squarePrototype",
        /x : 0,
        /y : 0
    }
}

Note that the x y coordinates of the use object set the top left corner of the original object. That means that in this case, the top left corder of the drawn rectangle will be at {50,50} not {0,0}. So, for best results, set defs object positions relative to {0,0}.

The use element’s href attribute can also be used to import an object by reference to an id present in an SVG file asset. For example, if there is a file called “demo.svg” stored in the public folder, you could reference an element with the id foo by using the # id selector:

/* : {
    /key : "svg",
    /val : {
        /new : "use",
        /id : "importedObject",
        /href : "demo.svg#foo",
        /x : 0,
        /y : 0
    }
}

An additional utility provided by drawsocket provides an offset to the imported object, offsetting its origin (top-left corner) to be {0,0}, helpful for placing objects intuitively in a new context. To enable this offsetting, send an extra 1 value for the href attribute. For example:

/* : {
    /key : "svg",
    /val : {
        /new : "use",
        /id : "importedObject",
        /href : ["demo.svg#foo", 1],
        /x : 0,
        /y : 0
    }
}

A note on foreignObject elements in SVG

HTML objects may be used inside SVG using a foreignObject element to wrap the HTML content. To create HTML elements within a SVG parent element, the drawsocket new keyword recognizes the identifier prefix html: as a flag to create a HTML node instead of an SVG element. For example:

/* : {
  /key : "svg",
  /val : {
    /new : "foreignObject",
    /x : 100,
    /y : 100,
    /width : "100%",
    /height : "100%",
    /children : {
        /new : "html:div",
        /text : "foo"
    }
  }
}

clear and remove

The clear and remove keys have similar, but slightly different behaviors.

For example, to clear all SVG elements, you can send the messages:

/* : {
    /key : "clear",
    /val : "svg"
}

To clear the elements of g layer, use the clear message. For example, using the layers we created above, we might want to clear the “main” and “overlay” layers while leaving the “back” layer:

/* : {
    /key : "clear",
    /val : ["main", "overlay"]
}

To remove a specific object, use the remove message. For example:

/* : {
    /key : "remove",
    /val : "main"
}

Note that removing a g object, will remove all of its children and the g object. This means that you will not be able to add objects to the g group “main” until you recreate it with the new keyword.

css

The css key allows the user to to add new CSS rules to the webpage’s <style> tag. See the online documentation for more information.

There are two keywords used by the drawsocket API: selector, and props.

selector

The selector sets the CSS rule’s selector, which could be one of three types:

props

The props nested object, contains the properties for the CSS rule.

For example, here we create two rules, one for line objects, and one specifically for objects with the id “bar”:

/* : {
    /key : "css",
    /val : [{
        /selector : "line",
        /props : {
            /stroke : "red",
            /stroke-width : 5
        }
    }, {
        /selector : "#bar",
        /props : {
            /stroke : "black",
            /stroke-width : 10
        }
    }]
}

html

The html key uses the same keywords as the svg key type:

call

Some HTML objects also can be manipulated with JS object methods, via the call keyword:

Note: if a method requires separated arguments, rather than a single object, you can use an array of objects for args, each containing the key val to set the value of that argument.

This is still in beta, but hypothetically the example below should work for a video player, you may need to click on the browser window first before the browser will let you call this though due to privacy restrictions.

/* : {
  /key : "html",
  /val : {
    /id : "foovideo",
    /call : {
    	/method : "play"
    }
  }
}

HTML layers

By default HTML objects will be added to an HTML div object, one layer below the SVG content (see the drawsocket-page.html file for details). However, HTML content requiring user interaction, for example input forms, or media players, will not be clickable if located behind the SVG layer. Therefore a special-purpose, top-layer div is set in the HTML file, called forms which will should always be reachable by user interaction. Set objects in the forms layer just as you would for other parent objects, using the parent keyword.

Additionally, HTML layers may be created with a new div tag, just as discussed above via the g SVG tag.

tween

drawsocket provides access to the GreenSock Animation Platform TweenMax and TimelineMax libraries via the tween key. The object types are identified by the keywords used.

TweenMax objects use the keywords:

TimelineMax objects use the keywords:

A special function keyword has been added to handle the tween var callbacks. For example:

/* : {
	/key : "tween",
	/val : {
		/id : "clock-tween",
		/target : "#clock",
		/dur : 3600,
		/vars : {
			/x : "+=0",
			/ease : "linear",
			/paused : "true",
			/onUpdate : {
				/function : "
          let text = document.getElementById('clock');

          let seconds = this.time() % 60;
          if( seconds < 10 ) seconds = '0'+seconds;

          let minutes = Math.floor( this.time() / 60);
          if( minutes < 10 ) minutes = '0'+minutes;

          text.innerHTML = minutes+':'+seconds;
        "
			}
		}
	}
}

See the TweenMax vars documentation, for more information about callbacks.

pdf

PDF files may be imported into drawsocket by reference, the settable attributes are as follows:

  /* : {
    /key : "pdf",
    /val : {
      /id : "newpdf",
      /href : "/media/flint_piccolo_excerpt.pdf",
      /width : 600,
      /x : 100,
      /page : 2
    }
  }

sound

drawsocket includes the tone.js library, note: currently in beta.

Keywords:

Note: if a method requires separated arguments, rather than a single object, you can use an array of objects for args, each containing the key val to set the value of that argument.

Some examples:

/* : {
  /key : "sound",
  /val : {
    /new : "Player",
    /id : "kick",
    /vars : {
      /url : "/media/808_mp3/kick1.mp3",
      /autostart : "false",
      /loop : "false"
    },
    /call : {
        /method : "toMaster"
    }
  }
}

Replay a sound via the restart object method:

/* : {
  /key : "sound",
  /val : {
    /id : "kick",
    /call : {
        /method : "restart"
    }
  }
}

Play a chord on a PolySynth via the triggerAttackRelease function:

/* : {
  /key : "sound",
  /val : {
    /id : "psynth",
    /call : {
    	/method : "triggerAttackRelease",
    	/args : [{
    		/val : ["Eb3", "G4", "C4"]
    	}, {
    		/val : 0.1
    	}]
    }
  }
}

set

To set the value of a Tone.js Signal object, for example the frequency of an Oscillator, we need to use a the set operator, which functions a bit like the call operator, but sets a member value rather than calling a function.

The set keyword should contain an object or array of objects, with member keywords:

For example:

/* : {
  /key : "sound",
  /val : {
    /id : "sine",
    /set : {
    	/member : "frequency.value",
    	/value : 1000
    }
  }
}

obj:get

In some cases we need to refer to an object from a library or one that we have created, which needs to be passed to a function that makes connections between things.

For this (currently only in the Tone.js interface) you can use the obj and get message to get an element from an object.

For example, the Tone.js PolySynth needs a member of the Tone library to set as the voice type. To do this we can use an object argument with the obj and get keywords, here to to ge the Synth member of the Tone library.

/* : {
	/key : "sound",
	/val : {
		/new : "PolySynth",
		/id : "psynth",
		/vars : {
			/polyphony : 4,
			/volume : 0,
			/detune : 0,
			/voice : {
				/obj : "Tone",
				/get : "Synth"
			}
		},
		/call : {
			/method : "toMaster"
		}
	}
}

cmd

A set of special commands wrappers for the Tone Player have been added to provide synchronized playback options:

/* : {
  /key : "sound",
  /val : {
    /id : "kick",
    /cmd : "start"
  }
}

file

Clients can load JSON of stored messages, formatted in the drawsocket API detailed here.

Keywords:

For example, here we tell clients logged into the URL /foo to load the messages for URL /bar from the file “savedState.json”.

/foo : {
    /key : "file",
    /val : {
        /fetch : "savedState.json",
        /prefix : "/bar"
    }
}

event

The event keyword provides a mechanism for scheduling future object sent to the drawsocket.input function.

For example, the following example, an event is created and set with a delay (del) of 1000ms (1s). After this delay, the object stored at the the obj address, is sent to drawsocket.input and is executed, resulting in a short diagonal line, with the id “foo1”.

/* : {
	/key : "event",
	/val : {
		/id : "event1",
		/del : 1000,
		/obj : {
			/key : "svg",
			/val : {
				/new : "line",
				/id : "foo2",
				/x1 : 10,
				/x2 : 20,
				/y1 : 30,
				/y2 : 10
			}
		}
	}
}

do_sync

The do_sync keyword triggers the client clock time synchronization routine.

/foo : {
  /key : "do_sync",
  /val : 1
}

writeSVG

The writeSVG keyword requests the SVG element from a client browser. The result is saved to disk in the local folder of the patch containing the drawsocket object.

For example:

/URLtoWrite : {
	/key : "writeSVG",
	/val : 1
}

will output the file: path/to/patch/downloaded-URLtoWrite.svg.

JS Methods

The drawsocket object itself maybe referred to in JS scripts, for example in an object event watcher. The drawsocket object, exposes the following methods for general usage:

For example, the following message creates a new HTML input field, where users can type. When the user hits the Enter key, the script will send the value of the HTML form to the server prefixed by the client’s OSC-prefix, and the id of this object:

/* : {
  /key : "html",
  /val : {
    /parent : "forms",
    /new : "input",
    /type : "text",
    /id : "userinput",
    /name : "userinput",
    /size : 10,
    /onkeydown : "if( event.key == 'Enter' ){
      let obj = {};
      obj[ drawsocket.oscprefix+'/'+this.id+'/input' ] = this.value;
      drawsocket.send( obj );
    }"
  }
}

callback function setters for use in custom HTML contexts

signalPeer

Clients can send messages to other URLs on the server by using the signalPeer key sent to the server.

For example, here is a button that sends a message to another client on being clicked:

/foo : {
  /key : "html",
  /val : {
    /parent : "forms",
    /id : "button-foo",
    /new : "button",
    /text : "click me!",
    /style : {
      /position : "absolute",
      /top : "100px",
      /left : "100px",
      /width : "70px"
    },
    /onclick : "

     drawsocket.send({
       key: 'signalPeer',
       url: '/bar',
       val: {
           key: 'svg',
           val: {
             new: 'text',
             text: 'hello bar!',
             x: 200,
             y: 200
           }
       }
     })

  "
  }
}

maxOutput

Outputs object specified as val to Max if the browser is running in jweb.

/* : {
  /key : "maxOutput",
  /val : {
    /someAddress : "hello maxOutput!"
  }
}

in dev keys

function

create and call user defined functions from JSON format.

creating a function

{
  /key : "function",
  /val : {
    /id : "foo",
    /args : ["a", "b"],
    /body : " let sum = a + b;
              console.log( sum );
            "
  }
}

calling a function

{
  /key : "function",
  /val : {
    /id : "foo",
    /call : [1, 2]
  }
}

prints 3 to browser console

function as type

In some object type parsers, the parameters passed an object including the address /function can be used to create an anonymous function:

  /id : "foo",
  /onload : {
    /function : "drawsocket.send({
      loaded : "foo"
    })
  }

get

… needs some testing

selector

relativeTo