2014-02-19 74 views
2

在畫布上創建維恩圖表。我試圖爲每個交叉路口和每個圓圈設置不同的顏色。雖然我可以用重疊的圓圈來做到這一點,但我需要讓每個交點成爲自己的一部分,這樣我就可以操縱每個交點的顏色,因爲我將在懸停時進行這種操作。html5 canvas venn 3個圈子

問題是我可以完成所有部分,但最終重疊。以下是現有解決方案的圖像:venn diagram image。需要標記/顯示來自黃色和藍色圓圈的重疊而不影響底部圓圈重疊。這裏是我到目前爲止(我知道這不是最乾淨的,在簡化工作):

<script> 
     window.LENS = {}; 

     LENS.init = function(){ 
      var self = this; 

      this.canvas = document.getElementById('canvas'); 
      this.ctx = canvas.getContext('2d'); 
      this.width = window.innerWidth; 
      this.height = window.innerHeight; 
      this.canvas.width = window.innerWidth; 
      this.canvas.height = window.innerHeight+50; //compensate for margin 
      this.drawLens(this.ctx, this.width, this.height); 

     } 

     LENS.drawLens = function (ctx, windowWidth, windowHeight){ 
      var self = this; 
      var radius=windowWidth/5.25; 
      var circle1={x:windowWidth/2.5, y:windowHeight/3, r:radius, color: 'rgb(130,205,240)'}; 
      var circle2={x:windowWidth/1.75, y:windowHeight/3, r:radius, color: 'rgb(255,240,180)'}; 
      var circle3={x:circle1.x+circle1.r/2, y:circle1.y+circle1.r/1.2, r:radius, color: 'rgb(245,120,125)'}; //dividing by 1.2 for visual purposes. radius would be centered, but provides optical illusiion 
      var intersect1={color:'rgb(0,170,145)'}; 
      var intersect2={color:'rgb(130,70,110)'}; 
      var intersect3={color:'rgb(255,160,75)'}; 
      var intersectCenter={color:'rgb(55,55,55)'}; 

      //draw circle1 
      //ctx.save(); //important or we lose the context and will hold all drawing 
      ctx.beginPath(); 
      ctx.arc(circle1.x, circle1.y, circle1.r, 0, 2*Math.PI, false); 
      ctx.fillStyle=circle1.color; 
      ctx.strokeStyle=circle1.color; 
      ctx.stroke(); 
      ctx.fill(); 

      //intersection1 top 
      ctx.beginPath(); 
      ctx.fillStyle=intersect1.color; 
      ctx.strokeStyle=intersect1.color; 
      ctx.globalCompositeOperation='source-atop'; 
      ctx.arc(circle2.x,circle2.y,circle2.r, 0, 2*Math.PI, false); 
      ctx.fill();    

      //intersection2 top 
      ctx.beginPath(); 
      ctx.fillStyle=intersect2.color; 
      ctx.strokeStyle=intersect2.color; 
      ctx.globalCompositeOperation='source-atop'; 
      ctx.arc(circle3.x,circle3.y,circle3.r, 0, 2*Math.PI, false); 
      ctx.fill(); 

      //intersect Center 
      ctx.beginPath(); 
      ctx.globalCompositeOperation='source-atop' 
      ctx.arc(circle2.x, circle2.y, circle2.r, 0, 2*Math.PI, false); 
      ctx.fillStyle=intersectCenter.color; 
      ctx.strokeStyle=intersectCenter.color; 
      ctx.stroke(); 
      ctx.fill();  

      //draw intersection3 bottom 
      ctx.beginPath(); 
      ctx.fillStyle=intersect3.color; 
      ctx.strokeStyle=intersect3.color;    
      ctx.globalCompositeOperation='destination-over'; 
      ctx.arc(circle2.x, circle2.y, circle2.r, 0, 2*Math.PI, false); 
      ctx.fill(); 
      ctx.stroke(); 

      //intersection 3 
      ctx.beginPath(); 
      ctx.fillStyle=intersect3.color; 
      ctx.strokeStyle=intersect3.color;     
      ctx.globalCompositeOperation='destination-in'; 
      ctx.arc(circle3.x, circle3.y, circle3.r, 0, 2*Math.PI, false); 
      ctx.fill(); 
      ctx.stroke(); 

      //circle3 
      ctx.beginPath(); 
      ctx.fillStyle=circle3.color; 
      ctx.globalCompositeOperation='destination-over'; 
      ctx.arc(circle3.x,circle3.y,circle3.r, 0, 2*Math.PI, false); 
      ctx.fill(); 

      //redraw circle 1 
      ctx.beginPath(); 
      ctx.globalCompositeOperation='destination-over'; 
      ctx.arc(circle1.x, circle1.y, circle1.r, 0, 2*Math.PI, false); 
      ctx.fillStyle=circle1.color; 
      ctx.strokeStyle=circle1.color; 
      ctx.stroke(); 
      ctx.fill(); 

      //redraw circle 2 
      ctx.beginPath(); 
      ctx.globalCompositeOperation='destination-over' 
      ctx.arc(circle2.x, circle2.y, circle2.r, 0, 2*Math.PI, false); 
      ctx.fillStyle=circle2.color; 
      ctx.strokeStyle=circle2.color; 
      ctx.stroke(); 
      ctx.fill(); 

     } 

    </script> 

回答

1

您可以使用使用合​​成來創建維恩工會的屏幕外的畫布。

enter image description here

如果合成被設置爲「源極 - 在」那麼任何新的附圖將僅顯示在現有的和新的附圖重疊。其他一切都會被清除(變得透明)。

「源內」合成對繪製維恩結合非常理想,因爲只有2個圓的交集才能存活。

如果合成設置爲「目標輸出」,那麼任何新圖形都會清除新圖形重疊的圖形。 (這就像一個「擦除」操作)

這個僞代碼會顯示您的藍色和黃色的圓圈(一切,但工會將被刪除)的工會:

  • 繪製藍色圓圈
  • 集合成以 「源式」
  • 畫黃圈

enter image description here

這個僞代碼會顯示您遇到麻煩頂藍黃聯盟:

  • 繪製藍色圓圈
  • 集合成以「源式」
  • 畫黃圈
  • 集合成以 「目的地出」
  • 畫紅圈

enter image description here

代碼和演示:http://jsfiddle.net/m1erickson/XLhT9/

<!doctype html> 
<html> 
<head> 
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> 
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> 
<style> 
    body{ background-color: white; } 
    canvas{border:1px solid red;} 
</style> 
<script> 
$(function(){ 

    var canvas=document.getElementById("canvas"); 
    var ctx=canvas.getContext("2d"); 
    var canvas1=document.createElement("canvas"); 
    var ctx1=canvas1.getContext("2d"); 

    var circleBlue={x:50,y:50,r:40}; 
    var circleYellow={x:100,y:50,r:40}; 
    var circleRed={x:75,y:85,r:40}; 

    drawCircle(ctx,circleRed,"salmon"); 
    drawCircle(ctx,circleYellow,"lemonchiffon"); 
    drawCircle(ctx,circleBlue,"lightblue"); 

    $r=$("#r")[0]; 
    $y=$("#y")[0]; 
    $b=$("#b")[0]; 
    $by=$("#by")[0]; 
    $br=$("#br")[0]; 
    $yr=$("#yr")[0]; 
    $byNotR=$("#byNotR")[0]; 
    $brNotY=$("#brNotY")[0]; 
    $yrNotB=$("#yrNotB")[0]; 
    $yrb=$("#yrb")[0]; 
    $r.checked=true; 
    $y.checked=true; 
    $b.checked=true; 

    $(":checkbox").change(function(){drawAll()}); 

    function drawIntersect(a,b,c,notC,color){ 

     ctx1.clearRect(0,0,canvas1.width,canvas1.height); 

     ctx1.save(); 

     // a 
     drawCircle(ctx1,a,color); 
     // b 
     ctx1.globalCompositeOperation="source-in"; 
     drawCircle(ctx1,b,color); 
     // c 
     if(c){drawCircle(ctx1,c,color); } 
     // notC 
     ctx1.globalCompositeOperation="destination-out"; 
     if(notC){ drawCircle(ctx1,notC,color); } 

     ctx1.restore(); 

     ctx.drawImage(canvas1,0,0); 

    } 

    function drawCircle(ctx,circle,color){ 
     ctx.beginPath(); 
     ctx.arc(circle.x,circle.y,circle.r,0,Math.PI*2); 
     ctx.closePath(); 
     ctx.fillStyle=color; 
     ctx.fill(); 
    } 

    function drawAll(){ 
     ctx.clearRect(0,0,canvas.width,canvas.height); 
     if($r.checked){drawCircle(ctx,circleRed,"salmon");} 
     if($y.checked){drawCircle(ctx,circleYellow,"lemonchiffon");} 
     if($b.checked){drawCircle(ctx,circleBlue,"lightblue");} 
     if($by.checked){drawIntersect(circleBlue,circleYellow,null,null,"green");} 
     if($br.checked){drawIntersect(circleBlue,circleRed,null,null,"blue");} 
     if($yr.checked){drawIntersect(circleYellow,circleRed,null,null,"red");} 
     if($byNotR.checked){drawIntersect(circleBlue,circleYellow,null,circleRed,"green");} 
     if($brNotY.checked){drawIntersect(circleBlue,circleRed,null,circleYellow,"blue");} 
     if($yrNotB.checked){drawIntersect(circleYellow,circleRed,null,circleBlue,"red");} 
     if($yrb.checked){drawIntersect(circleYellow,circleRed,circleBlue,null,"black");} 
    } 

}); // end $(function(){}); 
</script> 
</head> 
<body> 
    <input type="checkbox" id="r">Red Circle<br> 
    <input type="checkbox" id="y">Yellow Circle<br> 
    <input type="checkbox" id="b">Blue Circle<br> 
    <input type="checkbox" id="by">Blue+Yellow<br> 
    <input type="checkbox" id="br">Blue+Red<br> 
    <input type="checkbox" id="yr">Yellow+Red<br> 
    <input type="checkbox" id="byNotR">Blue+Yellow-Red<br> 
    <input type="checkbox" id="brNotY">Blue+Red-Yellow<br> 
    <input type="checkbox" id="yrNotB">Yellow+Red-Blue<br> 
    <input type="checkbox" id="yrb">Yellow+Red+Blue<br> 
    <canvas id="canvas" width=150 height=150></canvas> 
</body> 
</html>