chart = {
const svg = d3.create('svg');
const g = svg.append('g');
const markerBoxWidth = 20;
const markerBoxHeight = 20;
const refX = markerBoxWidth / 2;
const refY = markerBoxHeight / 2;
svg
.append('defs')
.append('marker')
.attr('id', 'arrow')
.attr('viewBox', [0, 0, markerBoxWidth, markerBoxHeight])
.attr('refX', refX)
.attr('refY', refY)
.attr('markerWidth', markerBoxWidth)
.attr('markerHeight', markerBoxHeight)
.attr('orient', 'auto-start-reverse')
.append('path')
.attr('d', d3.line()(arrowPoints))
.attr('stroke', 'black')
.attr('opacity', .3);
svg.call(size, () => [width, config.height]);
g.call(trans, () => [config.margin, config.margin]);
const enterCircle = node =>
node
.append('circle')
.attr('r', config.radius)
.attr('fill', d => colorScale(d.id));
const enterText = node =>
node
.append('text')
.text(d => d.id)
.attr('alignment-baseline', 'middle')
.attr('text-anchor', 'middle')
.attr('font-family', 'sans-serif')
.attr('font-size', '10px');
const enterNode = node =>
node
.append('g')
.attr('class', 'spot')
.attr('data-id', d => d.id)
.call(enterCircle)
.call(enterText);
const updateNode = node => node.call(trans, d => [scaleX(d.x), scaleY(d.y)]);
const lineGen = d3.line();
const enterLink = link =>
link
.append('path')
.attr('stroke', 'black')
.attr('marker-end', 'url(#arrow)')
.attr('opacity', .3)
.call(updateLink);
const updateLink = link =>
link.attr('d', d => {
const sourceLoc = [scaleX(d.sourceData.x), scaleY(d.sourceData.y)];
const targetLoc = [scaleX(d.targetData.x), scaleY(d.targetData.y)];
return lineGen([sourceLoc, targetLoc]);
});
function render(_data, _links) {
const xExtent = d3.extent(_data.map(d => d.x));
const yExtent = d3.extent(_data.map(d => d.y));
scaleX.domain(xExtent).range([0, width - config.margin]);
scaleY.domain(yExtent).range([0, config.height - config.margin * 2]);
const nodes = g
.selectAll('.spot')
.data(_data)
.join(enterNode, updateNode);
const dataById = getDataById(_data);
const compositeLinks = _links.map(l => {
return { ...l, sourceData: l.source, targetData: l.target };
});
console.log(compositeLinks);
const links = g
.selectAll('path')
.data(compositeLinks)
.join(enterLink, updateLink);
}
return Object.assign(svg.node(), { render });
}