Published
Edited
Jul 13, 2018
Fork of vx Dots
1 star
Insert cell
Insert cell
Insert cell
{
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

const colors = ['#025aac', '#02cff9', '#02efff', '#03aeed', '#0384d7', '#edfdff', '#ab31ff', '#5924d7', '#d145ff', '#1a02b1', '#e582ff', '#ff00d4', '#270eff', '#827ce2']
const width = 400
const height = 300

function genCircles({ num, width, height }) {
return Array(num).fill(1).map((d, i) => {
const radius = 25 - Math.random() * 20;
return {
id: i,
radius,
x: Math.round(Math.random() * (width - radius * 2) + radius),
y: Math.round(Math.random() * (height - radius * 2) + radius)
};
});
}

const genItems = ({ width, height }) => genCircles({
num: width < 360 ? 40 : 185,
width,
height
});

class DragI extends React.Component {
constructor(props) {
super(props);
this.state = {
items: genItems(_extends({}, props))
};
this.colorScale = vx.scaleOrdinal({
range: colors,
domain: this.state.items.map(d => d.id)
});
}

componentWillReceiveProps(nextProps) {
const { width, height } = nextProps;
if (width !== this.props.width) {
this.setState(() => {
return {
items: genItems(_extends({}, nextProps))
};
});
}
}

render() {
const { width, height } = this.props;
if (width < 10) return null;
return React.createElement(
'div',
{ className: 'Drag', style: { touchAction: 'none' } },
React.createElement(
'svg',
{ width: width, height: height },
React.createElement(vx.LinearGradient, { id: 'stroke', from: '#ff00a5', to: '#ffc500' }),
React.createElement('rect', {
fill: '#c4c3cb',
width: width,
height: height,
rx: 14
}),
this.state.items.map((d, i) => React.createElement(
vx.Drag,
{
key: `${d.id}`,
width: width,
height: height,
onDragStart: () => {
// svg follows the painter model
// so we need to move the data item
// to end of the array for it to be drawn
// "on top of" the other data items
this.setState((state, props) => {
return {
items: vx.raise(state.items, i)
};
});
}
},
({
dragStart,
dragEnd,
dragMove,
isDragging,
dx,
dy
}) => {
return React.createElement('circle', {
key: `dot-${d.id}`,
cx: d.x,
cy: d.y,
r: isDragging ? d.radius + 4 : d.radius,
fill: isDragging ? 'url(#stroke)' : this.colorScale(d.id),
transform: `translate(${dx}, ${dy})`,
fillOpacity: 0.9,
stroke: isDragging ? 'white' : 'transparent',
strokeWidth: 2,
onMouseMove: dragMove,
onMouseUp: dragEnd,
onMouseDown: dragStart,
onTouchStart: dragStart,
onTouchMove: dragMove,
onTouchEnd: dragEnd
});
}
))
),
React.createElement(
'div',
{ className: 'deets' },
React.createElement(
'div',
null,
'Based on Mike Bostock\'s',
' ',
React.createElement(
'a',
{ href: 'https://bl.ocks.org/mbostock/c206c20294258c18832ff80d8fd395c3' },
'Circle Dragging II'
)
)
)
);
}
}
ReactDOM.render(
React.createElement(DragI, {width: width, height: height}),
document.getElementById("chart")
)

}
Insert cell
Insert cell
// forked vx repo and used browserify standalone on vx-vx to make something we can use
// I know this is old school but at least it works
vx = require("https://timelyportfolio.github.io/vx/vx.min.js")
Insert cell
Insert cell
// using https://beta.observablehq.com/@tmcw/semiotic-in-observable
r = require.alias({
"react": "react@16/umd/react.production.min.js",
"react-dom": "react-dom@16/umd/react-dom.production.min.js"
})
Insert cell
React = r('react')
Insert cell
ReactDOM = r('react-dom')
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more