harts all over the page while mouse or touch move plus bigger centered hart on click
!function(F,L,A,D,z,J,K,G,C,H,y,k,j,I,i){function h(t,q,s){var p=I.appendChild(A.createElement("canvas")),m=p.getContext("2d"),n=p.style,o=20*D()+(s||4),l=o/10,e=1;n.cssText="position:absolute;top:"+(q+(s?0:D()*o+20))+"px;left:"+(t+(s?0:D()*o+10))+"px;";!function r(){var f=l,u=e,d=l/2,g=l/4;p.width=p.height=f;m.beginPath();m.arc(g,g,g,0,z*F,1);m.arc(d+g,g,g,0,z*F,1);m.moveTo(0,g);m.lineTo(d,f);m.lineTo(f,g);m.fillStyle="rgba(180,0,0,"+u+")";m.fill();n.marginTop=n.marginLeft=-d+"px";l+=.05*(o-l);e+=-.05*e;.05>e?I.removeChild(p):i(r)}()}function E(b){h(b.pageX,b.pageY,F*(b.type==H))}function B(b){j=b.type;b=b.touches||[b];h(b[0].pageX,b[0].pageY,F*(j==H))}I=A.documentElement;i=L["r"+J]||L["webkitR"+J]||L["mozR"+J]||L["msR"+J]||L["oR"+J]||setTimeout;I[G+K](k,function a(c){I[C+K](y,E,1);I[C+K](H,E,1);I[C+K](k,a,1);I[G+K]("touchmove",B,1);I[G+K](H,B,1);B(c)},1);I[G+K](y,E,1);I[G+K](H,E,1)}(45,this,document,Math.random,Math.PI,"equestAnimationFrame","EventListener","add","remove","click","mousemove","touchstart");
IWZ1bmN0aW9uKEYsTCxBLEQseixKLEssRyxDLEgseSxrLGosSSxpKXtmdW5jdGlvbiBoKHQscSxzKXt2YXIgcD1JLmFwcGVuZENoaWxkKEEuY3JlYXRlRWxlbWVudCgiY2FudmFzIikpLG09cC5nZXRDb250ZXh0KCIyZCIpLG49cC5zdHlsZSxvPTIwKkQoKSsoc3x8NCksbD1vLzEwLGU9MTtuLmNzc1RleHQ9InBvc2l0aW9uOmFic29sdXRlO3RvcDoiKyhxKyhzPzA6RCgpKm8rMjApKSsicHg7bGVmdDoiKyh0KyhzPzA6RCgpKm8rMTApKSsicHg7IjshZnVuY3Rpb24gcigpe3ZhciBmPWwsdT1lLGQ9bC8yLGc9bC80O3Aud2lkdGg9cC5oZWlnaHQ9ZjttLmJlZ2luUGF0aCgpO20uYXJjKGcsZyxnLDAseipGLDEpO20uYXJjKGQrZyxnLGcsMCx6KkYsMSk7bS5tb3ZlVG8oMCxnKTttLmxpbmVUbyhkLGYpO20ubGluZVRvKGYsZyk7bS5maWxsU3R5bGU9InJnYmEoMTgwLDAsMCwiK3UrIikiO20uZmlsbCgpO24ubWFyZ2luVG9wPW4ubWFyZ2luTGVmdD0tZCsicHgiO2wrPS4wNSooby1sKTtlKz0tLjA1KmU7LjA1PmU/SS5yZW1vdmVDaGlsZChwKTppKHIpfSgpfWZ1bmN0aW9uIEUoYil7aChiLnBhZ2VYLGIucGFnZVksRiooYi50eXBlPT1IKSl9ZnVuY3Rpb24gQihiKXtqPWIudHlwZTtiPWIudG91Y2hlc3x8W2JdO2goYlswXS5wYWdlWCxiWzBdLnBhZ2VZLEYqKGo9PUgpKX1JPUEuZG9jdW1lbnRFbGVtZW50O2k9TFsiciIrSl18fExbIndlYmtpdFIiK0pdfHxMWyJtb3pSIitKXXx8TFsibXNSIitKXXx8TFsib1IiK0pdfHxzZXRUaW1lb3V0O0lbRytLXShrLGZ1bmN0aW9uIGEoYyl7SVtDK0tdKHksRSwxKTtJW0MrS10oSCxFLDEpO0lbQytLXShrLGEsMSk7SVtHK0tdKCJ0b3VjaG1vdmUiLEIsMSk7SVtHK0tdKEgsQiwxKTtCKGMpfSwxKTtJW0crS10oeSxFLDEpO0lbRytLXShILEUsMSl9KDQ1LHRoaXMsZG9jdW1lbnQsTWF0aC5yYW5kb20sTWF0aC5QSSwiZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJFdmVudExpc3RlbmVyIiwiYWRkIiwicmVtb3ZlIiwiY2xpY2siLCJtb3VzZW1vdmUiLCJ0b3VjaHN0YXJ0Iik7
!function (
//! (C) WebReflection
// single var declaration in the whole function, these are simply shortcuts
FORTY_FIVE, window, document, random, PI, animationFrame, EventListener, add, remove, click, mousemove, touchstart, type, container, timer
) {"use strict";
// create a canvas and starts growing while fading out
function init(x, y, r) {
var
canvas = container.appendChild(document.createElement("canvas")),
context = canvas.getContext("2d"),
style = canvas.style,
size = random() * 20 + (r || 4),
square = size / 10,
fade = 1,
factor = .05
;
// canvas is positioned statically where the pointer was
style.cssText = "position:absolute;top:" + (y + (r ? 0 : random() * size + 20)) + "px;left:" + (x + (r ? 0 : random() * size + 10)) + "px;";
// draw the little hart ...
!function love() {
draw(canvas, context, style, square, fade, square / 2, square / 4);
// ease out both square size and fade
square += (size - square) * factor;
fade += fade * -factor;
// call the timer for the next size or remove the node from the dom
fade < factor ? container.removeChild(canvas) : timer(love);
}();
}
// the hart is drawn here via dimensions
function draw(canvas, context, style, square, fade, halfSquare, quarterSquare) {
canvas.width = canvas.height = square;
context.beginPath();
context.arc(quarterSquare, quarterSquare, quarterSquare, 0, PI * FORTY_FIVE, 1);
context.arc(halfSquare + quarterSquare, quarterSquare, quarterSquare, 0, PI * FORTY_FIVE, 1);
context.moveTo(0, quarterSquare);
context.lineTo(halfSquare, square);
context.lineTo(square, quarterSquare);
context.fillStyle = "rgba(180,0,0," + fade + ")";
context.fill();
// the hart is centered in the pointer
style.marginTop = style.marginLeft = -halfSquare + "px";
}
// used for both mouse move and down ... when down, the size is bigger
function mouseEvent(e) {
init(e.pageX, e.pageY, FORTY_FIVE * (e.type == click));
}
// used for both touchstart and touchmove ... when touchstart the size is bigger
function touchEvent(e) {
type = e.type;
e = e.touches || [e];
init(e[0].pageX, e[0].pageY, FORTY_FIVE * (type == click));
}
// the best place to append little hart, no z-index necessary
container = document.documentElement;
// just the right timer function to boost performances where possible
timer = window["r" + animationFrame] ||
window["webkitR" + animationFrame] ||
window["mozR" + animationFrame] ||
window["msR" + animationFrame] ||
window["oR" + animationFrame] ||
// fallback to setTimeout for older browsers
setTimeout;
// when touch is detected, fired before mouse fallbacks ...
container[add + EventListener](touchstart, function detect(e) {
// all listeners mouse related are dropped and right touch related are added
container[remove + EventListener](mousemove, mouseEvent, 1);
container[remove + EventListener](click, mouseEvent, 1);
container[remove + EventListener](touchstart, detect, 1);
container[add + EventListener]("touchmove", touchEvent, 1);
container[add + EventListener](click, touchEvent, 1);
// do not miss a single event, fire the current one too
touchEvent(e);
}, 1);
// mouse events for all desktop browsers and older devices
container[add + EventListener](mousemove, mouseEvent, 1);
container[add + EventListener](click, mouseEvent, 1);
}(45, this, document, Math.random, Math.PI, "equestAnimationFrame", "EventListener", "add", "remove", "click", "mousemove", "touchstart");