簡體   English   中英

填充重疊的圓形區域

[英]Fill in overlapping circle area

我有兩個相交的圓圈,我想讓相交區域有顏色,即使兩個圓圈是透明的。 我以為我可以找到一些方法來使用 css mix-blend-mode屬性來做到這一點,但我沒有成功。

當然,我可以讓圓圈有顏色並降低它們的不透明度,但我希望它們是白色或透明的,只有重疊區域才有背景顏色。

我希望相交區域能夠動態變化,因為一個圓圈將跟隨鼠標。 這是代碼筆

我不確定從哪里開始,如果 css 有一些技術,或者它是否必須用 jquery 來完成。

 $(document).mousemove(function(e) { $('.cursor').eq(0).css({ left: e.pageX - 25, top: e.pageY - 20 }); // circles var c1 = $('.cursor'); var c2 = $('.circle'); // radius var d1 = c1.outerWidth(true)/2; var d2 = c2.outerWidth(true)/2; // centers of first circle var x1 = c1.offset().left + c1.width()/2; var y1 = c1.offset().top + c1.height()/2; // centers of second circle var x2 = c2.offset().left + c2.width()/2; var y2 = c2.offset().top + c2.height()/2; var i1 = c2.find('.inter1'); var i2 = c2.find('.inter2'); var o = c1.find('.overlap'); function calc() { var a = d2; var b = d1; var c = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); var d = (b*b+c*ca*a)/(2*c); var h = Math.sqrt((b*b) - (d*d)); if (d < 0 || $.isNumeric(h)) { c2.css('border-color', 'red'); } else { c2.css('border-color', 'black'); } var x3 = (x2-x1)*d/c + (y2-y1)*h/c + x1; var y3 = (y2-y1)*d/c - (x2-x1)*h/c + y1; var x4 = (x2-x1)*d/c - (y2-y1)*h/c + x1; var y4 = (y2-y1)*d/c + (x2-x1)*h/c + y1; if ($.isNumeric(h)) { i1.show(); i2.show(); } else { i1.hide(); i2.hide(); } i1.offset({ top: y3-5, left: x3-5}); i2.offset({ top: y4-5, left: x4-5}); } calc(); });
 body { background: #fff; } .overlap { position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: rgba(0, 0, 0, 0.5); } .cursor { height: 50px; width: 50px; border-radius: 50%; position: absolute; pointer-events: none; z-index: 999; border: 1px solid black; outline: 1px solid #c9d3ff; overflow: none; } .circle { border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 200px; height: 200px; border: 1px solid black; outline: 1px solid #c9d3ff; } .circle::after, .cursor::after { display: block; content: ''; height: 1px; background: #c9d3ff; position: absolute; top: 50%; left: 0; right: 0; } .circle::before, .cursor::before { display: block; content: ''; width: 1px; background: #c9d3ff; position: absolute; left: 50%; top: 0; bottom: 0; } .inter { width: 10px; height: 10px; background: black; border-radius: 50%; position: absolute; display: none; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="cursor"> </div> <div class="circle"> <div class="inter1 inter"></div> <div class="inter2 inter"></div> <div>

解決此問題的一種方法是在主圓圈內添加一個“內部光標”圓圈。 基於鼠標移動,它會隨着主光標移動,產生重疊的錯覺。

在這種情況下,相交圓圈的背景顏色將無關緊要。 此外,您不必擔心混合模式,因為內部光標具有背景顏色並且是隱藏的。 僅當鼠標懸停在主圓圈上時才能查看。

看這個例子:

 $(document).mousemove(function(e) { // elements let cursor = $('.cursor'); let innerCursor = $('.inner-cursor'); let c2 = $('.circle'); let pos = { left: e.pageX - 25, top: e.pageY - 20 }; cursor.css(pos); innerCursor.css({ left: pos.left - c2.offset().left, top: pos.top - c2.offset().top }); // circles // radius var d1 = cursor.outerWidth(true) / 2; var d2 = c2.outerWidth(true) / 2; // centers of first circle var x1 = cursor.offset().left + cursor.width() / 2; var y1 = cursor.offset().top + cursor.height() / 2; // centers of second circle var x2 = c2.offset().left + c2.width() / 2; var y2 = c2.offset().top + c2.height() / 2; var i1 = c2.find('.inter1'); var i2 = c2.find('.inter2'); var o = cursor.find('.overlap'); function calc() { var a = d2; var b = d1; var c = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); var d = (b * b + c * c - a * a) / (2 * c); var h = Math.sqrt((b * b) - (d * d)); // console.log(a, b, c, d, h); if (d < 0 || $.isNumeric(h)) { c2.css('border-color', 'red'); } else { c2.css('border-color', 'black'); } var x3 = (x2 - x1) * d / c + (y2 - y1) * h / c + x1; var y3 = (y2 - y1) * d / c - (x2 - x1) * h / c + y1; var x4 = (x2 - x1) * d / c - (y2 - y1) * h / c + x1; var y4 = (y2 - y1) * d / c + (x2 - x1) * h / c + y1; if ($.isNumeric(h)) { i1.show(); i2.show(); } else { i1.hide(); i2.hide(); } i1.offset({ top: y3 - 5, left: x3 - 5 }); i2.offset({ top: y4 - 5, left: x4 - 5 }); } calc(); });
 body { background: #fff; } .clip { display: inline-block; background: blue; height: 50px; width: 50px; border-radius: 50%; clip-path: ellipse(50px 50px at 50% 0%); position: absolute; left: 750px; top: 40px; } .cursor { left: 750px; top: 40px; } .cursor { height: 50px; width: 50px; border-radius: 50%; position: absolute; pointer-events: none; z-index: 999; border: 1px solid black; outline: 1px solid #c9d3ff; overflow: none; mix-blend-mode: multiply; background: rgba(100, 100, 100, 0.1); } .circle { background: rgba(100, 100, 100, 0.1); border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 200px; height: 200px; border: 1px solid black; outline: 1px solid #c9d3ff; overflow: hidden; } .circle::after, .cursor::after { display: block; content: ''; height: 1px; background: #c9d3ff; position: absolute; top: 50%; left: 0; right: 0; } .circle::before, .cursor::before { display: block; content: ''; width: 1px; background: #c9d3ff; position: absolute; left: 50%; top: 0; bottom: 0; } .inter { width: 10px; height: 10px; background: black; border-radius: 50%; position: absolute; display: none; } .inner-cursor { height: 50px; width: 50px; border-radius: 50%; position: absolute; pointer-events: none; background: green; left: 50%; top: 50%; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="cursor"> </div> <span class="clip"></span> <div class="circle"> <div class='inner-cursor'></div> <div class="inter1 inter"></div> <div class="inter2 inter"></div> </div>

僅使用 CSS 的簡單想法是使用background-attachement:fixedradial-gradient視為背景。 您將此背景應用於光標元素,並使其尺寸/位置與固定元素相同。

您需要在代碼中添加的所有內容是:

background:radial-gradient(circle,blue 100px,transparent 100px) fixed no-repeat

我還優化了代碼以刪除您使用偽元素繪制的線條以考慮linear-gradient

 $(document).mousemove(function(e) { $('.cursor').eq(0).css({ left: e.pageX - 25, top: e.pageY - 20 }); // circles var c1 = $('.cursor'); var c2 = $('.circle'); // radius var d1 = c1.outerWidth(true)/2; var d2 = c2.outerWidth(true)/2; // centers of first circle var x1 = c1.offset().left + c1.width()/2; var y1 = c1.offset().top + c1.height()/2; // centers of second circle var x2 = c2.offset().left + c2.width()/2; var y2 = c2.offset().top + c2.height()/2; var i1 = c2.find('.inter1'); var i2 = c2.find('.inter2'); var o = c1.find('.overlap'); function calc() { var a = d2; var b = d1; var c = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); var d = (b*b+c*ca*a)/(2*c); var h = Math.sqrt((b*b) - (d*d)); if (d < 0 || $.isNumeric(h)) { c2.css('border-color', 'red'); } else { c2.css('border-color', 'black'); } var x3 = (x2-x1)*d/c + (y2-y1)*h/c + x1; var y3 = (y2-y1)*d/c - (x2-x1)*h/c + y1; var x4 = (x2-x1)*d/c - (y2-y1)*h/c + x1; var y4 = (y2-y1)*d/c + (x2-x1)*h/c + y1; if ($.isNumeric(h)) { i1.show(); i2.show(); } else { i1.hide(); i2.hide(); } i1.offset({ top: y3-5, left: x3-5}); i2.offset({ top: y4-5, left: x4-5}); } calc(); });
 body { background: #fff; margin:0; } *{ box-sizing:border-box; } .cursor { height: 50px; width: 50px; border-radius: 50%; position: absolute; pointer-events: none; z-index: 999; border: 1px solid black; outline: 1px solid #c9d3ff; background: linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px, linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%, radial-gradient(circle,blue 100px,transparent 101px) fixed, yellow; background-repeat:no-repeat; } .circle { border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 200px; height: 200px; border: 1px solid black; outline: 1px solid #c9d3ff; background: linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px, linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%, #f2f2f2; background-repeat:no-repeat; } .inter { width: 10px; height: 10px; background: black; border-radius: 50%; position: absolute; display: none; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="cursor"> </div> <div class="circle"> <div class="inter1 inter"></div> <div class="inter2 inter"></div> <div>

如果圓圈不在中間,您只需調整位置即可。

 $(document).mousemove(function(e) { $('.cursor').eq(0).css({ left: e.pageX - 25, top: e.pageY - 20 }); // circles var c1 = $('.cursor'); var c2 = $('.circle'); // radius var d1 = c1.outerWidth(true)/2; var d2 = c2.outerWidth(true)/2; // centers of first circle var x1 = c1.offset().left + c1.width()/2; var y1 = c1.offset().top + c1.height()/2; // centers of second circle var x2 = c2.offset().left + c2.width()/2; var y2 = c2.offset().top + c2.height()/2; var i1 = c2.find('.inter1'); var i2 = c2.find('.inter2'); var o = c1.find('.overlap'); function calc() { var a = d2; var b = d1; var c = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); var d = (b*b+c*ca*a)/(2*c); var h = Math.sqrt((b*b) - (d*d)); if (d < 0 || $.isNumeric(h)) { c2.css('border-color', 'red'); } else { c2.css('border-color', 'black'); } var x3 = (x2-x1)*d/c + (y2-y1)*h/c + x1; var y3 = (y2-y1)*d/c - (x2-x1)*h/c + y1; var x4 = (x2-x1)*d/c - (y2-y1)*h/c + x1; var y4 = (y2-y1)*d/c + (x2-x1)*h/c + y1; if ($.isNumeric(h)) { i1.show(); i2.show(); } else { i1.hide(); i2.hide(); } i1.offset({ top: y3-5, left: x3-5}); i2.offset({ top: y4-5, left: x4-5}); } calc(); });
 body { background: #fff; margin:0; } *{ box-sizing:border-box; } .cursor { height: 50px; width: 50px; border-radius: 50%; position: absolute; pointer-events: none; z-index: 999; border: 1px solid black; outline: 1px solid #c9d3ff; background: linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px, linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%, radial-gradient(circle at 20% 50%,blue 100px,transparent 101px) fixed yellow; background-repeat:no-repeat; } .circle { border-radius: 50%; position: absolute; top: 50%; left: 20%; transform: translate(-50%, -50%); width: 200px; height: 200px; border: 1px solid black; outline: 1px solid #c9d3ff; background: linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px, linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%, #f2f2f2; background-repeat:no-repeat; } .inter { width: 10px; height: 10px; background: black; border-radius: 50%; position: absolute; display: none; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="cursor"> </div> <div class="circle"> <div class="inter1 inter"></div> <div class="inter2 inter"></div> <div>

我們基本上使用相同的 top/left 值來獲得以下內容:

radial-gradient(circle at [left] [top],blue [radius],transparent [radius]);

我將1px添加到透明以避免鋸齒狀邊緣

如果您對 HTML <canvas>元素感到滿意,它可能是您執行此類任務的最佳朋友,我懷疑是否有一種 CSS 方式可以實現您想要的效果。

如果有一種 CSS 方式,它可能會比用畫布做的要復雜得多,而且性能要慢得多

你可以看看下面的代碼來獲得靈感( 源代碼和現場示例

 <!DOCTYPE HTML> <html> <head> <style> body { margin: 0px; padding: 0px; } </style> </head> <body data-rsssl=1> <canvas id="myCanvas" width="578" height="200"></canvas> <script> var canvas = document.getElementById('myCanvas'); var context = canvas.getContext('2d'); var x = canvas.width / 2; var y = canvas.height / 2; var radius = 75; var offset = 50; /* * save() allows us to save the canvas context before * defining the clipping region so that we can return * to the default state later on */ context.save(); context.beginPath(); context.arc(x, y, radius, 0, 2 * Math.PI, false); context.clip(); // draw blue circle inside clipping region context.beginPath(); context.arc(x - offset, y - offset, radius, 0, 2 * Math.PI, false); context.fillStyle = 'blue'; context.fill(); // draw yellow circle inside clipping region context.beginPath(); context.arc(x + offset, y, radius, 0, 2 * Math.PI, false); context.fillStyle = 'yellow'; context.fill(); // draw red circle inside clipping region context.beginPath(); context.arc(x, y + offset, radius, 0, 2 * Math.PI, false); context.fillStyle = 'red'; context.fill(); /* * restore() restores the canvas context to its original state * before we defined the clipping region */ context.restore(); context.beginPath(); context.arc(x, y, radius, 0, 2 * Math.PI, false); context.lineWidth = 10; context.strokeStyle = 'blue'; context.stroke(); </script> </body> </html>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM