Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@chriswhong
Last active September 9, 2019 15:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriswhong/b0b675d6970e77742b987a551bbf4c64 to your computer and use it in GitHub Desktop.
Save chriswhong/b0b675d6970e77742b987a551bbf4c64 to your computer and use it in GitHub Desktop.
Qri blob loading spinner prototype
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/ >
<title>Qri Loading Spinner Prototype</title>
<script src="https://d3js.org/d3.v3.min.js"></script>
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Bootstrap 3 -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
</head>
<body>
<div id="cont" class="container-fluid">
<div class="row text-center">
<div class="col-sm-12 column text-center">
<div class="chart"></div>
</div>
</div>
</div>
<script>
// Based on http://bl.ocks.org/nbremer/69808ec7ec07542ed7df
const element = document.documentElement
const bodyElement = document.getElementsByTagName('body')[0]
const x = window.innerWidth || element.clientWidth || bodyElement.clientWidth
const totalHeight = window.innerHeight || element.clientHeight || bodyElement.clientHeight
const margin = {
top: 30,
right: 30,
bottom: 30,
left: 30
}
const width = Math.min(500, (totalHeight - 20), $(".chart").width() - margin.left - margin.right);
const height = width;
//d3 scale for both x and y offsets, converts sin and cos (-1 - 1) to pixel from center
const offsetScale = d3.scale.linear()
.domain([-1, 1])
.range([-29, 29]);
//Create SVG
const svg = d3.select(".chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.style("filter", "url(#gooey)") //Set the filter on the container svg
.attr("transform", "translate(" + (width/2 + margin.left) + "," +(height/2 + margin.top) + ")");
// gets a random radian
const getRandomAngle = () => Math.floor((Math.random() * 6.28) + 1)
//SVG filter for the gooey effect
//Code taken from http://tympanus.net/codrops/2015/03/10/creative-gooey-effects/
var defs = svg.append('defs');
var filter = defs.append('filter').attr('id','gooey');
filter.append('feGaussianBlur')
.attr('in','SourceGraphic')
.attr('stdDeviation','4')
.attr('result','blur');
filter.append('feColorMatrix')
.attr('in','blur')
.attr('mode','matrix')
.attr('values','1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7')
.attr('result','gooey');
filter.append('feComposite')
.attr('in','SourceGraphic')
.attr('in2','gooey')
.attr('operator','atop');
// append a g element to contain the 'satellite' circles
// render it before the big circle so satellite circles are behind big circle
const satelliteGroup = svg.append('g')
//Append big circle at center
svg.append("circle")
.attr("class", "centerCircle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", 20)
.style("fill", "#81BC00");
// add eyes
const eyes = {
width: 3,
xOffset: 6,
height: 7,
y: -8
}
svg.append('rect')
.attr('x', 0 - eyes.xOffset - (eyes.width / 2))
.attr('y', eyes.y)
.attr('rx', eyes.width / 2)
.attr('ry', eyes.width / 2)
.attr('height', eyes.height)
.attr('width', eyes.width)
svg.append('rect')
.attr('x', 0 + eyes.xOffset - ( eyes.width / 2))
.attr('y', eyes.y)
.attr('rx', eyes.width / 2)
.attr('ry', eyes.width / 2)
.attr('height', eyes.height)
.attr('width', eyes.width)
const dur = 1000
let angle = getRandomAngle()
// getAngle gets a random radian measure that is more than 1 radian away from the
// previous one, so the subsequent satellite blob will not shoot out near the last one
const getAngle = () => {
let newAngle = getRandomAngle()
while (Math.abs(newAngle - angle) < 1) {
newAngle = getRandomAngle()
}
angle = newAngle
return newAngle
}
// make a new satellite circle every second, and animate it out and in again
setInterval(() => {
satelliteGroup.append("circle")
.datum(getAngle())
.attr("cx", 0)
.attr("cy", 0)
.attr("r", 8)
.style("fill", "#81BC00")
.transition("outward").duration(dur)
.attr("cy", (d) => offsetScale(Math.sin(d)))
.attr("cx", (d) => offsetScale(Math.cos(d)))
.transition("inward").duration(dur)
.attr("cx", 0)
.attr("cy", 0)
.remove()
}, 1000)
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment