gpt4 book ai didi

javascript - "Clipping"背景在堆叠上下文中看到自身下方

转载 作者:行者123 更新时间:2023-12-03 15:37:28 39 4
gpt4 key购买 nike

[注意:寻找一个跨浏览器的解决方案,它不会在每一波 goo 之间瞬间闪烁 body 的背景,如 ccprog 的回答中所见;理想情况下,解决方案不应涉及等到第一波结束才开始显示第二波,以便两个波可以同时运行。为了获得理想的解决方案,我愿意放弃动态随机 goop。 ]
有谁知道我怎样才能让第二波橙色粘液 (.goo-two) “穿过”第一波棕色粘液 (.goo-one) 和天蓝色容器 (.goo-container) 以显示或暴露红色主体元素( body )或者,就此而言,堆叠上下文中它下面的任何其他元素?可能吗?
值得注意的是,我给容器(.goo-container)一个坚实的背景的原因是因为我用它来掩盖网站其余部分的加载过程,我希望橙色粘液(.goo-two)可以用于显示内容。它变得更加棘手,因为橙色粘液在棕色粘液完成之前就开始滴落,这将是从 .goo-container 更改 contianer (skyblue) 背景的最佳时机至transparent ,尽管可以使用半透明渐变作为背景来实现这一点。 (无论是那个还是完全不同的东西,比如复制橙色层并使用一个来剪辑棕色路径,另一个来剪辑天蓝色层。)
有任何想法吗?

const
gooCont = document.querySelector('div.goo-container'),
gooOne = gooCont.querySelector('div.goo-one'),
gooTwo = gooCont.querySelector('div.goo-two'),
rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min

gooCont.style.setProperty('--translateY', `translateY(-${innerWidth * 0.21 / innerHeight * 100 + 100}%)`)
generateGoo(gooOne)

function generateGoo(goo) {
const
randQty = rand(20,30),
unit = innerWidth / (randQty - 1) / innerWidth * 100
if (getComputedStyle(goo).display === 'none') goo.style.display = 'block'
for (let i = 0; i < randQty; i++) {
const
div = document.createElement('div'),
minWidthPx = innerWidth < 500 ? innerWidth * 0.1 : innerWidth * 0.05,
minMaxWidthPx = innerWidth < 500 ? innerWidth * 0.2 : innerWidth * 0.1,
widthPx = rand(minWidthPx, minMaxWidthPx),
widthPerc = widthPx / innerWidth * 100,
heightPx = rand(widthPx / 2, widthPx * 3),
heightPerc = heightPx / gooCont.getBoundingClientRect().height * 100,
translateY = rand(45, 70),
targetTranslateY = rand(15, 100),
borderRadiusPerc = rand(40, 50)
div.style.width = widthPerc + '%'
div.style.height = heightPerc + '%'
div.style.left = i * unit + '%'
div.style.transform = `translate(-50%, ${translateY}%)`
div.style.borderRadius = borderRadiusPerc + '%'
div.setAttribute('data-translate', targetTranslateY)
goo.appendChild(div)
}
goo.style.transform = `translateY(0)`
goo.childNodes.forEach(
v => v.style.transform = `translateY(${v.getAttribute('data-translate')}%)`
)
}

setTimeout(() => {
gooTwo.innerHTML = ''
generateGoo(gooTwo)
}, 2300)
html,
body {
width: 100%;
height: 100%;
margin: 0;
background: red;
}

div.goo-container {
--translateY: translateY(-165%);
z-index: 1;
width: 100%;
height: 100%;
position: fixed;
overflow: hidden;
background: skyblue;
}

div.goo-container > div.goo-one,
div.goo-container > div.goo-two {
width: 100%;
height: 100%;
position: absolute;
transform: var(--translateY);
filter: url('#goo-filter');
background: #5b534a;
transition: transform 2.8s linear;
}

div.goo-container > div.goo-one > div,
div.goo-container > div.goo-two > div {
position: absolute;
bottom: 0;
background: #5b534a;
transition: transform 2.8s linear;
}

div.goo-container > div.goo-two {
display: none;
transition: transform 2.8s linear;
}

div.goo-container > div.goo-two,
div.goo-container > div.goo-two > div {
background: orange;
}

svg {
/* Prevents effect on Firefox */
/* display: none; */
}
<div class='goo-container'>
<div class='goo-one'></div>
<div class='goo-two'></div>
</div>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1'>
<defs>
<filter id='goo-filter'>
<feGaussianBlur in='SourceGraphic' stdDeviation='10' result='blur' />
<feColorMatrix in='blur' mode='matrix' values='1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7' result='goo' />
<feBlend in='SourceGraphic' in2='goo' />
</filter>
</defs>
</svg>

最佳答案

我很确定这不是最佳变体,但它似乎奏效了,至少在 Firefox 中是这样。 Chrome 对动画每个部分的初始帧都有一些问题。

  • 我稍微重写了粘性过滤器代码以提高可读性,同时保持相同的效果。解释见my article .
  • 仅限 .goo-one并且子 div 获得背景颜色。这使得 .goo-two 成为可能变得透明。
  • 两个部分得到不同的过滤器,但过滤器区域垂直增加,以便在过渡开始时到达屏幕底部。
  • 第一个过滤器具有天蓝色作为背景填充。
  • 第二个过滤器有一个棕色填充,但它的应用是相反的:它只显示在粘性区域之外,而内部区域是空的。组成 goo 区域的 div 矩形不跨越整个 .gooTwo .为了也填充(并在反转后,清空)顶部,额外的 <div class="first">是需要的。
  • 在第二个 goo 部分的过渡开始时,过滤器区域上限设置为低于屏幕下边界。这隐藏了天蓝色背景,同时第二个粘性部分变得可见。
  • 注意 svg 的 CSS 的细微变化元素以获得更好的浏览器兼容性。
  • 就像概念证明一样,在容器 div 中添加了一些内容。它表明 pointer-event: none需要;否则无法与页面交互。

  • const
    gooCont = document.querySelector('div.goo-container'),
    gooOne = gooCont.querySelector('div.goo-one'),
    gooTwo = gooCont.querySelector('div.goo-two'),
    filterOne = document.querySelector('#goo-filter-one')
    rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min

    gooCont.style.setProperty('--translateY', `translateY(-${innerWidth * 0.21 / innerHeight * 100 + 100}%)`)
    generateGoo(gooOne)

    function generateGoo(goo) {
    const
    randQty = rand(20,30),
    unit = innerWidth / (randQty - 1) / innerWidth * 100

    if (getComputedStyle(goo).display === 'none') goo.style.display = 'block'
    goo.removeAttribute('y')

    for (let i = 0; i < randQty; i++) {
    const
    div = document.createElement('div'),
    minWidthPx = innerWidth < 500 ? innerWidth * 0.1 : innerWidth * 0.05,
    minMaxWidthPx = innerWidth < 500 ? innerWidth * 0.2 : innerWidth * 0.1,
    widthPx = rand(minWidthPx, minMaxWidthPx),
    widthPerc = widthPx / innerWidth * 100,
    heightPx = rand(widthPx / 2, widthPx * 3),
    heightPerc = heightPx / gooCont.getBoundingClientRect().height * 100,
    translateY = rand(45, 70),
    targetTranslateY = rand(15, 100),
    borderRadiusPerc = rand(40, 50)
    div.style.width = widthPerc + '%'
    div.style.height = heightPerc + '%'
    div.style.left = i * unit + '%'
    div.style.transform = `translate(-50%, ${translateY}%)`
    div.style.borderRadius = borderRadiusPerc + '%'
    div.setAttribute('data-translate', targetTranslateY)
    goo.appendChild(div)
    }
    goo.style.transform = `translateY(0)`
    goo.childNodes.forEach(
    v => v.style.transform = `translateY(${v.getAttribute('data-translate')}%)`
    )
    }

    setTimeout(() => {
    gooTwo.innerHTML = '<div class="first"></div>'
    filterOne.setAttribute('y', '100%')
    generateGoo(gooTwo, true)
    }, 2300)
    html,
    body {
    width: 100%;
    height: 100%;
    margin: 0;
    background: red;
    }

    div.goo-container {
    --translateY: translateY(-165%);
    z-index: 1;
    width: 100%;
    height: 100%;
    position: fixed;
    overflow: hidden;
    }

    div.goo-container > div {
    width: 100%;
    height: 100%;
    position: absolute;
    pointer-events: none;
    transform: var(--translateY);
    transition: transform 2.8s linear;
    }

    div.goo-container > div.goo-one {
    filter: url('#goo-filter-one');
    background: #5b534a;
    }

    div.goo-container > div.goo-two {
    display: none;
    filter: url('#goo-filter-two');
    }

    div.goo-container > div.goo-one > div,
    div.goo-container > div.goo-two > div {
    position: absolute;
    bottom: 0;
    background: #5b534a;
    transition: transform 2.8s linear;
    }

    div.goo-container > div.goo-two > div.first {
    top: -10%;
    width: 100%;
    height: 110%;
    }

    svg {
    width: 0;
    height: 0;
    }
    <div class='goo-container'>
    <div class='goo-one'></div>
    <div class='goo-two'></div>
    <p><a href="#">Click me</a> and read.</p>
    </div>
    <svg xmlns='http://www.w3.org/2000/svg' version='1.1'>
    <filter id='goo-filter-one' height='200%'>
    <feGaussianBlur in='SourceGraphic' stdDeviation='10' result='blur' />
    <feComponentTransfer in='blur' result='goo'>
    <feFuncA type='linear' slope='18' intercept='-7' />
    </feComponentTransfer>
    <feFlood flood-color='skyblue' result='back' />
    <feMerge>
    <feMergeNode in='back' />
    <feMergeNode in='goo' />
    </feMerge>
    </filter>
    <filter id='goo-filter-two' height='200%'>
    <feGaussianBlur in='SourceGraphic' stdDeviation='10' result='blur' />
    <feComponentTransfer in='blur' result='goo'>
    <feFuncA type='linear' slope='18' intercept='-7' />
    </feComponentTransfer>
    <feFlood flood-color='#5b534a' result='back' />
    <feComposite operator='out' in='back' in2='goo' />
    </filter>
    </svg>

    关于javascript - "Clipping"背景在堆叠上下文中看到自身下方,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64976357/

    39 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com