Skip to content

Instantly share code, notes, and snippets.

@sifbuilder
Last active June 12, 2016 22:35
Show Gist options
  • Save sifbuilder/0bf2022469d6c5a286debacab3369599 to your computer and use it in GitHub Desktop.
Save sifbuilder/0bf2022469d6c5a286debacab3369599 to your computer and use it in GitHub Desktop.
d3lanes

Built with blockbuilder.org

d3lanes

REDUX model implementation of an unframed window and d3v4 animation

Author

inspired on

built upon

having found useful

Setup

$ npm install

Running

$ npm start

Build

$ npm run build

License

MIT

windows animation and #d3js transitions sync through unwired #redux store
<html>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<head></head>
<body>
<div id="container"></div>
<script src="https://d3js.org/d3.v4.0.0-alpha.41.min.js"></script>
<script src="index.js"></script>
</body>
</html>
/* */
/* d3controls.js */
/* */
if (typeof require === "function") {
var d3 = require('./d3.v4.0.0-alpha.40.js')
}
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.d3lanesControls = global.d3lanesControls || {})));
}(this, function (exports) { 'use strict';
/* ------------- */
/* stepControls */
/* ------------- */
function stepControls(store) {
var store = store
var currentListeners = []
var nextListeners = currentListeners
// ______________________________ ensureCanMutateNextListeners
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice()
}
}
// ____________________ tc
function tc() {}
// ____________________ start
tc.start = function start() {
var periodFactor = store.getState().configReducer.periodFactor
var beatTime = store.getState().configReducer.beatTime
var periodTime = periodFactor * beatTime // items added
var itemSpan = store.getState().configReducer.itemSpan
var tickspan = store.getState().configReducer.tickspan
var vLow = store.getState().lanesReducer.messagesCursorLow
var vHigh = store.getState().lanesReducer.messagesCursorHigh
var tf = setInterval(function() {
var currentMode = store.getState().courtReducer.currentMode
var listeners = currentListeners = nextListeners
for (var i = 0; i < listeners.length; i++) {
listeners[i]()
}
}, periodTime)
return tc
}
// ______________________________ subscribe
tc.subscribe = function subscribe (listener) {
if (typeof listener !== 'function') {
throw new Error('Expected listener to be a function.')
}
var isSubscribed = true
ensureCanMutateNextListeners()
nextListeners.push(listener)
return tc
}
return tc
}
/* ------------- */
/* tickControls */
/* ------------- */
function tickControls(store) {
var store = store
var currentListeners = []
var nextListeners = currentListeners
// ______________________________ ensureCanMutateNextListeners
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice()
}
}
// ____________________ tc
function tc() {}
// ____________________ start
tc.start = function start() {
// Anatomy of a video game
// Misuse of the requestAnimationFrme()
var started = false
var rfps = 60
var last = performance.now()
var timestamp = 0
var ticker = function(timestamp) {
window.requestAnimationFrame(ticker)
if (timestamp != undefined) rfps = rfps * 0.9 + (1000/(timestamp-last)) * 0.1
if (timestamp != undefined) last = timestamp
while( performance.now() - timestamp < 17 ) {}
var fps = parseFloat(Math.round(rfps * 100) / 100).toFixed(0)
store.dispatch(actions.setFps(fps))
var listeners = currentListeners = nextListeners
for (var i = 0; i < listeners.length; i++) {
listeners[i]()
}
}
if (!started) {
started = true
ticker()
}
return tc
}
// ______________________________ subscribe
tc.subscribe = function subscribe (listener) {
if (typeof listener !== 'function') {
throw new Error('Expected listener to be a function.')
}
var isSubscribed = true
ensureCanMutateNextListeners()
nextListeners.push(listener)
return tc
}
return tc
}
/* ------------- */
/* mouseControls */
/* ------------- */
function mouseControls(store) {
var store = store
// ____________________ mouseEventsActions
var mousedown = function mousedown(svg) {
// console.log("event: ", d3.event)
// var e = window.event;
var e = d3.event
pauseEvent(e);
function pauseEvent(e){
if(e.stopPropagation) e.stopPropagation();
if(e.preventDefault) e.preventDefault();
e.cancelBubble=true;
e.returnValue=false;
return false;
}
var coords = d3.mouse(svg);
store.dispatch(actions.updateMousePos(coords[0], coords[1]))
store.dispatch(actions.startParticles())
store.dispatch(actions.createParticles({
particlesPerTick: store.getState().particlesReducer.particlesPerTick,
x: coords[0],
y: coords[1],
xInit: 0,
xEnd: store.getState().courtReducer.svgWidth,
randNormal: store.getState().configReducer.randNormal,
randNormal2: store.getState().configReducer.randNormal2,
lanes: store.getState().lanesReducer.lanes,
}))
}
var touchstart = function touchstart(svg) {
var coords = d3.mouse(svg);
store.dispatch(actions.updateTouchPos(coords[0], coords[1]))
store.dispatch(actions.startParticles())
store.dispatch(actions.createParticles({
particlesPerTick: store.getState().particlesReducer.particlesPerTick,
x: coords[0],
y: coords[1],
xInit: 0,
xEnd: store.getState().courtReducer.svgWidth,
randNormal: store.getState().configReducer.randNormal,
randNormal2: store.getState().configReducer.randNormal2,
lanes: store.getState().lanesReducer.lanes,
}))
}
var mousemove = function mousemove(svg) {
var coords = d3.mouse(svg);
store.dispatch(actions.updateMousePos(coords[0], coords[1]))
var generating = store.getState().particlesReducer.particlesGenerating
if (generating === true) {
store.dispatch(actions.createParticles({
particlesPerTick: store.getState().particlesReducer.particlesPerTick,
x: coords[0],
y: coords[1],
xInit: 0,
xEnd: store.getState().courtReducer.svgWidth,
randNormal: store.getState().configReducer.randNormal,
randNormal2: store.getState().configReducer.randNormal2,
lanes: store.getState().lanesReducer.lanes,
}))
}
}
var touchmove = function touchmove(svg) {
var coords = d3.mouse(svg);
store.dispatch(actions.updateTouchPos(coords[0], coords[1]))
}
var mouseup = function mouseup(svg) {
store.dispatch(actions.stopParticles())
var generating = store.getState().particlesReducer.particlesGenerating
}
var touchend = function touchend(svg) {
store.dispatch(actions.stopParticles())
}
var mouseleave = function mouseleave(svg) {
store.dispatch(actions.stopParticles())
}
// ____________________ controlfn
function controlfn() {
}
// ____________________ startMouseEvents
controlfn.startMouseEvents = function startMouseEvents(svg) {
svg.on('mousedown', function() {mousedown(this)})
svg.on('touchstart', function() {touchstart(this)})
svg.on('mousemove', function() {mousemove(this)})
svg.on('touchmove', function() {touchmove(this)})
svg.on('mouseup', function() {mouseup(this)})
svg.on('mouseleave', function() {mouseleave(this)})
svg.on('mouseleave', function() {mouseleave(this)})
}
return controlfn
}
/* ------------- */
/* kbdControls */
/* ------------- */
function kbdControls(store) {
var store = store
// ____________________ handleKeyDown
// https://www.kirupa.com/html5/keyboard_events_in_javascript.htm
// https://github.com/gaearon/redux-devtools-dock-monitor
var handleKeyDown = function handleKeyDown(e) {
e.stopPropagation();
e.preventDefault();
store.dispatch(actions.setKeybKey(e.keyCode))
var keys = store.getState().courtReducer.keys
// keys[e.keyCode] = true;
if (keys[70] && keys[17]) fKeyCtrl() // change currentView
else if (keys[68] && keys[17]) dKeyCtrl() // change debugMode
else if (e.keyCode == '37' && !keys[17]) leftArrow() // change currentMode autoMode/walkMode
else if (e.keyCode == '37' && keys[17]) leftArrowCtrl() // change width
else if (e.keyCode == '39' && !keys[17]) rightArrow() // change currentMode
else if (e.keyCode == '39' && keys[17]) rightArrowCtrl() // change width
else if (e.keyCode == '38' && !keys[17]) upArrow() // change currentMode nextWalk
else if (e.keyCode == '38' && keys[17]) upArrowCtrl() // change height
else if (e.keyCode == '40' && !keys[17]) downArrow() // change currentMode
else if (e.keyCode == '40' && keys[17]) downArrowCtrl() // change height
}
// ____________________ downArrowCtrl
var downArrowCtrl = function downArrowCtrl() {
store.dispatch(actions.resizeHeight(+10))
}
// ____________________ fKeyCtrl
var fKeyCtrl = function fKeyCtrl() { // change view
// // Ctrl 17 + Shift 16 + f 70
var views = Object.keys(store.getState().configReducer.views)
var idx = views.indexOf(store.getState().courtReducer.currentView)
var newIdx = idx + 1 % views.length
var newview = store.getState().configReducer.views[views[newIdx]]
store.dispatch(actions.setView(newview))
}
// ____________________ dKeyCtrl
var dKeyCtrl = function dKeyCtrl() { // change debug mode
// // Ctrl 17 + Shift 16 + d 68
store.dispatch(actions.switchDebugMode())
}
// ____________________ matchesKey
function matchesKey(key, event) {
if (!key) return false
const charCode = event.keyCode || event.which;
const char = String.fromCharCode(charCode);
return key.name.toUpperCase() === char.toUpperCase() &&
key.alt === event.altKey &&
key.ctrl === event.ctrlKey &&
key.meta === event.metaKey &&
key.shift === event.shiftKey;
}
// ____________________ handleKeyPressed
var handleKeyPressed = function handleKeyPressed(e) {
}
// ____________________ handleKeyReleased
var handleKeyReleased = function handleKeyReleased(e) {
store.dispatch(actions.releaseKeybKey(e.keyCode))
}
// ____________________ keysEventsActions
// arrows up/down => currentMode walkMode
// arrow right => currentMode autoMode
// arrow left => currentMode walkMode
// ____________________ leftArrow
var leftArrow = function leftArrow() { // set currentMode walkMode
var currentMode = 'walkMode'
store.dispatch(actions.setMode(currentMode))
}
// ____________________ rightArrow
var rightArrow = function rightArrow() { // set currentMode autoMode
var currentMode = 'autoMode'
store.dispatch(actions.setMode(currentMode))
}
// ____________________ upArrow
var upArrow = function upArrow() {
var currentMode = store.getState().courtReducer.currentMode
if (currentMode == 'autoMode') {
var newMode = 'walkMode'
store.dispatch(actions.setMode(newMode))
} else if (currentMode == 'walkMode') {
var itemSpan = store.getState().configReducer.itemSpan
store.dispatch(actions.walkUpRecords(itemSpan, currentMode))
}
}
// ____________________ downArrow
var downArrow = function downArrow() {
var currentMode = store.getState().courtReducer.currentMode
if (currentMode == 'autoMode') {
var newMode = 'walkMode'
store.dispatch(actions.setMode(newMode))
} else if (currentMode == 'walkMode') {
var itemSpan = store.getState().configReducer.itemSpan
store.dispatch(actions.walkDownRecords(itemSpan, currentMode))
}
}
// ____________________ leftArrowCtrl
var leftArrowCtrl = function leftArrowCtrl() {
console.log("leftArrowCtrlFn")
store.dispatch(actions.resizeWidth(-10))
}
// ____________________ rightArrowCtrl
var rightArrowCtrl = function rightArrowCtrl() {
console.log("rightArrowCtrlFn")
store.dispatch(actions.resizeWidth(10))
}
// ____________________ upArrowCtrl
var upArrowCtrl = function upArrowCtrl() {
console.log("upArrowCtrlFn")
store.dispatch(actions.resizeWidth(-10))
}
// ____________________ controlfn
function controlfn() {
}
// ____________________ startKeysEvents
controlfn.startKeybKeyEvents = function startKeybKeyEvents() {
store.dispatch(actions.startKeybKeyEvents())
document.addEventListener("keydown", handleKeyDown, false);
document.addEventListener("keypress", handleKeyPressed, false);
document.addEventListener("keyup", handleKeyReleased, false);
}
return controlfn
}
/* ================================= */
/* posControls */
/* ================================= */
function posControls (scope) { // selection
var dName = 'pos'
var aTypes = {
start: dName + 'start', // tipstart
move: dName + 'move', // tipmove
end: dName + 'end' // tipend
}
var aTypesList = Object.keys(aTypes).map(function(k){return aTypes[k]})
var qaTypesList = aTypesList.map(function(k){return k + "." + dName})
// ______________________________ fnCallbacks
var fnCallbacks = {}
for (var i = 0; i < aTypesList.length; i++) {
fnCallbacks[aTypesList[i]] = function(action) {}
}
// ______________________________ start pos
fnCallbacks[aTypes.start] = function(action) {
var node = d3.select(this) // selection
var datum = node.datum() // datum
}
// ______________________________ move pos
fnCallbacks[aTypes.move] = function(action) {
var node = d3.select(this) // selection
// node.on("mousemove.tip", null)
createTextPad(action)
displayTextPad(action)
moveTextPad(action)
function createTextPad(a) {
var textPadDiv = d3.select("body")
.selectAll("div.postip")
.data(['divMousePos'])
.enter()
.append("div")
.attr("class", "postip")
.attr("viewBox", "0 0 10 10")
.style("top", "-5px")
.style("position", "absolute")
.style("padding", "10px")
.style("background", "rgba(255, 255, 255, .90)")
.style("border", "1px solid lightgray")
.style("pointer-events", "none")
.style("z-index", "100")
.style('border', '1px solid red')
.style('color', 'grey')
.classed('postip-hidden', true)
.style("opacity", 0)
}
function textPadFn (a) {
var s = String("|_____" + a.ox + " " + a.oy + "_____|")
return s
}
// https://github.com/1wheel/swoopy-drag/blob/master/lib/d3-jetpack.js
function displayTextPad(a) {
d3.select('.postip')
.classed('postip-hidden', false)
.style('opacity', 1)
.html('')
.selectAll('div')
.data([textPadFn]).enter()
.append('div')
.html(function(textPadFn) {
return (textPadFn(a))
})
}
function moveTextPad() {
var postip = d3.select('div.postip')
if (!postip.size()) return
var e = d3.event,
x = e.clientX,
y = e.clientY,
doctop = (window.scrollY)? window.scrollY : (document.documentElement && document.documentElement.scrollTop)? document.documentElement.scrollTop : document.body.scrollTop,
n = postip.node(),
nBB = n.getBoundingClientRect()
postip.style('top', (y+doctop-nBB.height-18)+"px");
postip.style('left', Math.min(Math.max(0, (x-nBB.width/2)), window.innerWidth - nBB.width)+"px");
}
}
// ______________________________ end pos
fnCallbacks[aTypes.end] = function(action) {
var node = d3.select(this) // selection
var datum = node.datum() // datum
d3.select('div.postip')
.classed('postip-hidden', true)
.style('opacity', 0)
d3.selectAll('.postipped')
.classed('postipped', false)
}
// ______________________________ dispatcher
var d3_event = d3.dispatch.apply(null, aTypesList)
for (var i=0; i < qaTypesList.length; i++) {
d3_event.on(qaTypesList[i], fnCallbacks[aTypesList[i]])
}
d3_event.of = function(thiz, argumentz) {
return function(e1) {
d3_event.call(e1.type, thiz, e1)
}
}
// ______________________________ started
function started(d, i, nodes) {
var datum = d, // d datum
node = this, // elem
parent = node.parentNode,
origin = d3.mouse(parent),
ox = origin[0],
oy = origin[1]
var context = d3.select(d3_window(node)) // selection
var a = {
type: aTypes.start,
ox: ox,
oy: oy
}
d3_event.of(node)(a)
}
// ______________________________ moved
function moved(d, i, nodes) {
var datum = d, // d datum
node = this, // elem
parent = node.parentNode,
origin = d3.mouse(parent),
ox = origin[0],
oy = origin[1]
var context = d3.select(d3_window(node)) // selection
var a = {
type: aTypes.move,
ox: ox,
oy: oy
}
d3_event.of(node)(a)
}
// ______________________________ ended
function ended(d, i, nodes) {
var datum = d, // d datum
node = this, // elem
parent = node.parentNode,
origin = d3.mouse(parent)
var a = {
type: aTypes.end
}
d3_event.of(node)(a)
}
// ______________________________ lib
function prevent() {
event.preventDefault();
}
function d3_window(node) {
return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView);
}
// ______________________________
function d3Control(scope) {
scope.on("mouseenter.pos", started)
scope.on("mousemove.pos", moved)
scope.on("mouseout.pos", ended)
}
d3Control.on = function() {
var value = d3_event.on.apply(d3_event, arguments);
return value === d3_event ? d3Control : value;
}
return d3Control
}
/* ================================= */
/* tipControls */
/* ================================= */
function tipControls (scope) { // selection
var dName = 'tip'
var aTypes = {
start: dName + 'start', // tipstart
move: dName + 'move', // tipmove
end: dName + 'end' // tipend
}
var aTypesList = Object.keys(aTypes).map(function(k){return aTypes[k]})
var qaTypesList = aTypesList.map(function(k){return k + "." + dName})
// ______________________________ fnCallbacks
var fnCallbacks = {}
for (var i = 0; i < aTypesList.length; i++) {
fnCallbacks[aTypesList[i]] = function(action) {}
}
// ______________________________ start tip
fnCallbacks[aTypes.start] = function(action) {
var node = d3.select(this) // selection
var datum = node.datum() // datum
createTooltip(action)
displayTooltip(action)
moveMoveTooltip(action)
function createTooltip() {
var tipDiv = d3.select("body")
.selectAll("div.tooltip")
.data(['divTooltip'])
.enter()
.append("div")
.attr("class", "tooltip")
.attr("viewBox", "0 0 10 10")
.style("top", "-5px")
.style("position", "absolute")
.style("padding", "10px")
.style("background", "rgba(255, 255, 255, .90)")
.style("border", "1px solid lightgray")
.style("pointer-events", "none")
.style("z-index", "100")
.style('border', '1px solid red')
.style('color', 'grey')
.classed('tooltip-hidden', true)
.style("opacity", 0)
}
// https://github.com/1wheel/swoopy-drag/blob/master/lib/d3-jetpack.js
function displayTooltip() {
var d = action.datum
var fieldFns = d3.keys(d)
.filter(function(str){
var r = (typeof d[str] != 'object') && (d[str] != 'array')
return r
})
.map(function(str){
return function (d) { return str + ': ' + '<b>' + d[str] + '</b>' }})
var tipfn = function(action) {
var s = String(action.datum.tip || action.datum.id || 'tip')
return wordwrap(s, 20)
}
d3.select('.tooltip')
.classed('tooltip-hidden', false)
.style('opacity', 1)
.html('')
.selectAll('div')
.data(fieldFns).enter()
.append('div')
.html(function(fieldFns) {
return (fieldFns(d))
})
}
function moveMoveTooltip() {
var tooltip = d3.select('.tooltip')
if (!tooltip.size()) return
var e = d3.event,
x = e.clientX,
y = e.clientY,
doctop = (window.scrollY)? window.scrollY : (document.documentElement && document.documentElement.scrollTop)? document.documentElement.scrollTop : document.body.scrollTop,
n = tooltip.node(),
nBB = n.getBoundingClientRect()
tooltip.style('top', (y+doctop-nBB.height-18)+"px");
tooltip.style('left', Math.min(Math.max(0, (x-nBB.width/2)), window.innerWidth - nBB.width)+"px");
}
function wordwrap (line, maxCharactersPerLine) {
var w = line.split(' '),
lines = [],
words = [],
maxChars = maxCharactersPerLine || 40,
l = 0;
w.forEach(function(d) {
if (l+d.length > maxChars) {
lines.push(words.join(' '));
words.length = 0;
l = 0;
}
l += d.length;
words.push(d);
});
if (words.length) {
lines.push(words.join(' '));
}
return lines;
}
}
// ______________________________ move tip
fnCallbacks[aTypes.move] = function(action) {
var node = d3.select(this) // selection
var datum = node.datum() // datum
}
// ______________________________ end tip
fnCallbacks[aTypes.end] = function(action) {
var node = d3.select(this) // selection
var datum = node.datum() // datum
d3.select('.tooltip')
.classed('tooltip-hidden', true)
.style('opacity', 0)
d3.selectAll('.tooltipped')
.classed('tooltipped', false)
}
// ______________________________ dispatcher
var d3_event = d3.dispatch.apply(null, aTypesList)
for (var i=0; i < qaTypesList.length; i++) {
d3_event.on(qaTypesList[i], fnCallbacks[aTypesList[i]])
}
d3_event.of = function(thiz, argumentz) {
return function(e1) {
d3_event.call(e1.type, thiz, e1)
}
}
// ______________________________ started tip
function started(d, i, nodes) {
var datum = d, // d datum
node = this, // elem
parent = node.parentNode,
origin = d3.mouse(parent),
ox = d.x - origin[0] || 0,
oy = d.y - origin[1] || 0,
tiped = false
var context = d3.select(d3_window(node)) // selection
var a = {
type: aTypes.start,
datum: d
}
d3_event.of(node)(a)
}
// ______________________________ ended tip
function ended(d, i, nodes) {
var datum = d, // d datum
node = this, // elem
parent = node.parentNode,
origin = d3.mouse(parent),
ox = d.x - origin[0] || 0,
oy = d.y - origin[1] || 0,
tiped = false
var a = {
type: aTypes.end,
}
d3_event.of(node)(a)
}
// ______________________________ lib
function prevent() {
event.preventDefault();
}
function d3_window(node) {
return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView);
}
// ______________________________
function d3Control(scope) {
scope.each(function() {
scope.on("mousemove.tip", started)
scope.on("mouseout.tip", ended)
})
}
d3Control.on = function() {
var value = d3_event.on.apply(d3_event, arguments);
return value === d3_event ? d3Control : value;
}
return d3Control
}
/* ================================= */
/* dragControls */
/* ================================= */
// https://github.com/d3/d3-drag/blob/master/src/drag.js
function dragControls (scope) {
function prevent() {
event.preventDefault();
}
function d3_window(node) {
return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView);
}
var scope = scope // selection
var dName = 'drag'
var aTypes = {
start: dName + 'start', // dragstart
move: dName + 'move', // dragmove
end: dName + 'end' // dragend
}
var aTypesList = Object.keys(aTypes).map(function(k){return aTypes[k]})
var qaTypesList = aTypesList.map(function(k){return k + "." + dName})
var fnCallbacks = {}
for (var i = 0; i < aTypesList.length; i++) {
fnCallbacks[aTypesList[i]] = function(action) {}
}
// ______________________________ dragend
fnCallbacks[aTypes.end] = function(action) {
var node = d3.select(this)
node.datum().dx1 = action.dx1
node.datum().dy1 = action.dy1
}
// ______________________________ dragmove
fnCallbacks[aTypes.move] = function(action) {
var node = d3.select(this)
node
.attr("transform", "translate(" + action.dx1 + "," + action.dy1 + ")")
}
// ______________________________ dispatcher
var d3_event = d3.dispatch.apply(null, aTypesList)
for (var i=0; i < qaTypesList.length; i++) {
d3_event.on(qaTypesList[i], fnCallbacks[aTypesList[i]])
}
d3_event.of = function(thiz, argumentz) {
return function(e1) {
d3_event.call(e1.type, thiz, e1)
}
}
// ______________________________ listener
function started(d, i, nodes) {
var node = this,
parent = node.parentNode,
origin = d3.mouse(parent),
ox = d.x - origin[0] || 0,
oy = d.y - origin[1] || 0,
dragged = false
var context = d3.select(d3_window(node))
.on("dragstart.drag", prevent)
.on("selectstart.drag", prevent)
.on("mouseup", ended)
.on("mousemove", moved)
var emit = d3_event.of(node, arguments)
// ______________________________ when moved
function moved() {
var p = d3.mouse(parent)
var a = {
type: aTypes.move,
x0: origin[0] + ox, // first x
y0: origin[1] + oy,
x1: p[0] + ox, // new x position
y1: p[1] + oy,
dx: p[0] - origin[0], // delta x
dy: p[1] - origin[1],
dx1: (d.dx1 || 0) + p[0] - origin[0], // aggregated delta x
dy1: (d.dy1 || 0) + p[1] - origin[1]
}
emit(a)
}
// ______________________________ when ended
function ended() {
context.on("mousemove", null)
.on("mouseup", null);
var p = d3.mouse(parent)
var a = {
type: aTypes.end,
x0: origin[0] + ox, // first x
y0: origin[1] + oy,
x1: p[0] + ox, // new x position
y1: p[1] + oy,
dx: p[0] - origin[0], // delta x
dy: p[1] - origin[1],
dx1: (d.dx1 || 0) + p[0] - origin[0], // aggregated delta x
dy1: (d.dy1 || 0) + p[1] - origin[1]
}
emit(a)
}
function afterended() {
context.on("click.drag", null);
}
}
function drag(selection) {
selection.on("mousedown.drag", started)
}
drag.on = function() {
var value = d3_event.on.apply(d3_event, arguments);
return value === d3_event ? drag : value;
};
return drag;
}
exports.stepControls = stepControls
exports.tickControls = tickControls
exports.mouseControls = mouseControls
exports.kbdControls = kbdControls
exports.dragControls = dragControls
exports.posControls = posControls
exports.tipControls = tipControls
}));
/* */
/* d3lanes-actions.js */
/* */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.d3lanesActions = global.d3lanesActions || {})));
}(this, function (exports) { 'use strict';
// ____________________ merge_objects
function merge_objects(ctt1,ctt2){
var i, obj = {}
for (i = 0; i < arguments.length; i++) {
Object.assign(obj, arguments[i])
}
return obj;
}
// ____________________ keyMirror
// https://github.com/STRML/keyMirror
var keyMirror = function(obj, prefix) {
var ret = {};
var key;
if (!(obj instanceof Object && !Array.isArray(obj))) {
throw new Error('keyMirror(...): Argument must be an object.');
}
for (key in obj) {
if (obj.hasOwnProperty(key)) {
ret[key] = prefix + key;
}
}
return ret;
};
// ____________________ action TYPES
var cttsCourt = {
ADD_KEYS_EVENT: '',
FETCH_RECORDS: '',
RELEASE_KEYBKEY: '',
RESET_KEYS_EVENTS: '',
RESIZE_SCREEN: '',
RESIZE_HEIGHT: '',
RESIZE_WIDTH: '',
SET_KEYBKEY: '',
SET_MODE: '',
SET_NOTICE: '',
SET_VIEW: '',
START_KEYS_EVENTS: '',
START_KEYBKEY_EVENTS: '',
UPDATE_MOUSE_POS: '',
}
var cttsLanes = {
DELETE_LANE: '',
SET_LANE: '',
SET_LANES: '',
SET_MESSAGES: '',
SET_RECORDS: '',
WALK_DOWN_RECORDS: '',
WALK_UP_RECORDS: '',
SET_RECORDS_COLLECTION: '',
SET_RECORDS_FETCHED: '',
UPDATE_MESSAGES: '',
}
var cttsDebug = {
SET_DEBUGMODE: '',
SET_FPS: '',
SWITCH_DEBUGMODE: '',
}
var cttsParticles = {
CREATE_PARTICLES: '',
START_PARTICLES: '',
START_TICKER: '',
STOP_PARTICLES: '',
STOP_TICKER: '',
TICK_PARTICLES: '',
}
// ____________________ actions COURT
var ActionCreatorsCourt = {
resizeHeight(height) {
return {
type: ActionTypes.RESIZE_HEIGHT,
delta: height
}
},
resizeScreen(width, height) {
return {
type: ActionTypes.RESIZE_SCREEN,
width: width,
height: height
}
},
resizeWidth(width) {
return {
type: ActionTypes.RESIZE_WIDTH,
delta: width
}
},
setKeybKey(keyCode) {
return {
type: ActionTypes.SET_KEYBKEY,
keyCode: keyCode,
}
},
releaseKeybKey(keyCode) {
return {
type: ActionTypes.RELEASE_KEYBKEY,
keyCode: keyCode,
}
},
setMode(currentMode) {
return {
type: ActionTypes.SET_MODE,
currentMode: currentMode,
}
},
setView(currentView) {
return {
type: ActionTypes.SET_VIEW,
currentView: currentView,
}
},
setNotice(notice) {
return {
type: ActionTypes.SET_NOTICE,
notice: notice,
}
},
startKeybKeyEvents() {
return {
type: ActionTypes.START_KEYBKEY_EVENTS
}
},
updateMousePos(x, y) {
return {
type: ActionTypes.UPDATE_MOUSE_POS,
x: x,
y: y
}
},
}
// ____________________ actions LANES
var ActionCreatorsLanes = {
setRecordsFetched(areRecordsFetched) {
return {
type: ActionTypes.SET_RECORDS_FETCHED,
areRecordsFetched: areRecordsFetched,
}
},
setRecordsCollection(recordsCollection) {
return {
type: ActionTypes.SET_RECORDS_COLLECTION,
recordsCollection: recordsCollection,
}
},
setRecords(argObj) { // SET_RECORDS
return {
type: ActionTypes.SET_RECORDS,
itemSpan: argObj.itemSpan,
mode: argObj.currentMode,
}
},
walkDownRecords(itemSpan, mode) { // WALK_DOWN_RECORDS
return {
type: ActionTypes.WALK_DOWN_RECORDS,
itemSpan: itemSpan,
mode: mode,
}
},
walkUpRecords(itemSpan, mode) { // WALK_UP_RECORDS
return {
type: ActionTypes.WALK_UP_RECORDS,
itemSpan: itemSpan,
mode: mode,
}
},
increaseCursorLow() { // INCREASE_CURSOR_LOW
return {
type: ActionTypes.INCREASE_CURSOR_LOW,
}
},
decreaseCursorLow() {
return {
type: ActionTypes.DECREASE_CURSOR_LOW,
}
},
increaseCursorHigh() {
return {
type: ActionTypes.INCREASE_CURSOR_HIGH,
}
},
decreaseCursorHigh() {
return {
type: ActionTypes.DECREASE_CURSOR_HIGH,
}
},
deleteLane(lane) {
return {
type: ActionTypes.DELETE_LANE,
lane: lane,
}
},
setLane(lane) {
return {
type: ActionTypes.SET_LANE,
lane: lane,
}
},
setLanes(lanes) {
return {
type: ActionTypes.SET_LANES,
lanes: lanes,
}
},
setMessages(messages) {
return {
type: ActionTypes.SET_MESSAGES,
messages: messages,
}
},
updateMessages(messages) {
return {
type: ActionTypes.UPDATE_MESSAGES,
cursorLow: cursorLow,
cursorHigh: cursorHigh,
}
},
}
// ____________________ actions DEBUG
var ActionCreatorsDebug = {
setDebugMode(debugMode) {
return {
type: ActionTypes.SET_DEBUG_MODE,
debugMode: debugMode,
}
},
setFps(fps) {
return {
type: ActionTypes.SET_FPS,
fps: fps,
}
},
switchDebugMode() {
return {
type: ActionTypes.SWITCH_DEBUGMODE
};
},
}
// ____________________ actions PARTICLES
var ActionCreatorsParticles = {
createParticles(obj) {
return {
type: ActionTypes.CREATE_PARTICLES, // createParticles
N: obj.particlesPerTick,
x: obj.x,
y: obj.y,
randNormal: obj.randNormal,
randNormal2: obj.randNormal2,
xInit: obj.xInit,
xEnd: obj.xEnd,
lanes: obj.lanes,
}
},
startParticles() {
return {
type: ActionTypes.START_PARTICLES
}
},
startTicker() {
return {
type: ActionTypes.START_TICKER
};
},
stopTicker() {
return {
type: ActionTypes.STOP_TICKER
};
},
tickParticles(arg) {
// console.log("arg: ", JSON.stringify(arg.lanes, null, 2))
return {
type: ActionTypes.TICK_PARTICLES, // tickParticles
width: arg.width,
height: arg.height,
gravity: arg.gravity,
lanes: arg.lanes,
}
},
stopParticles() {
return {
type: ActionTypes.STOP_PARTICLES
}
},
}
var ctts = merge_objects(cttsLanes, cttsCourt, cttsDebug, cttsParticles)
var ActionTypes = keyMirror(ctts, '')
var ActionCreators = merge_objects(ActionCreatorsCourt, ActionCreatorsParticles, ActionCreatorsDebug, ActionCreatorsLanes)
exports.ActionTypes = ActionTypes;
exports.ActionCreators = ActionCreators;
}));/* */
/* d3lanes-component-court.js */
/* */
if (typeof require === "function") {
var d3 = require('./d3.v4.0.0-alpha.40.js')
}
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.d3lanesComponentCourt = global.d3lanesComponentCourt || {})));
}(this, function (exports) { 'use strict';
function render(newState) {
var state
doRender(newState)
function doRender(newState) {
if (state === newState) return
state = newState
var svgContainer = d3.select(state.configReducer.containerElem)
.selectAll('svg')
.data(['svg'])
var svgContainerNew = svgContainer.enter()
.append("svg")
.attr("id", state.configReducer.containerId)
.style('width', state.courtReducer.svgWidth)
.style('height', state.courtReducer.svgHeight)
.attr('class', 'bar-chart') //
.style('border', '1px solid red')
.style('color', 'blue')
.attr('viewbox',"0 0 3 2")
var svg = d3.select('svg')
var itemsGroup = d3.select('svg')
.selectAll('g.notices') // items
.data(['items'])
itemsGroup.enter()
.append("g")
.classed("notices", true) // items
// _________________________________ render Notice Update
var errorNotice = (state.courtReducer.notice) ? state.courtReducer.notice : ""
var noticeToShow = " " +
"click particles arrow mode" +
" - " + state.configReducer.modeLabels[state.configReducer.modes[state.courtReducer.currentMode]] +
" - " + parseInt(svg.style("width")) + " x " + parseInt(svg.style("height")) +
" - N: " + state.particlesReducer.particleIndex +
" - fps: " + state.debugReducer.fps
var winWidthPixels = parseInt(svg.style("width"))
var winHeightPixels = parseInt(svg.style("height"))
var fontSizeHw = 3 + "hw"
var fontSize = winWidthPixels * 3/100
var fontname = 'sans-serif'
var c=document.createElement('canvas');
var ctx=c.getContext('2d');
ctx.font = fontSize + 'px ' + fontname;
var noticeLength = ctx.measureText(noticeToShow).width
var vlocation = winHeightPixels - fontSize
var hlocation = winWidthPixels - noticeLength
// items elems
var itemsElems = svgContainer
.select("g.notices")
.selectAll("g.notice")
.data([noticeToShow]);
// items elems enter
var itemsElemsNew = itemsElems.enter()
.append("g")
.classed("notice", true)
itemsElemsNew.each(function(d, i) {
var itemElemNew = d3.select(this)
.append("text")
.classed("info", true)
.style("font-family", fontname)
.attr("x", function(d) {
return hlocation; })
.attr("y", function(d) {
return vlocation
})
.style("font-size", function(d, i) {
return fontSize
})
.text(function(d) { return d })
.style("fill-opacity", 1)
})
// items elems update
itemsElems
.select('text')
.text(function(d) { return d })
.attr("x", function(d) {
return hlocation; })
.attr("y", function(d) {
return vlocation; })
// items elems exit
itemsElems.exit()
.select('text')
.remove()
} // render
}
exports.render = render;
}))/* */
/* d3lanes-component-lanes.js */
/* */
if (typeof require === "function") {
var d3 = require('./d3.v4.0.0-alpha.40.js')
}
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.d3lanesComponentLanes = global.d3lanesComponentLanes || {})));
}(this, function (exports) { 'use strict';
// _____________ coordsUtils
function coordsUtils () {
function index_hcoord_pct(arr, index) {
return (index+1) * (100/(arr.length+1));
}
function index_hcoord_pct_with_symbol(arr, index) {
return index_hcoord_pct(arr, index) + "%";
}
function horizontal_center(x1, x2) {
if (x1 > x2) return (x2 - x1)/2 + x1
else return (x1 - x2)/2 + x2
}
function horizontal_percent_to_coord(svg, percent) {
// https://bugzilla.mozilla.org/show_bug.cgi?id=874811 // _e_
if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
var xScrollWidth = svg[0].parentNode.scrollWidth;
} else {
var xScrollWidth = svg.property("scrollWidth");
}
return xScrollWidth * Number.parseFloat(percent)/100;
}
function horizontal_coord_to_percent(svg, length) {
var xScrollWidth = svg.property("scrollWidth");
return Number.parseFloat(length) / xScrollWidth;
}
var publicAPI = {
hcoord_tagged_pct: function hcoord_tagged_pct(arr, val) {
return index_hcoord_pct_with_symbol(arr, arr.indexOf(val));
},
hcoord_pct: function hcoord_pct(arr, val) {
return index_hcoord_pct(arr, arr.indexOf(val));
},
hcenter_tagged_pct: function hcenter_tagged_pct(x1, x2) {
return horizontal_center(x1, x2) + "%";
}
}
return publicAPI
}
// _____________ arrayUtils
function arrayUtils () {
function flattenArrByObjProp(a, p) {
return a.reduce(function(prevArr, currVal, i, a) {
if (prevArr.indexOf(currVal[p]) < 0)
var r = prevArr.push(currVal[p])
return prevArr
}, []);
}
function union_arrays (x, y) {
var obj = {};
for (var i = x.length-1; i >= 0; -- i)
obj[x[i]] = x[i];
for (var i = y.length-1; i >= 0; -- i)
obj[y[i]] = y[i];
var res = []
for (var k in obj) {
if (obj.hasOwnProperty(k))
res.push(obj[k]);
}
return res;
}
function array_names_from_props (arr, props) {
var r = props.reduce( function(prevArr, currVal, i, a) {
var q1 = flattenArrByObjProp(arr, currVal)
var q = union_arrays(prevArr, q1)
return q
}, [])
return r
}
var publicAPI = {
array_names_from_props: function array_names_from_props (arr, props) {
var r = props.reduce( function(prevArr, currVal, i, a) {
var q1 = flattenArrByObjProp(arr, currVal)
var q = union_arrays(prevArr, q1)
return q
}, [])
return r
},
}
return publicAPI
}
// _____________ context
var stateLanes = {
lanesReducer: {}
}
var intransition = false
// _____________ render
function render(newState) {
if (intransition == true) {
return
}
if (JSON.stringify(stateLanes.lanesReducer.records) === JSON.stringify(newState.lanesReducer.records)) {
return
}
// DATA
// store previous - will not change during render
var _messages0 = stateLanes.lanesReducer.records || []
var state = stateLanes = newState
var _messages1 = state.lanesReducer.records
var _fadeTime = state.configReducer.fadeFactor * state.configReducer.beatTime
var _itemProps = state.configReducer.itemProps
// SVG
var svgContainer = d3.select('body')
.selectAll('svg')
.data(['svgContainer'])
svgContainer
.enter()
.append("svg")
.attr("id", state.configReducer.container)
svgContainer
.style('width', state.courtReducer.svgWidth)
.style('height', state.courtReducer.svgHeight)
var messagesGroup = d3.select('svg')
.selectAll('g.messages') // items
.data(['messages'])
messagesGroup.enter()
.append("g")
.classed("messages", true) // items
var actorsGroup = d3.select('svg')
.selectAll('g.lanes') // items
.data(['lanes'])
actorsGroup.enter()
.append("g")
.classed("lanes", true) // items
var marker = svgContainer.append("marker")
.attr("id", "message-marker")
.attr("viewBox", "0 0 10 10")
.attr("refX", "10")
.attr("refY", "5")
.attr("markerWidth", "5")
.attr("markerHeight", "4")
.attr("orient", "auto")
.append("path")
.attr("class", "message-arrow")
.attr("d", "M 0 0 L 10 5 L 0 10 z")
// DATA
var _laneItems0 = arrayUtils()
.array_names_from_props(_messages0, _itemProps)
var _laneObjs0 = _laneItems0.map(function(d, i) {
return ({id: d,
name: d,
x0: parseFloat(coordsUtils().hcoord_pct(_laneItems0, d)
* parseInt(svgContainer.style("width")) / 100).toFixed(0)})})
var _lanesObj0 = _laneItems0.reduce(function(total,d,currentIndex,arr) {
var o = {}
o[d] = {name: d,
x0: parseFloat(coordsUtils().hcoord_pct(_laneItems0, d)
* parseInt(svgContainer.style("width")) / 100).toFixed(0)}
return (Object.assign({}, total, o))}, {})
var _laneItems1 = arrayUtils()
.array_names_from_props(_messages1, _itemProps)
var _laneObjs1 = _laneItems1.map(function(d, i) {
var x0 = 0
if ( _lanesObj0.hasOwnProperty( d) ) {
x0 = _lanesObj0[d].x0
}
return ({id: d,
name: d,
x0: x0})})
// lane elems trasition
var laneElemsTransition = d3.transition()
.duration(_fadeTime)
.ease(d3.easeLinear)
// laneElems DATA
var laneElems = svgContainer
.select("g.lanes")
.selectAll("g.actor")
.data(_laneObjs1, function(d) { return d.id })
// laneElems EXIT
laneElems.exit()
.transition(laneElemsTransition)
.style("opacity", function(d) {
store.dispatch(actions.deleteLane(d))
return 0
})
.remove(function(){console.log("++++++++++++++++++")})
// laneElems UPDATE texts
var actorTexts = laneElems.select("text")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.style("font-size", function(d, i) {
return parseInt(svgContainer.style("width")) * 2/100
})
.text(function(d) { return d.name })
.attr("dy", "20")
.transition(laneElemsTransition)
.attr("x", function(d, i) {
var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.name)
return r
})
.on("start", function start() {
intransition = true
})
.on("end", function end() {
intransition = false
})
// laneElems UPDATE lines
var actorLines = laneElems.select("line")
.attr("x0", function(d, i) {
var r = parseFloat(coordsUtils().hcoord_pct(_laneItems0, d.name)
* parseInt(svgContainer.style("width")) / 100).toFixed(0)
return r
})
.attr("y1", function() {
var text_bbox = this.parentNode.querySelector("text").getBBox();
return text_bbox.y + text_bbox.height;
})
.attr("y2", "100%")
.transition(laneElemsTransition)
.attrTween("x1", function(d, i, a) {
return function (t) {
var r = parseFloat(coordsUtils().hcoord_pct(_laneItems1, d.name)
* parseInt(svgContainer.style("width")) / 100).toFixed(0)
var x = parseFloat(parseInt(d.x0) + t * (r - parseInt(d.x0))).toFixed(0)
// dispatch lanes abscissa
var l = {name: d.name, id: d.id, x: x }
store.dispatch(actions.setLane(l))
return x
}
})
.attr("x2", function(d, i) {
var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.name)
return r
})
.on("start", function start() {
intransition = true
})
.on("end", function end() {
intransition = false
})
// laneElems ENTER
var newActorElements = laneElems
.enter()
.append("g")
.classed("actor", true)
// laneElems ENTER text
newActorElements.append("text")
.attr("class", "actor")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.style("font-family", "sans-serif")
.style("fill", "transparent")
.style("font-size", function(d, i) {
return parseInt(svgContainer.style("width")) * 2/100
})
.text(function(d) { return d.name })
.attr("dy", "20")
.attr("x", function(d, i, a) {
var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.name)
return r
})
.transition(laneElemsTransition)
.style("fill", "black")
.on("start", function start() {
intransition = true
})
.on("end", function end() {
intransition = false
})
// laneElems ENTER lines
newActorElements.append("line")
.attr("class", "actor")
.attr("stroke", "lightgray")
.style("stroke-width", "1px")
.attr("stroke-width", 1)
.attr("x0", function(d, i) {
var r = parseFloat(coordsUtils().hcoord_pct(_laneItems0, d.name)
* parseInt(svgContainer.style("width")) / 100).toFixed(0)
return r
})
.attr("x1", function(d, i, a) {
var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.name)
var x = parseFloat(coordsUtils().hcoord_pct(_laneItems1, d.name)
* parseInt(svgContainer.style("width")) / 100).toFixed(0)
var l = {name: d.name, id: d.id, x: x }
store.dispatch(actions.setLane(l))
return r
})
.attr("x2", function(d, i, a) {
var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.name)
return r
})
.attr("y1", function(_d, i) {
var text_bbox = this.parentNode.querySelector("text").getBBox();
return text_bbox.y + text_bbox.height;
})
.attr("y2", function(d, i, a) {
var r = "100%"
return r
})
// messageElements
var messageElements = svgContainer
.select("g.messages")
.selectAll("g.message")
.data(_messages1, function(d, i) { return d.id || (d.id = ++i); })
// message elems UPDATE texts
messageElements.select('text')
.transition(laneElemsTransition)
.attr("x", function(d, i) {
var r1 = coordsUtils().hcoord_pct(_laneItems1, d.from)
var r2 = coordsUtils().hcoord_pct(_laneItems1, d.to)
var r = coordsUtils().hcenter_tagged_pct(r1, r2)
return r
})
.attr("y", function(d, i, s) {
var r = (i + 2) * state.configReducer.vstep - 10
return r // (i+1)*10
})
.on("start", function start() {
intransition = true
})
.on("end", function end() {
intransition = false
})
// message elems UPDATE lines
messageElements.select('line')
.transition(laneElemsTransition)
.attr("x1", function(d, i, a) {
var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.from)
return r
})
.attr("x2", function(d, i, a) {
var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.to)
return r
})
.attr("y1", function(d, i) {
var r = (i + 2) * state.configReducer.vstep;
return r
})
.attr("y2", function(d, i) {
var r = (i + 2) * state.configReducer.vstep;
return r
})
.on("start", function start() {
intransition = true
})
.on("end", function end() {
intransition = false
})
// message elems UPDATE paths
messageElements.select("path")
.transition(laneElemsTransition)
.attr("d", function(d, i) {
var x_pc = coordsUtils().hcoord_tagged_pct(_laneItems1, d.from)
var xScrollWidth = parseInt(svgContainer.style("width"))
var t = xScrollWidth * Number.parseFloat(x_pc)/100
var x = t
var rx = 40
var ry = 20
var y = (i + 2)*50 - ry
var sweep_flag = 1
var r = [
"M", x, y,
"a", rx, ry, 0, 1, sweep_flag, 0, ry*2,
].join(" ");
return r
})
.on("start", function start() {
intransition = true
})
.on("end", function end() {
intransition = false
})
// message elems ENTER
var newMessageElements = messageElements
.enter()
.append("g")
.classed("message", true)
// messageElems ENTER TEXTs
newMessageElements.each(function(d, i) {
var new_message = d3.select(this)
.append("text")
.attr("class", "message")
.style("fill", "transparent")
.style("font-size", function(d, i) {
return parseInt(svgContainer.style("width")) * 2/100
})
.attr("dy", ".15em")
.attr("text-anchor", d.from == d.to ? "end" : "middle")
.attr("alignment-baseline", d.from == d.to ? "middle" : "autoMode")
.text(d.msg)
.attr("y", (i + 2) * state.configReducer.vstep - 10)
.attr("x", function() {
var x1 = coordsUtils().hcoord_pct(_laneItems1, d.from)
var x2 = coordsUtils().hcoord_pct(_laneItems1, d.to)
var r = coordsUtils().hcenter_tagged_pct(x1, x2)
return r
})
.transition(laneElemsTransition)
.style("fill", "grey")
.on("start", function start() {
intransition = true
})
.on("end", function end() {
intransition = false
})
})
// messageElems ENTER PATHs
newMessageElements.each(function(d, i) {
var new_message = d3.select(this)
if (d.from == d.to) {
new_message.append("path") // new mPATHs
.attr("fill-opacity", 0)
.attr("stroke", "transparent")
.each(function(d) {
// this._current = d_to_arc(d, i); // store initial state
})
.attr("d", function() {
var x_pc_to = coordsUtils().hcoord_pct(_laneItems1, d.to)
var xScrollWidth = parseInt(svgContainer.style("width"))
var t = xScrollWidth * Number.parseFloat(x_pc_to)/100
var x = t
var rx = 40
var ry = 20
var y = (i + 2)*50 - ry
var sweep_flag = 1
var r = [
"M", x, y,
"a", rx, ry, 0, 1, sweep_flag, 0, ry*2,
].join(" ");
return r
})
.transition(laneElemsTransition)
.attr("stroke", "grey")
.attr("fill", "grey")
.attrTween("marker-end", function(d) {
return function (t) {
if (t != 1) {
return null
} else {
return "url(#message-marker)"
}
}
})
.on("start", function start() {
intransition = true
})
.on("end", function end() {
intransition = false
})
// messageElems ENTER LINEs
} else {
var line = new_message.append("line")
.attr("class", "message")
.attr("stroke", "transparent")
.attr("stroke-width", 1)
.attr("y1", function() {
var r = (i + 2) * state.configReducer.vstep ;
return r
})
.attr("y2", function() {
var r = (i + 2) * state.configReducer.vstep ;
return r
})
.attr("x1", coordsUtils().hcoord_tagged_pct(_laneItems1, d.from))
.attr("x2", coordsUtils().hcoord_tagged_pct(_laneItems1, d.to))
.transition(laneElemsTransition)
.attr("stroke", "gray")
.attr("fill", "grey")
.attrTween("marker-end", function() {
return function (t) {
if (t != 1) {
return null
} else {
return "url(#message-marker)"
}
}
})
.on("start", function start() {
intransition = true
})
.on("end", function end() {
intransition = false
})
}
});
// message elems EXIT
messageElements.exit()
.transition()
.style("opacity", 0)
.remove()
}
exports.render = render;
}))/* */
/* d3lanes-component-particles.js */
/* */
if (typeof require === "function") {
var d3 = require('./d3.v4.0.0-alpha.40.js')
}
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.d3lanesComponentParticles = global.d3lanesComponentParticles || {})));
}(this, function (exports) { 'use strict';
// _____________ context
var stateParticles = {
particlesReducer: {}
}
var rendering = false
var intransition = false
// _______________________ render
function render(newState) {
if (rendering == true) return
if (newState.particlesReducer.particles.length == 0) return
rendering = true
var state = stateParticles= newState
var particleRadio = state.particlesReducer.particleRadio || 6.33
var svgContainer = d3.select('body')
.selectAll('svg')
.data(['svgContainer'])
svgContainer
.enter()
.append("svg")
.attr("id", state.configReducer.container)
svgContainer
.style('width', state.courtReducer.svgWidth)
.style('height', state.courtReducer.svgHeight)
var itemsGroup = d3.select('svg')
.selectAll('g.particles') // items
.data(['items'])
itemsGroup.enter()
.append("g")
.classed("particles", true) // items
// _________________________________ render Particles
var color = d3.scalePlasma()
.domain([0, 1])
var particleElements = svgContainer
.select("g.particles")
.selectAll("circle")
.data(state.particlesReducer.particles)
.attr('cx', function(d, i, a) { return d.x })
.attr('cy', function(d, i, a) { return d.y })
.attr('r', function(d, i, a) { return particleRadio })
.style("fill", function (d) {
var r = d.closestLaneUp.x / (d.closestLaneUp.x - d.closestLaneDown.x)
return color( ((3*r)%10 / 10) + (Math.random()* 3 /10))
})
.style("fill-opacity", 0.2)
.style("stroke", "none")
var newParticleElements = particleElements
.enter()
.append("circle")
.attr('cx', function(d, i, a) {
return d.x })
.attr('cy', function(d, i, a) { return d.y })
.attr('r', function(d, i, a) { return particleRadio })
.style("fill", function (d) {
var r = d.closestLaneUp.x / (d.closestLaneUp.x - d.closestLaneDown.x)
return color( ((3*r)%10 / 10) + (Math.random()/10))
})
.style("stroke", "none")
particleElements.exit()
.remove()
rendering = false
} // render
exports.render = render;
}))/* */
/* d3lanes-reducer.js */
/* */
if (typeof require === "function") {
var d3 = require('./d3.v4.0.0-alpha.40.js')
var d3lanesActions = require('./d3lanes-actions.js')
}
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.d3lanesReducer = global.d3lanesReducer || {})));
}(this, function (exports) { 'use strict';
// _____________ adapted from redux combineReducers
function combineReducers(reducers) {
var reducerKeys = Object.keys(reducers)
var finalReducers = {}
for (var i = 0; i < reducerKeys.length; i++) {
var key = reducerKeys[i]
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key]
}
}
var finalReducerKeys = Object.keys(finalReducers)
return function combination(state = {}, action) {
var hasChanged = false
var nextState = {}
for (var i = 0; i < finalReducerKeys.length; i++) {
var key = finalReducerKeys[i]
var reducer = finalReducers[key]
var previousStateForKey = state[key]
var nextStateForKey = reducer(previousStateForKey, action)
if (typeof nextStateForKey === 'undefined') {
var errorMessage = getUndefinedStateErrorMessage(key, action)
throw new Error(errorMessage)
}
nextState[key] = nextStateForKey
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
}
return hasChanged ? nextState : state
}
}
// _____________ CONFIG
var initialStateConfig = {
modes: {autoMode: 'autoMode', walkMode: 'walkMode'},
modeLabels: {autoMode: 'auto', walkMode: 'walk'},
views: {lanesView: 'lanesView'},
gravity: 0.5,
randNormal: d3.randomNormal(1.3, 2),
randNormal2: d3.randomNormal(0.5, 1.8),
containerElem: '#container',
containerId: 'svgid',
tickspan: 60,
beatTime: 500,
fadeFactor: 3, // times beat - fade items
periodFactor: 4, // times beat - add items
vstep: 50,
itemSpan: 6,
itemProps: ['to', 'from'],
itemVal: 'msg',
messageCollection_000: [
{id: "1", from: "customer", to: "barrista1", msg: "place order"},
{id: "2", from: "barrista1", to: "register", msg: "enter order"},
{id: "3", from: "register", to: "barrista1", msg: "give total"},
{id: "4", from: "barrista1", to: "barrista1", msg: "get cup making sure that it is fine for purpose"},
{id: "5", from: "barrista1", to: "barrista2", msg: "give cup"},
{id: "6", from: "barrista1", to: "customer", msg: "request money"},
{id: "7", from: "customer", to: "barrista1", msg: "pay order"},
{id: "8", from: "barrista2", to: "barrista2", msg: "get chai mix"},
{id: "9", from: "barrista2", to: "barrista2", msg: "add flavor"},
{id: "10", from: "barrista2", to: "barrista2", msg: "add milk"},
{id: "11", from: "barrista2", to: "barrista2", msg: "add ice"},
{id: "12", from: "barrista2", to: "barrista2", msg: "swirl"},
{id: "13", from: "barrista2", to: "customer", msg: "give tasty beverage"},
{id: "14", from: "customer", to: "tasty beverage", msg: "sip"},
{id: "15", from: "tasty beverage", to: "customer", msg: "burn"},
{id: "16", from: "customer", to: "customer", msg: "cry"},
{id: "17", from: "customer", to: "manager", msg: "complain"},
{id: "18", from: "manager", to: "barrista1", msg: "fire"},
{id: "19", from: "manager", to: "barrista2", msg: "fire"},
],
messageCollection: [
{id: "1", from: "app", to: "store", msg: "create store"},
{id: "2", from: "store", to: "store", msg: "subscribe lanes listener"},
{id: "3", from: "store", to: "store", msg: "subscribe particles listener"},
{id: "4", from: "app", to: "app", msg: "start kbd controller"},
{id: "5", from: "app", to: "app", msg: "start mouse controller"},
{id: "6", from: "ticker", to: "ticker", msg: "subscribe tickParticles"},
{id: "7", from: "ticker", to: "ticker", msg: "subscribe setRecords"},
{id: "8", from: "ticker", to: "ticker", msg: "start auto"},
{id: "9", from: "store", to: "reducer", msg: "dispatch setRecords action"},
{id: "10", from: "reducer", to: "reducer", msg: "apply action logic"},
{id: "11", from: "reducer", to: "store", msg: "return new state"},
{id: "12", from: "ticker", to: "ticker", msg: "run listeners"},
{id: "13", from: "component", to: "UI", msg: "render lanes"},
{id: "14", from: "UI", to: "app", msg: "trigger left arrow event"},
{id: "15", from: "store", to: "reducer", msg: "dispatch setMode action"},
{id: "16", from: "reducer", to: "reducer", msg: "run action"},
{id: "17", from: "reducer", to: "store", msg: "return new state"},
{id: "18", from: "ticker", to: "ticker", msg: "run listeners"},
{id: "19", from: "UI", to: "app", msg: "send down arrow event"},
{id: "20", from: "store", to: "reducer", msg: "dispatch setRecods action"},
{id: "21", from: "reducer", to: "reducer", msg: "run action and get record"},
{id: "22", from: "reducer", to: "reducer", msg: "return new set"},
{id: "23", from: "ticker", to: "ticker", msg: "run listeners"},
{id: "24", from: "component", to: "UI", msg: "render lanes"},
{id: "25", from: "UI", to: "app", msg: "send right arrow event"},
{id: "26", from: "store", to: "reducer", msg: "dispatch setMode action"},
{id: "27", from: "reducer", to: "reducer", msg: "run action"},
{id: "28", from: "reducer", to: "reducer", msg: "return new mode auto"},
{id: "29", from: "ticker", to: "ticker", msg: "run listeners with new state"},
{id: "30", from: "component", to: "UI", msg: "render auto lanes"},
{id: "31", from: "store", to: "reducer", msg: "dispatch createParticles action"},
{id: "32", from: "reducer", to: "reducer", msg: "run action"},
{id: "33", from: "reducer", to: "store", msg: "return new state with particles"},
{id: "34", from: "ticker", to: "ticker", msg: "run particles listeners"},
{id: "35", from: "component", to: "UI", msg: "render particles"},
],
}
function configReducer(state = initialStateConfig, action) {
if (actions == null) return state
var ActionTypes = d3lanesActions.ActionTypes
switch (action.type) {
default:
return state;
}
}
// _____________ DEBUG
var initialStateDebug = {
debugMode: true,
fps: 0
}
function debugReducer(state = initialStateDebug, action) {
if (actions == null) return state
var ActionTypes = d3lanesActions.ActionTypes
switch (action.type) {
case ActionTypes.SET_FPS:
return setFps(state, action)
case ActionTypes.SWITCH_DEBUGMODE:
console.log('SWITCH_DEBUGMODE')
return switchDebugMode(state, action)
default:
return state;
}
}
function setFps(state, action) {
return Object.assign({}, state, {
fps: action.fps
})
}
function switchDebugMode(state, action) {
return Object.assign({}, state, {
debugMode: !state.debugMode
})
}
// _____________ COURT
var initialStateCourt = {
svgHeight: 400, //
svgWidth: 600, //
keys: [],
notice: 'auto lanes',
currentMode: 'autoMode',
currentView: 'lanesView',
arrowKeysStarted: false,
keybKeyEventsStarted: false,
tickerStarted: false,
lastTick: 0,
mousePos: [null, null],
}
function courtReducer(state = initialStateCourt, action) {
if (actions == null) return state
var ActionTypes = d3lanesActions.ActionTypes
switch (action.type) {
case ActionTypes.SET_KEYBKEY:
console.log('SET_KEYBKEY')
var ks = state.keys
ks[action.keyCode] = true
return Object.assign({}, state, {
keys: ks
});
case ActionTypes.RELEASE_KEYBKEY:
console.log('RELEASE_KEYBKEY')
var ks = state.keys
ks[action.keyCode] = false
return Object.assign({}, state, {
keys: ks
});
case ActionTypes.START_KEYBKEY_EVENTS:
console.log('START_KEYBKEY_EVENTS')
return Object.assign({}, state, {
keybKeyEventsStarted: true
});
case ActionTypes.SET_MODE:
console.log('SET_MODE')
return Object.assign({}, state, {
currentMode: action.currentMode,
});
case ActionTypes.SET_VIEW:
console.log('SET_VIEW')
return Object.assign({}, state, {
currentView: action.currentView,
});
case ActionTypes.SET_NOTICE:
console.log('SET_NOTICE')
return Object.assign({}, state, {
notice: action.notice,
});
case ActionTypes.START_TICKER:
console.log('START_TICKER')
return Object.assign({}, state, {
tickerStarted: true
});
case ActionTypes.STOP_TICKER:
console.log('STOP_TICKER')
return Object.assign({}, state, {
tickerStarted: false
});
case ActionTypes.UPDATE_MOUSE_POS:
return Object.assign({}, state, {
mousePos: [action.x, action.y]
});
case ActionTypes.RESIZE_SCREEN:
console.log('RESIZE_SCREEN')
return Object.assign({}, state, {
svgWidth: action.width,
svgHeight: action.height
});
case ActionTypes.RESIZE_WIDTH:
console.log('RESIZE_WIDTH')
return Object.assign({}, state, {
svgWidth: state.svgWidth + action.delta
});
case ActionTypes.RESIZE_HEIGHT:
console.log('RESIZE_HEIGHT')
return Object.assign({}, state, {
svgHeight: state.svgHeight + action.delta
});
default:
return state;
}
}
// _____________ LANES
var initialStateLanes = {
lanes: [],
lanesIndex: 0,
messages: [],
records: [],
recordsCollection: [],
areRecordsFetched: false,
messagesCursorLow: 0,
messagesCursorHigh: 0,
}
function lanesReducer(state = initialStateLanes, action) {
if (actions == null) return state
var ActionTypes = d3lanesActions.ActionTypes
switch (action.type) {
case ActionTypes.INCREASE_CURSOR_LOW:
var r = Object.assign({}, state,
{messagesCursorLow: ++state.messagesCursorLow}
);
return r
case ActionTypes.REDUCE_CURSOR_LOW:
var r = Object.assign({}, state,
{messagesCursorLow: --state.messagesCursorLow}
);
return r
case ActionTypes.INCREASE_CURSOR_HIGH:
var r = Object.assign({}, state,
{messagesCursorHigh: ++state.messagesCursorHigh}
);
return r
case ActionTypes.REDUCE_CURSOR_HIGH:
var r = Object.assign({}, state,
{messagesCursorHigh: --state.messagesCursorHigh}
);
return r
case ActionTypes.DELETE_LANE: // setLane
var lanes = state.lanes
var ls = lanes.filter(function( obj ) {
return obj.id !== action.lane.id;
});
var r = Object.assign({}, state,
{lanes: ls},
{lanesIndex: ls.length}
);
return r
case ActionTypes.SET_LANE: // setLane
var lanes = state.lanes
var ls = {}
var result = lanes.filter(function( obj ) {
return obj.id == action.lane.id;
});
if (result.length === 0) { // add
ls = {lanes: [
{
id: action.lane.id,
name: action.lane.name,
x: action.lane.x
},
...lanes
]}
} else { // edit
ls = {lanes: lanes.map(lane =>
lane.id === action.lane.id ?
Object.assign({}, lane, { id: action.lane.id, name: action.lane.name, x: action.lane.x }) :
lane
)}
}
var r = Object.assign({}, state,
ls,
{
lanesIndex: ls.lanes.length
});
return r
case ActionTypes.SET_LANES:
console.log('SET_LANES')
return Object.assign({}, state, {
lanes: action.lanes,
lanesIndex: Object.keys(action.lanes).length
});
case ActionTypes.FETCH_RECORDS:
console.log('FETCH_RECORDS')
var processRecord = function processRecord(d) {
d.amount = +d.amount;
d.risk = +d.risk;
d.valueOf = function value() {
return this.amount;
}
return d;
}
var processData = function processData(error, dataCsv) {
if (store.getState().court.currentMode == 0) { // _tbd_
++timeTick
++vLast
store.dispatch(actions.setMessages(store.getState().configReducer.messageCollection.slice(0,
store.getState().configReducer.messageCollection.length)))
}
}
d3.queue()
.defer(d3.csv, action.src, processRecord)
.await(processData)
return Object.assign({}, state);
case ActionTypes.SET_MESSAGES:
console.log('SET_MESSAGES')
return Object.assign({}, state, {
messages: action.messages,
});
case ActionTypes.SET_RECORDS_FETCHED:
console.log('SET_RECORDS_FETCHED')
return Object.assign({}, state, {
areRecordsFetched: action.areRecordsFetched
})
case ActionTypes.SET_RECORDS_COLLECTION:
console.log('SET_RECORDS_COLLECTION')
return Object.assign({}, state, {
recordsCollection: action.recordsCollection
})
case ActionTypes.SET_RECORDS:
console.log('SET_RECORDS')
var vLow = state.messagesCursorLow
var vHigh = state.messagesCursorHigh
var itemSpan = action.itemSpan
var mode = action.mode
var r = state
if (mode == 'autoMode') {
var records = state.recordsCollection
var numRecords = records.length
if (vHigh >= vLow) vHigh = vHigh + 1 // add one to upper border
if (vHigh > numRecords) vHigh = -1 // upper border
if (((vHigh - vLow) > itemSpan) // all spteps full
|| (vHigh == -1) // infinitum with vLow active
|| (vLow == -1) // get always from reset
) vLow = vLow + 1 // increase lower border
if (vLow > numRecords) vLow = -1 // reset at end of cycle
r = Object.assign({}, state, {
records: state.recordsCollection.slice(vLow, vHigh),
messagesCursorLow: vLow,
messagesCursorHigh: vHigh,
})
}
return r
case ActionTypes.WALK_UP_RECORDS:
console.log('WALK_UP_RECORDS')
var vLow = state.messagesCursorLow
var vHigh = state.messagesCursorHigh
var itemSpan = action.itemSpan
var mode = action.mode
var r = state
if (mode == 'walkMode') {
vLow = Math.max(0, --vLow)
r = Object.assign({}, state, {
records: state.recordsCollection.slice(vLow, vHigh),
messagesCursorLow: vLow,
messagesCursorHigh: vHigh,
})
}
return r
case ActionTypes.WALK_DOWN_RECORDS:
console.log('WALK_DOWN_RECORDS')
var vLow = state.messagesCursorLow
var vHigh = state.messagesCursorHigh
var itemSpan = action.itemSpan
var mode = action.mode
var r = state
if (mode == 'walkMode') {
if ((vHigh - vLow) > itemSpan) ++vLow
++vHigh
r = Object.assign({}, state, {
records: state.recordsCollection.slice(vLow, vHigh),
messagesCursorLow: vLow,
messagesCursorHigh: vHigh,
})
}
return r
default:
return state;
}
}
// _____________ PARTICLES
var initialStateParticles = {
particles: [],
particleIndex: 0,
particlesGenerating: false,
particlesPerTick: 33,
particleRadio: 9,
}
function particlesReducer(state = initialStateParticles, action) {
if (actions == null) return state
var ActionTypes = d3lanesActions.ActionTypes
switch (action.type) {
case ActionTypes.START_PARTICLES: // startParticles
return Object.assign({}, state, {
particlesGenerating: true
});
case ActionTypes.STOP_PARTICLES: // stopParticles
return Object.assign({}, state, {
particlesGenerating: false
});
case ActionTypes.CREATE_PARTICLES: // createParticles
var newParticles = state.particles.slice(0)
var i
for (i = 0; i < action.N; i++) {
var ref = parseInt(action.x)
var closestLaneUp = action.lanes
.filter(function (d) {return d.x >= ref} )
.reduce(function (prev, curr) {
return (Math.abs(curr.x - ref) < Math.abs(prev.x - ref) ? curr : prev);
}, {id: 'end', x: action.xEnd})
var closestLaneDown = action.lanes
.filter(function (d) {return d.x <= ref} )
.reduce(function (prev, curr) {
return (Math.abs(curr.x - ref) < Math.abs(prev.x - ref) ? curr : prev);
}, {id: 'init', x: action.xInit})
var particle = {id: state.particleIndex+i,
x: action.x,
y: action.y,
closestLaneDown: closestLaneDown,
closestLaneUp: closestLaneUp,
};
particle.vector = [particle.id%2 ? - action.randNormal() : action.randNormal(),
- action.randNormal2()*3.3];
newParticles.unshift(particle);
}
return Object.assign({}, state, {
particles: newParticles,
particleIndex: state.particleIndex+i+1
});
case ActionTypes.TICK_PARTICLES: // tickParticles
var laneXs = action.lanes
.map(function(l) {
var x = parseInt(l.x)
return x})
var svgWidth = action.width
var svgHeight = action.height
var gravity = action.gravity
var movedParticles = state.particles
.filter(function (p) {
return (!(p.y > svgHeight))
})
.filter(function (p) {
return (!(p.y < 0))
})
.map(function (p) {
var vx = p.vector[0]
var vy = p.vector[1]
p.x += vx
p.y += vy
var ref = parseInt(p.x)
var laneUp = action.lanes
.filter(function(l) {
return (l.id == p.closestLaneUp.id)
})
p.closestLaneUp.x = (laneUp.length > 0 ) ? +laneUp[0].x : +p.closestLaneUp.x
var laneDown = action.lanes
.filter(function(l) {
return (l.id == p.closestLaneDown.id)
})
p.closestLaneDown.x = (laneDown.length > 0 ) ? +laneDown[0].x : +p.closestLaneDown.x
if (ref < (p.closestLaneDown.x + state.particleRadio) || ref > (p.closestLaneUp.x - state.particleRadio)) {
p.vector[0] = -p.vector[0]
}
p.vector[1] += gravity + 2 * gravity * (p.y - svgHeight) / svgHeight
return p
});
return Object.assign({}, state, {
particles: movedParticles,
particleIndex: movedParticles.length,
});
default:
return state;
}
}
// _____________ combined reducer
var reducer = combineReducers({
debugReducer: debugReducer,
configReducer: configReducer,
courtReducer: courtReducer,
lanesReducer: lanesReducer,
particlesReducer: particlesReducer,
})
exports.reducer = reducer;
}));/* */
/* d3lanes-store.js */
/* */
/* adapted from REDUX http://redux.js.org/ */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.d3lanesStore = global.d3lanesStore || {})));
}(this, function (exports) { 'use strict';
var createStore = function createStore(reducer, initialState) {
var currentReducer = reducer
var currentState = initialState
var currentListeners = []
var nextListeners = currentListeners
var isDispatching = false
// ______________________________ ensureCanMutateNextListeners
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice()
}
}
// ______________________________ getState
function getState() {
return currentState
}
// redux compose
function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
} else {
const last = funcs[funcs.length - 1]
const rest = funcs.slice(0, -1)
return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}
}
// ______________________________ subscribe
function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error('Expected listener to be a function.')
}
var isSubscribed = true
ensureCanMutateNextListeners()
nextListeners.push(listener)
return function unsubscribe() {
if (!isSubscribed) {
return
}
isSubscribed = false
ensureCanMutateNextListeners()
var index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
}
// ______________________________ dispatch
function dispatch(action) {
if (typeof action.type === 'undefined') {
throw new Error(
'Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant?'
)
}
if (isDispatching) {
throw new Error('Reducers may not dispatch actions.')
}
try {
isDispatching = true
currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
}
var listeners = currentListeners = nextListeners
for (var i = 0; i < listeners.length; i++) {
listeners[i]()
}
return action
}
return {
compose: compose,
dispatch: dispatch,
subscribe: subscribe,
getState: getState
}
}
exports.createStore = createStore;
}));
/* */
/* index.js */
/* */
if (typeof require === "function") {
var d3 = require('./d3.v4.0.0-alpha.40.js')
var d3lanesComponentLanes = require('./d3lanes-component-lanes.js')
var d3lanesComponentCourt = require('./d3lanes-component-court.js')
var d3lanesComponentParticles = require('./d3lanes-component-particles.js')
var d3lanesReducer = require('./d3lanes-reducer.js')
var d3lanesStore = require('./d3lanes-store.js')
var d3lanesActions = require('./d3lanes-actions.js')
var d3lanesControls = require('./d3lanes-controls.js')
}
var store = d3lanesStore.createStore(d3lanesReducer.reducer, d3lanesReducer.reducer())
store.subscribe(store.compose(d3lanesComponentCourt.render, store.getState))
store.subscribe(store.compose(d3lanesComponentLanes.render, store.getState))
store.subscribe(store.compose(d3lanesComponentParticles.render, store.getState))
var actions = d3lanesActions.ActionCreators
var svgContainer = d3.select(store.getState().configReducer.containerElem)
.selectAll('svg')
.data(['svg'])
var svgContainerNew = svgContainer.enter()
.append("svg")
.attr("id", store.getState().configReducer.containerId)
.style('width', store.getState().courtReducer.svgWidth)
.style('height', store.getState().courtReducer.svgHeight)
.style('background', 'oldlace')
.attr('class', 'bar-chart') //
.style('border', '1px solid darkgrey')
.attr('viewbox',"0 0 3 2")
d3lanesControls.kbdControls(store, d3.select('svg')).startKeybKeyEvents()
d3lanesControls.mouseControls(store).startMouseEvents(d3.select('svg'))
store.dispatch(actions.setRecordsCollection(
store.getState().configReducer.messageCollection))
store.dispatch(actions.setRecordsFetched(true))
// jff
store.dispatch(actions.startParticles())
store.dispatch(actions.createParticles({
particlesPerTick: store.getState().particlesReducer.particlesPerTick * 5,
x: store.getState().courtReducer.svgWidth / 2,
y: store.getState().courtReducer.svgWidth / 2,
xInit: 0,
xEnd: store.getState().courtReducer.svgWidth,
randNormal: store.getState().configReducer.randNormal,
randNormal2:store.getState().configReducer.randNormal2,
lanes: [],
}))
store.dispatch(actions.stopParticles())
var ticker = d3lanesControls.tickControls(store)
.subscribe(
store.compose(
store.dispatch,
actions.tickParticles,
function() { return {
width: store.getState().courtReducer.svgWidth,
height: store.getState().courtReducer.svgHeight,
gravity: store.getState().configReducer.gravity,
lanes: store.getState().lanesReducer.lanes
}
}
))
.start()
var walker = d3lanesControls.stepControls(store)
.subscribe(
store.compose(
store.dispatch,
actions.setRecords,
function() { return {
itemSpan: store.getState().configReducer.itemSpan,
currentMode: store.getState().courtReducer.currentMode
}
}
))
.start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment