This example is an early attempt in using svgR to write stories or plays. To make it easier to read, I’ve broke the code into 3 blocks. Skip to output
The first block defines the actors in the play (story). That is, it defines an svgR tree and populates it with shapes.
colors<-c("red","blue", "green", "orange")
WH=c(600,400)
A=120
B=90
triPts<-matrix(c(c(0,0),c(A,0),c(0,-B),c(0,0)),2,4)
trianglePts<-list(
lower= triPts,
upper=matrix(c(A,-B),2,4)-triPts
)
center<-WH/2 # center
triangleID<-paste0("triangle-",1:4)
dur<-0.5
addTriangle %<c-% function(tri.id, tri.pts, opacity=1, fillColor="white"){
g( id=tri.id, opacity=opacity,
lapply(1:3,
function(i){
line(id=paste0(tri.id,"-",i),
opacity=1, stroke.width=4,
stroke=colors[i],
xy1=tri.pts[,i],
xy2=tri.pts[,i+1])
}
),
polygon(points=tri.pts[,1:4], fill=fillColor, stroke="none", opacity=1)
)
}
doc<-svgR( playBar(wh=WH),
g(id = "textArea", transform=list(translate=(center*c(0.8,0.2)))),
g(id = "graphArea", transform=list(translate=center),
rect(id="ASquared", wh=c(A,A), xy=-c(0,A), stroke="black",
fill="pink", opacity=0),
rect(id="BSquared", wh=c(B,B), xy=-c(B,0), stroke="black",
fill="lightgreen", opacity=0),
rect(id="CSquared", wh=c(A+B,A+B), xy=-c(B,A), stroke="black",
stroke.width=3, fill=colors[4], opacity=0),
g(id="A",
addTriangle("triangle-I", trianglePts$lower, opacity=1),
addTriangle("triangle-II", trianglePts$upper, opacity=0)
),
g(id="B", opacity=0,
addTriangle("triangle-III", trianglePts$lower, opacity=1),
addTriangle("triangle-IV", trianglePts$upper, opacity=1)
)
)
)
This second block simply defines the actions than can be performed by the actors. This is just a simply list functions to operate on the svgR object.
delta<-2
story.new<-function(adoc, dt=2){
doc=adoc
indx<-0
function(code){
fnsList<-list(
step=function(){
indx<<-indx+1
},
btime=function(){
paste0(svgR:::playButton.click(),"+",indx*delta)
},
displayText=function(txt, color="black", freeze=FALSE){
txtId=paste0("txt-",indx )
doc[["textArea"]]( text(id=txtId, xy=c(0,0), opacity=0,
stroke=color, font.size=20,
lapply(txt, function(tx){
if(grepl("^\\^",tx)){
tx<-gsub("^\\^","",tx)
tspan(baseline.shift='super', tx)
} else {
tx
}}),
if(!freeze){
set(attributeName='opacity', to=1, begin=btime(), dur=delta)
} else {
set(attributeName='opacity', to=1, begin=btime())
}
))
},
wideStroke=function(id){
doc[[id]](
set(attributeName="stroke.width", attributeType="CSS", to=10, begin=btime(), dur=delta)
)
},
setOpacity=function(id, value){
doc[[id]](
set(attributeName="opacity", attributeType="CSS", to=value, begin=btime(), dur=delta, fill="freeze")
)
},
moveTo=function(id, from, to){
doc[[id]](
animateMotion( from=from, to=to , begin=btime(), dur=delta, fill="freeze")
)
},
rotate=function(id, angles, about=c(0,0)){
doc[[id]](
animateTransform(
attributeName="transform",
type="rotate",
from=c(angles[1], about ),
to=c(angles[2], about),
begin=btime(),
dur=delta,
fill="freeze"
))
},
setFill=function(id, value){
doc[[id]](set(attributeName="fill", attributeType="CSS", to=value, begin=btime() )
)
}
)
eval(substitute(code), list2env(fnsList, parent.frame() ))
tmp<-as.character(doc)
tmp
}
}
This final block defines the story to be told. Each scene in the story ends with a call to the step function.
story<-story.new(doc)
story({
displayText('A right triangle')
step()
displayText('Side A', color=colors[1])
wideStroke("triangle-I-1")
step()
displayText('Side B', color=colors[3])
wideStroke("triangle-I-3")
step()
displayText('Side C', color=colors[2])
wideStroke("triangle-I-2")
step()
displayText('An A by B rectangle ')
setOpacity("triangle-II", 1)
step()
displayText('Copy')
setOpacity("B", .5)
moveTo("B", from=c(0,0), to=c(0,B))
step()
displayText('Rotate')
setOpacity("B", 1)
rotate("A", angles=c(0,-90), about=c(0,0))
step()
displayText(c('A ', '^2') , 'red')
setOpacity("ASquared", 1)
step()
displayText(c('B','^2'), 'green')
setOpacity("BSquared", 1)
step()
displayText(c('A', '^2',' + ','B', '^2'), 'brown')
setOpacity("CSquared", 1)
step()
displayText(c('A', '^2',' + ','B', '^2'), 'brown')
moveTo("triangle-III", from=c(0,0), to=c(-B,0))
step()
displayText(c('A', '^2',' + ','B', '^2'), 'brown')
moveTo("triangle-IV", from=c(0,0), to=c(0,-A))
step()
displayText(c('A', '^2',' + ','B', '^2'), 'brown')
moveTo("triangle-I", from=c(0,0), to=c(-B,A))
step()
displayText(c('A', '^2',' + ','B', '^2',' = ','C','^2'), 'blue', freeze=TRUE)
setFill("CSquared", "lightblue" )
})->tale
cat(tale)
Press the button on the play bar to start the animation.