简体   繁体   English

如何仅使两个重叠图像的重叠部分响应透明?

[英]How to make only the overlapping part of two overlapping images responsively transparent?

I used clip-path to overlap the two images and make only the overlap transparent:我使用clip-path重叠两个图像并仅使重叠透明:

 .bg { position: absolute; top: 0px; left: 0px; } .image-red { position: absolute; top: 150px; left: 150px; clip-path: polygon(0px 0px, 150px 0, 150px 50px, 50px 50px, 50px 150px, 0 150px); } .image-green { position: absolute; top: 200px; left: 200px; clip-path: polygon(100px 0, 150px 0, 150px 150px, 0 150px, 0 100px, 100px 100px); }
 <img class="bg" src="https://via.placeholder.com/500/ffffff/888888/500x500.png"> <img class="image-red" src="https://via.placeholder.com/150/ffeeee/ff8888/150x150.png"> <img class="image-green" src="https://via.placeholder.com/150/eeffee/008800/150x150.png">

However, this does not work if the image is placed in % , vw , vh ...但是,如果图像放置在%vwvh ...

I don't want to use JavaScript if possible, is this a solution to this problem in CSS (or JavaScript)?如果可能的话,我不想使用 JavaScript,这是 CSS(或 JavaScript)中这个问题的解决方案吗?

I don't think that it is possible to use pure CSS to do the above, but if someone has a solution using pure CSS, please do share ;-)我不认为可以使用纯 CSS 来完成上述操作,但是如果有人有使用纯 CSS 的解决方案,请分享;-)

As for my solution, here's the minimal working example (adjust the position of the two images arbitrarily to see the effect).至于我的解决方案,这是最小的工作示例(任意调整两个图像的位置以查看效果)。

 let redImage = document.querySelector('img.image-red') let greenImage = document.querySelector('img.image-green') let redImageRect = redImage.getBoundingClientRect() let greenImageRect = greenImage.getBoundingClientRect() function returnIntersectionPoints(rectOne, rectTwo) { let intersectionLeft = Math.max(rectOne.left, rectTwo.left) let intersectionTop = Math.max(rectOne.top, rectTwo.top) let intersectionRight = Math.min(rectOne.right, rectTwo.right) let intersectionBottom = Math.min(rectOne.bottom, rectTwo.bottom) if (intersectionLeft < intersectionRight && intersectionTop < intersectionBottom) return { left: intersectionLeft, top: intersectionTop, right: intersectionRight, bottom: intersectionBottom } else return false } function returnClipPathPolygon(rect, clippedRect) { let horizontalClip = rect.left === clippedRect.left ? 'left' : 'right' let verticalClip = rect.top === clippedRect.top ? 'top' : 'bottom' let polygonPoints = [] if (horizontalClip === 'left' && verticalClip === 'top') { polygonPoints.push([clippedRect.right, clippedRect.bottom]) polygonPoints.push([clippedRect.right, clippedRect.top]) polygonPoints.push([rect.right, rect.top]) polygonPoints.push([rect.right, rect.bottom]) polygonPoints.push([rect.left, rect.bottom]) polygonPoints.push([clippedRect.left, clippedRect.bottom]) } else if (horizontalClip === 'right' && verticalClip === 'top') { polygonPoints.push([clippedRect.right, clippedRect.bottom]) polygonPoints.push([rect.right, rect.bottom]) polygonPoints.push([rect.left, rect.bottom]) polygonPoints.push([rect.left, rect.top]) polygonPoints.push([clippedRect.left, clippedRect.top]) polygonPoints.push([clippedRect.left, clippedRect.bottom]) } else if (horizontalClip === 'left' && verticalClip === 'bottom') { polygonPoints.push([rect.right, rect.top]) polygonPoints.push([rect.right, rect.bottom]) polygonPoints.push([clippedRect.right, clippedRect.bottom]) polygonPoints.push([clippedRect.right, clippedRect.top]) polygonPoints.push([clippedRect.left, clippedRect.top]) polygonPoints.push([rect.left, rect.top]) } else if (horizontalClip === 'right' && verticalClip === 'bottom') { polygonPoints.push([rect.right, rect.top]) polygonPoints.push([clippedRect.right, clippedRect.top]) polygonPoints.push([clippedRect.left, clippedRect.top]) polygonPoints.push([clippedRect.left, clippedRect.bottom]) polygonPoints.push([rect.left, rect.bottom]) polygonPoints.push([rect.left, rect.top]) } let polygonString = 'polygon(' polygonPoints.forEach(point => { polygonString += `${point[0] - rect.left}px ${point[1] - rect.top}px, ` }) polygonString = polygonString.substring(0, polygonString.length - 2) polygonString += ')' return polygonString } let intersectionPoints = returnIntersectionPoints(redImageRect, greenImageRect) if (intersectionPoints) { redImage.style.clipPath = returnClipPathPolygon(redImageRect, intersectionPoints) greenImage.style.clipPath = returnClipPathPolygon(greenImageRect, intersectionPoints) }
 .bg { position: absolute; top: 0px; left: 0px; } .image-red { position: absolute; top: 10%; left: 20%; } .image-green { position: absolute; top: 25%; left: 15%; }
 <img class="bg" src="https://via.placeholder.com/500/ffffff/888888/500x500.png"> <img class="image-red" src="https://via.placeholder.com/150/ffeeee/ff8888/150x150.png"> <img class="image-green" src="https://via.placeholder.com/150/eeffee/008800/150x150.png">

Basically, what I'm doing is:基本上,我正在做的是:

  • Find intersecting points of the two rectangles (if intersection does occur) using the function returnIntersectionPoints .使用函数returnIntersectionPoints查找两个矩形的相交点(如果确实发生了相交)。
  • If there is an intersecting point, I will call the function returnClipPathPolygon to form the polygon string value to pass to clip-path for each of the images.如果有交点,我将调用函数returnClipPathPolygon来形成polygon字符串值,以传递给每个图像的剪辑路径。

EDIT编辑

The above code fails when one image can totally encompass the other image.当一个图像可以完全包含另一个图像时,上面的代码失败。 Also, the returnClipPathPolygon function is a bit lengthy.此外, returnClipPathPolygon函数有点冗长。 As a result, I came up with a new idea to deal with said problems:结果,我想出了一个新的想法来处理上述问题:

  • Get the intersection points of the two rectangles获取两个矩形的交点
  • Create a replica bg that acts as an overlay.创建一个副本bg作为覆盖。 This replica is clipped to a shape based on the intersection points (always will be a rectangle)这个副本根据交点被剪裁成一个形状(总是一个矩形)
  • Use that replica bg to cover the other two images (by using z-index ), thus making the two images appear transparent (when it's really not)使用副本 bg 覆盖其他两个图像(通过使用z-index ),从而使两个图像看起来透明(当它真的不是时)

Here's the working example below:这是下面的工作示例:

 window.onload = (() => { let redImage = document.querySelector('img.image-red') let greenImage = document.querySelector('img.image-green') let redImageRect = redImage.getBoundingClientRect() let greenImageRect = greenImage.getBoundingClientRect() function returnIntersectionPoints(rectOne, rectTwo) { let intersectionLeft = Math.max(rectOne.left, rectTwo.left) let intersectionTop = Math.max(rectOne.top, rectTwo.top) let intersectionRight = Math.min(rectOne.right, rectTwo.right) let intersectionBottom = Math.min(rectOne.bottom, rectTwo.bottom) if (intersectionLeft < intersectionRight && intersectionTop < intersectionBottom) return { left: intersectionLeft, top: intersectionTop, right: intersectionRight, bottom: intersectionBottom } else return false } function returnClipPathInset(rect, intersectionPoints) { let insetTop = intersectionPoints.top let insetRight = rect.right - intersectionPoints.right let insetBottom = rect.bottom - intersectionPoints.bottom let insetLeft = intersectionPoints.left return `inset(${insetTop}px ${insetRight}px ${insetBottom}px ${insetLeft}px` } let intersectionPoints = returnIntersectionPoints(redImageRect, greenImageRect) if (intersectionPoints) { let bg = document.querySelector('img.bg') let bgRect = bg.getBoundingClientRect() let bgReplicaOverlay = document.createElement('img') let clipPathValue = returnClipPathInset(bgRect, intersectionPoints) bgReplicaOverlay.classList.add('bg') bgReplicaOverlay.src = bg.src bgReplicaOverlay.style.zIndex = 2 bgReplicaOverlay.style.clipPath = clipPathValue document.querySelector('body').prepend(bgReplicaOverlay) } })
 .bg { position: absolute; top: 0px; left: 0px; } .image-red { position: absolute; top: 10%; left: 10%; } .image-green { width: 100px; position: absolute; top: 15%; left: 12.5%; }
 <img class="bg" src="https://via.placeholder.com/500/ffffff/888888/500x500.png"> <img class="image-red" src="https://via.placeholder.com/150/ffeeee/ff8888/150x150.png"> <img class="image-green" src="https://via.placeholder.com/150/eeffee/008800/150x150.png">

The two codes above do not handle window resizing.上面的两个代码不处理窗口大小调整。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM