diff --git a/package-lock.json b/package-lock.json index 1572f03..147d651 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4366,6 +4366,25 @@ "object-assign": "4.1.1" } }, + "parcoord-es": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parcoord-es/-/parcoord-es-2.0.3.tgz", + "integrity": "sha512-cixdO2iMEQOssj5+I72qzNPA4JjaXh6K63PcHnSk65gj0WJZ6SxXlVT7Bj+sKCpz+g/aQblmt5LLKW4eEeWgUw==", + "requires": { + "d3-array": "1.2.1", + "d3-axis": "1.0.8", + "d3-brush": "1.0.4", + "d3-collection": "1.0.4", + "d3-dispatch": "1.0.3", + "d3-drag": "1.2.1", + "d3-interpolate": "1.1.6", + "d3-scale": "2.0.0", + "d3-selection": "1.3.0", + "d3-shape": "1.2.0", + "d3-transition": "1.1.1", + "requestanimationframe": "0.0.23" + } + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -6648,9 +6667,9 @@ "dev": true }, "vizart-core": { - "version": "2.0.0-rc.6", - "resolved": "https://registry.npmjs.org/vizart-core/-/vizart-core-2.0.0-rc.6.tgz", - "integrity": "sha512-HMUyDR1876YLSVi8lX7QT0aTk0ZVOj9YmnYxm1Nq4Pl6FUGgAVPI0fiVQLFLdCnxkSi3jYZ54cx1aseUs99Ndg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vizart-core/-/vizart-core-2.0.0.tgz", + "integrity": "sha512-a88bhRMfIyCmrgpRXg7PFq6AhWhcXankUO/YdPWbmvkxTNOZt19Fy5OkBwRhNuQYVbx2maBiijvc9SV5e9QEuQ==", "requires": { "d3-array": "1.2.1", "d3-collection": "1.0.4", diff --git a/package.json b/package.json index 651b333..e1ce699 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "d3-shape": "^1.2.0", "d3-timer": "^1.0.7", "d3-transition": "^1.1.1", + "parcoord-es": "^2.0.3", "requestanimationframe": "0.0.23", "sylvester": "0.0.21", "vizart-core": "^2.0.0" diff --git a/src/parallelCoordinates/api/api-render.js b/src/parallelCoordinates/api/api-render.js index d911b49..bb958bb 100644 --- a/src/parallelCoordinates/api/api-render.js +++ b/src/parallelCoordinates/api/api-render.js @@ -1,9 +1,11 @@ import { apiRenderSVG } from 'vizart-core'; +import { select } from 'd3-selection'; import draw from './draw'; const apiRender = state => ({ render(data) { apiRenderSVG(state).render(data); + select('svg').remove(); draw(state); }, }); diff --git a/src/parallelCoordinates/api/draw.js b/src/parallelCoordinates/api/draw.js index 209ec72..7747b56 100644 --- a/src/parallelCoordinates/api/draw.js +++ b/src/parallelCoordinates/api/draw.js @@ -1,5 +1,5 @@ import { select } from 'd3-selection'; -import ParCoords from '../parcoords-es'; +import ParCoords from 'parcoord-es'; import sortDim from './sort-dim'; const draw = state => { diff --git a/src/parallelCoordinates/index.js b/src/parallelCoordinates/index.js index 85b2fd8..b469cc6 100644 --- a/src/parallelCoordinates/index.js +++ b/src/parallelCoordinates/index.js @@ -23,7 +23,7 @@ import { apiResetBrushes, } from './api/api-delegates'; -import './parcoords-es/parallel-coordinates.css'; +import 'parcoord-es/dist/parcoords.css'; import opt from './options'; const composers = { diff --git a/src/parallelCoordinates/parcoords-es/api/adjacentPairs.js b/src/parallelCoordinates/parcoords-es/api/adjacentPairs.js deleted file mode 100644 index a643a67..0000000 --- a/src/parallelCoordinates/parcoords-es/api/adjacentPairs.js +++ /dev/null @@ -1,10 +0,0 @@ -// pairs of adjacent dimensions -const adjacentPairs = arr => { - let ret = []; - for (let i = 0; i < arr.length - 1; i++) { - ret.push([arr[i], arr[i + 1]]); - } - return ret; -}; - -export default adjacentPairs; diff --git a/src/parallelCoordinates/parcoords-es/api/applyAxisConfig.js b/src/parallelCoordinates/parcoords-es/api/applyAxisConfig.js deleted file mode 100644 index e4cff80..0000000 --- a/src/parallelCoordinates/parcoords-es/api/applyAxisConfig.js +++ /dev/null @@ -1,35 +0,0 @@ -import { axisBottom, axisLeft, axisRight, axisTop } from 'd3-axis'; - -const applyAxisConfig = (axis, dimension) => { - let axisCfg; - - switch (dimension.orient) { - case 'left': - axisCfg = axisLeft(dimension.yscale); - break; - case 'right': - axisCfg = axisRight(dimension.yscale); - break; - case 'top': - axisCfg = axisTop(dimension.yscale); - break; - case 'bottom': - axisCfg = axisBottom(dimension.yscale); - break; - default: - axisCfg = axisLeft(dimension.yscale); - break; - } - - axisCfg - .ticks(dimension.ticks) - .tickValues(dimension.tickValues) - .tickSizeInner(dimension.innerTickSize) - .tickSizeOuter(dimension.outerTickSize) - .tickPadding(dimension.tickPadding) - .tickFormat(dimension.tickFormat); - - return axisCfg; -}; - -export default applyAxisConfig; diff --git a/src/parallelCoordinates/parcoords-es/api/applyDimensionDefaults.js b/src/parallelCoordinates/parcoords-es/api/applyDimensionDefaults.js deleted file mode 100644 index 04a1d0c..0000000 --- a/src/parallelCoordinates/parcoords-es/api/applyDimensionDefaults.js +++ /dev/null @@ -1,26 +0,0 @@ -import { keys } from 'd3-collection'; - -const applyDimensionDefaults = (config, pc) => - function(dims) { - const types = pc.detectDimensionTypes(config.data); - dims = dims ? dims : keys(types); - - return dims.reduce((acc, cur, i) => { - const k = config.dimensions[cur] ? config.dimensions[cur] : {}; - - acc[cur] = { - ...k, - orient: k.orient ? k.orient : 'left', - ticks: k.ticks != null ? k.ticks : 5, - innerTickSize: k.innerTickSize != null ? k.innerTickSize : 6, - outerTickSize: k.outerTickSize != null ? k.outerTickSize : 0, - tickPadding: k.tickPadding != null ? k.tickPadding : 3, - type: k.type ? k.type : types[cur], - index: k.index != null ? k.index : i, - }; - - return acc; - }, {}); - }; - -export default applyDimensionDefaults; diff --git a/src/parallelCoordinates/parcoords-es/api/autoscale.js b/src/parallelCoordinates/parcoords-es/api/autoscale.js deleted file mode 100644 index 00e9d58..0000000 --- a/src/parallelCoordinates/parcoords-es/api/autoscale.js +++ /dev/null @@ -1,121 +0,0 @@ -import { scaleLinear, scaleOrdinal, scalePoint, scaleTime } from 'd3-scale'; -import { keys } from 'd3-collection'; -import { extent } from 'd3-array'; - -import getRange from '../util/getRange'; -import w from '../util/width'; -import h from '../util/height'; - -const autoscale = (config, pc, xscale, ctx) => - function() { - // yscale - const defaultScales = { - date: function(k) { - let _extent = extent(config.data, d => (d[k] ? d[k].getTime() : null)); - // special case if single value - if (_extent[0] === _extent[1]) { - return scalePoint() - .domain(_extent) - .range(getRange(config)); - } - if (config.flipAxes.includes(k)) { - _extent = _extent.map(val => tempDate.unshift(val)); - } - return scaleTime() - .domain(_extent) - .range(getRange(config)); - }, - number: function(k) { - let _extent = extent(config.data, d => +d[k]); - // special case if single value - if (_extent[0] === _extent[1]) { - return scalePoint() - .domain(_extent) - .range(getRange(config)); - } - if (config.flipAxes.includes(k)) { - _extent = _extent.map(val => tempDate.unshift(val)); - } - return scaleLinear() - .domain(_extent) - .range(getRange(config)); - }, - string: function(k) { - let counts = {}, - domain = []; - // Let's get the count for each value so that we can sort the domain based - // on the number of items for each value. - config.data.map(p => { - if (p[k] === undefined && config.nullValueSeparator !== 'undefined') { - return null; // null values will be drawn beyond the horizontal null value separator! - } - if (counts[p[k]] === undefined) { - counts[p[k]] = 1; - } else { - counts[p[k]] = counts[p[k]] + 1; - } - }); - if (config.flipAxes.includes(k)) { - domain = Object.getOwnPropertyNames(counts).sort(); - } else { - let tempArr = Object.getOwnPropertyNames(counts).sort(); - for (let i = 0; i < Object.getOwnPropertyNames(counts).length; i++) { - domain.push(tempArr.pop()); - } - } - - //need to create an ordinal scale for categorical data - let categoricalRange = []; - if (domain.length === 1) { - //edge case - domain = [' ', domain[0], ' ']; - } - let addBy = getRange(config)[0] / (domain.length - 1); - for (let j = 0; j < domain.length; j++) { - if (categoricalRange.length === 0) { - categoricalRange.push(0); - continue; - } - categoricalRange.push(categoricalRange[j - 1] + addBy); - } - return scaleOrdinal() - .domain(domain) - .range(categoricalRange); - }, - }; - keys(config.dimensions).forEach(function(k) { - config.dimensions[k].yscale = defaultScales[config.dimensions[k].type](k); - }); - - // xscale - xscale.range([0, w(config)], 1); - // Retina display, etc. - const devicePixelRatio = window.devicePixelRatio || 1; - - // canvas sizes - pc.selection - .selectAll('canvas') - .style('margin-top', config.margin.top + 'px') - .style('margin-left', config.margin.left + 'px') - .style('width', w(config) + 2 + 'px') - .style('height', h(config) + 2 + 'px') - .attr('width', (w(config) + 2) * devicePixelRatio) - .attr('height', (h(config) + 2) * devicePixelRatio); - // default styles, needs to be set when canvas width changes - ctx.foreground.strokeStyle = config.color; - ctx.foreground.lineWidth = 1.4; - ctx.foreground.globalCompositeOperation = config.composite; - ctx.foreground.globalAlpha = config.alpha; - ctx.foreground.scale(devicePixelRatio, devicePixelRatio); - ctx.brushed.strokeStyle = config.brushedColor; - ctx.brushed.lineWidth = 1.4; - ctx.brushed.globalCompositeOperation = config.composite; - ctx.brushed.globalAlpha = config.alpha; - ctx.brushed.scale(devicePixelRatio, devicePixelRatio); - ctx.highlight.lineWidth = 3; - ctx.highlight.scale(devicePixelRatio, devicePixelRatio); - - return this; - }; - -export default autoscale; diff --git a/src/parallelCoordinates/parcoords-es/api/axisDots.js b/src/parallelCoordinates/parcoords-es/api/axisDots.js deleted file mode 100644 index 4587ddc..0000000 --- a/src/parallelCoordinates/parcoords-es/api/axisDots.js +++ /dev/null @@ -1,28 +0,0 @@ -import { entries } from 'd3-collection'; -import { min } from 'd3-array'; - -//draw dots with radius r on the axis line where data intersects -const axisDots = (config, pc, position) => _r => { - const r = _r || 0.1; - const ctx = pc.ctx.marks; - const startAngle = 0; - const endAngle = 2 * Math.PI; - ctx.globalAlpha = min([1 / Math.pow(config.data.length, 1 / 2), 1]); - config.data.forEach(d => { - entries(config.dimensions).forEach((p, i) => { - ctx.beginPath(); - ctx.arc( - position(p), - config.dimensions[p.key].yscale(d[p]), - r, - startAngle, - endAngle - ); - ctx.stroke(); - ctx.fill(); - }); - }); - return this; -}; - -export default axisDots; diff --git a/src/parallelCoordinates/parcoords-es/api/brushMode.js b/src/parallelCoordinates/parcoords-es/api/brushMode.js deleted file mode 100644 index cb33430..0000000 --- a/src/parallelCoordinates/parcoords-es/api/brushMode.js +++ /dev/null @@ -1,50 +0,0 @@ -const brushPredicate = (brushGroup, config, pc) => (predicate = null) => { - if (predicate === null) { - return brushGroup.predicate; - } - - predicate = String(predicate).toUpperCase(); - if (predicate !== 'AND' && predicate !== 'OR') { - throw new Error('Invalid predicate ' + predicate); - } - - brushGroup.predicate = predicate; - config.brushed = brushGroup.currentMode().selected(); - pc.renderBrushed(); - return pc; -}; - -const brushMode = (brushGroup, config, pc) => (mode = null) => { - if (mode === null) { - return brushGroup.mode; - } - - if (pc.brushModes().indexOf(mode) === -1) { - throw new Error('pc.brushmode: Unsupported brush mode: ' + mode); - } - - // Make sure that we don't trigger unnecessary events by checking if the mode - // actually changes. - if (mode !== brushGroup.mode) { - // When changing brush modes, the first thing we need to do is clearing any - // brushes from the current mode, if any. - if (brushGroup.mode !== 'None') { - pc.brushReset(); - } - - // Next, we need to 'uninstall' the current brushMode. - brushGroup.modes[brushGroup.mode].uninstall(pc); - // Finally, we can install the requested one. - brushGroup.mode = mode; - brushGroup.modes[brushGroup.mode].install(); - if (mode === 'None') { - delete pc.brushPredicate; - } else { - pc.brushPredicate = brushPredicate(brushGroup, config, pc); - } - } - - return pc; -}; - -export default brushMode; diff --git a/src/parallelCoordinates/parcoords-es/api/brushReset.js b/src/parallelCoordinates/parcoords-es/api/brushReset.js deleted file mode 100644 index 33f2130..0000000 --- a/src/parallelCoordinates/parcoords-es/api/brushReset.js +++ /dev/null @@ -1,31 +0,0 @@ -import { select, selectAll } from 'd3-selection'; - -const brushReset = config => - function(dimension) { - const brushesToKeep = []; - for (let j = 0; j < config.brushes.length; j++) { - if (config.brushes[j].data !== dimension) { - brushesToKeep.push(config.brushes[j]); - } - } - - config.brushes = brushesToKeep; - config.brushed = false; - - if (pc.g() !== undefined) { - const nodes = selectAll('.brush').nodes(); - for (let i = 0; i < nodes.length; i++) { - if (nodes[i].__data__ === dimension) { - // remove all dummy brushes for this axis or the real brush - select(select(nodes[i]).nodes()[0].parentNode) - .selectAll('.dummy') - .remove(); - config.dimensions[dimension].brush.move(select(nodes[i], null)); - } - } - } - - return this; - }; - -export default brushReset; diff --git a/src/parallelCoordinates/parcoords-es/api/brushable.js b/src/parallelCoordinates/parcoords-es/api/brushable.js deleted file mode 100644 index 353e371..0000000 --- a/src/parallelCoordinates/parcoords-es/api/brushable.js +++ /dev/null @@ -1,82 +0,0 @@ -import { brushSelection, brushY } from 'd3-brush'; -import { event, select } from 'd3-selection'; - -const brushable = (config, pc, flags) => - function() { - if (!pc.g()) { - pc.createAxes(); - } - - const g = pc.g(); - - // Add and store a brush for each axis. - g - .append('svg:g') - .attr('class', 'brush') - .each(function(d) { - if (config.dimensions[d] !== undefined) { - config.dimensions[d]['brush'] = brushY(select(this)).extent([ - [-15, 0], - [15, config.dimensions[d].yscale.range()[0]], - ]); - select(this).call( - config.dimensions[d]['brush'] - .on('start', function() { - if (event.sourceEvent !== null && !event.sourceEvent.ctrlKey) { - pc.brushReset(); - } - }) - .on('brush', function() { - if (!event.sourceEvent.ctrlKey) { - pc.brush(); - } - }) - .on('end', function() { - // save brush selection is ctrl key is held - // store important brush information and - // the html element of the selection, - // to make a dummy selection element - if (event.sourceEvent.ctrlKey) { - let html = select(this) - .select('.selection') - .nodes()[0].outerHTML; - html = html.replace( - 'class="selection"', - 'class="selection dummy' + - ' selection-' + - config.brushes.length + - '"' - ); - let dat = select(this).nodes()[0].__data__; - let brush = { - id: config.brushes.length, - extent: brushSelection(this), - html: html, - data: dat, - }; - config.brushes.push(brush); - select(select(this).nodes()[0].parentNode) - .select('.axis') - .nodes()[0].outerHTML += html; - pc.brush(); - config.dimensions[d].brush.move(select(this, null)); - select(this) - .select('.selection') - .attr('style', 'display:none'); - pc.brushable(); - } else { - pc.brush(); - } - }) - ); - select(this).on('dblclick', function() { - pc.brushReset(d); - }); - } - }); - - flags.brushable = true; - return this; - }; - -export default brushable; diff --git a/src/parallelCoordinates/parcoords-es/api/clear.js b/src/parallelCoordinates/parcoords-es/api/clear.js deleted file mode 100644 index 57301c2..0000000 --- a/src/parallelCoordinates/parcoords-es/api/clear.js +++ /dev/null @@ -1,21 +0,0 @@ -import h from '../util/height'; -import w from '../util/width'; -import isBrushed from '../util/isBrushed'; - -const clear = (config, pc, ctx, brushGroup) => - function(layer) { - ctx[layer].clearRect(0, 0, w(config) + 2, h(config) + 2); - - // This will make sure that the foreground items are transparent - // without the need for changing the opacity style of the foreground canvas - // as this would stop the css styling from working - if (layer === 'brushed' && isBrushed(config, brushGroup)) { - ctx.brushed.fillStyle = pc.selection.style('background-color'); - ctx.brushed.globalAlpha = 1 - config.alphaOnBrushed; - ctx.brushed.fillRect(0, 0, w(config) + 2, h(config) + 2); - ctx.brushed.globalAlpha = config.alpha; - } - return this; - }; - -export default clear; diff --git a/src/parallelCoordinates/parcoords-es/api/commonScale.js b/src/parallelCoordinates/parcoords-es/api/commonScale.js deleted file mode 100644 index 48c20f0..0000000 --- a/src/parallelCoordinates/parcoords-es/api/commonScale.js +++ /dev/null @@ -1,46 +0,0 @@ -import { keys } from 'd3-collection'; -import { extent } from 'd3-array'; - -const commonScale = (config, pc) => - function(global, type) { - const t = type || 'number'; - if (typeof global === 'undefined') { - global = true; - } - - // try to autodetect dimensions and create scales - if (!keys(config.dimensions).length) { - pc.detectDimensions(); - } - pc.autoscale(); - - // scales of the same type - const scales = keys(config.dimensions).filter( - p => config.dimensions[p].type == t - ); - - if (global) { - let _extent = extent( - scales - .map(d => config.dimensions[d].yscale.domain()) - .reduce((cur, acc) => cur.concat(acc)) - ); - - scales.forEach(d => { - config.dimensions[d].yscale.domain(_extent); - }); - } else { - scales.forEach(d => { - config.dimensions[d].yscale.domain(extent(config.data, d => +d[k])); - }); - } - - // update centroids - if (config.bundleDimension !== null) { - pc.bundleDimension(config.bundleDimension); - } - - return this; - }; - -export default commonScale; diff --git a/src/parallelCoordinates/parcoords-es/api/computeRealCentroids.js b/src/parallelCoordinates/parcoords-es/api/computeRealCentroids.js deleted file mode 100644 index f17b565..0000000 --- a/src/parallelCoordinates/parcoords-es/api/computeRealCentroids.js +++ /dev/null @@ -1,10 +0,0 @@ -import { keys } from 'd3-collection'; - -const computeRealCentroids = (dimensions, position) => row => - keys(dimensions).map(d => { - const x = position(d); - const y = dimensions[d].yscale(row[d]); - return [x, y]; - }); - -export default computeRealCentroids; diff --git a/src/parallelCoordinates/parcoords-es/api/createAxes.js b/src/parallelCoordinates/parcoords-es/api/createAxes.js deleted file mode 100644 index 31d675b..0000000 --- a/src/parallelCoordinates/parcoords-es/api/createAxes.js +++ /dev/null @@ -1,101 +0,0 @@ -import { select } from 'd3-selection'; - -import dimensionLabels from '../util/dimensionLabels'; -import flipAxisAndUpdatePCP from '../util/flipAxisAndUpdatePCP'; -import rotateLabels from '../util/rotateLabels'; - -import w from '../util/width'; -import h from '../util/height'; - -/** - * Create static SVG axes with dimension names, ticks, and labels. - * - * @param config - * @param pc - * @param xscale - * @param flags - * @param axis - * @returns {Function} - */ -const createAxes = (config, pc, xscale, flags, axis) => - function() { - if (pc.g() !== undefined) { - pc.removeAxes(); - } - // Add a group element for each dimension. - pc._g = pc.svg - .selectAll('.dimension') - .data(pc.getOrderedDimensionKeys(), function(d) { - return d; - }) - .enter() - .append('svg:g') - .attr('class', 'dimension') - .attr('transform', function(d) { - return 'translate(' + xscale(d) + ')'; - }); - // Add an axis and title. - pc._g - .append('svg:g') - .attr('class', 'axis') - .attr('transform', 'translate(0,0)') - .each(function(d) { - let axisElement = select(this).call( - pc.applyAxisConfig(axis, config.dimensions[d]) - ); - - axisElement - .selectAll('path') - .style('fill', 'none') - .style('stroke', '#222') - .style('shape-rendering', 'crispEdges'); - - axisElement - .selectAll('line') - .style('fill', 'none') - .style('stroke', '#222') - .style('shape-rendering', 'crispEdges'); - }) - - .append('svg:text') - .attr('text-anchor', 'middle') - .attr('y', 0) - .attr( - 'transform', - 'translate(0,-5) rotate(' + config.dimensionTitleRotation + ')' - ) - .attr('x', 0) - .attr('class', 'label') - .text(dimensionLabels(config)) - .on('dblclick', flipAxisAndUpdatePCP(config, pc, axis)) - .on('wheel', rotateLabels(config, pc)); - - if (config.nullValueSeparator == 'top') { - pc.svg - .append('line') - .attr('x1', 0) - .attr('y1', 1 + config.nullValueSeparatorPadding.top) - .attr('x2', w(config)) - .attr('y2', 1 + config.nullValueSeparatorPadding.top) - .attr('stroke-width', 1) - .attr('stroke', '#777') - .attr('fill', 'none') - .attr('shape-rendering', 'crispEdges'); - } else if (config.nullValueSeparator == 'bottom') { - pc.svg - .append('line') - .attr('x1', 0) - .attr('y1', h(config) + 1 - config.nullValueSeparatorPadding.bottom) - .attr('x2', w(config)) - .attr('y2', h(config) + 1 - config.nullValueSeparatorPadding.bottom) - .attr('stroke-width', 1) - .attr('stroke', '#777') - .attr('fill', 'none') - .attr('shape-rendering', 'crispEdges'); - } - - flags.axes = true; - return this; - }; - -export default createAxes; diff --git a/src/parallelCoordinates/parcoords-es/api/detectDimensionTypes.js b/src/parallelCoordinates/parcoords-es/api/detectDimensionTypes.js deleted file mode 100644 index 3ed7fb8..0000000 --- a/src/parallelCoordinates/parcoords-es/api/detectDimensionTypes.js +++ /dev/null @@ -1,14 +0,0 @@ -import { keys } from 'd3-collection'; - -import toTypeCoerceNumbers from './toTypeCoerceNumbers'; - -// attempt to determine types of each dimension based on first row of data -const detectDimensionTypes = data => - keys(data[0]).reduce((acc, cur) => { - const key = isNaN(Number(cur)) ? cur : parseInt(cur); - acc[key] = toTypeCoerceNumbers(data[0][cur]); - - return acc; - }, {}); - -export default detectDimensionTypes; diff --git a/src/parallelCoordinates/parcoords-es/api/detectDimensions.js b/src/parallelCoordinates/parcoords-es/api/detectDimensions.js deleted file mode 100644 index c037403..0000000 --- a/src/parallelCoordinates/parcoords-es/api/detectDimensions.js +++ /dev/null @@ -1,7 +0,0 @@ -const detectDimensions = pc => - function() { - pc.dimensions(pc.applyDimensionDefaults()); - return this; - }; - -export default detectDimensions; diff --git a/src/parallelCoordinates/parcoords-es/api/flip.js b/src/parallelCoordinates/parcoords-es/api/flip.js deleted file mode 100644 index ccfdd94..0000000 --- a/src/parallelCoordinates/parcoords-es/api/flip.js +++ /dev/null @@ -1,11 +0,0 @@ -const flip = config => - function(d) { - //__.dimensions[d].yscale.domain().reverse(); // does not work - config.dimensions[d].yscale.domain( - config.dimensions[d].yscale.domain().reverse() - ); // works - - return this; - }; - -export default flip; diff --git a/src/parallelCoordinates/parcoords-es/api/getOrderedDimensionKeys.js b/src/parallelCoordinates/parcoords-es/api/getOrderedDimensionKeys.js deleted file mode 100644 index 2f8482f..0000000 --- a/src/parallelCoordinates/parcoords-es/api/getOrderedDimensionKeys.js +++ /dev/null @@ -1,9 +0,0 @@ -import { ascending } from 'd3-array'; -import { keys } from 'd3-collection'; - -const getOrderedDimensionKeys = config => () => - keys(config.dimensions).sort((x, y) => - ascending(config.dimensions[x].index, config.dimensions[y].index) - ); - -export default getOrderedDimensionKeys; diff --git a/src/parallelCoordinates/parcoords-es/api/highlight.js b/src/parallelCoordinates/parcoords-es/api/highlight.js deleted file mode 100644 index fbbb60c..0000000 --- a/src/parallelCoordinates/parcoords-es/api/highlight.js +++ /dev/null @@ -1,26 +0,0 @@ -import { selectAll } from 'd3-selection'; - -import colorPath from '../util/colorPath'; -import functor from '../util/functor'; - -const pathHighlight = (config, ctx, position) => (d, i) => { - ctx.highlight.strokeStyle = functor(config.color)(d, i); - return colorPath(config, position, d, ctx.highlight); -}; - -// highlight an array of data -const highlight = (config, pc, canvas, events, ctx, position) => - function(data = null) { - if (data === null) { - return config.highlighted; - } - - config.highlighted = data; - pc.clear('highlight'); - selectAll([canvas.foreground, canvas.brushed]).classed('faded', true); - data.forEach(pathHighlight(config, ctx, position)); - events.call('highlight', this, data); - return this; - }; - -export default highlight; diff --git a/src/parallelCoordinates/parcoords-es/api/init.js b/src/parallelCoordinates/parcoords-es/api/init.js deleted file mode 100644 index 39b5f28..0000000 --- a/src/parallelCoordinates/parcoords-es/api/init.js +++ /dev/null @@ -1,53 +0,0 @@ -import { select } from 'd3-selection'; - -/** - * Setup a new parallel coordinates chart. - * - * @param config - * @param canvas - * @param ctx - * @returns {pc} a parcoords closure - */ -const init = (config, canvas, ctx) => { - /** - * Create the chart within a container. The selector can also be a d3 selection. - * - * @param selection a d3 selection - * @returns {pc} instance for chained api - */ - const pc = function(selection) { - selection = pc.selection = select(selection); - - config.width = selection.node().clientWidth; - config.height = selection.node().clientHeight; - // canvas data layers - ['marks', 'foreground', 'brushed', 'highlight'].forEach(layer => { - canvas[layer] = selection - .append('canvas') - .attr('class', layer) - .node(); - ctx[layer] = canvas[layer].getContext('2d'); - }); - - // svg tick and brush layers - pc.svg = selection - .append('svg') - .attr('width', config.width) - .attr('height', config.height) - .style('font', '14px sans-serif') - .style('position', 'absolute') - - .append('svg:g') - .attr( - 'transform', - 'translate(' + config.margin.left + ',' + config.margin.top + ')' - ); - // for chained api - return pc; - }; - - // for partial-application style programming - return pc; -}; - -export default init; diff --git a/src/parallelCoordinates/parcoords-es/api/interactive.js b/src/parallelCoordinates/parcoords-es/api/interactive.js deleted file mode 100644 index ef5d58d..0000000 --- a/src/parallelCoordinates/parcoords-es/api/interactive.js +++ /dev/null @@ -1,7 +0,0 @@ -const interactive = flags => - function() { - flags.interactive = true; - return this; - }; - -export default interactive; diff --git a/src/parallelCoordinates/parcoords-es/api/intersection.js b/src/parallelCoordinates/parcoords-es/api/intersection.js deleted file mode 100644 index f8b12d8..0000000 --- a/src/parallelCoordinates/parcoords-es/api/intersection.js +++ /dev/null @@ -1,16 +0,0 @@ -// calculate 2d intersection of line a->b with line c->d -// points are objects with x and y properties -const intersection = (a, b, c, d) => { - return { - x: - ((a.x * b.y - a.y * b.x) * (c.x - d.x) - - (a.x - b.x) * (c.x * d.y - c.y * d.x)) / - ((a.x - b.x) * (c.y - d.y) - (a.y - b.y) * (c.x - d.x)), - y: - ((a.x * b.y - a.y * b.x) * (c.y - d.y) - - (a.y - b.y) * (c.x * d.y - c.y * d.x)) / - ((a.x - b.x) * (c.y - d.y) - (a.y - b.y) * (c.x - d.x)), - }; -}; - -export default intersection; diff --git a/src/parallelCoordinates/parcoords-es/api/mergeParcoords.js b/src/parallelCoordinates/parcoords-es/api/mergeParcoords.js deleted file mode 100644 index 43ad51d..0000000 --- a/src/parallelCoordinates/parcoords-es/api/mergeParcoords.js +++ /dev/null @@ -1,56 +0,0 @@ -// Merges the canvases and SVG elements into one canvas element which is then passed into the callback -// (so you can choose to save it to disk, etc.) -const mergeParcoords = pc => callback => { - // Retina display, etc. - const devicePixelRatio = window.devicePixelRatio || 1; - - // Create a canvas element to store the merged canvases - const mergedCanvas = document.createElement('canvas'); - mergedCanvas.width = pc.canvas.foreground.clientWidth * devicePixelRatio; - mergedCanvas.height = - (pc.canvas.foreground.clientHeight + 30) * devicePixelRatio; - mergedCanvas.style.width = mergedCanvas.width / devicePixelRatio + 'px'; - mergedCanvas.style.height = mergedCanvas.height / devicePixelRatio + 'px'; - - // Give the canvas a white background - const context = mergedCanvas.getContext('2d'); - context.fillStyle = '#ffffff'; - context.fillRect(0, 0, mergedCanvas.width, mergedCanvas.height); - - // Merge all the canvases - for (const key in pc.canvas) { - context.drawImage( - pc.canvas[key], - 0, - 24 * devicePixelRatio, - mergedCanvas.width, - mergedCanvas.height - 30 * devicePixelRatio - ); - } - - // Add SVG elements to canvas - const DOMURL = window.URL || window.webkitURL || window; - const serializer = new XMLSerializer(); - const svgStr = serializer.serializeToString( - pc.selection.select('svg').node() - ); - - // Create a Data URI. - const src = 'data:image/svg+xml;base64,' + window.btoa(svgStr); - const img = new Image(); - img.onload = () => { - context.drawImage( - img, - 0, - 0, - img.width * devicePixelRatio, - img.height * devicePixelRatio - ); - if (typeof callback === 'function') { - callback(mergedCanvas); - } - }; - img.src = src; -}; - -export default mergeParcoords; diff --git a/src/parallelCoordinates/parcoords-es/api/removeAxes.js b/src/parallelCoordinates/parcoords-es/api/removeAxes.js deleted file mode 100644 index b299bce..0000000 --- a/src/parallelCoordinates/parcoords-es/api/removeAxes.js +++ /dev/null @@ -1,9 +0,0 @@ -const removeAxes = pc => - function() { - pc._g.remove(); - - delete pc._g; - return this; - }; - -export default removeAxes; diff --git a/src/parallelCoordinates/parcoords-es/api/render.js b/src/parallelCoordinates/parcoords-es/api/render.js deleted file mode 100644 index 68e576b..0000000 --- a/src/parallelCoordinates/parcoords-es/api/render.js +++ /dev/null @@ -1,28 +0,0 @@ -import { keys } from 'd3-collection'; - -/** - * Renders the polylines. - * If no dimensions have been specified, it will attempt to detect quantitative - * dimensions based on the first data entry. If scales haven't been set, it will - * autoscale based on the extent for each dimension. - * - * @param config - * @param pc - * @param events - * @returns {Function} - */ -const render = (config, pc, events) => - function() { - // try to autodetect dimensions and create scales - if (!keys(config.dimensions).length) { - pc.detectDimensions(); - } - pc.autoscale(); - - pc.render[config.mode](); - - events.call('render', this); - return this; - }; - -export default render; diff --git a/src/parallelCoordinates/parcoords-es/api/renderBrushed.js b/src/parallelCoordinates/parcoords-es/api/renderBrushed.js deleted file mode 100644 index 3467923..0000000 --- a/src/parallelCoordinates/parcoords-es/api/renderBrushed.js +++ /dev/null @@ -1,41 +0,0 @@ -import { keys } from 'd3-collection'; - -import isBrushed from '../util/isBrushed'; -import colorPath from '../util/colorPath'; -import functor from '../util/functor'; - -const pathBrushed = (config, ctx, position) => (d, i) => { - if (config.brushedColor !== null) { - ctx.brushed.strokeStyle = functor(config.brushedColor)(d, i); - } else { - ctx.brushed.strokeStyle = functor(config.color)(d, i); - } - return colorPath(config, position, d, ctx.brushed); -}; - -const renderBrushedDefault = (config, ctx, position, pc, brushGroup) => () => { - pc.clear('brushed'); - - if (isBrushed(config, brushGroup)) { - config.brushed.forEach(pathBrushed(config, ctx, position)); - } -}; - -const renderBrushedQueue = (config, brushGroup, brushedQueue) => () => { - if (isBrushed(config, brushGroup)) { - brushedQueue(config.brushed); - } else { - brushedQueue([]); // This is needed to clear the currently brushed items - } -}; - -const renderBrushed = (config, pc, events) => - function() { - if (!keys(config.dimensions).length) pc.detectDimensions(); - - pc.renderBrushed[config.mode](); - events.call('render', this); - return this; - }; - -export { pathBrushed, renderBrushed, renderBrushedDefault, renderBrushedQueue }; diff --git a/src/parallelCoordinates/parcoords-es/api/renderDefault.js b/src/parallelCoordinates/parcoords-es/api/renderDefault.js deleted file mode 100644 index bf78b19..0000000 --- a/src/parallelCoordinates/parcoords-es/api/renderDefault.js +++ /dev/null @@ -1,25 +0,0 @@ -import colorPath from '../util/colorPath'; -import functor from '../util/functor'; - -const pathForeground = (config, ctx, position) => (d, i) => { - ctx.foreground.strokeStyle = functor(config.color)(d, i); - return colorPath(config, position, d, ctx.foreground); -}; - -const renderDefault = (config, pc, ctx, position) => () => { - pc.clear('foreground'); - pc.clear('highlight'); - - pc.renderBrushed.default(); - - config.data.forEach(pathForeground(config, ctx, position)); -}; - -const renderDefaultQueue = (config, pc, foregroundQueue) => () => { - pc.renderBrushed.queue(); - foregroundQueue(config.data); -}; - -export default renderDefault; - -export { pathForeground, renderDefaultQueue }; diff --git a/src/parallelCoordinates/parcoords-es/api/reorder.js b/src/parallelCoordinates/parcoords-es/api/reorder.js deleted file mode 100644 index 338bf73..0000000 --- a/src/parallelCoordinates/parcoords-es/api/reorder.js +++ /dev/null @@ -1,32 +0,0 @@ -// Reorder dimensions, such that the highest value (visually) is on the left and -// the lowest on the right. Visual values are determined by the data values in -// the given row. -const reorder = (config, pc, xscale) => rowdata => { - const firstDim = pc.getOrderedDimensionKeys()[0]; - - pc.sortDimensionsByRowData(rowdata); - // NOTE: this is relatively cheap given that: - // number of dimensions < number of data items - // Thus we check equality of order to prevent rerendering when this is the case. - const reordered = firstDim !== pc.getOrderedDimensionKeys()[0]; - - if (reordered) { - xscale.domain(pc.getOrderedDimensionKeys()); - const highlighted = config.highlighted.slice(0); - pc.unhighlight(); - - const g = pc.g(); - g - .transition() - .duration(1500) - .attr('transform', d => 'translate(' + xscale(d) + ')'); - pc.render(); - - // pc.highlight() does not check whether highlighted is length zero, so we do that here. - if (highlighted.length !== 0) { - pc.highlight(highlighted); - } - } -}; - -export default reorder; diff --git a/src/parallelCoordinates/parcoords-es/api/reorderable.js b/src/parallelCoordinates/parcoords-es/api/reorderable.js deleted file mode 100644 index 142469d..0000000 --- a/src/parallelCoordinates/parcoords-es/api/reorderable.js +++ /dev/null @@ -1,40 +0,0 @@ -import { drag } from 'd3-drag'; -import { event, select } from 'd3-selection'; - -import w from '../util/width'; - -// Jason Davies, http://bl.ocks.org/1341281 -const reorderable = (config, pc, xscale, position, dragging, flags) => - function() { - if (pc.g() === undefined) pc.createAxes(); - const g = pc.g(); - - g.style('cursor', 'move').call( - drag() - .on('start', function(d) { - dragging[d] = this.__origin__ = xscale(d); - }) - .on('drag', function(d) { - dragging[d] = Math.min( - w(__), - Math.max(0, (this.__origin__ += event.dx)) - ); - pc.sortDimensions(); - xscale.domain(pc.getOrderedDimensionKeys()); - pc.render(); - g.attr('transform', d => 'translate(' + position(d) + ')'); - }) - .on('end', function(d) { - delete this.__origin__; - delete dragging[d]; - select(this) - .transition() - .attr('transform', 'translate(' + xscale(d) + ')'); - pc.render(); - }) - ); - flags.reorderable = true; - return this; - }; - -export default reorderable; diff --git a/src/parallelCoordinates/parcoords-es/api/resize.js b/src/parallelCoordinates/parcoords-es/api/resize.js deleted file mode 100644 index 090183f..0000000 --- a/src/parallelCoordinates/parcoords-es/api/resize.js +++ /dev/null @@ -1,36 +0,0 @@ -// rescale for height, width and margins -// TODO currently assumes chart is brushable, and destroys old brushes -const resize = (config, pc, flags, events) => { - return function() { - // selection size - pc.selection - .select('svg') - .attr('width', config.width) - .attr('height', config.height); - pc.svg.attr( - 'transform', - 'translate(' + config.margin.left + ',' + config.margin.top + ')' - ); - - // FIXME: the current brush state should pass through - if (flags.brushable) pc.brushReset(); - - // scales - pc.autoscale(); - - // axes, destroys old brushes. - if (pc.g()) pc.createAxes(); - if (flags.brushable) pc.brushable(); - if (flags.reorderable) pc.reorderable(); - - events.call('resize', this, { - width: config.width, - height: config.height, - margin: config.margin, - }); - - return this; - }; -}; - -export default resize; diff --git a/src/parallelCoordinates/parcoords-es/api/scale.js b/src/parallelCoordinates/parcoords-es/api/scale.js deleted file mode 100644 index 14f128c..0000000 --- a/src/parallelCoordinates/parcoords-es/api/scale.js +++ /dev/null @@ -1,8 +0,0 @@ -const scale = config => - function(d, domain) { - config.dimensions[d].yscale.domain(domain); - - return this; - }; - -export default scale; diff --git a/src/parallelCoordinates/parcoords-es/api/selected.js b/src/parallelCoordinates/parcoords-es/api/selected.js deleted file mode 100644 index c3b44f6..0000000 --- a/src/parallelCoordinates/parcoords-es/api/selected.js +++ /dev/null @@ -1,207 +0,0 @@ -import { brushSelection } from 'd3-brush'; -import { selectAll } from 'd3-selection'; - -const selected = config => { - let actives = []; - let extents = []; - let ranges = {}; - //get brush selections from each node, convert to actual values - //invert order of values in array to comply with the parcoords architecture - if (config.brushes.length === 0) { - let nodes = selectAll('.brush').nodes(); - for (let k = 0; k < nodes.length; k++) { - if (brushSelection(nodes[k]) !== null) { - actives.push(nodes[k].__data__); - let values = []; - let ranger = brushSelection(nodes[k]); - if ( - typeof config.dimensions[nodes[k].__data__].yscale.domain()[0] === - 'number' - ) { - for (let i = 0; i < ranger.length; i++) { - if ( - actives.includes(nodes[k].__data__) && - config.flipAxes.includes(nodes[k].__data__) - ) { - values.push( - config.dimensions[nodes[k].__data__].yscale.invert(ranger[i]) - ); - } else if (config.dimensions[nodes[k].__data__].yscale() !== 1) { - values.unshift( - config.dimensions[nodes[k].__data__].yscale.invert(ranger[i]) - ); - } - } - extents.push(values); - for (let ii = 0; ii < extents.length; ii++) { - if (extents[ii].length === 0) { - extents[ii] = [1, 1]; - } - } - } else { - ranges[nodes[k].__data__] = brushSelection(nodes[k]); - let dimRange = config.dimensions[nodes[k].__data__].yscale.range(); - let dimDomain = config.dimensions[nodes[k].__data__].yscale.domain(); - for (let j = 0; j < dimRange.length; j++) { - if ( - dimRange[j] >= ranger[0] && - dimRange[j] <= ranger[1] && - actives.includes(nodes[k].__data__) && - config.flipAxes.includes(nodes[k].__data__) - ) { - values.push(dimRange[j]); - } else if (dimRange[j] >= ranger[0] && dimRange[j] <= ranger[1]) { - values.unshift(dimRange[j]); - } - } - extents.push(values); - for (let ii = 0; ii < extents.length; ii++) { - if (extents[ii].length === 0) { - extents[ii] = [1, 1]; - } - } - } - } - } - // test if within range - const within = { - date: function(d, p, dimension) { - let category = d[p]; - let categoryIndex = config.dimensions[p].yscale - .domain() - .indexOf(category); - let categoryRangeValue = config.dimensions[p].yscale.range()[ - categoryIndex - ]; - return ( - categoryRangeValue >= ranges[p][0] && - categoryRangeValue <= ranges[p][1] - ); - }, - number: function(d, p, dimension) { - return extents[dimension][0] <= d[p] && d[p] <= extents[dimension][1]; - }, - string: function(d, p, dimension) { - let category = d[p]; - let categoryIndex = config.dimensions[p].yscale - .domain() - .indexOf(category); - let categoryRangeValue = config.dimensions[p].yscale.range()[ - categoryIndex - ]; - return ( - categoryRangeValue >= ranges[p][0] && - categoryRangeValue <= ranges[p][1] - ); - }, - }; - return config.data.filter(d => - actives.every((p, dimension) => - within[config.dimensions[p].type](d, p, dimension) - ) - ); - } else { - // need to get data from each brush instead of each axis - // first must find active axes by iterating through all brushes - // then go through similiar process as above. - let multiBrushData = []; - for (let idx = 0; idx < config.brushes.length; idx++) { - let brush = config.brushes[idx]; - let values = []; - let ranger = brush.extent; - let actives = [brush.data]; - if ( - typeof config.dimensions[brush.data].yscale.domain()[0] === 'number' - ) { - for (let i = 0; i < ranger.length; i++) { - if ( - actives.includes(brush.data) && - config.flipAxes.includes(brush.data) - ) { - values.push(config.dimensions[brush.data].yscale.invert(ranger[i])); - } else if (config.dimensions[brush.data].yscale() !== 1) { - values.unshift( - config.dimensions[brush.data].yscale.invert(ranger[i]) - ); - } - } - extents.push(values); - for (let ii = 0; ii < extents.length; ii++) { - if (extents[ii].length === 0) { - extents[ii] = [1, 1]; - } - } - } else { - ranges[brush.data] = brush.extent; - let dimRange = config.dimensions[brush.data].yscale.range(); - let dimDomain = config.dimensions[brush.data].yscale.domain(); - for (let j = 0; j < dimRange.length; j++) { - if ( - dimRange[j] >= ranger[0] && - dimRange[j] <= ranger[1] && - actives.includes(brush.data) && - config.flipAxes.includes(brush.data) - ) { - values.push(dimRange[j]); - } else if (dimRange[j] >= ranger[0] && dimRange[j] <= ranger[1]) { - values.unshift(dimRange[j]); - } - } - extents.push(values); - for (let ii = 0; ii < extents.length; ii++) { - if (extents[ii].length === 0) { - extents[ii] = [1, 1]; - } - } - } - let within = { - date: function(d, p, dimension) { - let category = d[p]; - let categoryIndex = config.dimensions[p].yscale - .domain() - .indexOf(category); - let categoryRangeValue = config.dimensions[p].yscale.range()[ - categoryIndex - ]; - return ( - categoryRangeValue >= ranges[p][0] && - categoryRangeValue <= ranges[p][1] - ); - }, - number: function(d, p, dimension) { - return extents[idx][0] <= d[p] && d[p] <= extents[idx][1]; - }, - string: function(d, p, dimension) { - let category = d[p]; - let categoryIndex = config.dimensions[p].yscale - .domain() - .indexOf(category); - let categoryRangeValue = config.dimensions[p].yscale.range()[ - categoryIndex - ]; - return ( - categoryRangeValue >= ranges[p][0] && - categoryRangeValue <= ranges[p][1] - ); - }, - }; - - // filter data, but instead of returning it now, - // put it into multiBrush data which is returned after - // all brushes are iterated through. - let filtered = config.data.filter(d => - actives.every((p, dimension) => - within[config.dimensions[p].type](d, p, dimension) - ) - ); - for (let z = 0; z < filtered.length; z++) { - multiBrushData.push(filtered[z]); - } - actives = []; - ranges = {}; - } - return multiBrushData; - } -}; - -export default selected; diff --git a/src/parallelCoordinates/parcoords-es/api/shadows.js b/src/parallelCoordinates/parcoords-es/api/shadows.js deleted file mode 100644 index ebb960e..0000000 --- a/src/parallelCoordinates/parcoords-es/api/shadows.js +++ /dev/null @@ -1,9 +0,0 @@ -const shadows = (flags, pc) => - function() { - flags.shadows = true; - pc.alphaOnBrushed(0.1); - pc.render(); - return this; - }; - -export default shadows; diff --git a/src/parallelCoordinates/parcoords-es/api/sortDimensions.js b/src/parallelCoordinates/parcoords-es/api/sortDimensions.js deleted file mode 100644 index 9c09989..0000000 --- a/src/parallelCoordinates/parcoords-es/api/sortDimensions.js +++ /dev/null @@ -1,15 +0,0 @@ -import { keys } from 'd3-collection'; - -const sortDimensions = (config, position) => () => { - const copy = Object.assign({}, config.dimensions); - const positionSortedKeys = keys(config.dimensions).sort( - (a, b) => (position(a) - position(b) === 0 ? 1 : position(a) - position(b)) - ); - config.dimensions = {}; - positionSortedKeys.forEach((p, i) => { - config.dimensions[p] = copy[p]; - config.dimensions[p].index = i; - }); -}; - -export default sortDimensions; diff --git a/src/parallelCoordinates/parcoords-es/api/sortDimensionsByRowData.js b/src/parallelCoordinates/parcoords-es/api/sortDimensionsByRowData.js deleted file mode 100644 index e277268..0000000 --- a/src/parallelCoordinates/parcoords-es/api/sortDimensionsByRowData.js +++ /dev/null @@ -1,22 +0,0 @@ -import { keys } from 'd3-collection'; - -const sortDimensionsByRowData = config => rowdata => { - const copy = Object.assign({}, config.dimensions); - const positionSortedKeys = keys(config.dimensions).sort((a, b) => { - const pixelDifference = - config.dimensions[a].yscale(rowdata[a]) - - config.dimensions[b].yscale(rowdata[b]); - - // Array.sort is not necessarily stable, this means that if pixelDifference is zero - // the ordering of dimensions might change unexpectedly. This is solved by sorting on - // variable name in that case. - return pixelDifference === 0 ? a.localeCompare(b) : pixelDifference; - }); - config.dimensions = {}; - positionSortedKeys.forEach((p, i) => { - config.dimensions[p] = copy[p]; - config.dimensions[p].index = i; - }); -}; - -export default sortDimensionsByRowData; diff --git a/src/parallelCoordinates/parcoords-es/api/toString.js b/src/parallelCoordinates/parcoords-es/api/toString.js deleted file mode 100644 index 6473124..0000000 --- a/src/parallelCoordinates/parcoords-es/api/toString.js +++ /dev/null @@ -1,16 +0,0 @@ -import { keys } from 'd3-collection'; - -// this descriptive text should live with other introspective methods -const toString = config => () => { - return ( - 'Parallel Coordinates: ' + - keys(config.dimensions).length + - ' dimensions (' + - keys(config.data[0]).length + - ' total) , ' + - config.data.length + - ' rows' - ); -}; - -export default toString; diff --git a/src/parallelCoordinates/parcoords-es/api/toType.js b/src/parallelCoordinates/parcoords-es/api/toType.js deleted file mode 100644 index a449858..0000000 --- a/src/parallelCoordinates/parcoords-es/api/toType.js +++ /dev/null @@ -1,9 +0,0 @@ -// a better "typeof" from this post: http://stackoverflow.com/questions/7390426/better-way-to-get-type-of-a-javascript-variable -const toType = v => { - return {}.toString - .call(v) - .match(/\s([a-zA-Z]+)/)[1] - .toLowerCase(); -}; - -export default toType; diff --git a/src/parallelCoordinates/parcoords-es/api/toTypeCoerceNumbers.js b/src/parallelCoordinates/parcoords-es/api/toTypeCoerceNumbers.js deleted file mode 100644 index c8ee371..0000000 --- a/src/parallelCoordinates/parcoords-es/api/toTypeCoerceNumbers.js +++ /dev/null @@ -1,7 +0,0 @@ -import toType from './toType'; - -// try to coerce to number before returning type -const toTypeCoerceNumbers = v => - parseFloat(v) == v && v != null ? 'number' : toType(v); - -export default toTypeCoerceNumbers; diff --git a/src/parallelCoordinates/parcoords-es/api/unhighlight.js b/src/parallelCoordinates/parcoords-es/api/unhighlight.js deleted file mode 100644 index ee73f97..0000000 --- a/src/parallelCoordinates/parcoords-es/api/unhighlight.js +++ /dev/null @@ -1,12 +0,0 @@ -import { selectAll } from 'd3-selection'; - -// clear highlighting -const unhighlight = (config, pc, canvas) => - function() { - config.highlighted = []; - pc.clear('highlight'); - selectAll([canvas.foreground, canvas.brushed]).classed('faded', false); - return this; - }; - -export default unhighlight; diff --git a/src/parallelCoordinates/parcoords-es/api/updateAxes.js b/src/parallelCoordinates/parcoords-es/api/updateAxes.js deleted file mode 100644 index 29bd448..0000000 --- a/src/parallelCoordinates/parcoords-es/api/updateAxes.js +++ /dev/null @@ -1,104 +0,0 @@ -import { select } from 'd3-selection'; - -import dimensionLabels from '../util/dimensionLabels'; -import flipAxisAndUpdatePCP from '../util/flipAxisAndUpdatePCP'; -import rotateLabels from '../util/rotateLabels'; - -const updateAxes = (config, pc, position, axis, flags) => ( - animationTime = null -) => { - if (animationTime === null) { - animationTime = config.animationTime; - } - - const g_data = pc.svg - .selectAll('.dimension') - .data(pc.getOrderedDimensionKeys()); - // Enter - g_data - .enter() - .append('svg:g') - .attr('class', 'dimension') - .attr('transform', p => 'translate(' + position(p) + ')') - .style('opacity', 0) - .append('svg:g') - .attr('class', 'axis') - .attr('transform', 'translate(0,0)') - .each(function(d) { - const axisElement = select(this).call( - pc.applyAxisConfig(axis, config.dimensions[d]) - ); - - axisElement - .selectAll('path') - .style('fill', 'none') - .style('stroke', '#222') - .style('shape-rendering', 'crispEdges'); - - axisElement - .selectAll('line') - .style('fill', 'none') - .style('stroke', '#222') - .style('shape-rendering', 'crispEdges'); - }) - .append('svg:text') - .attr({ - 'text-anchor': 'middle', - y: 0, - transform: - 'translate(0,-5) rotate(' + config.dimensionTitleRotation + ')', - x: 0, - class: 'label', - }) - .text(dimensionLabels(config)) - .on('dblclick', flipAxisAndUpdatePCP(config, pc, axis)) - .on('wheel', rotateLabels(config, pc)); - - // Update - g_data.attr('opacity', 0); - g_data - .select('.axis') - .transition() - .duration(animationTime) - .each(function(d) { - select(this).call(pc.applyAxisConfig(axis, config.dimensions[d])); - }); - g_data - .select('.label') - .transition() - .duration(animationTime) - .text(dimensionLabels(config)) - .attr( - 'transform', - 'translate(0,-5) rotate(' + config.dimensionTitleRotation + ')' - ); - - // Exit - g_data.exit().remove(); - - g = pc.svg.selectAll('.dimension'); - g - .transition() - .duration(animationTime) - .attr('transform', p => 'translate(' + position(p) + ')') - .style('opacity', 1); - - pc.svg - .selectAll('.axis') - .transition() - .duration(animationTime) - .each(function(d) { - select(this).call(pc.applyAxisConfig(axis, config.dimensions[d])); - }); - - if (flags.brushable) pc.brushable(); - if (flags.reorderable) pc.reorderable(); - if (pc.brushMode() !== 'None') { - let mode = pc.brushMode(); - pc.brushMode('None'); - pc.brushMode(mode); - } - return this; -}; - -export default updateAxes; diff --git a/src/parallelCoordinates/parcoords-es/bindEvents.js b/src/parallelCoordinates/parcoords-es/bindEvents.js deleted file mode 100644 index a11aa7c..0000000 --- a/src/parallelCoordinates/parcoords-es/bindEvents.js +++ /dev/null @@ -1,57 +0,0 @@ -// side effects for setters -import sideEffects from './state/sideEffects'; -import getset from './util/getset'; - -const d3_rebind = (target, source, method) => - function() { - const value = method.apply(source, arguments); - return value === source ? target : value; - }; - -const _rebind = (target, source, method) => { - target[method] = d3_rebind(target, source, source[method]); - return target; -}; - -const bindEvents = ( - __, - ctx, - pc, - xscale, - flags, - brushedQueue, - foregroundQueue, - events, - axis -) => { - const side_effects = sideEffects( - __, - ctx, - pc, - xscale, - flags, - brushedQueue, - foregroundQueue - ); - - // create getter/setters - getset(pc, __, events, side_effects, pc); - - // expose events - // getter/setter with event firing - _rebind(pc, events, 'on'); - - _rebind( - pc, - axis, - 'ticks', - 'orient', - 'tickValues', - 'tickSubdivide', - 'tickSize', - 'tickPadding', - 'tickFormat' - ); -}; - -export default bindEvents; diff --git a/src/parallelCoordinates/parcoords-es/brush/1d/brushExtents.js b/src/parallelCoordinates/parcoords-es/brush/1d/brushExtents.js deleted file mode 100644 index 7491bc0..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/1d/brushExtents.js +++ /dev/null @@ -1,60 +0,0 @@ -import { keys } from 'd3-collection'; -import { select } from 'd3-selection'; -import { brushSelection } from 'd3-brush'; - -const brushExtents = (state, config, pc) => extents => { - const { brushes, brushNodes } = state; - - if (typeof extents === 'undefined') { - return keys(config.dimensions).reduce((acc, cur) => { - const brush = brushes[cur]; - //todo: brush check - if (brush !== undefined && brushSelection(brushNodes[cur]) !== null) { - acc[d] = brush.extent(); - } - - return acc; - }, {}); - } else { - //first get all the brush selections - const brushSelections = {}; - pc - .g() - .selectAll('.brush') - .each(function(d) { - brushSelections[d] = select(this); - }); - - // loop over each dimension and update appropriately (if it was passed in through extents) - keys(config.dimensions).forEach(d => { - if (extents[d] === undefined) { - return; - } - - const brush = brushes[d]; - if (brush !== undefined) { - const dim = config.dimensions[d]; - const yExtent = extents[d].map(dim.yscale); - - //update the extent - //sets the brushable extent to the specified array of points [[x0, y0], [x1, y1]] - brush.extent([[-15, yExtent[1]], [15, yExtent[0]]]); - - //redraw the brush - //https://github.com/d3/d3-brush#brush_move - // For an x-brush, it must be defined as [x0, x1]; for a y-brush, it must be defined as [y0, y1]. - brushSelections[d].call(brush).call(brush.move, yExtent.reverse()); - - //fire some events - // brush.event(brushSelections[d]); - } - }); - - //redraw the chart - pc.renderBrushed(); - - return pc; - } -}; - -export default brushExtents; diff --git a/src/parallelCoordinates/parcoords-es/brush/1d/brushFor.js b/src/parallelCoordinates/parcoords-es/brush/1d/brushFor.js deleted file mode 100644 index d468df5..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/1d/brushFor.js +++ /dev/null @@ -1,46 +0,0 @@ -import { brushY } from 'd3-brush'; -import { event } from 'd3-selection'; - -import selected from './selected'; - -const brushUpdated = (config, pc, events) => newSelection => { - config.brushed = newSelection; - events.call('brush', pc, config.brushed); - pc.renderBrushed(); -}; - -const brushFor = (state, config, pc, events, brushGroup) => ( - axis, - _selector -) => { - const brushRangeMax = - config.dimensions[axis].type === 'string' - ? config.dimensions[axis].yscale.range()[ - config.dimensions[axis].yscale.range().length - 1 - ] - : config.dimensions[axis].yscale.range()[0]; - - const _brush = brushY(_selector).extent([[-15, 0], [15, brushRangeMax]]); - - _brush - .on('start', function() { - if (event.sourceEvent !== null) { - events.call('brushstart', pc, config.brushed); - event.sourceEvent.stopPropagation(); - } - }) - .on('brush', function() { - brushUpdated(config, pc, events)(selected(state, config, brushGroup)()); - }) - .on('end', function() { - brushUpdated(config, pc, events)(selected(state, config, brushGroup)()); - events.call('brushend', pc, config.brushed); - }); - - state.brushes[axis] = _brush; - state.brushNodes[axis] = _selector.node(); - - return _brush; -}; - -export default brushFor; diff --git a/src/parallelCoordinates/parcoords-es/brush/1d/brushReset.js b/src/parallelCoordinates/parcoords-es/brush/1d/brushReset.js deleted file mode 100644 index 91254dc..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/1d/brushReset.js +++ /dev/null @@ -1,33 +0,0 @@ -import { select } from 'd3-selection'; - -const brushReset = (state, config, pc) => dimension => { - const { brushes } = state; - - if (dimension === undefined) { - config.brushed = false; - if (pc.g() !== undefined && pc.g() !== null) { - pc - .g() - .selectAll('.brush') - .each(function(d) { - select(this).call(brushes[d].move, null); - }); - pc.renderBrushed(); - } - } else { - if (pc.g() !== undefined && pc.g() !== null) { - pc - .g() - .selectAll('.brush') - .each(function(d) { - if (d != dimension) return; - select(this).call(brushes[d].move, null); - brushes[d].event(select(this)); - }); - pc.renderBrushed(); - } - } - return this; -}; - -export default brushReset; diff --git a/src/parallelCoordinates/parcoords-es/brush/1d/index.js b/src/parallelCoordinates/parcoords-es/brush/1d/index.js deleted file mode 100644 index cea9fa2..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/1d/index.js +++ /dev/null @@ -1,22 +0,0 @@ -import brushExtents from './brushExtents'; -import install from './install'; -import selected from './selected'; -import uninstall from './uninstall'; - -const BrushState = { - brushes: {}, - brushNodes: {}, -}; - -const install1DAxes = (brushGroup, config, pc, events) => { - const state = Object.assign({}, BrushState); - - brushGroup.modes['1D-axes'] = { - install: install(state, config, pc, events, brushGroup), - uninstall: uninstall(state, pc), - selected: selected(state, config, brushGroup), - brushState: brushExtents(state, config, pc), - }; -}; - -export default install1DAxes; diff --git a/src/parallelCoordinates/parcoords-es/brush/1d/install.js b/src/parallelCoordinates/parcoords-es/brush/1d/install.js deleted file mode 100644 index f51875f..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/1d/install.js +++ /dev/null @@ -1,41 +0,0 @@ -import { select } from 'd3-selection'; -import brushExtents from './brushExtents'; -import brushReset from './brushReset'; -import brushFor from './brushFor'; - -const install = (state, config, pc, events, brushGroup) => () => { - if (!pc.g()) { - pc.createAxes(); - } - - // Add and store a brush for each axis. - const brush = pc - .g() - .append('svg:g') - .attr('class', 'brush') - .each(function(d) { - select(this).call( - brushFor(state, config, pc, events, brushGroup)(d, select(this)) - ); - }); - brush - .selectAll('rect') - .style('visibility', null) - .attr('x', -15) - .attr('width', 30); - - brush.selectAll('rect.background').style('fill', 'transparent'); - - brush - .selectAll('rect.extent') - .style('fill', 'rgba(255,255,255,0.25)') - .style('stroke', 'rgba(0,0,0,0.6)'); - - brush.selectAll('.resize rect').style('fill', 'rgba(0,0,0,0.1)'); - - pc.brushExtents = brushExtents(state, config, pc); - pc.brushReset = brushReset(state, config, pc); - return pc; -}; - -export default install; diff --git a/src/parallelCoordinates/parcoords-es/brush/1d/selected.js b/src/parallelCoordinates/parcoords-es/brush/1d/selected.js deleted file mode 100644 index d71813c..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/1d/selected.js +++ /dev/null @@ -1,79 +0,0 @@ -import { brushSelection } from 'd3-brush'; -//https://github.com/d3/d3-brush/issues/10 -import { keys } from 'd3-collection'; - -// data within extents -const selected = (state, config, brushGroup) => () => { - const { brushNodes } = state; - const is_brushed = p => brushSelection(brushNodes[p]) !== null; - - const actives = keys(config.dimensions).filter(is_brushed); - const extents = actives.map(p => { - const _brushRange = brushSelection(brushNodes[p]); - - if (typeof config.dimensions[p].yscale.invert === 'function') { - return [ - config.dimensions[p].yscale.invert(_brushRange[1]), - config.dimensions[p].yscale.invert(_brushRange[0]), - ]; - } else { - return _brushRange; - } - }); - // We don't want to return the full data set when there are no axes brushed. - // Actually, when there are no axes brushed, by definition, no items are - // selected. So, let's avoid the filtering and just return false. - //if (actives.length === 0) return false; - - // Resolves broken examples for now. They expect to get the full dataset back from empty brushes - if (actives.length === 0) return config.data; - - // test if within range - const within = { - date: (d, p, dimension) => { - if (typeof config.dimensions[p].yscale.bandwidth === 'function') { - // if it is ordinal - return ( - extents[dimension][0] <= config.dimensions[p].yscale(d[p]) && - config.dimensions[p].yscale(d[p]) <= extents[dimension][1] - ); - } else { - return extents[dimension][0] <= d[p] && d[p] <= extents[dimension][1]; - } - }, - number: (d, p, dimension) => { - if (typeof config.dimensions[p].yscale.bandwidth === 'function') { - // if it is ordinal - return ( - extents[dimension][0] <= config.dimensions[p].yscale(d[p]) && - config.dimensions[p].yscale(d[p]) <= extents[dimension][1] - ); - } else { - return extents[dimension][0] <= d[p] && d[p] <= extents[dimension][1]; - } - }, - string: (d, p, dimension) => { - return ( - extents[dimension][0] <= config.dimensions[p].yscale(d[p]) && - config.dimensions[p].yscale(d[p]) <= extents[dimension][1] - ); - }, - }; - - return config.data.filter(d => { - switch (brushGroup.predicate) { - case 'AND': - return actives.every(function(p, dimension) { - return within[config.dimensions[p].type](d, p, dimension); - }); - case 'OR': - return actives.some(function(p, dimension) { - return within[config.dimensions[p].type](d, p, dimension); - }); - default: - throw new Error('Unknown brush predicate ' + config.brushPredicate); - } - }); -}; - -export default selected; diff --git a/src/parallelCoordinates/parcoords-es/brush/1d/uninstall.js b/src/parallelCoordinates/parcoords-es/brush/1d/uninstall.js deleted file mode 100644 index a39dedc..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/1d/uninstall.js +++ /dev/null @@ -1,13 +0,0 @@ -const uninstall = (state, pc) => () => { - if (pc.g() !== undefined && pc.g() !== null) - pc - .g() - .selectAll('.brush') - .remove(); - - state.brushes = {}; - delete pc.brushExtents; - delete pc.brushReset; -}; - -export default uninstall; diff --git a/src/parallelCoordinates/parcoords-es/brush/angular/brushReset.js b/src/parallelCoordinates/parcoords-es/brush/angular/brushReset.js deleted file mode 100644 index 994e616..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/angular/brushReset.js +++ /dev/null @@ -1,14 +0,0 @@ -import onDragEnd from './onDragEnd'; -import removeStrum from './removeStrum'; - -const brushReset = (brushGroup, state, config, pc, events) => () => { - const ids = Object.getOwnPropertyNames(state.arcs).filter(d => !isNaN(d)); - - ids.forEach(d => { - state.arcs.active = d; - removeStrum(state, pc); - }); - onDragEnd(brushGroup, state, config, pc, events)(); -}; - -export default brushReset; diff --git a/src/parallelCoordinates/parcoords-es/brush/angular/index.js b/src/parallelCoordinates/parcoords-es/brush/angular/index.js deleted file mode 100644 index 3a9453e..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/angular/index.js +++ /dev/null @@ -1,21 +0,0 @@ -import uninstall from './uninstall'; -import install from './install'; -import selected from './selected'; - -const BrushState = { - arcs: {}, - strumRect: {}, -}; - -const installAngularBrush = (brushGroup, config, pc, events, xscale) => { - const state = Object.assign({}, BrushState); - - brushGroup.modes['angular'] = { - install: install(brushGroup, state, config, pc, events, xscale), - uninstall: uninstall(state, pc), - selected: selected(brushGroup, state, config), - brushState: () => state.arcs, - }; -}; - -export default installAngularBrush; diff --git a/src/parallelCoordinates/parcoords-es/brush/angular/install.js b/src/parallelCoordinates/parcoords-es/brush/angular/install.js deleted file mode 100644 index d955a05..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/angular/install.js +++ /dev/null @@ -1,141 +0,0 @@ -import { drag } from 'd3-drag'; -import onDragEnd from './onDragEnd'; -import onDrag from './onDrag'; -import onDragStart from './onDragStart'; -import removeStrum from './removeStrum'; -import brushReset from './brushReset'; -import w from '../../util/width'; -import h from '../../util/height'; - -import hypothenuse from './util/hypothenuse'; -import consecutive from '../consecutive'; - -// returns angles in [-PI/2, PI/2] -const angle = (p1, p2) => { - const a = p1[0] - p2[0], - b = p1[1] - p2[1], - c = hypothenuse(a, b); - - return Math.asin(b / c); -}; - -const endAngle = state => id => { - const arc = state.arcs[id]; - if (arc === undefined) { - return undefined; - } - let sAngle = angle(arc.p1, arc.p2), - uAngle = -sAngle + Math.PI / 2; - - if (arc.p1[0] > arc.p2[0]) { - uAngle = 2 * Math.PI - uAngle; - } - - return uAngle; -}; - -const startAngle = state => id => { - const arc = state.arcs[id]; - if (arc === undefined) { - return undefined; - } - - let sAngle = angle(arc.p1, arc.p3), - uAngle = -sAngle + Math.PI / 2; - - if (arc.p1[0] > arc.p3[0]) { - uAngle = 2 * Math.PI - uAngle; - } - - return uAngle; -}; - -const length = state => id => { - const arc = state.arcs[id]; - - if (arc === undefined) { - return undefined; - } - - const a = arc.p1[0] - arc.p2[0], - b = arc.p1[1] - arc.p2[1]; - - return hypothenuse(a, b); -}; - -const install = (brushGroup, state, config, pc, events, xscale) => () => { - if (!pc.g()) { - pc.createAxes(); - } - - const _drag = drag(); - - // Map of current arcs. arcs are stored per segment of the PC. A segment, - // being the area between two axes. The left most area is indexed at 0. - state.arcs.active = undefined; - // Returns the width of the PC segment where currently a arc is being - // placed. NOTE: even though they are evenly spaced in our current - // implementation, we keep for when non-even spaced segments are supported as - // well. - state.arcs.width = id => { - const arc = state.arcs[id]; - return arc === undefined ? undefined : arc.maxX - arc.minX; - }; - - // returns angles in [0, 2 * PI] - state.arcs.endAngle = endAngle(state); - state.arcs.startAngle = startAngle(state); - state.arcs.length = length(state); - - pc.on('axesreorder.arcs', () => { - const ids = Object.getOwnPropertyNames(arcs).filter(d => !isNaN(d)); - - if (ids.length > 0) { - // We have some arcs, which might need to be removed. - ids.forEach(d => { - const dims = arcs[d].dims; - state.arcs.active = d; - // If the two dimensions of the current arc are not next to each other - // any more, than we'll need to remove the arc. Otherwise we keep it. - if (!consecutive(dims)(dims.left, dims.right)) { - removeStrum(state, pc); - } - }); - onDragEnd(brushGroup, state, config, pc, events)(); - } - }); - - // Add a new svg group in which we draw the arcs. - pc.selection - .select('svg') - .append('g') - .attr('id', 'arcs') - .attr( - 'transform', - 'translate(' + config.margin.left + ',' + config.margin.top + ')' - ); - - // Install the required brushReset function - pc.brushReset = brushReset(brushGroup, state, config, pc, events); - - _drag - .on('start', onDragStart(state, config, pc, xscale)) - .on('drag', onDrag(brushGroup, state, config, pc, events)) - .on('end', onDragEnd(brushGroup, state, config, pc, events)); - - // NOTE: The styling needs to be done here and not in the css. This is because - // for 1D brushing, the canvas layers should not listen to - // pointer-events._. - state.strumRect = pc.selection - .select('svg') - .insert('rect', 'g#arcs') - .attr('id', 'arc-events') - .attr('x', config.margin.left) - .attr('y', config.margin.top) - .attr('width', w(config)) - .attr('height', h(config) + 2) - .style('opacity', 0) - .call(_drag); -}; - -export default install; diff --git a/src/parallelCoordinates/parcoords-es/brush/angular/onDrag.js b/src/parallelCoordinates/parcoords-es/brush/angular/onDrag.js deleted file mode 100644 index 2cd644d..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/angular/onDrag.js +++ /dev/null @@ -1,111 +0,0 @@ -import { event, select } from 'd3-selection'; -import { drag } from 'd3-drag'; -import onDragEnd from './onDragEnd'; - -const drawStrum = (brushGroup, state, config, pc, events, arc, activePoint) => { - const svg = pc.selection.select('svg').select('g#arcs'), - id = arc.dims.i, - points = [arc.p2, arc.p3], - _line = svg - .selectAll('line#arc-' + id) - .data([{ p1: arc.p1, p2: arc.p2 }, { p1: arc.p1, p2: arc.p3 }]), - circles = svg.selectAll('circle#arc-' + id).data(points), - _drag = drag(), - _path = svg.selectAll('path#arc-' + id).data([arc]); - - _path - .enter() - .append('path') - .attr('id', 'arc-' + id) - .attr('class', 'arc') - .style('fill', 'orange') - .style('opacity', 0.5); - - _path - .attr('d', arc.arc) - .attr('transform', 'translate(' + arc.p1[0] + ',' + arc.p1[1] + ')'); - - _line - .enter() - .append('line') - .attr('id', 'arc-' + id) - .attr('class', 'arc'); - - _line - .attr('x1', d => d.p1[0]) - .attr('y1', d => d.p1[1]) - .attr('x2', d => d.p2[0]) - .attr('y2', d => d.p2[1]) - .attr('stroke', 'black') - .attr('stroke-width', 2); - - _drag - .on('drag', (d, i) => { - const ev = event; - i = i + 2; - - arc['p' + i][0] = Math.min(Math.max(arc.minX + 1, ev.x), arc.maxX); - arc['p' + i][1] = Math.min(Math.max(arc.minY, ev.y), arc.maxY); - - const angle = - i === 3 ? state.arcs.startAngle(id) : state.arcs.endAngle(id); - - if ( - (arc.startAngle < Math.PI && - arc.endAngle < Math.PI && - angle < Math.PI) || - (arc.startAngle >= Math.PI && - arc.endAngle >= Math.PI && - angle >= Math.PI) - ) { - if (i === 2) { - arc.endAngle = angle; - arc.arc.endAngle(angle); - } else if (i === 3) { - arc.startAngle = angle; - arc.arc.startAngle(angle); - } - } - - drawStrum(brushGroup, state, config, pc, events, arc, i - 2); - }) - .on('end', onDragEnd(brushGroup, state, config, pc, events)); - - circles - .enter() - .append('circle') - .attr('id', 'arc-' + id) - .attr('class', 'arc'); - - circles - .attr('cx', d => d[0]) - .attr('cy', d => d[1]) - .attr('r', 5) - .style( - 'opacity', - (d, i) => (activePoint !== undefined && i === activePoint ? 0.8 : 0) - ) - .on('mouseover', function() { - select(this).style('opacity', 0.8); - }) - .on('mouseout', function() { - select(this).style('opacity', 0); - }) - .call(_drag); -}; - -const onDrag = (brushGroup, state, config, pc, events) => () => { - const ev = event, - arc = state.arcs[state.arcs.active]; - - // Make sure that the point is within the bounds - arc.p2[0] = Math.min( - Math.max(arc.minX + 1, ev.x - config.margin.left), - arc.maxX - ); - arc.p2[1] = Math.min(Math.max(arc.minY, ev.y - config.margin.top), arc.maxY); - arc.p3 = arc.p2.slice(); - drawStrum(brushGroup, state, config, pc, events, arc, 1); -}; - -export default onDrag; diff --git a/src/parallelCoordinates/parcoords-es/brush/angular/onDragEnd.js b/src/parallelCoordinates/parcoords-es/brush/angular/onDragEnd.js deleted file mode 100644 index 4b2a318..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/angular/onDragEnd.js +++ /dev/null @@ -1,30 +0,0 @@ -import selected from './selected'; -import removeStrum from './removeStrum'; - -const onDragEnd = (brushGroup, state, config, pc, events) => () => { - const arc = state.arcs[state.arcs.active]; - - // Okay, somewhat unexpected, but not totally unsurprising, a mousclick is - // considered a drag without move. So we have to deal with that case - if (arc && arc.p1[0] === arc.p2[0] && arc.p1[1] === arc.p2[1]) { - removeStrum(state, pc); - } - - if (arc) { - const angle = state.arcs.startAngle(state.arcs.active); - - arc.startAngle = angle; - arc.endAngle = angle; - arc.arc - .outerRadius(state.arcs.length(state.arcs.active)) - .startAngle(angle) - .endAngle(angle); - } - - state.arcs.active = undefined; - config.brushed = selected(brushGroup, state, config); - pc.renderBrushed(); - events.call('brushend', pc, config.brushed); -}; - -export default onDragEnd; diff --git a/src/parallelCoordinates/parcoords-es/brush/angular/onDragStart.js b/src/parallelCoordinates/parcoords-es/brush/angular/onDragStart.js deleted file mode 100644 index 87ebaa4..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/angular/onDragStart.js +++ /dev/null @@ -1,38 +0,0 @@ -import { mouse } from 'd3-selection'; -import h from '../../util/height'; -import { arc as d3Arc } from 'd3-shape'; -import dimensionsForPoint from '../dimensionsForPoint'; - -// First we need to determine between which two axes the arc was started. -// This will determine the freedom of movement, because a arc can -// logically only happen between two axes, so no movement outside these axes -// should be allowed. -const onDragStart = (state, config, pc, xscale) => () => { - const p = mouse(state.strumRect.node()); - - p[0] = p[0] - config.margin.left; - p[1] = p[1] - config.margin.top; - - const dims = dimensionsForPoint(config, pc, xscale, p); - const arc = { - p1: p, - dims: dims, - minX: xscale(dims.left), - maxX: xscale(dims.right), - minY: 0, - maxY: h(config), - startAngle: undefined, - endAngle: undefined, - arc: d3Arc().innerRadius(0), - }; - - // Make sure that the point is within the bounds - arc.p1[0] = Math.min(Math.max(arc.minX, p[0]), arc.maxX); - arc.p2 = arc.p1.slice(); - arc.p3 = arc.p1.slice(); - - state.arcs[dims.i] = arc; - state.arcs.active = dims.i; -}; - -export default onDragStart; diff --git a/src/parallelCoordinates/parcoords-es/brush/angular/removeStrum.js b/src/parallelCoordinates/parcoords-es/brush/angular/removeStrum.js deleted file mode 100644 index af9df4e..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/angular/removeStrum.js +++ /dev/null @@ -1,12 +0,0 @@ -const removeStrum = (state, pc) => { - const arc = state.arcs[state.arcs.active], - svg = pc.selection.select('svg').select('g#arcs'); - - delete state.arcs[state.arcs.active]; - state.arcs.active = undefined; - svg.selectAll('line#arc-' + arc.dims.i).remove(); - svg.selectAll('circle#arc-' + arc.dims.i).remove(); - svg.selectAll('path#arc-' + arc.dims.i).remove(); -}; - -export default removeStrum; diff --git a/src/parallelCoordinates/parcoords-es/brush/angular/selected.js b/src/parallelCoordinates/parcoords-es/brush/angular/selected.js deleted file mode 100644 index 528e30c..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/angular/selected.js +++ /dev/null @@ -1,63 +0,0 @@ -import hypothenuse from './util/hypothenuse'; - -// [0, 2*PI] -> [-PI/2, PI/2] -const signedAngle = angle => - angle > Math.PI ? 1.5 * Math.PI - angle : 0.5 * Math.PI - angle; - -/** - * angles are stored in radians from in [0, 2*PI], where 0 in 12 o'clock. - * However, one can only select lines from 0 to PI, so we compute the - * 'signed' angle, where 0 is the horizontal line (3 o'clock), and +/- PI/2 - * are 12 and 6 o'clock respectively. - */ -const containmentTest = arc => a => { - let startAngle = signedAngle(arc.startAngle); - let endAngle = signedAngle(arc.endAngle); - - if (startAngle > endAngle) { - const tmp = startAngle; - startAngle = endAngle; - endAngle = tmp; - } - - // test if segment angle is contained in angle interval - return a >= startAngle && a <= endAngle; -}; - -const crossesStrum = (state, config) => (d, id) => { - const arc = state.arcs[id], - test = containmentTest(arc), - d1 = arc.dims.left, - d2 = arc.dims.right, - y1 = config.dimensions[d1].yscale, - y2 = config.dimensions[d2].yscale, - a = state.arcs.width(id), - b = y1(d[d1]) - y2(d[d2]), - c = hypothenuse(a, b), - angle = Math.asin(b / c); // rad in [-PI/2, PI/2] - return test(angle); -}; - -const selected = (brushGroup, state, config) => { - const ids = Object.getOwnPropertyNames(state.arcs).filter(d => !isNaN(d)); - const brushed = config.data; - - if (ids.length === 0) { - return brushed; - } - - const crossTest = crossesStrum(state, config); - - return brushed.filter(d => { - switch (brushGroup.predicate) { - case 'AND': - return ids.every(id => crossTest(d, id)); - case 'OR': - return ids.some(id => crossTest(d, id)); - default: - throw new Error('Unknown brush predicate ' + config.brushPredicate); - } - }); -}; - -export default selected; diff --git a/src/parallelCoordinates/parcoords-es/brush/angular/uninstall.js b/src/parallelCoordinates/parcoords-es/brush/angular/uninstall.js deleted file mode 100644 index 490ada7..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/angular/uninstall.js +++ /dev/null @@ -1,17 +0,0 @@ -const uninstall = (state, pc) => () => { - pc.selection - .select('svg') - .select('g#arcs') - .remove(); - pc.selection - .select('svg') - .select('rect#arc-events') - .remove(); - pc.on('axesreorder.arcs', undefined); - - delete pc.brushReset; - - state.strumRect = undefined; -}; - -export default uninstall; diff --git a/src/parallelCoordinates/parcoords-es/brush/angular/util/hypothenuse.js b/src/parallelCoordinates/parcoords-es/brush/angular/util/hypothenuse.js deleted file mode 100644 index 4ae92c5..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/angular/util/hypothenuse.js +++ /dev/null @@ -1,3 +0,0 @@ -const hypothenuse = (a, b) => Math.sqrt(a * a + b * b); - -export default hypothenuse; diff --git a/src/parallelCoordinates/parcoords-es/brush/consecutive.js b/src/parallelCoordinates/parcoords-es/brush/consecutive.js deleted file mode 100644 index 96332b5..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/consecutive.js +++ /dev/null @@ -1,13 +0,0 @@ -// Checks if the first dimension is directly left of the second dimension. -import { keys } from 'd3-collection'; - -const consecutive = dimensions => (first, second) => { - const keys = keys(dimensions); - - return keys.some( - (d, i) => - d === first ? i + i < keys.length && dimensions[i + 1] === second : false - ); -}; - -export default consecutive; diff --git a/src/parallelCoordinates/parcoords-es/brush/dimensionsForPoint.js b/src/parallelCoordinates/parcoords-es/brush/dimensionsForPoint.js deleted file mode 100644 index 5c53694..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/dimensionsForPoint.js +++ /dev/null @@ -1,34 +0,0 @@ -import { keys } from 'd3-collection'; - -const dimensionsForPoint = (config, pc, xscale, p) => { - const dims = { i: -1, left: undefined, right: undefined }; - keys(config.dimensions).some((dim, i) => { - if (xscale(dim) < p[0]) { - dims.i = i; - dims.left = dim; - dims.right = keys(config.dimensions)[ - pc.getOrderedDimensionKeys().indexOf(dim) + 1 - ]; - return false; - } - return true; - }); - - if (dims.left === undefined) { - // Event on the left side of the first axis. - dims.i = 0; - dims.left = pc.getOrderedDimensionKeys()[0]; - dims.right = pc.getOrderedDimensionKeys()[1]; - } else if (dims.right === undefined) { - // Event on the right side of the last axis - dims.i = keys(config.dimensions).length - 1; - dims.right = dims.left; - dims.left = pc.getOrderedDimensionKeys()[ - keys(config.dimensions).length - 2 - ]; - } - - return dims; -}; - -export default dimensionsForPoint; diff --git a/src/parallelCoordinates/parcoords-es/brush/strums/brushReset.js b/src/parallelCoordinates/parcoords-es/brush/strums/brushReset.js deleted file mode 100644 index 988c440..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/strums/brushReset.js +++ /dev/null @@ -1,14 +0,0 @@ -import onDragEnd from './onDragEnd'; -import removeStrum from './removeStrum'; - -const brushReset = (brushGroup, state, config, pc, events) => () => { - const ids = Object.getOwnPropertyNames(state.strums).filter(d => !isNaN(d)); - - ids.forEach(d => { - state.strums.active = d; - removeStrum(state, pc); - }); - onDragEnd(brushGroup, state, config, pc, events)(); -}; - -export default brushReset; diff --git a/src/parallelCoordinates/parcoords-es/brush/strums/index.js b/src/parallelCoordinates/parcoords-es/brush/strums/index.js deleted file mode 100644 index d538d03..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/strums/index.js +++ /dev/null @@ -1,21 +0,0 @@ -import uninstall from './uninstall'; -import install from './install'; -import selected from './selected'; - -const BrushState = { - strums: {}, - strumRect: {}, -}; - -const install2DStrums = (brushGroup, config, pc, events, xscale) => { - const state = Object.assign({}, BrushState); - - brushGroup.modes['2D-strums'] = { - install: install(brushGroup, state, config, pc, events, xscale), - uninstall: uninstall(state, pc), - selected: selected(brushGroup, state, config), - brushState: () => state.strums, - }; -}; - -export default install2DStrums; diff --git a/src/parallelCoordinates/parcoords-es/brush/strums/install.js b/src/parallelCoordinates/parcoords-es/brush/strums/install.js deleted file mode 100644 index 6e74a3a..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/strums/install.js +++ /dev/null @@ -1,81 +0,0 @@ -import { drag } from 'd3-drag'; -import onDragEnd from './onDragEnd'; -import onDrag from './onDrag'; -import onDragStart from './onDragStart'; -import removeStrum from './removeStrum'; -import brushReset from './brushReset'; -import w from '../../util/width'; -import h from '../../util/height'; -import consecutive from '../consecutive'; - -const install = (brushGroup, state, config, pc, events, xscale) => () => { - if (pc.g() === undefined || pc.g() === null) { - pc.createAxes(); - } - - const _drag = drag(); - - // Map of current strums. Strums are stored per segment of the PC. A segment, - // being the area between two axes. The left most area is indexed at 0. - state.strums.active = undefined; - // Returns the width of the PC segment where currently a strum is being - // placed. NOTE: even though they are evenly spaced in our current - // implementation, we keep for when non-even spaced segments are supported as - // well. - state.strums.width = id => - state.strums[id] === undefined - ? undefined - : state.strums[id].maxX - state.strums[id].minX; - - pc.on('axesreorder.strums', () => { - const ids = Object.getOwnPropertyNames(state.strums).filter(d => !isNaN(d)); - - if (ids.length > 0) { - // We have some strums, which might need to be removed. - ids.forEach(d => { - const dims = state.strums[d].dims; - state.strums.active = d; - // If the two dimensions of the current strum are not next to each other - // any more, than we'll need to remove the strum. Otherwise we keep it. - if (!consecutive(config.dimensions)(dims.left, dims.right)) { - removeStrum(state, pc); - } - }); - onDragEnd(brushGroup, state, config, pc, events)(); - } - }); - - // Add a new svg group in which we draw the strums. - pc.selection - .select('svg') - .append('g') - .attr('id', 'strums') - .attr( - 'transform', - 'translate(' + config.margin.left + ',' + config.margin.top + ')' - ); - - // Install the required brushReset function - pc.brushReset = brushReset(brushGroup, state, config, pc, events); - - _drag - .on('start', onDragStart(state, config, pc, xscale)) - .on('drag', onDrag(brushGroup, state, config, pc, events)) - .on('end', onDragEnd(brushGroup, state, config, pc, events)); - - // NOTE: The styling needs to be done here and not in the css. This is because - // for 1D brushing, the canvas layers should not listen to - // pointer-events._. - state.strumRect = pc.selection - .select('svg') - .insert('rect', 'g#strums') - .attr('id', 'strum-events') - .attr('x', config.margin.left) - .attr('y', config.margin.top) - .attr('width', w(config)) - .attr('height', h(config) + 2) - .style('opacity', 0) - .call(_drag); -}; - -export default install; diff --git a/src/parallelCoordinates/parcoords-es/brush/strums/onDrag.js b/src/parallelCoordinates/parcoords-es/brush/strums/onDrag.js deleted file mode 100644 index c7af180..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/strums/onDrag.js +++ /dev/null @@ -1,85 +0,0 @@ -import { event, select } from 'd3-selection'; -import { drag } from 'd3-drag'; -import onDragEnd from './onDragEnd'; - -const drawStrum = ( - brushGroup, - state, - config, - pc, - events, - strum, - activePoint -) => { - let _svg = pc.selection.select('svg').select('g#strums'), - id = strum.dims.i, - points = [strum.p1, strum.p2], - _line = _svg.selectAll('line#strum-' + id).data([strum]), - circles = _svg.selectAll('circle#strum-' + id).data(points), - _drag = drag(); - - _line - .enter() - .append('line') - .attr('id', 'strum-' + id) - .attr('class', 'strum'); - - _line - .attr('x1', d => d.p1[0]) - .attr('y1', d => d.p1[1]) - .attr('x2', d => d.p2[0]) - .attr('y2', d => d.p2[1]) - .attr('stroke', 'black') - .attr('stroke-width', 2); - - _drag - .on('drag', function(d, i) { - const ev = event; - i = i + 1; - strum['p' + i][0] = Math.min(Math.max(strum.minX + 1, ev.x), strum.maxX); - strum['p' + i][1] = Math.min(Math.max(strum.minY, ev.y), strum.maxY); - drawStrum(brushGroup, state, config, pc, events, strum, i - 1); - }) - .on('end', onDragEnd(brushGroup, state, config, pc, events)); - - circles - .enter() - .append('circle') - .attr('id', 'strum-' + id) - .attr('class', 'strum'); - - circles - .attr('cx', d => d[0]) - .attr('cy', d => d[1]) - .attr('r', 5) - .style( - 'opacity', - (d, i) => (activePoint !== undefined && i === activePoint ? 0.8 : 0) - ) - .on('mouseover', function() { - select(this).style('opacity', 0.8); - }) - .on('mouseout', function() { - select(this).style('opacity', 0); - }) - .call(_drag); -}; - -const onDrag = (brushGroup, state, config, pc, events) => () => { - const ev = event, - strum = state.strums[state.strums.active]; - - // Make sure that the point is within the bounds - strum.p2[0] = Math.min( - Math.max(strum.minX + 1, ev.x - config.margin.left), - strum.maxX - ); - strum.p2[1] = Math.min( - Math.max(strum.minY, ev.y - config.margin.top), - strum.maxY - ); - - drawStrum(brushGroup, state, config, pc, events, strum, 1); -}; - -export default onDrag; diff --git a/src/parallelCoordinates/parcoords-es/brush/strums/onDragEnd.js b/src/parallelCoordinates/parcoords-es/brush/strums/onDragEnd.js deleted file mode 100644 index cd12713..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/strums/onDragEnd.js +++ /dev/null @@ -1,20 +0,0 @@ -import selected from './selected'; -import removeStrum from './removeStrum'; - -const onDragEnd = (brushGroup, state, config, pc, events) => () => { - const strum = state.strums[state.strums.active]; - - // Okay, somewhat unexpected, but not totally unsurprising, a mousclick is - // considered a drag without move. So we have to deal with that case - if (strum && strum.p1[0] === strum.p2[0] && strum.p1[1] === strum.p2[1]) { - removeStrum(state, pc); - } - - const brushed = selected(brushGroup, state, config); - state.strums.active = undefined; - config.brushed = brushed; - pc.renderBrushed(); - events.call('brushend', pc, config.brushed); -}; - -export default onDragEnd; diff --git a/src/parallelCoordinates/parcoords-es/brush/strums/onDragStart.js b/src/parallelCoordinates/parcoords-es/brush/strums/onDragStart.js deleted file mode 100644 index 4183655..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/strums/onDragStart.js +++ /dev/null @@ -1,33 +0,0 @@ -import { mouse } from 'd3-selection'; -import h from '../../util/height'; -import dimensionsForPoint from '../dimensionsForPoint'; - -// First we need to determine between which two axes the sturm was started. -// This will determine the freedom of movement, because a strum can -// logically only happen between two axes, so no movement outside these axes -// should be allowed. -const onDragStart = (state, config, pc, xscale) => () => { - let p = mouse(state.strumRect.node()); - - p[0] = p[0] - config.margin.left; - p[1] = p[1] - config.margin.top; - - const dims = dimensionsForPoint(config, pc, xscale, p); - const strum = { - p1: p, - dims: dims, - minX: xscale(dims.left), - maxX: xscale(dims.right), - minY: 0, - maxY: h(config), - }; - - // Make sure that the point is within the bounds - strum.p1[0] = Math.min(Math.max(strum.minX, p[0]), strum.maxX); - strum.p2 = strum.p1.slice(); - - state.strums[dims.i] = strum; - state.strums.active = dims.i; -}; - -export default onDragStart; diff --git a/src/parallelCoordinates/parcoords-es/brush/strums/removeStrum.js b/src/parallelCoordinates/parcoords-es/brush/strums/removeStrum.js deleted file mode 100644 index d922f29..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/strums/removeStrum.js +++ /dev/null @@ -1,10 +0,0 @@ -const removeStrum = (state, pc) => { - const strum = state.strums[state.strums.active], - svg = pc.selection.select('svg').select('g#strums'); - - delete state.strums[state.strums.active]; - svg.selectAll('line#strum-' + strum.dims.i).remove(); - svg.selectAll('circle#strum-' + strum.dims.i).remove(); -}; - -export default removeStrum; diff --git a/src/parallelCoordinates/parcoords-es/brush/strums/selected.js b/src/parallelCoordinates/parcoords-es/brush/strums/selected.js deleted file mode 100644 index a6d3942..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/strums/selected.js +++ /dev/null @@ -1,52 +0,0 @@ -// test if point falls between lines -const containmentTest = (strum, width) => p => { - const p1 = [strum.p1[0] - strum.minX, strum.p1[1] - strum.minX], - p2 = [strum.p2[0] - strum.minX, strum.p2[1] - strum.minX], - m1 = 1 - width / p1[0], - b1 = p1[1] * (1 - m1), - m2 = 1 - width / p2[0], - b2 = p2[1] * (1 - m2); - - const x = p[0], - y = p[1], - y1 = m1 * x + b1, - y2 = m2 * x + b2; - - return y > Math.min(y1, y2) && y < Math.max(y1, y2); -}; - -const crossesStrum = (state, config) => (d, id) => { - let strum = state.strums[id], - test = containmentTest(strum, state.strums.width(id)), - d1 = strum.dims.left, - d2 = strum.dims.right, - y1 = config.dimensions[d1].yscale, - y2 = config.dimensions[d2].yscale, - point = [y1(d[d1]) - strum.minX, y2(d[d2]) - strum.minX]; - return test(point); -}; - -const selected = (brushGroup, state, config) => { - // Get the ids of the currently active strums. - const ids = Object.getOwnPropertyNames(state.strums).filter(d => !isNaN(d)), - brushed = config.data; - - if (ids.length === 0) { - return brushed; - } - - const crossTest = crossesStrum(state, config); - - return brushed.filter(d => { - switch (brushGroup.predicate) { - case 'AND': - return ids.every(id => crossTest(d, id)); - case 'OR': - return ids.some(id => crossTest(d, id)); - default: - throw new Error('Unknown brush predicate ' + config.brushPredicate); - } - }); -}; - -export default selected; diff --git a/src/parallelCoordinates/parcoords-es/brush/strums/uninstall.js b/src/parallelCoordinates/parcoords-es/brush/strums/uninstall.js deleted file mode 100644 index 6af6157..0000000 --- a/src/parallelCoordinates/parcoords-es/brush/strums/uninstall.js +++ /dev/null @@ -1,16 +0,0 @@ -const uninstall = (state, pc) => () => { - pc.selection - .select('svg') - .select('g#strums') - .remove(); - pc.selection - .select('svg') - .select('rect#strum-events') - .remove(); - pc.on('axesreorder.strums', undefined); - delete pc.brushReset; - - state.strumRect = undefined; -}; - -export default uninstall; diff --git a/src/parallelCoordinates/parcoords-es/index.js b/src/parallelCoordinates/parcoords-es/index.js deleted file mode 100644 index f43b66a..0000000 --- a/src/parallelCoordinates/parcoords-es/index.js +++ /dev/null @@ -1,202 +0,0 @@ -// misc -import renderQueue from './util/renderQueue'; -import w from './util/width'; - -// brush -import install1DAxes from './brush/1d'; -import install2DStrums from './brush/strums'; -import installAngularBrush from './brush/angular'; - -// api -import intersection from './api/intersection'; -import mergeParcoords from './api/mergeParcoords'; -import selected from './api/selected'; -import brushMode from './api/brushMode'; -import updateAxes from './api/updateAxes'; -import autoscale from './api/autoscale'; -import brushable from './api/brushable'; -import commonScale from './api/commonScale'; -import computeRealCentroids from './api/computeRealCentroids'; -import applyDimensionDefaults from './api/applyDimensionDefaults'; -import createAxes from './api/createAxes'; -import axisDots from './api/axisDots'; -import applyAxisConfig from './api/applyAxisConfig'; -import reorderable from './api/reorderable'; -import resize from './api/resize'; -import reorder from './api/reorder'; -import sortDimensions from './api/sortDimensions'; -import sortDimensionsByRowData from './api/sortDimensionsByRowData'; -import clear from './api/clear'; -import { - pathBrushed, - renderBrushed, - renderBrushedDefault, - renderBrushedQueue, -} from './api/renderBrushed'; -import brushReset from './api/brushReset'; -import toType from './api/toType'; -import toString from './api/toString'; -import adjacentPairs from './api/adjacentPairs'; -import highlight from './api/highlight'; -import unhighlight from './api/unhighlight'; -import removeAxes from './api/removeAxes'; -import render from './api/render'; -import renderDefault, { - pathForeground, - renderDefaultQueue, -} from './api/renderDefault'; -import toTypeCoerceNumbers from './api/toTypeCoerceNumbers'; -import detectDimensionTypes from './api/detectDimensionTypes'; -import getOrderedDimensionKeys from './api/getOrderedDimensionKeys'; -import interactive from './api/interactive'; -import shadows from './api/shadows'; -import init from './api/init'; -import flip from './api/flip'; -import detectDimensions from './api/detectDimensions'; -import scale from './api/scale'; - -import initState from './state'; -import bindEvents from './bindEvents'; - -//css -import './parallel-coordinates.css'; - -const ParCoords = userConfig => { - const state = initState(userConfig); - const { - config, - events, - flags, - xscale, - dragging, - axis, - ctx, - canvas, - brush, - } = state; - - const pc = init(config, canvas, ctx); - - const position = d => { - if (xscale.range().length === 0) { - xscale.range([0, w(config)], 1); - } - return dragging[d] == null ? xscale(d) : dragging[d]; - }; - - const brushedQueue = renderQueue(pathBrushed(config, ctx, position)) - .rate(50) - .clear(() => pc.clear('brushed')); - - const foregroundQueue = renderQueue(pathForeground(config, ctx, position)) - .rate(50) - .clear(function() { - pc.clear('foreground'); - pc.clear('highlight'); - }); - - bindEvents( - config, - ctx, - pc, - xscale, - flags, - brushedQueue, - foregroundQueue, - events, - axis - ); - - // expose the state of the chart - pc.state = config; - pc.flags = flags; - - pc.autoscale = autoscale(config, pc, xscale, ctx); - pc.scale = scale(config); - pc.flip = flip(config); - pc.commonScale = commonScale(config, pc); - pc.detectDimensions = detectDimensions(pc); - // attempt to determine types of each dimension based on first row of data - pc.detectDimensionTypes = detectDimensionTypes; - pc.applyDimensionDefaults = applyDimensionDefaults(config, pc); - pc.getOrderedDimensionKeys = getOrderedDimensionKeys(config); - - //Renders the polylines. - pc.render = render(config, pc, events); - pc.renderBrushed = renderBrushed(config, pc, events); - pc.render.default = renderDefault(config, pc, ctx, position); - pc.render.queue = renderDefaultQueue(config, pc, foregroundQueue); - pc.renderBrushed.default = renderBrushedDefault( - config, - ctx, - position, - pc, - brush - ); - pc.renderBrushed.queue = renderBrushedQueue(config, brush, brushedQueue); - - pc.compute_real_centroids = computeRealCentroids(config.dimensions, position); - pc.shadows = shadows(flags, pc); - pc.axisDots = axisDots(config, pc, position); - pc.clear = clear(config, pc, ctx, brush); - pc.createAxes = createAxes(config, pc, xscale, flags, axis); - pc.removeAxes = removeAxes(pc); - pc.updateAxes = updateAxes(config, pc, position, axis, flags); - pc.applyAxisConfig = applyAxisConfig; - pc.brushable = brushable(config, pc, flags); - pc.brushReset = brushReset(config); - pc.selected = selected(config); - pc.reorderable = reorderable(config, pc, xscale, position, dragging, flags); - - // Reorder dimensions, such that the highest value (visually) is on the left and - // the lowest on the right. Visual values are determined by the data values in - // the given row. - pc.reorder = reorder(config, pc, xscale); - pc.sortDimensionsByRowData = sortDimensionsByRowData(config); - pc.sortDimensions = sortDimensions(config, position); - - // pairs of adjacent dimensions - pc.adjacent_pairs = adjacentPairs; - pc.interactive = interactive(flags); - - // expose internal state - pc.xscale = xscale; - pc.ctx = ctx; - pc.canvas = canvas; - pc.g = () => pc._g; - - // rescale for height, width and margins - // TODO currently assumes chart is brushable, and destroys old brushes - pc.resize = resize(config, pc, flags, events); - - // highlight an array of data - pc.highlight = highlight(config, pc, canvas, events, ctx, position); - // clear highlighting - pc.unhighlight = unhighlight(config, pc, canvas); - - // calculate 2d intersection of line a->b with line c->d - // points are objects with x and y properties - pc.intersection = intersection; - - // Merges the canvases and SVG elements into one canvas element which is then passed into the callback - // (so you can choose to save it to disk, etc.) - pc.mergeParcoords = mergeParcoords(pc); - pc.brushModes = () => Object.getOwnPropertyNames(brush.modes); - pc.brushMode = brushMode(brush, config, pc); - - // install brushes - install1DAxes(brush, config, pc, events); - install2DStrums(brush, config, pc, events, xscale); - installAngularBrush(brush, config, pc, events, xscale); - - pc.version = '2.0.0'; - // this descriptive text should live with other introspective methods - pc.toString = toString(config); - pc.toType = toType; - // try to coerce to number before returning type - pc.toTypeCoerceNumbers = toTypeCoerceNumbers; - - return pc; -}; - -export default ParCoords; diff --git a/src/parallelCoordinates/parcoords-es/parallel-coordinates.css b/src/parallelCoordinates/parcoords-es/parallel-coordinates.css deleted file mode 100644 index 6adbd9e..0000000 --- a/src/parallelCoordinates/parcoords-es/parallel-coordinates.css +++ /dev/null @@ -1,57 +0,0 @@ -.parcoords > svg, .parcoords > canvas { - font: 14px sans-serif; - position: absolute; -} - -.parcoords > canvas { - pointer-events: none; -} - -.parcoords text.label { - cursor: default; - fill: black; -} - -.parcoords rect.background { - fill: transparent; -} - -.parcoords rect.background:hover { - fill: rgba(120, 120, 120, 0.2); -} - -.parcoords .resize rect { - fill: rgba(0, 0, 0, 0.1); -} - -.parcoords rect.extent { - fill: rgba(255, 255, 255, 0.25); - stroke: rgba(0, 0, 0, 0.6); -} - -.parcoords .axis line, .parcoords .axis path { - fill: none; - stroke: #222; - shape-rendering: crispEdges; -} - -.parcoords canvas { - opacity: 1; - -moz-transition: opacity 0.3s; - -webkit-transition: opacity 0.3s; - -o-transition: opacity 0.3s; -} - -.parcoords canvas.faded { - opacity: 0.25; -} - -.parcoords { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-color: white; -} diff --git a/src/parallelCoordinates/parcoords-es/state/defaultConfig.js b/src/parallelCoordinates/parcoords-es/state/defaultConfig.js deleted file mode 100644 index 7e60d37..0000000 --- a/src/parallelCoordinates/parcoords-es/state/defaultConfig.js +++ /dev/null @@ -1,30 +0,0 @@ -const DefaultConfig = { - data: [], - highlighted: [], - dimensions: {}, - dimensionTitleRotation: 0, - brushes: [], - brushed: false, - brushedColor: null, - alphaOnBrushed: 0.0, - mode: 'default', - rate: 20, - width: 600, - height: 300, - margin: { top: 24, right: 20, bottom: 12, left: 20 }, - nullValueSeparator: 'undefined', // set to "top" or "bottom" - nullValueSeparatorPadding: { top: 8, right: 0, bottom: 8, left: 0 }, - color: '#069', - composite: 'source-over', - alpha: 0.7, - bundlingStrength: 0.5, - bundleDimension: null, - smoothness: 0.0, - showControlPoints: false, - hideAxis: [], - flipAxes: [], - animationTime: 1100, // How long it takes to flip the axis when you double click - rotateLabels: false, -}; - -export default DefaultConfig; diff --git a/src/parallelCoordinates/parcoords-es/state/index.js b/src/parallelCoordinates/parcoords-es/state/index.js deleted file mode 100644 index 64649d1..0000000 --- a/src/parallelCoordinates/parcoords-es/state/index.js +++ /dev/null @@ -1,86 +0,0 @@ -import { entries, keys } from 'd3-collection'; -import { axisLeft } from 'd3-axis'; -import { dispatch } from 'd3-dispatch'; -import { scalePoint } from 'd3-scale'; - -import DefaultConfig from './defaultConfig'; - -const initState = userConfig => { - const config = Object.assign({}, DefaultConfig, userConfig); - - if (userConfig && userConfig.dimensionTitles) { - console.warn( - 'dimensionTitles passed in userConfig is deprecated. Add title to dimension object.' - ); - entries(userConfig.dimensionTitles).forEach(d => { - if (config.dimensions[d.key]) { - config.dimensions[d.key].title = config.dimensions[d.key].title - ? config.dimensions[d.key].title - : d.value; - } else { - config.dimensions[d.key] = { - title: d.value, - }; - } - }); - } - - const eventTypes = [ - 'render', - 'resize', - 'highlight', - 'brush', - 'brushend', - 'brushstart', - 'axesreorder', - ].concat(keys(config)); - - const events = dispatch.apply(this, eventTypes), - flags = { - brushable: false, - reorderable: false, - axes: false, - interactive: false, - debug: false, - }, - xscale = scalePoint(), - dragging = {}, - axis = axisLeft().ticks(5), - ctx = {}, - canvas = {}; - - const brush = { - modes: { - None: { - install: function(pc) {}, // Nothing to be done. - uninstall: function(pc) {}, // Nothing to be done. - selected: function() { - return []; - }, // Nothing to return - brushState: function() { - return {}; - }, - }, - }, - mode: 'None', - predicate: 'AND', - currentMode: function() { - return this.modes[this.mode]; - }, - }; - - return { - config, - events, - eventTypes, - flags, - xscale, - dragging, - axis, - ctx, - canvas, - brush, - }; -}; - -export default initState; diff --git a/src/parallelCoordinates/parcoords-es/state/sideEffects.js b/src/parallelCoordinates/parcoords-es/state/sideEffects.js deleted file mode 100644 index b13261b..0000000 --- a/src/parallelCoordinates/parcoords-es/state/sideEffects.js +++ /dev/null @@ -1,85 +0,0 @@ -// side effects for setters -import { keys } from 'd3-collection'; -import { dispatch } from 'd3-dispatch'; -import computeClusterCentroids from '../util/computeClusterCentroids'; -import flipAxisAndUpdatePCP from '../util/flipAxisAndUpdatePCP'; - -const without = (arr, items) => { - items.forEach(el => { - delete arr[el]; - }); - return arr; -}; - -const sideEffects = ( - config, - ctx, - pc, - xscale, - flags, - brushedQueue, - foregroundQueue -) => - dispatch - .apply(this, keys(config)) - .on('composite', d => { - ctx.foreground.globalCompositeOperation = d.value; - ctx.brushed.globalCompositeOperation = d.value; - }) - .on('alpha', d => { - ctx.foreground.globalAlpha = d.value; - ctx.brushed.globalAlpha = d.value; - }) - .on('brushedColor', d => { - ctx.brushed.strokeStyle = d.value; - }) - .on('width', d => pc.resize()) - .on('height', d => pc.resize()) - .on('margin', d => pc.resize()) - .on('rate', d => { - brushedQueue.rate(d.value); - foregroundQueue.rate(d.value); - }) - .on('dimensions', d => { - config.dimensions = pc.applyDimensionDefaults(keys(d.value)); - xscale.domain(pc.getOrderedDimensionKeys()); - pc.sortDimensions(); - if (flags.interactive) { - pc.render().updateAxes(); - } - }) - .on('bundleDimension', d => { - if (!keys(config.dimensions).length) pc.detectDimensions(); - pc.autoscale(); - if (typeof d.value === 'number') { - if (d.value < keys(config.dimensions).length) { - config.bundleDimension = config.dimensions[d.value]; - } else if (d.value < config.hideAxis.length) { - config.bundleDimension = config.hideAxis[d.value]; - } - } else { - config.bundleDimension = d.value; - } - - config.clusterCentroids = computeClusterCentroids( - config, - config.bundleDimension - ); - if (flags.interactive) { - pc.render(); - } - }) - .on('hideAxis', d => { - pc.dimensions(pc.applyDimensionDefaults()); - pc.dimensions(without(config.dimensions, d.value)); - }) - .on('flipAxes', d => { - if (d.value && d.value.length) { - d.value.forEach(function(axis) { - flipAxisAndUpdatePCP(config, pc, axis); - }); - pc.updateAxes(0); - } - }); - -export default sideEffects; diff --git a/src/parallelCoordinates/parcoords-es/util/colorPath.js b/src/parallelCoordinates/parcoords-es/util/colorPath.js deleted file mode 100644 index f7999ba..0000000 --- a/src/parallelCoordinates/parcoords-es/util/colorPath.js +++ /dev/null @@ -1,79 +0,0 @@ -// draw single cubic bezier curve -import { entries } from 'd3-collection'; -import computeCentroids from './computeCentroids'; -import computeControlPoints from './computeControlPoints'; -import h from './height'; - -const singleCurve = (config, position, d, ctx) => { - const centroids = computeCentroids(config, position, d); - const cps = computeControlPoints(config.smoothness, centroids); - - ctx.moveTo(cps[0].e(1), cps[0].e(2)); - - for (let i = 1; i < cps.length; i += 3) { - if (config.showControlPoints) { - for (let j = 0; j < 3; j++) { - ctx.fillRect(cps[i + j].e(1), cps[i + j].e(2), 2, 2); - } - } - ctx.bezierCurveTo( - cps[i].e(1), - cps[i].e(2), - cps[i + 1].e(1), - cps[i + 1].e(2), - cps[i + 2].e(1), - cps[i + 2].e(2) - ); - } -}; - -// returns the y-position just beyond the separating null value line -const getNullPosition = config => { - if (config.nullValueSeparator == 'bottom') { - return h(config) + 1; - } else if (config.nullValueSeparator == 'top') { - return 1; - } else { - console.log( - "A value is NULL, but nullValueSeparator is not set; set it to 'bottom' or 'top'." - ); - } - return h(config) + 1; -}; - -const singlePath = (config, position, d, ctx) => { - entries(config.dimensions).forEach((p, i) => { - //p isn't really p - if (i == 0) { - ctx.moveTo( - position(p.key), - typeof d[p.key] == 'undefined' - ? getNullPosition(config) - : config.dimensions[p.key].yscale(d[p.key]) - ); - } else { - ctx.lineTo( - position(p.key), - typeof d[p.key] == 'undefined' - ? getNullPosition(config) - : config.dimensions[p.key].yscale(d[p.key]) - ); - } - }); -}; - -// draw single polyline -const colorPath = (config, position, d, ctx) => { - ctx.beginPath(); - if ( - (config.bundleDimension !== null && config.bundlingStrength > 0) || - config.smoothness > 0 - ) { - singleCurve(config, position, d, ctx); - } else { - singlePath(config, position, d, ctx); - } - ctx.stroke(); -}; - -export default colorPath; diff --git a/src/parallelCoordinates/parcoords-es/util/computeCentroids.js b/src/parallelCoordinates/parcoords-es/util/computeCentroids.js deleted file mode 100644 index 5ea1522..0000000 --- a/src/parallelCoordinates/parcoords-es/util/computeCentroids.js +++ /dev/null @@ -1,44 +0,0 @@ -import { keys } from 'd3-collection'; - -const computeCentroids = (config, position, row) => { - const centroids = []; - - const p = keys(config.dimensions); - const cols = p.length; - const a = 0.5; // center between axes - for (let i = 0; i < cols; ++i) { - // centroids on 'real' axes - const x = position(p[i]); - const y = config.dimensions[p[i]].yscale(row[p[i]]); - centroids.push($V([x, y])); - - // centroids on 'virtual' axes - if (i < cols - 1) { - const cx = x + a * (position(p[i + 1]) - x); - let cy = y + a * (config.dimensions[p[i + 1]].yscale(row[p[i + 1]]) - y); - if (config.bundleDimension !== null) { - const leftCentroid = config.clusterCentroids - .get( - config.dimensions[config.bundleDimension].yscale( - row[config.bundleDimension] - ) - ) - .get(p[i]); - const rightCentroid = config.clusterCentroids - .get( - config.dimensions[config.bundleDimension].yscale( - row[config.bundleDimension] - ) - ) - .get(p[i + 1]); - let centroid = 0.5 * (leftCentroid + rightCentroid); - cy = centroid + (1 - config.bundlingStrength) * (cy - centroid); - } - centroids.push($V([cx, cy])); - } - } - - return centroids; -}; - -export default computeCentroids; diff --git a/src/parallelCoordinates/parcoords-es/util/computeClusterCentroids.js b/src/parallelCoordinates/parcoords-es/util/computeClusterCentroids.js deleted file mode 100644 index 18b5457..0000000 --- a/src/parallelCoordinates/parcoords-es/util/computeClusterCentroids.js +++ /dev/null @@ -1,35 +0,0 @@ -import { keys, map } from 'd3-collection'; - -const computeClusterCentroids = (config, d) => { - const clusterCentroids = map(); - const clusterCounts = map(); - // determine clusterCounts - config.data.forEach(function(row) { - let scaled = config.dimensions[d].yscale(row[d]); - if (!clusterCounts.has(scaled)) { - clusterCounts.set(scaled, 0); - } - let count = clusterCounts.get(scaled); - clusterCounts.set(scaled, count + 1); - }); - - config.data.forEach(function(row) { - keys(config.dimensions).map(p => { - let scaled = config.dimensions[d].yscale(row[d]); - if (!clusterCentroids.has(scaled)) { - let _map = map(); - clusterCentroids.set(scaled, _map); - } - if (!clusterCentroids.get(scaled).has(p)) { - clusterCentroids.get(scaled).set(p, 0); - } - let value = clusterCentroids.get(scaled).get(p); - value += config.dimensions[p].yscale(row[p]) / clusterCounts.get(scaled); - clusterCentroids.get(scaled).set(p, value); - }); - }); - - return clusterCentroids; -}; - -export default computeClusterCentroids; diff --git a/src/parallelCoordinates/parcoords-es/util/computeControlPoints.js b/src/parallelCoordinates/parcoords-es/util/computeControlPoints.js deleted file mode 100644 index 0b8fc8a..0000000 --- a/src/parallelCoordinates/parcoords-es/util/computeControlPoints.js +++ /dev/null @@ -1,35 +0,0 @@ -const computeControlPoints = (smoothness, centroids) => { - const cols = centroids.length; - const a = smoothness; - const cps = []; - - cps.push(centroids[0]); - cps.push( - $V([ - centroids[0].e(1) + a * 2 * (centroids[1].e(1) - centroids[0].e(1)), - centroids[0].e(2), - ]) - ); - for (let col = 1; col < cols - 1; ++col) { - let mid = centroids[col]; - let left = centroids[col - 1]; - let right = centroids[col + 1]; - - let diff = left.subtract(right); - cps.push(mid.add(diff.x(a))); - cps.push(mid); - cps.push(mid.subtract(diff.x(a))); - } - cps.push( - $V([ - centroids[cols - 1].e(1) + - a * 2 * (centroids[cols - 2].e(1) - centroids[cols - 1].e(1)), - centroids[cols - 1].e(2), - ]) - ); - cps.push(centroids[cols - 1]); - - return cps; -}; - -export default computeControlPoints; diff --git a/src/parallelCoordinates/parcoords-es/util/dimensionLabels.js b/src/parallelCoordinates/parcoords-es/util/dimensionLabels.js deleted file mode 100644 index dd4225c..0000000 --- a/src/parallelCoordinates/parcoords-es/util/dimensionLabels.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * dimension display names - * - * @param config - * @param d - * @returns {*} - */ -const dimensionLabels = config => d => - config.dimensions[d].title ? config.dimensions[d].title : d; - -export default dimensionLabels; diff --git a/src/parallelCoordinates/parcoords-es/util/flipAxisAndUpdatePCP.js b/src/parallelCoordinates/parcoords-es/util/flipAxisAndUpdatePCP.js deleted file mode 100644 index 7c6a389..0000000 --- a/src/parallelCoordinates/parcoords-es/util/flipAxisAndUpdatePCP.js +++ /dev/null @@ -1,14 +0,0 @@ -import { select } from 'd3-selection'; - -const flipAxisAndUpdatePCP = (config, pc, axis) => - function(dimension) { - pc.flip(dimension); - pc.brushReset(dimension); - select(this.parentElement) - .transition() - .duration(config.animationTime) - .call(axis.scale(config.dimensions[dimension].yscale)); - pc.render(); - }; - -export default flipAxisAndUpdatePCP; diff --git a/src/parallelCoordinates/parcoords-es/util/functor.js b/src/parallelCoordinates/parcoords-es/util/functor.js deleted file mode 100644 index d2498a1..0000000 --- a/src/parallelCoordinates/parcoords-es/util/functor.js +++ /dev/null @@ -1,3 +0,0 @@ -const _functor = v => (typeof v === 'function' ? v : () => v); - -export default _functor; diff --git a/src/parallelCoordinates/parcoords-es/util/getRange.js b/src/parallelCoordinates/parcoords-es/util/getRange.js deleted file mode 100644 index 4590561..0000000 --- a/src/parallelCoordinates/parcoords-es/util/getRange.js +++ /dev/null @@ -1,24 +0,0 @@ -/** adjusts an axis' default range [h()+1, 1] if a NullValueSeparator is set */ -const getRange = config => { - const h = config.height - config.margin.top - config.margin.bottom; - - if (config.nullValueSeparator == 'bottom') { - return [ - h + - 1 - - config.nullValueSeparatorPadding.bottom - - config.nullValueSeparatorPadding.top, - 1, - ]; - } else if (config.nullValueSeparator == 'top') { - return [ - h + 1, - 1 + - config.nullValueSeparatorPadding.bottom + - config.nullValueSeparatorPadding.top, - ]; - } - return [h + 1, 1]; -}; - -export default getRange; diff --git a/src/parallelCoordinates/parcoords-es/util/getset.js b/src/parallelCoordinates/parcoords-es/util/getset.js deleted file mode 100644 index 5567df6..0000000 --- a/src/parallelCoordinates/parcoords-es/util/getset.js +++ /dev/null @@ -1,25 +0,0 @@ -import { keys } from 'd3-collection'; - -const getset = (obj, state, events, side_effects, pc) => { - keys(state).forEach(function(key) { - obj[key] = function(x) { - if (!arguments.length) { - return state[key]; - } - if ( - key === 'dimensions' && - Object.prototype.toString.call(x) === '[object Array]' - ) { - console.warn('pc.dimensions([]) is deprecated, use pc.dimensions({})'); - x = obj.applyDimensionDefaults(x); - } - let old = state[key]; - state[key] = x; - side_effects.call(key, obj, { value: x, previous: old }); - events.call(key, obj, { value: x, previous: old }); - return obj; - }; - }); -}; - -export default getset; diff --git a/src/parallelCoordinates/parcoords-es/util/height.js b/src/parallelCoordinates/parcoords-es/util/height.js deleted file mode 100644 index b00a085..0000000 --- a/src/parallelCoordinates/parcoords-es/util/height.js +++ /dev/null @@ -1,3 +0,0 @@ -const h = config => config.height - config.margin.top - config.margin.bottom; - -export default h; diff --git a/src/parallelCoordinates/parcoords-es/util/isBrushed.js b/src/parallelCoordinates/parcoords-es/util/isBrushed.js deleted file mode 100644 index 179b15d..0000000 --- a/src/parallelCoordinates/parcoords-es/util/isBrushed.js +++ /dev/null @@ -1,15 +0,0 @@ -const isBrushed = (config, brushGroup) => { - if (config.brushed && config.brushed.length !== config.data.length) - return true; - - const object = brushGroup.currentMode().brushState(); - - for (let key in object) { - if (object.hasOwnProperty(key)) { - return true; - } - } - return false; -}; - -export default isBrushed; diff --git a/src/parallelCoordinates/parcoords-es/util/renderQueue.js b/src/parallelCoordinates/parcoords-es/util/renderQueue.js deleted file mode 100644 index ae62cf7..0000000 --- a/src/parallelCoordinates/parcoords-es/util/renderQueue.js +++ /dev/null @@ -1,67 +0,0 @@ -import 'requestanimationframe'; - -const renderQueue = function(func) { - let _queue = [], // data to be rendered - _rate = 1000, // number of calls per frame - _invalidate = function() {}, // invalidate last render queue - _clear = function() {}; // clearing function - - let rq = function(data) { - if (data) rq.data(data); - _invalidate(); - _clear(); - rq.render(); - }; - - rq.render = function() { - let valid = true; - _invalidate = rq.invalidate = function() { - valid = false; - }; - - function doFrame() { - if (!valid) return true; - let chunk = _queue.splice(0, _rate); - chunk.map(func); - requestAnimationFrame(doFrame); - } - - doFrame(); - }; - - rq.data = function(data) { - _invalidate(); - _queue = data.slice(0); // creates a copy of the data - return rq; - }; - - rq.add = function(data) { - _queue = _queue.concat(data); - }; - - rq.rate = function(value) { - if (!arguments.length) return _rate; - _rate = value; - return rq; - }; - - rq.remaining = function() { - return _queue.length; - }; - - // clear the canvas - rq.clear = function(func) { - if (!arguments.length) { - _clear(); - return rq; - } - _clear = func; - return rq; - }; - - rq.invalidate = _invalidate; - - return rq; -}; - -export default renderQueue; diff --git a/src/parallelCoordinates/parcoords-es/util/rotateLabels.js b/src/parallelCoordinates/parcoords-es/util/rotateLabels.js deleted file mode 100644 index ab6d2af..0000000 --- a/src/parallelCoordinates/parcoords-es/util/rotateLabels.js +++ /dev/null @@ -1,20 +0,0 @@ -import { event } from 'd3-selection'; - -const rotateLabels = (config, pc) => { - if (!config.rotateLabels) return; - - let delta = event.deltaY; - delta = delta < 0 ? -5 : delta; - delta = delta > 0 ? 5 : delta; - - config.dimensionTitleRotation += delta; - pc.svg - .selectAll('text.label') - .attr( - 'transform', - 'translate(0,-5) rotate(' + config.dimensionTitleRotation + ')' - ); - event.preventDefault(); -}; - -export default rotateLabels; diff --git a/src/parallelCoordinates/parcoords-es/util/width.js b/src/parallelCoordinates/parcoords-es/util/width.js deleted file mode 100644 index 7d0448a..0000000 --- a/src/parallelCoordinates/parcoords-es/util/width.js +++ /dev/null @@ -1,3 +0,0 @@ -const w = config => config.width - config.margin.right - config.margin.left; - -export default w;