The design of svgR is influenced by three considerations:
The first is easy to satisfy, just replicate the svg interface in R. The second and third give rise to the structural variations/enhancements described in this document.
Combo Attributes is short for combined attributes.
Vectors are natural to the R language. A single assignment statement to assign multiple values is second nature to the R programmer. For example, consider specifying the center of a circle. The typical R programmer is likely to use a single vector assignment such as cxy=c(400,100), instead of a pair of assignments cx=400, cy=100.
Since svgR is designed to be easy to use for R programmers, svgR supports using combined SVG attributes. That means, that although SVG requires cx cy to be specified seperately, svgR allows them to be specified jointly as a single vector.
Consider the following:
Consider the following
svgR(
wh=c(600,100),
circle(cxy=c(100,50), r=30, fill='red')
)
We can visualize the call structure of the above code as
The root node represents the function svgR The light yellow nodes represent named parameters, which in svgR lingo are called attributes. The blue node represents a call to the circle function, which in svgR lingo is called an element. This element is a shape element, and tells svgR that a circle is wanted. Elements are only available for use within the scope of the svgR call. |
The above call will generate the following SVG markup:
## <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" id="root" width="600" height="100">
## <circle r="30" fill="red" cx="100" cy="50"/>
## </svg>
This SVG markup looks like
|
The svgR automatically generates an SVG root node and gives it an id of ‘root’. The wh attribute is split into 2 SVG attributes width, and height, which specify width and height of the display region The svgR circle element creates the SVG circle element. The cxy attribute is split into 2 SVG attributes cx, cy which specify the center of the circle. We should note that instead of cxy and wh, we can also use cx, cy, width, and height directly in svgR, its just a little more typing. In the tree to left, light yellow is used to indicate attributes. |
Another feature of svgR is that an unnamed argument that is a list, can be “promoted”, providing a convenient way to do iteration. We illustrate this with another slightly more complex example
colors<-c('red','yellow','green')
WH<-c(900,100)
svgR(
wh=WH,
lapply(1:3, function(i)
circle(cxy=c(i*100,50), r=50, fill= colors[i])
)
)
Noting that lapply returns a list, we see that the structure of this call is essentially:
|
The svgR function has two arguments (child nodes): a wh attribute and a list, The list is the return value of the lapply. The list contains three elements, the circle nodes, resulting from the circle function calls. |
What happens next is that svgR promotes the children of the list to become arguments of the root.
|
The three circle elements in the list are promoted up to become arguments to the svgR call. List promotion occurs whenever an argument is unnamed and a list. In that case, the elements of the list argument are then moved one level up in the call tree. This process is performed recursively, so that the resulting arguments will either be named or non-lists. This behaviour is similar to the usual R unlist, except that names lists are not unlisted (since named arguments are attributes.) This behaviour is one of the features that give svgR it power of expressibilty. |
Finally, svgR generates an SVG tree, as shown below
|
Again, the svgR attributes that consist of vectors are split into seperate svg attributes. Also, light yellow denotes attributes, blue denotes shape elements, green denotes container elements, |
Traditionally, Patterns, Gradients, Masks and Filters are defined inside a defs element and when used, are referenced by an xlink. However, tracing/unraveling the reference can be painful and frustrating, particullary when it is only needed once.
In svgR, we introduce the notion of anonymous Patterns, Gradients, Masks and Filters. This can be thought of as analogous to the use of anonymous functions, namely define where used. Since svgR creates SVG markup, to implement these anonymous elements, behind the scenes svgR relocate those elements while providing identifiers.
In the subsequent sections we provide details the svgR anonymous patters, Gradients, Masks and Filters.
Consider the following mask
WH<-c(900,100)
svgR( wh=WH,
circle( cxy=c(50,50), r=50,
fill=pattern( xy=c(0,0), wh=c(20,20), patternUnits='userSpaceOnUse',
polygon( points=c(c(0,0), c(20,0), c(10,20) ), fill='red' )
)
)
)
The call tree looks like
The generated SVG tree, is
Consider the following mask
WH<-c(900,100)
svgR( wh=WH,
circle( cxy=c(50,50), r=50,
fill=radialGradient( colors=c('yellow','blue') )
)
)
The call tree looks like
The generated SVG tree, is
Consider the following mask
WH<-c(800,100)
svgR( wh=WH,
text(xy=c(20,70),'Masking Example!',font.size=50),
circle(cxy=c(50,50), r=50, fill='red',
mask=mask(
rect( xy=c(0,0), wh=WH, fill='#AAAAAA' ),
rect( cxy=c(50,50), wh=c(60,80), fill='black' )
)
)
)
The call tree looks like
The generated SVG tree, is
WH=c(800, 120) # window rect
svgR( wh=WH,
text( 'svgR', xy=c(50,70), font.size=50, fill="lightblue", stroke="darkblue",
filter = filter( xy=c(-10,-10), wh=c(200,60),
feBlend( x=-10, width=200,
in1="SourceGraphic",
in2=feGaussianBlur( stdDeviation=3, in1=feOffset( dxy=c(3,3), in1="SourceAlpha") )
)
)
)
)
The call tree looks like
The generated SVG tree, is
todo: clippath, marker