Skip to content

Instantly share code, notes, and snippets.

@bqpd
Created September 30, 2016 11:52
Show Gist options
  • Save bqpd/10689d2d1940c0582ac1cc9c9fa81971 to your computer and use it in GitHub Desktop.
Save bqpd/10689d2d1940c0582ac1cc9c9fa81971 to your computer and use it in GitHub Desktop.
sensitivity slider
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>sensitive sliders</title>
<style>
body {
width: 800px;
margin: 0 auto;
}
.sensitivity {
stroke: black;
stroke-width: 6;
}
.sensitivity.free {
stroke-width: 0;
}
.sensitivity.arrowhead {
fill: black;
stroke-width: 0;
}
.value {
fill: #2eabe2;
}
.value.active {
stroke: black;
}
.bound.active {
stroke: red;
}
</style>
<script src="d3.v4.min.js"></script>
</head>
<body>
<svg id="test"></svg>
<script>
vk = {"lowerbound": 0, "upperbound": 100, "value": 100, "sensitivity":20}
radii = {"value": 10, "bound_outer": 16, "bound_inner": 10}
size = {"x": 800, "y": 100}
pad = 50
if (!(pad >= radii.bound_outer)) console.log("assert fail")
slidersvg = d3.select("#test")
.attr("width", size.x)
.attr("height", size.y)
sliderg = slidersvg.append("g")
.attr("transform", "translate("+pad+","+size.y/2+")")
// Bounding arcs
var arc = d3.arc()
.innerRadius(radii.bound_inner)
.outerRadius(radii.bound_outer)
// Arrowheads
slidersvg.append("defs")
.append("marker")
.attr("id", "sensitivity")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 5)
.attr("refY", 0)
.attr("markerWidth", 2)
.attr("markerHeight", 2)
.attr("orient", "auto")
.append("path")
.classed("sensitivity", true)
.classed("arrowhead", true)
.attr("d", "M0,-5L10,0L0,5")
// Interactive functions
var activate = function(d){ d3.select(this).classed("active", true) },
deactivate = function(d){ d3.select(this).classed("active", false) }
function drag(dragfn) {
return d3.drag()
.on("start", activate)
.on("drag", function(){dragfn()
if (vk.lowerbound >= vk.value) {
vk.value = vk.lowerbound
vk.sensitivity = -30
} else if (vk.upperbound <= vk.value) {
vk.value = vk.upperbound
vk.sensitivity = 30
} else {
vk.sensitivity = 0
}
redrawslider()
})
.on("end", deactivate)
}
function draglower() {
vk.lowerbound = d3.event.x
if (vk.upperbound < vk.lowerbound)
vk.upperbound = vk.lowerbound
}
function dragupper() {
vk.upperbound = d3.event.x
if (vk.upperbound < vk.lowerbound)
vk.lowerbound = vk.upperbound
}
function dragtight() {
anytight = false
if (vk.value == vk.upperbound) {
dragupper()
anytight = true
}
if (vk.value == vk.lowerbound) {
draglower()
anytight = true
}
if (anytight)
vk.value = d3.event.x
}
lowerbound = sliderg.append("path")
.classed("bound", true).classed("lower", true)
.attr("d", arc.startAngle(0).endAngle(-Math.PI))
.call(drag(draglower))
upperbound = sliderg.append("path")
.classed("bound", true).classed("upper", true)
.attr("d", arc.startAngle(0).endAngle(Math.PI))
.call(drag(dragupper))
sensitivityarrow = sliderg.append("line")
.classed("sensitivity", true)
.attr("marker-end", "url(#sensitivity)")
.call(drag(dragtight))
value = sliderg.append("circle")
.classed("value", true)
.attr("cy", 0)
.attr("r", radii.value)
.call(drag(dragtight))
function redrawslider() {
lowerbound.attr("transform", "translate("+vk.lowerbound+",0)")
upperbound.attr("transform", "translate("+vk.upperbound+",0)")
sensitivityarrow.attr("x1", vk.value).attr("y1", 0)
.attr("x2", vk.value+radii.bound_outer*Math.sign(vk.sensitivity)+vk.sensitivity).attr("y2", 0)
.classed("free", vk.sensitivity == 0)
value.attr("cx", vk.value)
}
redrawslider()
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment