最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Creating a 3 circle Venn diagram with pure csshtml - Stack Overflow

programmeradmin4浏览0评论

Maybe there's not a way, but I'm looking to create 3 circles that would appear to overlap, yet would be actually individual objects with pure css. I can easily create a crescent moon shape, but I also need this object to only be reactive to the actual colored object, not the border as well.

I need to make something like this:

And to show you more of what I mean, each object needs to be it's own shape like this:

Really prefer css if possible. SVG could be another way, but again, I need each object to react to the visible object on hover/click and NOT outside it's visible area.

Maybe there's not a way, but I'm looking to create 3 circles that would appear to overlap, yet would be actually individual objects with pure css. I can easily create a crescent moon shape, but I also need this object to only be reactive to the actual colored object, not the border as well.

I need to make something like this:

And to show you more of what I mean, each object needs to be it's own shape like this:

Really prefer css if possible. SVG could be another way, but again, I need each object to react to the visible object on hover/click and NOT outside it's visible area.

Share Improve this question edited Apr 5, 2015 at 11:43 web-tiki 104k33 gold badges224 silver badges257 bronze badges asked Apr 3, 2015 at 0:55 CodeMonkeyCodeMonkey 1351 silver badge7 bronze badges 3
  • Really great question, I think I have a css solution. Ill let you know when/if I finish it. – Hurricane Development Commented Apr 3, 2015 at 2:04
  • If you would accept a canvas element solution then "I haz teh codez..." – markE Commented Apr 3, 2015 at 22:54
  • Why do you need each element to be an individual object? What kind of user interactions do you need? Or do you just want each element to have it's own background? – web-tiki Commented Apr 6, 2015 at 11:52
Add a comment  | 

5 Answers 5

Reset to default 7

Making the shapes really concaves in CSS is really hard, in this case your best bet would be SVG.

But, if you want a pure CSS solution, may be you don't need really those shapes. If you set your z-index ok, then you can get your topmost div to hide the others, and then you don't care about the concave side ...

In this demo, the hover works ok. It would be the same for other events.

div {
  width: 240px;
  height: 240px;
  position: absolute;
  border-radius: 50%;
}

.innerw {
  left: 0px;
  top: 0px;
  overflow: hidden;
}

.innerw2 {
  left: 170px;
  top: 0px;
  overflow: hidden;
}

.inner {
  left: -85px;
  top: 130px;
  background-color: palegreen;
  z-index: 20;
}

.inner:hover {
  background-color: green;
}

#midw1 {
  left: 0px;
  top: 0px;
  overflow: hidden;
}
#mid1 {
  left: 170px;
  top: 0px;
}
#midw2 {
  left: 0px;
  top: 0px;
  overflow: hidden;
}
#mid2 {
  left: 85px;
  top: 130px;
}
#midw3 {
  left: 170px;
  top: 0px;
  overflow: hidden;
}
#mid3 {
  left: -85px;
  top: 130px;
}
.mid {
  background-color: lightblue;
  z-index: 15;
}
.mid:hover {
  background-color: blue;
}


#outer1 {
  left: 0px;
  top: 0px;
}

#outer2 {
  left: 170px;
  top: 0px;
}
#outer3 {
  left: 85px;
  top: 130px;
}
.outer {
  background-color: lightcoral;
  z-index: 10;
}
.outer:hover {
  background-color: red;
}
<div id="outer1" class="outer">
</div>
<div id="outer2" class="outer">
</div>
<div id="outer3" class="outer">
</div>
<div id="midw1">
<div id="mid1" class="mid"></div>
</div>
<div id="midw2">
<div id="mid2" class="mid"></div>
</div>
<div id="midw3">
<div id="mid3" class="mid"></div>
</div>
<div class="innerw">
<div class="innerw2">
<div class="inner">
</div>
</div>
</div>

A more complex layout, bug-free in Chrome and IE

div {
  width: 240px;
  height: 240px;
  border-radius: 50%;
  pointer-events: none;
  position: absolute;
}

.innerw {
  left: 0px;
  top: 0px;
  overflow: hidden;
  position: absolute;
  /* border: solid; */
  z-index: 20;
  /* transform: translateZ(10px); */
  pointer-events: none;
}

.innerw2 {
  margin-left: 0px;
  top: 0px;
  overflow: hidden;
  position: static;
  /* border: solid; */
  /* z-index: 20; */
  pointer-events: none;
}

.innerw3 {
  margin-left: 170px;
  top: 0px;
  overflow: hidden;
  position: static;
  /* border: solid; */
  /* z-index: 20; */
  pointer-events: none;
}

.inner {
  margin-left: -85px;
  margin-top: 130px;
  background-color: palegreen;
  z-index: 20;
  position: static;
  pointer-events: auto;
}

.inner:hover {
  background-color: green;
}

.mwrap {
  position: absolute;
  overflow: hidden;
  pointer-events: none;
  z-index: 10;
}
.mwrap2 {
  position: static;
  margin-left: 0px;
  margin-top: 0px;
  overflow: hidden;
  pointer-events: none;
}
.mid {
  position: static;
  pointer-events: auto;
}
#midaw1 {
  left: 0px;
  top: 0px;
}
#mida {
  margin-left: 170px;
  margin-top: 0px;
}
#midbw1 {
  left: 170px;
  top: 0px;
}
#midb {
  margin-left: -85px;
  margin-top: 130px;
}
#midcw1 {
  left: 85px;
  top: 130px;
}
#midc {
  margin-left: -85px;
  margin-top: -130px;
}
.mid {
  background-color: lightblue;
  z-index: 15;
}
.mid:hover {
  background-color: blue;
}


#outer1 {
  left: 0px;
  top: 0px;
}

#outer2 {
  left: 170px;
  top: 0px;
}
#outer3 {
  left: 85px;
  top: 130px;
}
.outer {
  background-color: lightcoral;
  z-index: 1;
  pointer-events: auto;
}
.outer:hover {
  background-color: red;
}
<div id="outer1" class="outer">
</div>
<div id="outer2" class="outer">
</div>
<div id="outer3" class="outer">
</div>
<div id="midaw1" class="mwrap">
<div id="midaw2" class="mwrap2">
<div id="mida" class="content mid"></div>
</div>
</div>
<div id="midbw1" class="mwrap">
<div id="midbw2" class="mwrap2">
<div id="midb" class="content mid"></div>
</div>
</div>
<div id="midcw1" class="mwrap">
<div id="midcw2" class="mwrap2">
<div id="midc" class="content mid"></div>
</div>
</div>
<div class="innerw">
<div class="innerw2">
<div class="innerw3">
<div class="inner">
</div>
</div>
</div>
</div>

Thanks to theleggett for his help on this

The best tool to use is SVG. Vals answer with CSS is great! but its not working in my GC.

With SVG, you can use path elements with arcs. EG, my shape is divided into 7 arc paths.

svg {
  overflow: visible;
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="40%" width="40%" viewBox="0 0 100 100" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <style type="text/css">
      path {
        fill: transparent;
        stroke: red;
        stroke-width: 0.5;
      }
      path:hover {
        fill: red;
      }
    </style>
  </defs>
  <path d="M 50 8 A 30 30 0 1 0 21 59 30 30 0 0 1 41 36 30 30 0 0 1 50 8" />
  <path d="M 50 8 A 30 30 0 0 0 41 36 30 30 0 0 1 59 36 30 30 0 0 0 50 8" />
  <path d="M 50 8 A 30 30 0 1 1 79 59 30 30 0 0 0 59 36 30 30 0 0 0 50 8" />
  <path d="M 50 52 A 30 30 0 0 1 21 59 30 30 0 0 1 41 36 30 30 0 0 0 50 52" />
  <path d="M 50 52 A 30 30 0 0 1 41 36 30 30 0 0 1 59 36 30 30 0 0 1 50 52" />
  <path d="M 50 52 A 30 30 0 0 0 79 59 30 30 0 0 0 59 36 30 30 0 0 1 50 52" />
  <path d="M 21 59 A 30 30 0 1 0 79 59 30 30 0 0 1 50 52 30 30 0 0 1 21 59" />
</svg>

If you want image inside separate arc shapes (for some reason. don't ask)

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="40%" width="40%" viewBox="0 0 100 100" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <style type="text/css">
      path {
        fill: transparent;
        stroke: red;
        stroke-width: 0.5;
      }
      path:hover {
        fill: url(#img);
      }
    </style>
    <pattern id="img" patternUnits="userSpaceOnUse" width="100" height="100">
      <image xlink:href="http://www.placecage.com/g/200/300" x="0" y="-25" width="100" height="200" />
    </pattern>
  </defs>
  <path d="M 50 8 A 30 30 0 1 0 21 59 30 30 0 0 1 41 36 30 30 0 0 1 50 8" />
  <path d="M 50 8 A 30 30 0 0 0 41 36 30 30 0 0 1 59 36 30 30 0 0 0 50 8" />
  <path d="M 50 8 A 30 30 0 1 1 79 59 30 30 0 0 0 59 36 30 30 0 0 0 50 8" />
  <path d="M 50 52 A 30 30 0 0 1 21 59 30 30 0 0 1 41 36 30 30 0 0 0 50 52" />
  <path d="M 50 52 A 30 30 0 0 1 41 36 30 30 0 0 1 59 36 30 30 0 0 1 50 52" />
  <path d="M 50 52 A 30 30 0 0 0 79 59 30 30 0 0 0 59 36 30 30 0 0 1 50 52" />
  <path d="M 21 59 A 30 30 0 1 0 79 59 30 30 0 0 1 50 52 30 30 0 0 1 21 59" />
</svg>

I have SVG solution for your question:

DEMO: http://jsfiddle.net/kboksc04/

The code recreates the circles and intersections with polygons.

var r = 200,              // radius of the circles

// colors of the circles
// you can create functions for colors or load them from array etc.
    colors = {            
        a: "#ADD8E6",     
        b: "#FFFACD",     
        c: "#FA8072",
        ab: "#008000",
        bc: "#FF0000",
        ca: "#0000FF",
        abc: "#000000"
    };

// the body of the picture
var board = d3.select("body").append("svg:svg").attr({
    width: 3 * r,
    height: 3 * r
});

// function creates array of x,y pairs for dots
// uses parametric function of circle
// @param {float} x_0, y_0 - center of the circle
// @param {float} r - radius
// @param {integer} n - number of sections  
// @returns {Array} - array of coordinates for "n" dots of polygon
function dots(x_0, y_0, r, n) {
    var a = [],
        d_alpha = 2 * Math.PI / n;
    for (var alpha = 0; alpha < 2 * Math.PI; alpha += d_alpha) {
        a.push([
        x_0 + r * Math.cos(alpha),
        y_0 + r * Math.sin(alpha)]);
    }
    return (a);
}

// the coordinates for points of three basic circles
var shape_a = d3.geom.polygon(dots(r, r, r, 80));
var shape_b = d3.geom.polygon(dots(2 * r, r, r, 80));
var shape_c = d3.geom.polygon(dots(1.5 * r, 2 * r, r, 80));

// intersections of circles in pairs
var shape_a_x_b = shape_a.slice();
shape_b.reverse().clip(shape_a_x_b);

var shape_b_x_c = shape_c.slice();
shape_b.clip(shape_b_x_c);

var shape_c_x_a = shape_c.slice();
shape_a.reverse().clip(shape_c_x_a);

// central intersection for all the circles
// actually it is intersection of pair previous calculated intersections
var shape_abc = shape_c_x_a.slice();
d3.geom.polygon(shape_b_x_c.reverse()).clip(shape_abc);

// drawing
board.append("svg:polygon")
    .attr({
    points: shape_a,
    fill: colors.a
});
board.append("svg:polygon")
    .attr({
    points: shape_b,
    fill: colors.b
});
board.append("svg:polygon")
    .attr({
    points: shape_c,
    fill: colors.c
});
board.append("svg:polygon")
    .attr({
    points: shape_a_x_b,
    fill: colors.ab
});
board.append("svg:polygon")
    .attr({
    points: shape_b_x_c,
    fill: colors.bc
});
board.append("svg:polygon")
    .attr({
    points: shape_c_x_a,
    fill: colors.ca
});
board.append("svg:polygon")
    .attr({
    points: shape_abc,
    fill: colors.abc
});

Finally, there you can see a version with clickable-responsible pieces:

http://jsfiddle.net/kboksc04/2/

You can click on a green or black pieces.

DEMO: http://jsfiddle.net/u5e5mhgx/

I believe the final mix is depends of the color and transparence of the circles, like:

background-color: rgba(0, 0, 255, 0.4);

Using the border-radius property, you can create pure css Venn diagram like this:

Here's my pen http://jsfiddle.net/sLzUG/195/

 .circle{
    position:absolute;
    width:150px;
    height: 150px;

    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
    filter: alpha(opacity=30);
    -moz-opacity: 0.3;
    -khtml-opacity: 0.3;
    opacity:0.3;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
    border: 2px solid black;
}


#second{position:relative; left:92px; top:4px;
 background: yellow;

}

#first {
    background: blue;
}




#third {
    position: relative; 
    top: -70px;
    left: 40px;
    background: red;
}

#problem{
    font-size: 8pt;
    color:white;
    position: absolute;
    width: 75px;
    height: 75px;
    border-left:2px solid red;
    border-top:2px solid red;
    top : 41px;
    left:71px;
    z-index:-4;
    background:red;
}
#problem:after{
    position:absolute;
    content:" ";
    background:white;
    width:150px;
    height:150px;
    top:-2px;
    left: -2px;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
    z-index:-3;
}



<div id="first" class="circle"></div>
<div id="second" class="circle"></div>
<div id="third" class="circle"></div>
发布评论

评论列表(0)

  1. 暂无评论