Last active
November 23, 2015 09:53
-
-
Save rikkertkoppes/a8d961daa8e877de6dd2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Document</title> | |
<link rel="stylesheet" href="style.css"> | |
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=RobotoDraft:300,400,500,700,400italic"> | |
</head> | |
<body> | |
<div class="card"> | |
<div class="card-content"> | |
<h2>Title</h2> | |
<p class="spinnerline"> | |
<span class="pull-left">Something something</span> | |
<span class="pull-right" spinner>8</span> | |
</p> | |
</div> | |
</div> | |
<div class="card"> | |
<div class="card-content"> | |
<h2>Title</h2> | |
<p class="spinnerline"> | |
<span class="pull-left">Something something</span> | |
<span class="pull-right" spinner min="0" max="10">8</span> | |
</p> | |
</div> | |
</div> | |
<div class="card"> | |
<div class="card-content"> | |
<h2>Title</h2> | |
<p class="spinnerline"> | |
<span class="pull-left">Something something</span> | |
<span class="pull-right" spinner min="0" max="10">8</span> | |
</p> | |
</div> | |
</div> | |
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script> | |
<script src="spinner.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* math */ | |
function getDifference(from,to) { | |
return [ | |
to[0] - from[0], | |
to[1] - from[1] | |
]; | |
} | |
function getAngle(from,to) { | |
var d = getDifference(from,to); | |
return 180 * Math.atan2(d[1],d[0]) / Math.PI; | |
} | |
function getDistance(from,to) { | |
var d = getDifference(from,to); | |
return Math.sqrt(d[0]*d[0]+d[1]*d[1]); | |
} | |
/* widget */ | |
function Widget() { | |
this.el = document.createElement('div'); | |
this.el.classList.add('spinnerwidget'); | |
this.mousemoveListener = this.handleMove.bind(this); | |
this.mouseupListener = this.handleUp.bind(this); | |
this.centerListener = this.hide.bind(this); | |
this.el.innerHTML = [ | |
'<div class="line"></div>', | |
'<div class="value"></div>' | |
].join(''); | |
this.lineEl = this.el.querySelector('.line'); | |
this.valueEl = this.el.querySelector('.value'); | |
} | |
Widget.prototype.getCenter = function() { | |
var r = this.el.getBoundingClientRect(); | |
this.center = [ | |
(r.left + r.right) / 2, | |
(r.top + r.bottom) /2 | |
]; | |
} | |
Widget.prototype.update = function(mouse) { | |
var newAngle = getAngle(this.center,mouse); | |
while (Math.abs(newAngle-this.angle) > 180) { | |
//angle rollover | |
newAngle += (newAngle < this.angle)?360:-360; | |
} | |
this.angle = newAngle; | |
console.log(newAngle); | |
this.radius = getDistance(this.center,mouse); | |
this.lineEl.style.transform = 'rotate('+this.angle+'deg)'; | |
this.lineEl.style.width = (Math.max(100,this.radius))+'px'; | |
this.value = this.startValue + Math.round((this.angle - this.startAngle) / 36); | |
this.valueEl.innerHTML = this.value; | |
} | |
Widget.prototype.show = function(value, start, cb) { | |
document.body.appendChild(this.el); | |
document.body.addEventListener('mousemove',this.mousemoveListener); | |
document.body.addEventListener('mouseup',this.mouseupListener); | |
this.valueEl.addEventListener('click',this.centerListener); | |
this.start = start; | |
this.getCenter(); | |
this.startAngle = getAngle(this.center,this.start); | |
this.startValue = value; | |
this.angle = this.startAngle; | |
this.update(start); | |
this.onDone = cb; | |
} | |
Widget.prototype.hide = function() { | |
document.body.removeChild(this.el); | |
document.body.removeEventListener('mousemove',this.mousemoveListener); | |
document.body.removeEventListener('mouseup',this.mouseupListener); | |
this.valueEl.removeEventListener('click',this.centerListener); | |
if (this.onDone) { | |
this.onDone(this.value); | |
} | |
} | |
Widget.prototype.handleMove = function(e) { | |
this.update([e.pageX,e.pageY]); | |
e.preventDefault(); | |
return false; | |
} | |
Widget.prototype.handleUp = function() { | |
console.log(this.value,this.startValue); | |
if (this.value !== this.startValue) { | |
this.hide(); | |
} | |
} | |
/* singleton for all spinners */ | |
var widget = new Widget(); | |
/* spinner */ | |
function Spinner(el,widget) { | |
this.el = el; | |
this.widget = widget; | |
this.value = 0; | |
console.log('create'); | |
el.classList.add('spinner'); | |
el.addEventListener('mousedown',this.activate.bind(this)); | |
} | |
Spinner.prototype.activate = function(e) { | |
this.widget.show(this.value, [e.pageX,e.pageY], this.update.bind(this)); | |
} | |
Spinner.prototype.update = function(value) { | |
this.value = value; | |
console.log(value); | |
this.el.innerHTML = this.value; | |
} | |
Spinner.create = function(el) { | |
return new Spinner(el,widget); | |
} | |
Array.prototype.slice.call(document.querySelectorAll('[spinner]')).forEach(Spinner.create); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html, body { | |
margin: 0; | |
font-family: RobotoDraft,Roboto,'Helvetica Neue',sans-serif; | |
} | |
/* generic material design stuff */ | |
.card { | |
box-sizing: border-box; | |
margin: 8px; | |
box-shadow: 0 3px 1px -2px rgba(0,0,0,.14),0 2px 2px 0 rgba(0,0,0,.098),0 1px 5px 0 rgba(0,0,0,.084); | |
background-color: rgb(255,255,255); | |
border-radius: 2px; | |
overflow: hidden; | |
} | |
.card-content { | |
padding: 16px; | |
} | |
.pull-left { | |
float: left; | |
} | |
.pull-right { | |
float: right; | |
} | |
h2 { | |
font-size: 20px; | |
} | |
p { | |
overflow: hidden; | |
} | |
p.spinnerline { | |
line-height: 48px; | |
} | |
/* spinner styling */ | |
.spinner { | |
border-radius: 50%; | |
background-color: whitesmoke; | |
display: inline-block; | |
width: 48px; | |
height: 48px; | |
line-height: 48px; | |
text-align: center; | |
} | |
.spinner:hover { | |
background-color: darkblue; | |
color: white; | |
} | |
.spinnerwidget { | |
width: 200px; | |
height: 200px; | |
border: 2px solid silver; | |
background-color: rgba(0,0,0,0.1); | |
border-radius: 100%; | |
position: absolute; | |
left: 50%; | |
margin-left: -100px; | |
top: 100px; | |
} | |
.spinnerwidget .line { | |
border: 1px solid silver; | |
position: absolute; | |
left: 100px; | |
top: 100px; | |
width: 100%; | |
height: 0; | |
box-sizing: border-box; | |
transform-origin: 0 50%; | |
} | |
.spinnerwidget .value { | |
position: absolute; | |
left: 50%; | |
top: 50%; | |
height: 48px; | |
width: 48px; | |
margin-top: -24px; | |
margin-left: -24px; | |
line-height: 48px; | |
text-align: center; | |
font-size: 20px; | |
border-radius: 100%; | |
background-color: white; | |
box-shadow: 0 3px 1px -2px rgba(0,0,0,.14),0 2px 2px 0 rgba(0,0,0,.098),0 1px 5px 0 rgba(0,0,0,.084); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment