Javascript html5画布3圈

Javascript html5画布3圈,javascript,html,canvas,Javascript,Html,Canvas,在画布中创建维恩图。我尝试为每个交叉点和每个圆使用不同的颜色。虽然我可以用重叠的圆来做这件事,但我需要让每个交叉点都是它自己的部分,这样我就可以操纵每个交叉点的颜色,就像我在悬停时做的那样 问题是我可以完成所有部分,但最后的重叠部分除外。以下是现有解决方案的映像:。需要标记/显示黄色和蓝色圆圈的重叠,而不影响底部圆圈的重叠。以下是我到目前为止所做的(我意识到这不是最干净的,正在努力简化): window.LENS={}; LENS.init=函数(){ var self=这个; this.ca

在画布中创建维恩图。我尝试为每个交叉点和每个圆使用不同的颜色。虽然我可以用重叠的圆来做这件事,但我需要让每个交叉点都是它自己的部分,这样我就可以操纵每个交叉点的颜色,就像我在悬停时做的那样

问题是我可以完成所有部分,但最后的重叠部分除外。以下是现有解决方案的映像:。需要标记/显示黄色和蓝色圆圈的重叠,而不影响底部圆圈的重叠。以下是我到目前为止所做的(我意识到这不是最干净的,正在努力简化):


window.LENS={};
LENS.init=函数(){
var self=这个;
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;//补偿边距
this.drawLens(this.ctx,this.width,this.height);
}
LENS.drawLens=功能(ctx、窗宽、窗高){
var self=这个;
var半径=窗宽/5.25;
var circle1={x:windowWidth/2.5,y:windowHeight/3,r:radius,color:'rgb(130205240)'};
var circle2={x:windowWidth/1.75,y:windowHeight/3,r:radius,color:'rgb(255240180)};
var circle3={x:circle1.x+circle1.r/2,y:circle1.y+circle1.r/1.2,r:radius,color:'rgb(245120125)};//除以1.2用于视觉目的。半径将居中,但提供了视觉错觉
var intersect1={color:'rgb(0170145)};
var intersect2={color:'rgb(130,70110)};
var intersect3={color:'rgb(255160,75)};
var intersectCenter={color:'rgb(55,55,55)};
//画圆圈1
//ctx.save();//很重要,否则我们将丢失上下文并保留所有图形
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();
//交叉1顶部
ctx.beginPath();
ctx.fillStyle=1.color;
ctx.strokeStyle=intersect1.color;
ctx.globalCompositeOperation='source-top';
ctx.arc(circle2.x,circle2.y,circle2.r,0,2*Math.PI,false);
ctx.fill();
//交叉2顶部
ctx.beginPath();
ctx.fillStyle=intersect2.color;
ctx.strokeStyle=intersect2.color;
ctx.globalCompositeOperation='source-top';
ctx.arc(circle3.x,circle3.y,circle3.r,0,2*Math.PI,false);
ctx.fill();
//相交中心
ctx.beginPath();
ctx.globalCompositeOperation='source-top'
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();
//在底部绘制交点3
ctx.beginPath();
ctx.fillStyle=3.color;
ctx.strokeStyle=3.color;
ctx.globalCompositeOperation='destination-over';
ctx.arc(circle2.x,circle2.y,circle2.r,0,2*Math.PI,false);
ctx.fill();
ctx.stroke();
//交叉口3
ctx.beginPath();
ctx.fillStyle=3.color;
ctx.strokeStyle=3.color;
ctx.globalCompositeOperation='destination-in';
ctx.arc(circle3.x,circle3.y,circle3.r,0,2*Math.PI,false);
ctx.fill();
ctx.stroke();
//圆圈3
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();
//重画圆圈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();
//重画圆圈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();
}

您可以使用屏幕外画布,该画布使用合成来创建您的Venn接头

如果“合成”设置为“源输入”,则任何新图形将仅在现有图形和新图形重叠的位置显示。其他一切都将被清除(透明化)

“source in”合成是绘制维恩联合的理想选择,因为只有两个圆的交点会存在

如果“合成”设置为“目标输出”,则任何新图形都将清除新图形重叠的图形。(这类似于“擦除”操作)

此伪代码将显示蓝色和黄色圆圈的并集(除并集外的所有内容都将被删除):

  • 画蓝色的圆圈
  • 将合成设置为“源输入”
  • 画黄色的圆圈

此伪代码将显示您遇到问题的顶部蓝-黄联合:

  • 画蓝色的圆圈
  • 将合成设置为“源输入”
  • 画黄色的圆圈
  • 将合成设置为“目标输出”
  • 画红色圆圈

代码和演示:

    <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>
<!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>