diff --git a/src/components/BeeswarmChart.vue b/src/components/BeeswarmChart.vue index 173c3389e8f425e621e58f9b996dfe7792e181e5..735d40cfe4edb0cf8dc94b04b2a8191756d23dca 100644 --- a/src/components/BeeswarmChart.vue +++ b/src/components/BeeswarmChart.vue @@ -181,96 +181,15 @@ const forceManyBody = d3.forceManyBody().strength(1); const bubbles = svg - .selectAll('.bubble') - .data(data.value) - .enter() - .append('circle') - .attr('class', 'bubble') - .attr('r', d => radiusScale(d.evidence_val)) - .style('fill', d => dimensionColors[d.dimension.replace(' ', '')]) - .on('mouseover', function (event, d) { - const [x, y] = d3.pointer(event); - const tooltip = d3.select('#tooltip') - - tooltip.html('') - tooltip.append('div') - .html(`<strong>${d.determinant}</strong><br>appeared in ${d.evidence_val} ${d.evidence_val === 1 ? 'study' : 'studies'}`); - - // add stacked bar chart - const barData = [ - { name: 'positive', value: d.pos_related_total, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: dimensionColors[d.dimension.replace(' ', '')] }, - { name: 'negative', value: d.neg_related_total, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: 'white' }, - { name: 'unknown', value: d.unk_direction_total, pattern: true, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: 'white' } - ]; - - // Set dimensions for the bar chart - const barWidth = 130; - const barHeight = 10; - - // Create an SVG element for the bar chart - const svgBar = tooltip.append('svg') - .attr('width', barWidth + 10) - .attr('height', barHeight + 10); - - const defs = svgBar.append('defs'); - - const pattern = defs.append('pattern') - .attr('id', 'pattern-stripe') - .attr('patternUnits', 'userSpaceOnUse') - .attr('width', 8) // Adjusted to make pattern larger - .attr('height', 8) - - pattern.append('rect') - .attr('width', 8) - .attr('height', 8) - .attr('fill', 'white'); - - pattern.append('path') - .attr('d', 'M-2,2 l4,-4 M0,8 l8,-8 M6,10 l4,-4') // Adjusted path for thicker stripes - .attr('stroke', dimensionColors[d.dimension.replace(' ', '')]) - .attr('stroke-width', 3); // Thicker stripes - - const g = svgBar.append('g') - .attr('transform', 'translate(8, 8)'); - - // Create a scale for the x-axis - const xBar = d3.scaleLinear() - .domain([0, d3.sum(barData, d => d.value)]) - .range([0, barWidth]); - - // Create groups for each bar segment - const barGroups = g.selectAll('g') - .data(barData) - .enter() - .append('g'); - - // Add the rectangles - barGroups.append('rect') - .attr('x', (d, i) => i > 0 ? xBar(d3.sum(barData.slice(0, i), d => d.value)) : 0) - .attr('y', 0) - .attr('width', d => xBar(d.value)) - .attr('height', barHeight) - .style('fill', d => d.pattern ? 'url(#pattern-stripe)' : d.fill) - .style('stroke', d => d.stroke ? d.stroke : 'none'); - - // Position the tooltip - tooltip - .style('opacity', 1) - .attr('stroke', dimensionColors[d.dimension.replace(' ', '')]) - .style('left', (x + 10) + 'px') - .style('top', (y - 28) + 'px'); - - // Highlight the circle - d3.select(this) - .attr('stroke', d => dimensionColors[d.dimension.replace(' ', '')]) - .attr('stroke-width', 15); - }) - .on('mouseout', function () { - d3.select('#tooltip').style('opacity', 0); - d3.select(this) - .attr('stroke', null) - .attr('stroke-width', null); - }); + .selectAll('.bubble') + .data(data.value) + .enter() + .append('circle') + .attr('class', 'bubble') + .attr('r', d => radiusScale(d.evidence_val)) + .style('fill', d => dimensionColors[d.dimension.replace(' ', '')]) + .on('mouseover', handleMouseOver) + .on('mouseout', handleMouseOut); // Run simulation simulation = d3.forceSimulation() @@ -332,11 +251,100 @@ .style('fill', d => activeCategories.includes(d.dimension.replace(' ', '')) ? dimensionColors[d.dimension.replace(' ', '')] : 'rgba(250, 250, 250, 0.93)') .attr('cx', d => d.x) // Use existing x position .attr('cy', d => d.y) + .on('mouseover', handleMouseOver) + .on('mouseout', handleMouseOut) .merge(bubbles); // Ensure all bubbles are handled correctly bubbles.exit().remove(); } + +//tooltip +function handleMouseOver(event, d) { + const [x, y] = d3.pointer(event, svg.node()); + const tooltip = d3.select('#tooltip'); + + tooltip.html('') + .append('div') + .html(`<strong>${d.determinant}</strong><br>appeared in ${d.evidence_val} ${d.evidence_val === 1 ? 'study' : 'studies'}`); + + // Add stacked bar chart + const barData = [ + { name: 'positive', value: d.pos_related_total, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: dimensionColors[d.dimension.replace(' ', '')] }, + { name: 'negative', value: d.neg_related_total, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: 'white' }, + { name: 'unknown', value: d.unk_direction_total, pattern: true, stroke: dimensionColors[d.dimension.replace(' ', '')], fill: 'white' } + ]; + + // Set dimensions for the bar chart + const barWidth = 130; + const barHeight = 10; + + // Create an SVG element for the bar chart + const svgBar = tooltip.append('svg') + .attr('width', barWidth + 10) + .attr('height', barHeight + 10); + + const defs = svgBar.append('defs'); + + const pattern = defs.append('pattern') + .attr('id', 'pattern-stripe') + .attr('patternUnits', 'userSpaceOnUse') + .attr('width', 8) // Adjusted to make pattern larger + .attr('height', 8); + + pattern.append('rect') + .attr('width', 8) + .attr('height', 8) + .attr('fill', 'white'); + + pattern.append('path') + .attr('d', 'M-2,2 l4,-4 M0,8 l8,-8 M6,10 l4,-4') // Adjusted path for thicker stripes + .attr('stroke', dimensionColors[d.dimension.replace(' ', '')]) + .attr('stroke-width', 3); // Thicker stripes + + const g = svgBar.append('g') + .attr('transform', 'translate(8, 8)'); + + // Create a scale for the x-axis + const xBar = d3.scaleLinear() + .domain([0, d3.sum(barData, d => d.value)]) + .range([0, barWidth]); + + // Create groups for each bar segment + const barGroups = g.selectAll('g') + .data(barData) + .enter() + .append('g'); + + // Add the rectangles + barGroups.append('rect') + .attr('x', (d, i) => i > 0 ? xBar(d3.sum(barData.slice(0, i), d => d.value)) : 0) + .attr('y', 0) + .attr('width', d => xBar(d.value)) + .attr('height', barHeight) + .style('fill', d => d.pattern ? 'url(#pattern-stripe)' : d.fill) + .style('stroke', d => d.stroke ? d.stroke : 'none'); + + // Position the tooltip + tooltip + .style('opacity', 1) + .style('left', (x + 10) + 'px') + .style('top', (y - 28) + 'px'); + + // Highlight the circle + d3.select(this) + .attr('stroke', dimensionColors[d.dimension.replace(' ', '')]) + .attr('stroke-width', 8); +} + +function handleMouseOut() { + d3.select('#tooltip').style('opacity', 0); + d3.select(this) + .attr('stroke', null) + .attr('stroke-width', null); +} + + </script> <style scoped lang="scss">