Sample code to produce a Venn diagram of 3 circles using SVG.

Venn diagram

examples/svg_venn_diagram.psgi

#!/usr/bin/perl
use strict;
use warnings;

use SVG;
 
my $app = sub {
    my $svg = SVG->new(
        width  => 200,
        height => 200,
    );
    $svg->title()->cdata('I am a title');

    # add a circle
    my $red = $svg->circle(
        cx => 100,
        cy => 100,
        r  => 50,
        id => 'red_circle',
        style => {
            'fill'         => '#FF0000',
            'fill-opacity' => 0.5,
        }
    );

    my $blue = $svg->circle(
        cx => 150,
        cy => 100,
        r  => 50,
        id => 'blue_circle',
        style => {
            'fill'         => '#0000FF',
            'fill-opacity' => 0.5,
        }
    );

    my $green = $svg->circle(
        cx => 125,
        cy => 150,
        r  => 50,
        id => 'green_circle',
        style => {
            'fill'         => '#00FF00',
            'fill-opacity' => 0.5,
        }
    );


    return [
        '200',
        [ 'Content-Type' => 'image/svg+xml' ],
        [ $svg->xmlify ],
    ];
};


We create 3 circles with the same radius r => 50, but with different center position (cx, cy).

It is also important to set the fill-opacity to something less than 1. Especially for the circles drawn on top of the other circles. Otherwise we would not see the common areas as common.

Clickable Venn diagram in SVG

In the next example we make the circles clickable and link each circle to a different URL:

I am a title

The source code looks like this:

examples/svg_venn_diagram_clickable.psgi

#!/usr/bin/perl
use strict;
use warnings;

# run this example using plackup -r examples/svg.psgi

use SVG;
 
my $app = sub {
    my $svg = SVG->new(
        width  => 200,
        height => 200,
    );
    $svg->title()->cdata('I am a title');

    my $red_tag = $svg->anchor(
        -href => 'http://perlmaven.com/'
    );
    my $red = $red_tag->circle(
        cx => 100,
        cy => 100,
        r  => 50,
        id => 'red_circle',
        style => {
            'fill'         => '#FF0000',
            'fill-opacity' => 0.5,
        }
    );

    my $blue_tag = $svg->anchor(
        -href => 'http://code-maven.com/'
    );
    my $blue = $blue_tag->circle(
        cx => 150,
        cy => 100,
        r  => 50,
        id => 'blue_circle',
        style => {
            'fill'         => '#0000FF',
            'fill-opacity' => 0.5,
        }
    );

    my $green_tag = $svg->anchor(
        -href => 'http://perl6maven.com/'
    );
    my $green = $green_tag->circle(
        cx => 125,
        cy => 150,
        r  => 50,
        id => 'green_circle',
        style => {
            'fill'         => '#00FF00',
            'fill-opacity' => 0.5,
        }
    );


    return [
        '200',
        [ 'Content-Type' => 'image/svg+xml' ],
        [ $svg->xmlify ],
    ];
};


Here, instead of creating the circles from the $svg object itself, first we create Anchor objects from SVG and then from those Anchor object we create the circles. Each Anchor object will handle a single URL and a single circle.

    my $red_tag = $svg->anchor(
        -href => 'https://perlmaven.com/'
    );
    my $red = $red_tag->circle(
       ...

There is also a big difference from the previous cases. Especially in the way the result is displayed on this page. Earlier we used the results of the SVG in an img element like this:

<img src="/img/some.svg" />

The same could would not work properly with anchors and links. For those to work we had to embed the generated XML code in the HTML file. So if you now "view source" of this page, you'll see that the Clickable Venn diagram is a piece of XML code.

There is another issue, which might be even more problematic. The entire green circle now leads to the same URL, both where it is alone and also where it is overlapping other circles. This is probably not what we want.

I think we cannot solve this problem with regular circle elements. So we'll have to see what can we do with more advanced SVG elements.