Skip to content

Instantly share code, notes, and snippets.

@acidsound
Created February 27, 2019 18:58
Show Gist options
  • Save acidsound/b9bccfc390f2169c3fbb87a1e406b5d8 to your computer and use it in GitHub Desktop.
Save acidsound/b9bccfc390f2169c3fbb87a1e406b5d8 to your computer and use it in GitHub Desktop.
Simple Knob simple SVG knob // source https://jsbin.com/nupeke
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="simple SVG knob">
<meta charset="utf-8">
<title>Simple Knob</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<script type="text/spacebars" name="main">
<svg>
<defs>
<filter id="f3" x="-10%" y="-5%" width="210%" height="205%">
<feoffset result="offOut" in="SourceAlpha" dx="0" dy="2" />
<fegaussianblur result="blurOut" in="offOut" stddeviation="1" />
<feblend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
<filter id="f4" x="-10%" y="-30%" width="210%" height="205%">
<feoffset result="offOut" in="SourceAlpha" dx="0" dy="-4" />
<fegaussianblur result="blurOut" in="offOut" stddeviation="1" />
<feblend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
</defs>
<g class="jog" style="-webkit-transform: rotate3d(0,0,1,{{knob}}deg); transform: rotate3d(0,0,1,{{knob}}deg)">
<circle class="floor" cx="6em" cy="6em" r="5em" filter="url(#f3)"/>
<circle class="handle" cx="6em" cy="3em" r="0.6em" filter="url(#f4)"/>
</g>
</svg>
</script>
<script src="http://output.jsbin.com/yeceqe.js"></script>
<style id="jsbin-css">
svg {
width: 80vw;
height: 80vh;
}
svg circle {
fill: white;
stroke: #ccc;
}
svg .jog {
transform-origin: 50% 50%;
-webkit-transform-origin: 50% 50%;
}
</style>
</head>
<body>
<script id="jsbin-javascript">
var mstatus, setNob;
this.knob = new Blaze.Var(0);
mstatus = false;
setNob = function(target, e) {
var deg, dt, pt, rad;
if (e.originalEvent.touches != null) {
e = e.originalEvent.touches[0];
}
pt = {
x: e.clientX - target.getBBox().x / 2,
y: e.clientY - target.getBBox().y / 2
};
dt = {
x: pt.x - target.cx.animVal.value,
y: pt.y - target.cy.animVal.value
};
rad = Math.atan2(dt.y, dt.x);
deg = rad * (180 / Math.PI) + 90;
if (deg > 180) {
deg = -360 + deg;
}
return knob.set((deg < -140 && -140) || (deg > 140 && 140) || deg);
};
Template.main.created = function() {
return knob.set(0);
};
Template.main.events({
'mousedown svg, touchstart svg': function(e) {
mstatus = true;
if (mstatus) {
return setNob(document.querySelector('.floor'), e);
}
},
'mouseup svg, touchend svg': function() {
return mstatus = false;
},
'mousemove svg, touchmove svg': function(e) {
if (mstatus) {
setNob(document.querySelector('.floor'), e);
}
return e.preventDefault();
}
});
Template.main.helpers({
'knob': function() {
return knob.get();
}
});
</script>
<script id="jsbin-source-css" type="text/css">svg {
width: 80vw;
height: 80vh;
circle {
fill: white;
stroke: #ccc;
}
.jog {
transform-origin: 50% 50%;
-webkit-transform-origin: 50% 50%;
}
}</script>
<script id="jsbin-source-javascript" type="text/javascript">@knob = new Blaze.Var(0)
mstatus = false
setNob = (target, e)->
e=e.originalEvent.touches[0] if e.originalEvent.touches?
pt =
# mobile has no offsetX
x: e.clientX - target.getBBox().x/2
y: e.clientY - target.getBBox().y/2
dt =
x: pt.x - target.cx.animVal.value
y: pt.y - target.cy.animVal.value
rad = Math.atan2 dt.y, dt.x
deg = rad * (180 / Math.PI) + 90
# range -140 ~ 140
deg= -360+deg if deg > 180
knob.set (deg < -140 and -140) or (deg > 140 and 140) or deg
# knob.set deg
Template.main.created = ->
knob.set 0
Template.main.events
'mousedown svg, touchstart svg': (e)->
mstatus = true
setNob document.querySelector('.floor'), e if mstatus
'mouseup svg, touchend svg': ->
mstatus = false
'mousemove svg, touchmove svg': (e)->
setNob document.querySelector('.floor'), e if mstatus
e.preventDefault() # for iOS Safari
Template.main.helpers
'knob': ->
knob.get()</script></body>
</html>
svg {
width: 80vw;
height: 80vh;
}
svg circle {
fill: white;
stroke: #ccc;
}
svg .jog {
transform-origin: 50% 50%;
-webkit-transform-origin: 50% 50%;
}
var mstatus, setNob;
this.knob = new Blaze.Var(0);
mstatus = false;
setNob = function(target, e) {
var deg, dt, pt, rad;
if (e.originalEvent.touches != null) {
e = e.originalEvent.touches[0];
}
pt = {
x: e.clientX - target.getBBox().x / 2,
y: e.clientY - target.getBBox().y / 2
};
dt = {
x: pt.x - target.cx.animVal.value,
y: pt.y - target.cy.animVal.value
};
rad = Math.atan2(dt.y, dt.x);
deg = rad * (180 / Math.PI) + 90;
if (deg > 180) {
deg = -360 + deg;
}
return knob.set((deg < -140 && -140) || (deg > 140 && 140) || deg);
};
Template.main.created = function() {
return knob.set(0);
};
Template.main.events({
'mousedown svg, touchstart svg': function(e) {
mstatus = true;
if (mstatus) {
return setNob(document.querySelector('.floor'), e);
}
},
'mouseup svg, touchend svg': function() {
return mstatus = false;
},
'mousemove svg, touchmove svg': function(e) {
if (mstatus) {
setNob(document.querySelector('.floor'), e);
}
return e.preventDefault();
}
});
Template.main.helpers({
'knob': function() {
return knob.get();
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment