Skip to content

Commit

Permalink
Refactor Chord vis (apache#5671)
Browse files Browse the repository at this point in the history
* refactor Chord vis

* Add PropTypes

* change module.exports to export default
  • Loading branch information
kristw authored and mistercrunch committed Aug 21, 2018
1 parent fef39a7 commit 683edc3
Showing 1 changed file with 80 additions and 46 deletions.
126 changes: 80 additions & 46 deletions superset/assets/src/visualizations/chord.jsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,93 @@
/* eslint-disable no-param-reassign */
import d3 from 'd3';
import PropTypes from 'prop-types';
import { getColorFromScheme } from '../modules/colors';
import './chord.css';

function chordViz(slice, json) {
slice.container.html('');

const div = d3.select(slice.selector);
const nodes = json.data.nodes;
const fd = slice.formData;
const f = d3.format(fd.y_axis_format);

const width = slice.width();
const height = slice.height();
const propTypes = {
data: PropTypes.shape({
nodes: PropTypes.arrayOf(PropTypes.string),
matrix: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)),
}),
width: PropTypes.number,
height: PropTypes.number,
numberFormat: PropTypes.string,
colorScheme: PropTypes.string,
};

function chordVis(element, props) {
PropTypes.checkPropTypes(propTypes, props, 'prop', 'ChordVis');

const {
data,
width,
height,
numberFormat,
colorScheme,
} = props;

element.innerHTML = '';

const div = d3.select(element);
const { nodes, matrix } = data;
const f = d3.format(numberFormat);

const outerRadius = Math.min(width, height) / 2 - 10;
const innerRadius = outerRadius - 24;

let chord;

const arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
.innerRadius(innerRadius)
.outerRadius(outerRadius);

const layout = d3.layout.chord()
.padding(0.04)
.sortSubgroups(d3.descending)
.sortChords(d3.descending);
.padding(0.04)
.sortSubgroups(d3.descending)
.sortChords(d3.descending);

const path = d3.svg.chord()
.radius(innerRadius);
.radius(innerRadius);

const svg = div.append('svg')
.attr('width', width)
.attr('height', height)
.on('mouseout', () => chord.classed('fade', false))
.append('g')
.attr('id', 'circle')
.attr('transform', `translate(${width / 2}, ${height / 2})`);
.attr('width', width)
.attr('height', height)
.on('mouseout', () => chord.classed('fade', false))
.append('g')
.attr('id', 'circle')
.attr('transform', `translate(${width / 2}, ${height / 2})`);

svg.append('circle')
.attr('r', outerRadius);
.attr('r', outerRadius);

// Compute the chord layout.
layout.matrix(json.data.matrix);
layout.matrix(matrix);

const group = svg.selectAll('.group')
.data(layout.groups)
.enter().append('g')
.attr('class', 'group')
.on('mouseover', (d, i) => {
chord.classed('fade', p => p.source.index !== i && p.target.index !== i);
});
.data(layout.groups)
.enter().append('g')
.attr('class', 'group')
.on('mouseover', (d, i) => {
chord.classed('fade', p => p.source.index !== i && p.target.index !== i);
});

// Add a mouseover title.
group.append('title').text((d, i) => `${nodes[i]}: ${f(d.value)}`);

// Add the group arc.
const groupPath = group.append('path')
.attr('id', (d, i) => 'group' + i)
.attr('d', arc)
.style('fill', (d, i) => getColorFromScheme(nodes[i], slice.formData.color_scheme));
.attr('id', (d, i) => 'group' + i)
.attr('d', arc)
.style('fill', (d, i) => getColorFromScheme(nodes[i], colorScheme));

// Add a text label.
const groupText = group.append('text')
.attr('x', 6)
.attr('dy', 15);
.attr('x', 6)
.attr('dy', 15);

groupText.append('textPath')
.attr('xlink:href', (d, i) => `#group${i}`)
.text((d, i) => nodes[i]);
.attr('xlink:href', (d, i) => `#group${i}`)
.text((d, i) => nodes[i]);
// Remove the labels that don't fit. :(
groupText.filter(function (d, i) {
return groupPath[0][i].getTotalLength() / 2 - 16 < this.getComputedTextLength();
Expand All @@ -78,14 +96,14 @@ function chordViz(slice, json) {

// Add the chords.
chord = svg.selectAll('.chord')
.data(layout.chords)
.enter().append('path')
.attr('class', 'chord')
.on('mouseover', (d) => {
chord.classed('fade', p => p !== d);
})
.style('fill', d => getColorFromScheme(nodes[d.source.index], slice.formData.color_scheme))
.attr('d', path);
.data(layout.chords)
.enter().append('path')
.attr('class', 'chord')
.on('mouseover', (d) => {
chord.classed('fade', p => p !== d);
})
.style('fill', d => getColorFromScheme(nodes[d.source.index], colorScheme))
.attr('d', path);

// Add an elaborate mouseover title for each chord.
chord.append('title').text(function (d) {
Expand All @@ -98,4 +116,20 @@ function chordViz(slice, json) {
});
}

module.exports = chordViz;
chordVis.propTypes = propTypes;

function adaptor(slice, payload) {
const { selector, formData } = slice;
const { y_axis_format: numberFormat, color_scheme: colorScheme } = formData;
const element = document.querySelector(selector);

return chordVis(element, {
data: payload.data,
width: slice.width(),
height: slice.height(),
numberFormat,
colorScheme,
});
}

export default adaptor;

0 comments on commit 683edc3

Please sign in to comment.