/* global d3, _*/ 'use strict' var newDataSets = [ { meta: { id: 1, name: 'A' }, data: [ {x: 1, y: 10}, {x: 2, y: 20}, {x: 3, y: 30}, {x: 4, y: 40}, {x: 5, y: 50} ] }, { meta: { id: 3, name: 'C' }, data: [ {x: 100, y: 10}, {x: 200, y: 20}, {x: 300, y: 30}, {x: 400, y: 40}, {x: 500, y: 50} ] } ] var newDataSets2 = [ { meta: { id: 1, name: 'A' }, data: [ {x: 10, y: 10}, {x: 20, y: 20}, {x: 30, y: 30}, {x: 40, y: 40}, {x: 50, y: 50} ] }, { meta: { id: 2, name: 'B' }, data: [ {x: 10, y: 1}, {x: 20, y: 2}, {x: 30, y: 3}, {x: 40, y: 4}, {x: 50, y: 5} ] }, { meta: { id: 3, name: 'C' }, data: [ {x: 100, y: 10}, {x: 200, y: 20}, {x: 300, y: 30}, {x: 400, y: 40}, {x: 500, y: 50} ] } ] var firstDataSets = [ { meta: { id: 1, name: 'A' }, data: [ {x: 10, y: 10}, {x: 20, y: 20}, {x: 30, y: 30}, {x: 40, y: 40}, {x: 50, y: 50} ] }, { meta: { id: 2, name: 'B' }, data: [ {x: 10, y: 1}, {x: 20, y: 2}, {x: 30, y: 3}, {x: 40, y: 4}, {x: 50, y: 5} ] } ] var __width = 500 var __height = 500 var _margin = {top: 50, right: 50, bottom: 50, left: 50} var getId = function (dataset) { return dataset.meta.id } var getLabel = function (dataset) { return dataset.meta.name } var getData = function (dataset) { return dataset.data } var getLastData = function (dataset) { return dataset.data[dataset.data.length - 1] } var getX = function (data) { return data.x } var getY = function (data) { return data.y } var _width = __width - _margin.left - _margin.right var _height = __height - _margin.top - _margin.bottom var xScale = d3.scale.linear().range([0, _width]) var yScale = d3.scale.linear().range([_height, 0]) var line = d3.svg.line().interpolate('linear') .x(function (data) { return xScale(getX(data)) }) .y(function (data) { return yScale(getY(data)) }) var dataTooltip = d3.select('#container') .append('div') .classed('data-tooltip', true) var svg = d3.select('#container') .append('svg') .attr('width', __width) .attr('height', __height) var g = svg.append('g') .attr('transform', 'translate(' + _margin.left + ',' + _margin.top + ')') setInterval(function () { var dataSetsArray = [newDataSets, newDataSets2, firstDataSets] var randDataSets = dataSetsArray[Math.floor(Math.random() * dataSetsArray.length)] render(randDataSets) }, 2000) function render (datasets) { // ltWatch({'dataset': datasets.length, 'date': Date.now()}) var xs = _.chain(datasets).map(getData).flatten().map(getX).value() var ys = _.chain(datasets).map(getData).flatten().map(getY).value() xScale.domain(d3.extent(xs)) yScale.domain(d3.extent(ys)) var xAxis = d3.svg.axis().scale(xScale).orient('bottom') var yAxis = d3.svg.axis().scale(yScale).orient('left') if (g.selectAll('g.x.axis').empty()) { g.append('g') .classed('x axis', true) .attr('transform', 'translate(0,' + _height + ')') .call(xAxis) } else { g.selectAll('g.x.axis') .transition().duration(1000) .call(xAxis) } if (g.selectAll('g.y.axis').empty()) { g.append('g') .classed('y axis', true) .call(yAxis) } else { g.selectAll('g.y.axis') .transition().duration(1000) .call(yAxis) } // bind dataset var datasetContainers = g.selectAll('g.dataset') .data(datasets, getId) // enter datasetContainers .enter().append('g') .classed('dataset', true) .attr('id', function (dataset) { return getId(dataset) }) .on('mouseover', function (dataset) { var self = this var gs = d3.selectAll('g.dataset') gs.filter(function () { return self.id !== this.id }) .transition().duration(1000) .style('opacity', 0.2) }) .on('mouseout', function (dataset) { var self = this var gs = d3.selectAll('g.dataset') gs.filter(function () { return self.id !== this.id }) .transition().duration(1000) .style('opacity', 1.0) }) .style('opacity', 0.0) .transition().duration(1000) .style('opacity', 1.0) datasetContainers.selectAll('path.line') .data(function (dataset) { return [dataset] }) .enter().append('path') .classed('line', true) .attr('d', function (dataset) { return line(getData(dataset)) }) datasetContainers.selectAll('circle.point') .data(function (dataset) { return getData(dataset) }) .enter().append('circle') .classed('point', true) .attr('cx', function (data) { return xScale(getX(data)) }) .attr('cy', function (data) { return yScale(getY(data)) }) .attr('r', 4) .on('mouseover', function (data) { d3.select(this) .transition().duration(1000) .attr('r', 5) .style('stroke-width', '3px') var dataTooltipContainer = dataTooltip.data([data]) dataTooltipContainer.append('div') .classed('x', true) .html(getX) dataTooltipContainer.append('div') .classed('y', true) .html(getY) dataTooltipContainer.append('div') .classed('data-tooltip-arrow', true) dataTooltip .transition().duration(1000) .style('left', (+d3.select(this).attr('cx') + _margin.left) + 'px') .style('top', (+d3.select(this).attr('cy') + _margin.top) + 'px') .style('opacity', 1) .style('display', 'block') }) .on('mouseout', function (data) { d3.select(this) .transition().duration(1000) .attr('r', 4) .style('stroke-width', '2px') // hide tooltip dataTooltip .transition().duration(1000) .style('opacity', 0) .style('display', 'none') dataTooltip.selectAll('.x').remove() dataTooltip.selectAll('.y').remove() dataTooltip.selectAll('.data-tooltip-arrow').remove() }) datasetContainers.selectAll('text.label') .data(function (dataset) { return [dataset] }) .enter().append('text') .classed('label', true) .attr('x', function (dataset) { return xScale(getX(getLastData(dataset))) }) .attr('y', function (dataset) { return yScale(getY(getLastData(dataset))) }) .text(getLabel) // exit datasetContainers .exit() .transition().duration(1000) .style('opacity', 0.0) .remove() // update datasetContainers .selectAll('path.line') .transition().duration(1000) .attr('d', function (dataset) { return line(getData(dataset)) }) datasetContainers .selectAll('circle.point') .transition().duration(1000) .attr('cx', function (data) { return xScale(getX(data)) }) .attr('cy', function (data) { return yScale(getY(data)) }) datasetContainers .selectAll('text.label') .transition().duration(1000) .attr('x', function (dataset) { return xScale(getX(getLastData(dataset))) }) .attr('y', function (dataset) { return yScale(getY(getLastData(dataset))) }) }