UNPKG

react-venn-diagram

Version:

A Venn diagram React component

106 lines (105 loc) 4.46 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { useEffect, useRef } from 'react'; import * as d3 from 'd3'; var VennDiagram = function (_a) { var _b = _a.data, a = _b.a, b = _b.b, intersection = _b.intersection, width = _a.width, height = _a.height, _c = _a.labels, labels = _c === void 0 ? {} : _c, _d = _a.colors, colors = _d === void 0 ? {} : _d; var svgRef = useRef(null); useEffect(function () { if (!svgRef.current) return; var svg = d3.select(svgRef.current); svg.selectAll("*").remove(); var scale = d3.scaleSqrt() .domain([0, Math.max(a, b)]) .range([0, width / 5]); var radiusA = scale(a); var radiusB = scale(b); var positions = { A: { cx: width / 2 - radiusB / 2, cy: height / 2 }, B: { cx: width / 2 + radiusA / 2, cy: height / 2 }, }; var handleMouseOver = function () { d3.select(this) .transition() .duration(300) .style('fill-opacity', 0.7); }; var handleMouseOut = function () { d3.select(this) .transition() .duration(300) .style('fill-opacity', 0.5); }; var drawCircleAndText = function (key, value, label, color, fontColor) { var pos = positions[key]; var radius = key === 'A' ? radiusA : radiusB; var circle = svg.append('circle') .attr('cx', pos.cx) .attr('cy', pos.cy) .attr('r', 0) .style('fill', color) .style('fill-opacity', 0.5) .transition() .duration(800) .attr('r', radius) .on('end', function () { d3.select(this) .on('mouseover', handleMouseOver) .on('mouseout', handleMouseOut) .on('touchstart', handleMouseOver) .on('touchend', handleMouseOut); }); var textX = key === 'A' ? pos.cx - radius : pos.cx + radius; var textAnchor = key === 'A' ? 'start' : 'end'; var textElement = svg.append('text') .attr('x', textX) .attr('y', pos.cy) .style('fill', fontColor) .style('font-size', '14px') .style('font-family', 'Arial, sans-serif') .attr('text-anchor', textAnchor) .style('opacity', 0); textElement.transition() .duration(800) .style('opacity', 1); textElement.append("tspan") .attr('x', textX) .attr('dy', '0em') .style('font-weight', 'bold') .text("".concat(value)); textElement.append("tspan") .attr('x', textX) .attr('dy', '1.2em') .text(label); }; drawCircleAndText('A', a, labels.labelA || 'Group A', colors.colorA || '#9467bd', colors.fontColorA || 'white'); drawCircleAndText('B', b, labels.labelB || 'Group B', colors.colorB || '#2ca02c', colors.fontColorB || 'white'); var intersectionCenterX = (positions.A.cx + positions.B.cx) / 2; var intersectionTextElement = svg.append('text') .attr('x', intersectionCenterX) .attr('y', height / 2) .style('fill', colors.fontColorIntersection || 'white') .style('font-size', '12px') .style('font-family', 'Arial, sans-serif') .attr('text-anchor', 'middle') .style('opacity', 0); intersectionTextElement.transition() .duration(800) .style('opacity', 1) .tween("text", function () { var self = this; return function () { d3.select(self).text("".concat(intersection)); }; }) .on("end", function () { d3.select(this).append("tspan") .attr('x', intersectionCenterX) .attr('dy', '1.2em') .style('font-weight', 'normal') .text(labels.labelIntersection || 'Intersection'); }); }, [a, b, intersection, width, height, labels, colors]); return _jsx("svg", { ref: svgRef, width: width, height: height }); }; export default VennDiagram;