HTML
<svg id="s" viewBox="0,0,128,128">
<symbol id="ninjaCat" viewBox="0,0,128,128">
<!-- meta name=generator value=vim ;) -->
<path class="cat-body" d="M24,120 Q24,64 64,64 Q104,64 104,120 L24,120" fill="#000" stroke="black" stroke-width="6" stroke-linecap="square"/>
<path d="M32,24 Q32,80 64,80 Q96,80 96,24 L84,32 Q64,20 44,32Z" fill="#777" stroke="black" stroke-width="6" stroke-linecap="round"/>
<circle cx="50" cy="50" r="3" fill="black"/>
<circle cx="78" cy="50" r="3" fill="black"/>
<path d="M56,30 q8,-2 16,0 l0,28 l-16,0Z" fill="#aaa"/>
<path d="M57,57 l16,0 l-8,8Z" fill="salmon"/>
<circle cx="57" cy="64" r="7" fill="white"/>
<circle cx="71" cy="64" r="7" fill="white"/>
<path d="M37,48 Q37,32 64,28 Q91,32 91,48Z q0,8 8,8 l38,0 q8,0 8,-8 Q88,77 64,78 Q40,77 37,48" fill="rgba(0,0,0,.8)" />
<path id="sunglasses" d="M37,48 Q48,64 64,48 Q80,64 91,48Z" fill="rgba(0,0,0,.2)" stroke-width="1" stroke="rgba(0,0,0,.1)"/>
<path d="M35.5,41 92.5,41 91,48 37,48Z" fill="red"/>
<path d="M92,42 q0,-4 4,-4 l2,0 l0,4 l-6,0 M90,48 q0,4 4,4 l2,0 l0,-4Z" fill="red" />
<path d="M97,44 l12,0 q08,0 08,-8 l-20,0" fill="red" stroke="black" stroke-width="4"/>
<path d="M93,54 l12,0 q08,0 08,-8 l-20,0" fill="red" stroke="black" stroke-width="4"/>
<path d="M32,88 L73,117 L85,117 L35,82Z" fill="#555"/>
<path class="laser-eyes" d="M50,51 L120,120 M78,51 L120,120" stroke-width="4" stroke-linecap="round"/>
</symbol>
<use xlink:href="#ninjaCat"/>
</svg>
JAVASCRIPT
with(Math)R=random,Q=sqrt,π=PI,S=sin,C=cos
W=innerWidth,H=innerHeight
function setSize(){
W=innerWidth
H=innerHeight
s.setAttribute("viewBox",[0,0,W,H].join(","))
}
setSize()
onresize=setSize
laserLeft={x:(R()*128)|0,y:(R()*128)|0}
laserRight={x:(R()*128)|0,y:(R()*128)|0}
laserTargetLeft={x:(R()*128)|0,y:(R()*128)|0}
laserTargetRight={x:(R()*128)|0,y:(R()*128)|0}
function distance(p0,p1) {
return Q((p1.x-p0.x)*(p1.x-p0.x)+(p1.y-p0.y)*(p1.y-p0.y))
}
function randomSparks(p,t,x,y,r,i,d,l){
r=""
x=p.x
y=p.y
for(i=3;i--;){
d=((R()*360)|0)*π/180
l=((R()*80)|0)/10
r+="M"+x+","+y+" L"+((x+C(d)*l)|0)+","+((y+S(d)*l)|0)+" "
}
return r
}
onmousemove=function(e){
laserTargetLeft.x=128*e.clientX/W
laserTargetLeft.y=128*e.clientY/H
laserTargetRight.x=128*e.clientX/W
laserTargetRight.y=128*e.clientY/H
}
onblur=function(e){
laserTargetLeft={x:(R()*128)|0,y:(R()*128)|0}
laserTargetRight={x:(R()*128)|0,y:(R()*128)|0}
}
~function L(t){
document.body.style.background="hsl("+(((t/10)|0)%360)+",33%,44%)";
[].slice.call(document.querySelectorAll('.laser-eyes')).forEach(function (path){
path.setAttribute("d",
"M50,51 L"+laserLeft.x+","+laserLeft.y +
" M78,51 L"+laserRight.x+","+laserRight.y + " " +
randomSparks(laserLeft,t)+" "+randomSparks(laserRight,t)
)
if(laserLeft.x<laserTargetLeft.x)laserLeft.x+=.5
if(laserLeft.x>laserTargetLeft.x)laserLeft.x-=.5
if(laserLeft.y<laserTargetLeft.y)laserLeft.y+=.5
if(laserLeft.y>laserTargetLeft.y)laserLeft.y-=.5
if(distance(laserLeft,laserTargetLeft)<2)laserTargetLeft={x:(R()*128)|0,y:(R()*128)|0}
if(laserRight.x<laserTargetRight.x)laserRight.x+=.5
if(laserRight.x>laserTargetRight.x)laserRight.x-=.5
if(laserRight.y<laserTargetRight.y)laserRight.y+=.5
if(laserRight.y>laserTargetRight.y)laserRight.y-=.5
if(distance(laserRight,laserTargetRight)<2)laserTargetRight={x:(R()*128)|0,y:(R()*128)|0}
})
requestAnimationFrame(L)
}(0)