Skip to content

Instantly share code, notes, and snippets.

@vkuchinov
Last active June 15, 2019 20:51
Show Gist options
  • Save vkuchinov/774539b489d6381caedaa4e3c0e6b91a to your computer and use it in GitHub Desktop.
Save vkuchinov/774539b489d6381caedaa4e3c0e6b91a to your computer and use it in GitHub Desktop.
D3.JS UI Player Controls
<!DOCTYPE html>
<html>
<head lang="en"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="keywords" content="d3.js,javascript">
<title>D3.JS Player with Iterator</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
@font-face {
font-family: "Material Icons";
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/materialicons/v47/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2) format("woff2");
}
body { margin: 64px; }
.material-icons {
font-family: "Material Icons";
font-weight: normal;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: "liga";
-webkit-font-smoothing: antialiased;
}
.mdl-button {
background: 0 0;
border: none;
border-radius: 2px;
color: #000;
position: relative;
height: 36px;
margin: 0;
min-width: 64px;
padding: 0 16px;
display: inline-block;
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
font-size: 14px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0;
overflow: hidden;
will-change: box-shadow;
transition: box-shadow .2s cubic-bezier(.4, 0, 1, 1), background-color .2s cubic-bezier(.4, 0, .2, 1), color .2s cubic-bezier(.4, 0, .2, 1);
outline: none;
cursor: pointer;
text-decoration: none;
text-align: center;
line-height: 36px;
vertical-align: middle;
}
.mdl-button--fab {
border-radius: 50%;
font-size: 24px;
height: 56px;
margin: auto;
min-width: 56px;
width: 56px;
padding: 0;
overflow: hidden;
background: #ECECEC;
position: relative;
line-height: normal;
}
.mdl-button--fab .material-icons {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-12px, -12px);
transform: translate(-12px, -12px);
line-height: 24px;
width: 24px;
}
.mdl-button--fab.mdl-button--colored:hover { background-color: #FFBD39; }
.mdl-button--fab.mdl-button--colored:disabled { background-color: #ECECEC; color: #DEDEDE; }
.mdl-button--mini {
border-radius: 50%;
font-size: 24px;
height: 32px;
margin-left: 8px;
margin-right: 8px;
min-width: 32px;
width: 32px;
padding: 0;
overflow: hidden;
color: inherit;
line-height: normal
}
.mdl-button--mini .material-icons {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-12px, -12px);
transform: translate(-12px, -12px);
line-height: 24px;
width: 24px
}
.mdl-button--mini.mdl-button--colored:hover { background-color: #FFBD39; }
.mdl-button--mini.mdl-button--colored:disabled { background-color: #ECECEC; color: #DEDEDE; }
.timeline-controls{
width:auto;
}
.graph{
width:auto;
}
.label { padding: 8px 0px 8px 8px; }
.value { padding: 8px 8px 8px 0px; }
</style>
</head>
<body>
<div class="timeline-controls">
<button class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored ui-resetButton" id="reset-button" title="Reset the network" data-upgraded=",MaterialButton" disabled>
<i class="material-icons">replay</i>
</button>
<button class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored ui-playButton" id="play-pause-button" title="Run/Pause" data-upgraded=",MaterialButton">
<i class="material-icons">play_arrow</i>
</button>
<button class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored ui-stepButton" id="next-step-button" title="Step" data-upgraded=",MaterialButton">
<i class="material-icons">skip_next</i>
</button>
<span class="label">Iterator: </span>
<span class="value" id="iter-number">0</span>
</div>
<div class="graph"></div>
<script>
var colors = ["#930077", "#E4007C"];
var data = [
{ a: 0.037, b: 0.912 },
{ a: 0.729, b: 0.654 },
{ a: 0.080, b: 0.592 },
{ a: 0.263, b: 0.833 },
{ a: 0.583, b: 0.160 },
{ a: 0.922, b: 0.516 },
{ a: 0.470, b: 0.673 },
{ a: 0.485, b: 0.382 },
{ a: 0.405, b: 0.271 },
{ a: 0.145, b: 0.142 },
{ a: 0.862, b: 0.311 },
{ a: 0.349, b: 0.520 },
{ a: 0.793, b: 0.441 },
{ a: 0.876, b: 0.021 },
{ a: 0.116, b: 0.383 },
{ a: 0.982, b: 0.315 }
];
function Player() {
this.interval = 500;
this.state = false;
this.iter = 0;
this.limits = [0, 0];
this.reset = function() {
this.state = "play";
this.iter = 0;
d3.select("#reset-button").node().disabled = true;
d3.select("#play-pause-button").node().disabled = false;
d3.select("#play-pause-button").select("i").node().innerHTML = "play_arrow";
d3.select("#next-step-button").node().disabled = false;
this.state = false;
update(this.iter, this.limits);
}
this.next = function() {
var this_ = player;
d3.select("#reset-button").node().disabled = false;
this_.iter++;
if(this_.iter > this_.limits[1]){
d3.select("#play-pause-button").node().disabled = true;
d3.select("#play-pause-button").select("i").node().innerHTML = "stop";
d3.select("#next-step-button").node().disabled = true;
}else{
update(this_.iter, this_.limits);
}
}
this.setLimits = function(value0_, value1_) { this.limits = [value0_, value1_]; }
this.run = function(t_) {
var this_ = player;
if(this_.state ){ this_.next(); }
}
this.timer = d3.interval(this.run, this.interval);
d3.select("#play-pause-button").on("click", function(d_) {
var this_ = player;
this_.state = !this_.state;
if(d3.select(this).select("i").node().innerHTML != "stop"){
if(this_.state){
d3.select(this).select("i").node().innerHTML = "pause";
d3.select("#reset-button").node().disabled = true;
d3.select("#next-step-button").node().disabled = true;
}else{
d3.select(this).select("i").node().innerHTML = "play_arrow";
if(this.iter > 0) { d3.select("#reset-button").node().disabled = false; }
d3.select("#next-step-button").node().disabled = false;
}
}
});
d3.select("#reset-button").on("click", function(d_) { player.reset(); });
d3.select("#next-step-button").on("click", function(d_) { player.next(); });
}
var player = new Player();
player.setLimits(0, data.length - 1);
var svg, w = 250, h = 80;
svg = d3.select(".graph").append("svg").attr("width", w).attr("height", h);
var top = svg.append("line").attr("x1", 0).attr("y1", 16).attr("x2", w).attr("y2", 16).attr("stroke", "#000000").attr("stroke-width", 1.5);
var botton = svg.append("line").attr("x1", 0).attr("y1", h - 16).attr("x2", w).attr("y2", h - 16).attr("stroke", "#000000").attr("stroke-width", 1.5);
var x = d3.scaleLinear().domain([0, 1]).range([0, w]);
var y = d3.scaleLinear().domain([0.0, 1.0]).range([18, h - 18]);
var curveA = d3.line()
.x(function(d_, i_) { return x(i_); })
.y(function(d_) { return y(d_.a); })
.curve(d3.curveMonotoneX);
var curveB = d3.line()
.x(function(d_, i_) { return x(i_); })
.y(function(d_) { return y(d_.b); })
.curve(d3.curveMonotoneX);
var lineA = svg.append("path")
.data([data[0]])
.attr("class", "line")
.attr("d", curveA)
.attr("stroke", colors[0])
.attr("fill", "none");
var lineB = svg.append("path")
.data([data[0]])
.attr("class", "line")
.attr("d", curveB)
.attr("stroke", colors[1])
.attr("fill", "none");
function update(index_){
d3.select("#iter-number").node().innerHTML = index_;
x.domain([0, index_ - 1]);
lineA.data([getDataSegment(index_)]).attr("d", curveA);
lineB.data([getDataSegment(index_)]).attr("d", curveB);
}
function getDataSegment(index_){ return data.slice(0, index_); }
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment