亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

“裁剪”背景以在堆疊上下文中看到下方本身

“裁剪”背景以在堆疊上下文中看到下方本身

慕神8447489 2023-06-15 16:53:14
[注意:尋找一種跨瀏覽器的解決方案,它不會像 ccprog 的答案中所見那樣在每一波 goo 之間瞬間閃爍身體的背景;理想情況下,解決方案不應涉及等到第一個 wave 結束才開始顯示第二個 wave,以便兩個 wave 可以同時運行。我愿意放棄動態隨機化的 goop 以獲得理想的解決方案。]有誰知道我怎樣才能讓第二波橙色黏液 ( .goo-two) “切開”第一波棕色黏液 ( .goo-one) 和天藍色容器 ( .goo-container) 以顯示或暴露紅色主體元素 ( body),或者就此而言,任何堆疊上下文中它下面的其他元素?是否可以?值得注意的是,我給容器 ( .goo-container) 一個堅實的背景的原因是因為我用它來掩蓋網站其余部分的加載過程,因此我希望橙色粘液 ( .goo-two) 可以用來揭示內容。它變得更加棘手,因為橙色粘液在棕色粘液完成之前開始滴落,這將是將 contianer ( .goo-container) 的背景從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)) + mingooCont.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)
查看完整描述

3 回答

?
POPMUISE

TA貢獻1765條經驗 獲得超5個贊

我很確定這不是最佳變體,但它似乎可行,至少在 Firefox 中是這樣。Chrome 在動畫每個部分的初始幀方面存在一些問題。

  • 我稍微重寫了 gooey 過濾器代碼以提高可讀性,同時保持相同的效果。

  • 只有.goo-one和子 div 獲得背景顏色。這使得.goo-two變得透明成為可能。

  • 這兩個部分有不同的過濾器,但過濾器區域垂直增加,以便在過渡開始時到達屏幕底部。

  • 第一個濾鏡使用天藍色作為背景填充。

  • 第二個過濾器有一個棕色填充,但它的應用是相反的:它只顯示在 goo 區域之外,而內部區域是空的。構成 goo 區域的 div 矩形不跨越整個.gooTwo.?為了也填充(并在倒置后為空)頂部,<div class="first">需要額外的部分。

  • 在第二個 goo 部分的過渡開始時,過濾器區域上限設置在屏幕下邊界下方。這隱藏了天藍色背景,同時第二個粘性部分變得可見。

  • 請注意,為了更好的瀏覽器兼容性,元素的 CSS 略有變化svg。

  • 作為概念證明,在容器 div 中添加了一些內容。表明pointer-event: none需要a;否則無法與頁面進行交互。

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>


查看完整回答
反對 回復 2023-06-15
?
慕桂英3389331

TA貢獻2036條經驗 獲得超8個贊

首先,我將開始使用一個 div 和多個漸變來構建形狀。


這是一個使用我們可以輕松定位的不固定漸變(相同寬度和不同高度)的想法:


Hide code snippet


:root {

  --c:linear-gradient(red,red);

}

div.goo-container {

  position:fixed;

  top:0;

  left:-20px;

  right:-20px;

  height:200px;

  background:

     var(--c) calc(0*100%/9) 0/calc(100%/10) 80%,

     var(--c) calc(1*100%/9) 0/calc(100%/10) 60%,

     var(--c) calc(2*100%/9) 0/calc(100%/10) 30%,

     var(--c) calc(3*100%/9) 0/calc(100%/10) 50%,

     var(--c) calc(4*100%/9) 0/calc(100%/10) 59%,

     var(--c) calc(5*100%/9) 0/calc(100%/10) 48%,

     var(--c) calc(6*100%/9) 0/calc(100%/10) 36%,

     var(--c) calc(7*100%/9) 0/calc(100%/10) 70%,

     var(--c) calc(8*100%/9) 0/calc(100%/10) 75%,

     var(--c) calc(9*100%/9) 0/calc(100%/10) 35%;

  background-repeat:no-repeat;

  filter: url('#goo-filter');

}

<div class='goo-container'>

</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 20 -5' result='goo' />

      <feBlend in='SourceGraphic' in2='goo' />

    </filter>

  </defs>

</svg>

展開片段

我們也可以有可變寬度,這里需要 JS 來生成所有這些寬度:


Hide code snippet


:root {

  --c:linear-gradient(red,red);

}

div.goo-container {

  position:fixed;

  top:0;

  left:-20px;

  right:-20px;

  height:200px;

  background:

     var(--c) 0     0/20px 80%,

     var(--c) 20px  0/80px 60%,

     var(--c) 100px 0/10px 30%,

     var(--c) 110px 0/50px 50%,

     var(--c) 160px 0/30px 59%,

     var(--c) 190px 0/80px 48%,

     var(--c) 270px 0/10px 36%,

     var(--c) 280px 0/20px 70%,

     var(--c) 300px 0/50px 75%,

     var(--c) 350px 0/80px 35%

     /* and so on ... */;

  background-repeat:no-repeat;

  filter: url('#goo-filter');

}

<div class='goo-container'>

</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 20 -5' result='goo' />

      <feBlend in='SourceGraphic' in2='goo' />

    </filter>

  </defs>

</svg>

展開片段

然后用更多的 CSS 我們可以有我們的第一個動畫:


Hide code snippet


:root {

  --c:linear-gradient(red,red);

}

div.goo-container {

  position:fixed;

  height:100vh;

  top:0;

  left:0;

  right:0;

  background:red;

  transform:translateY(-150vh);

  animation:move 3s 1s forwards;

}


div.goo-container::after {

  position:absolute;

  content:"";

  top:100%;

  left:-20px;

  right:-20px;

  height:50vh;

  margin:0 -20px;

  background:

     var(--c) calc(0*100%/9) 0/calc(100%/10) 80%,

     var(--c) calc(1*100%/9) 0/calc(100%/10) 60%,

     var(--c) calc(2*100%/9) 0/calc(100%/10) 30%,

     var(--c) calc(3*100%/9) 0/calc(100%/10) 50%,

     var(--c) calc(4*100%/9) 0/calc(100%/10) 59%,

     var(--c) calc(5*100%/9) 0/calc(100%/10) 48%,

     var(--c) calc(6*100%/9) 0/calc(100%/10) 36%,

     var(--c) calc(7*100%/9) 0/calc(100%/10) 70%,

     var(--c) calc(8*100%/9) 0/calc(100%/10) 75%,

     var(--c) calc(9*100%/9) 0/calc(100%/10) 35%;

  background-repeat:no-repeat;

  filter: url('#goo-filter');

}

div.goo-container::before {

  position:absolute;

  content:"";

  top:100%;

  height:150vh;

  background:blue;

  left:0;

  right:0;

}


@keyframes move {

  to {

     transform:translateY(0);

  }

}

<div class='goo-container'>

</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 20 -5' result='goo' />

      <feBlend in='SourceGraphic' in2='goo' />

    </filter>

  </defs>

</svg>

展開片段

仍然不完美,但我們也可以添加一些漸變動畫來調整大?。?/p>


Hide code snippet


:root {

  --c:linear-gradient(red,red);

}

div.goo-container {

  position:fixed;

  height:100vh;

  top:0;

  left:0;

  right:0;

  background:red;

  transform:translateY(-150vh);

  animation:move 5s 0.5s forwards;

}


div.goo-container::after {

  position:absolute;

  content:"";

  top:100%;

  left:-20px;

  right:-20px;

  height:50vh;

  margin:0 -20px;

  background:

     var(--c) calc(0*100%/9) 0/calc(100%/10) 80%,

     var(--c) calc(1*100%/9) 0/calc(100%/10) 60%,

     var(--c) calc(2*100%/9) 0/calc(100%/10) 30%,

     var(--c) calc(3*100%/9) 0/calc(100%/10) 50%,

     var(--c) calc(4*100%/9) 0/calc(100%/10) 59%,

     var(--c) calc(5*100%/9) 0/calc(100%/10) 48%,

     var(--c) calc(6*100%/9) 0/calc(100%/10) 36%,

     var(--c) calc(7*100%/9) 0/calc(100%/10) 70%,

     var(--c) calc(8*100%/9) 0/calc(100%/10) 75%,

     var(--c) calc(9*100%/9) 0/calc(100%/10) 35%;

  background-repeat:no-repeat;

  filter: url('#goo-filter');

  animation:grad 4.5s 1s forwards;

}

div.goo-container::before {

  position:absolute;

  content:"";

  top:100%;

  height:150vh;

  background:blue;

  left:0;

  right:0;

}


@keyframes move {

  to {

     transform:translateY(0);

  }

}

@keyframes grad {

  to {

     background-size:

     calc(100%/10) 50%,

     calc(100%/10) 75%,

     calc(100%/10) 20%,

     calc(100%/10) 60%,

     calc(100%/10) 55%,

     calc(100%/10) 80%,

     calc(100%/10) 23%,

     calc(100%/10) 80%,

     calc(100%/10) 90%,

     calc(100%/10) 20%;

  }

}

<div class='goo-container'>

</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 20 -5' result='goo' />

      <feBlend in='SourceGraphic' in2='goo' />

    </filter>

  </defs>

</svg>

展開片段

上面有點棘手,因為每個漸變的位置將取決于所有前一個漸變的大?。ㄟ@里可能需要 JS 或 SASS 來生成代碼)


對于第二個動畫,我們將做同樣的事情,但我們認為遮罩屬性中的漸變層具有相反的效果(漸變層將被移除以查看剩余部分)


Hide code snippet


:root {

  --c:linear-gradient(red,red);

  background:pink;

}

div.goo-container {

  position:fixed;

  height:150vh;

  top:0;

  left:0;

  right:0;

  transform:translateY(-200vh);

  animation:move 8s 0.5s forwards;

  filter: url('#goo-filter');

}

div.goo-container > div {

  height:100%;

  background:red;

  -webkit-mask:

     var(--c) calc(0*100%/9) 0/calc(100%/10 + 4px) 40vh,

     var(--c) calc(1*100%/9) 0/calc(100%/10 + 4px) 30vh,

     var(--c) calc(2*100%/9) 0/calc(100%/10 + 4px) 15vh,

     var(--c) calc(3*100%/9) 0/calc(100%/10 + 4px) 20vh,

     var(--c) calc(4*100%/9) 0/calc(100%/10 + 4px) 29vh,

     var(--c) calc(5*100%/9) 0/calc(100%/10 + 4px) 35vh,

     var(--c) calc(6*100%/9) 0/calc(100%/10 + 4px) 12vh,

     var(--c) calc(7*100%/9) 0/calc(100%/10 + 4px) 50vh,

     var(--c) calc(8*100%/9) 0/calc(100%/10 + 4px) 48vh,

     var(--c) calc(9*100%/9) 0/calc(100%/10 + 4px) 40vh,

     linear-gradient(#fff,#fff);

  -webkit-mask-composite:destination-out;

  mask-composite:exclude;

  -webkit-mask-repeat:no-repeat;

  animation:mask 7.5s 1s forwards;

}


div.goo-container::after {

  position:absolute;

  content:"";

  top:100%;

  left:-20px;

  right:-20px;

  height:50vh;

  margin:0 -20px;

  background:

     var(--c) calc(0*100%/9) 0/calc(100%/10) 80%,

     var(--c) calc(1*100%/9) 0/calc(100%/10) 60%,

     var(--c) calc(2*100%/9) 0/calc(100%/10) 30%,

     var(--c) calc(3*100%/9) 0/calc(100%/10) 50%,

     var(--c) calc(4*100%/9) 0/calc(100%/10) 59%,

     var(--c) calc(5*100%/9) 0/calc(100%/10) 48%,

     var(--c) calc(6*100%/9) 0/calc(100%/10) 36%,

     var(--c) calc(7*100%/9) 0/calc(100%/10) 60%,

     var(--c) calc(8*100%/9) 0/calc(100%/10) 65%,

     var(--c) calc(9*100%/9) 0/calc(100%/10) 35%;

  background-repeat:no-repeat;

  filter: url('#goo-filter');

  animation:grad 7.5s 1s forwards;

}

div.goo-container::before {

  position:absolute;

  content:"";

  top:100%;

  height:150vh;

  background:blue;

  left:0;

  right:0;

}


@keyframes move {

  to {

     transform:translateY(150vh);

  }

}

@keyframes grad {

  to {

     background-size:

     calc(100%/10) 50%,

     calc(100%/10) 75%,

     calc(100%/10) 20%,

     calc(100%/10) 60%,

     calc(100%/10) 55%,

     calc(100%/10) 80%,

     calc(100%/10) 23%,

     calc(100%/10) 80%,

     calc(100%/10) 90%,

     calc(100%/10) 20%;

  }

}

@keyframes mask {

  to {

     -webkit-mask-size:

     calc(100%/10) 30vh,

     calc(100%/10) 10vh,

     calc(100%/10) 50vh,

     calc(100%/10) 45vh,

     calc(100%/10) 12vh,

     calc(100%/10) 22vh,

     calc(100%/10) 60vh,

     calc(100%/10) 10vh,

     calc(100%/10) 8vh,

     calc(100%/10) 35vh,

     auto;

  }

}

<h1>Lorem ipsum dolor sit amet</h1>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu sodales lectus. Sed non erat accumsan, placerat purus quis, sodales mi. Suspendisse potenti. Sed eu viverra odio. </p>




<div class='goo-container'>

  <div></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 20 -5' result='goo' />

      <feBlend in='SourceGraphic' in2='goo' />

    </filter>

  </defs>

</svg>

展開片段

我們做了一些代碼優化,只保留一個元素:


Hide code snippet


:root {

  --c:linear-gradient(red,red);

  background:pink;

}

div.goo-container {

  position:fixed;

  top:0;

  left:0;

  right:0;

  bottom:0;

  transform:translateY(-150%);

  animation:move 8s 0.5s forwards;

  filter: url('#goo-filter');

}


div.goo-container::after {

  position:absolute;

  content:"";

  top:-50%;

  left:0;

  right:0;

  bottom:-50%;

  background:

     var(--c) calc(0*100%/9) 0/calc(100%/10) calc(100% - 40vh),

     var(--c) calc(1*100%/9) 0/calc(100%/10) calc(100% - 30vh),

     var(--c) calc(2*100%/9) 0/calc(100%/10) calc(100% - 35vh),

     var(--c) calc(3*100%/9) 0/calc(100%/10) calc(100% - 50vh),

     var(--c) calc(4*100%/9) 0/calc(100%/10) calc(100% - 10vh),

     var(--c) calc(5*100%/9) 0/calc(100%/10) calc(100% - 15vh),

     var(--c) calc(6*100%/9) 0/calc(100%/10) calc(100% - 30vh),

     var(--c) calc(7*100%/9) 0/calc(100%/10) calc(100% - 28vh),

     var(--c) calc(8*100%/9) 0/calc(100%/10) calc(100% - 30vh),

     var(--c) calc(9*100%/9) 0/calc(100%/10) calc(100% - 50vh);

  background-repeat:no-repeat;

  -webkit-mask:

     var(--c) calc(0*100%/9) 100%/calc(100%/10 + 4px) calc(100% - 20vh),

     var(--c) calc(1*100%/9) 100%/calc(100%/10 + 4px) calc(100% - 10vh),

     var(--c) calc(2*100%/9) 100%/calc(100%/10 + 4px) calc(100% - 50vh),

     var(--c) calc(3*100%/9) 100%/calc(100%/10 + 4px) calc(100% - 30vh),

     var(--c) calc(4*100%/9) 100%/calc(100%/10 + 4px) calc(100% - 35vh),

     var(--c) calc(5*100%/9) 100%/calc(100%/10 + 4px) calc(100% - 10vh),

     var(--c) calc(6*100%/9) 100%/calc(100%/10 + 4px) calc(100% - 50vh),

     var(--c) calc(7*100%/9) 100%/calc(100%/10 + 4px) calc(100% - 40vh),

     var(--c) calc(8*100%/9) 100%/calc(100%/10 + 4px) calc(100% - 45vh),

     var(--c) calc(9*100%/9) 100%/calc(100%/10 + 4px) calc(100% - 35vh);

  -webkit-mask-repeat:no-repeat;

  filter: inherit;

  animation: inherit;

  animation-name:grad, mask;

}

div.goo-container::before {

  position:absolute;

  content:"";

  top:50%;

  bottom:-150%;

  background:blue;

  left:0;

  right:0;

}


@keyframes move {

  to {

     transform:translateY(200%);

  }

}

@keyframes grad {

  to {

     background-size:

     calc(100%/10) calc(100% - 10vh),

     calc(100%/10) calc(100% - 50vh),

     calc(100%/10) calc(100% - 30vh),

     calc(100%/10) calc(100% - 10vh),

     calc(100%/10) calc(100% - 40vh),

     calc(100%/10) calc(100% - 25vh),

     calc(100%/10) calc(100% - 32vh),

     calc(100%/10) calc(100% - 18vh),

     calc(100%/10) calc(100% - 50vh),

     calc(100%/10) calc(100% - 10vh);

  }

}

@keyframes mask {

  to {

     -webkit-mask-size:

     calc(100%/10) calc(100% - 10vh),

     calc(100%/10) calc(100% - 50vh),

     calc(100%/10) calc(100% - 10vh),

     calc(100%/10) calc(100% - 30vh),

     calc(100%/10) calc(100% - 32vh),

     calc(100%/10) calc(100% - 40vh),

     calc(100%/10) calc(100% - 50vh),

     calc(100%/10) calc(100% - 25vh),

     calc(100%/10) calc(100% - 18vh),

     calc(100%/10) calc(100% - 10vh);

  }

}

<h1>Lorem ipsum dolor sit amet</h1>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu sodales lectus. Sed non erat accumsan, placerat purus quis, sodales mi. Suspendisse potenti. Sed eu viverra odio. </p>




<div class='goo-container'></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 20 -5' result='goo' />

      <feBlend in='SourceGraphic' in2='goo' />

    </filter>

  </defs>

</svg>

展開片段

最后是使用 SASS 生成漸變層和遮罩層的動態解決方案:https://codepen.io/t_afif/pen/oNzxYgV


更新


不使用面具的另一個想法。訣竅是使漸變居中。此解決方案將有更多支持,但底部和頂部形狀都是對稱的


Hide code snippet


:root {

  --c:linear-gradient(red,red);

  background:pink;

}

div.goo-container {

  position:fixed;

  top:0;

  left:0;

  right:0;

  bottom:0;

  transform:translateY(-150%);

  animation:move 8s 0.5s forwards;

  filter: url('#goo-filter');

}


div.goo-container::after {

  position:absolute;

  content:"";

  top:-50%;

  left:0;

  right:0;

  bottom:-50%;

  background:

     var(--c) calc(0*100%/9) 50%/calc(100%/10) calc(100% - 80vh),

     var(--c) calc(1*100%/9) 50%/calc(100%/10) calc(100% - 60vh),

     var(--c) calc(2*100%/9) 50%/calc(100%/10) calc(100% - 70vh),

     var(--c) calc(3*100%/9) 50%/calc(100%/10) calc(100% - 100vh),

     var(--c) calc(4*100%/9) 50%/calc(100%/10) calc(100% - 20vh),

     var(--c) calc(5*100%/9) 50%/calc(100%/10) calc(100% - 30vh),

     var(--c) calc(6*100%/9) 50%/calc(100%/10) calc(100% - 60vh),

     var(--c) calc(7*100%/9) 50%/calc(100%/10) calc(100% - 56vh),

     var(--c) calc(8*100%/9) 50%/calc(100%/10) calc(100% - 60vh),

     var(--c) calc(9*100%/9) 50%/calc(100%/10) calc(100% - 100vh);

  background-repeat:no-repeat;

  filter: inherit;

  animation:grad 8s 0.5s forwards;

}

div.goo-container::before {

  position:absolute;

  content:"";

  top:50%;

  bottom:-150%;

  background:blue;

  left:0;

  right:0;

}


@keyframes move {

  to {

     transform:translateY(200%);

  }

}

@keyframes grad {

  to {

     background-size:

     calc(100%/10) calc(100% - 20vh),

     calc(100%/10) calc(100% - 100vh),

     calc(100%/10) calc(100% - 60vh),

     calc(100%/10) calc(100% - 20vh),

     calc(100%/10) calc(100% - 80vh),

     calc(100%/10) calc(100% - 50vh),

     calc(100%/10) calc(100% - 64vh),

     calc(100%/10) calc(100% - 34vh),

     calc(100%/10) calc(100% - 100vh),

     calc(100%/10) calc(100% - 20vh);

  }

}

<h1>Lorem ipsum dolor sit amet</h1>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu sodales lectus. Sed non erat accumsan, placerat purus quis, sodales mi. Suspendisse potenti. Sed eu viverra odio. </p>




<div class='goo-container'></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 20 -5' result='goo' />

      <feBlend in='SourceGraphic' in2='goo' />

    </filter>

  </defs>

</svg>

展開片段

還有一個 SASS 版本:https://codepen.io/t_afif/pen/wvzGoeJ


查看完整回答
反對 回復 2023-06-15
?
慕絲7291255

TA貢獻1859條經驗 獲得超6個贊

這是避免所有過濾器、掩蔽和組合困難的嘗試。它只是一些 bezier 路徑的SMIL 動畫,應該支持,沒有任何錯誤。我還沒有找到第一波和第二波同時出現在屏幕上的解決方案。

我承認最費力的部分是為路徑設計算法,其他一切都相對簡單。

“goo”是跨客戶區移動的具有上下邊界的區域,同時路徑的形式發生變化。我試圖在代碼注釋中描述哪些部分可以調整。路徑組合的基本結構確保了一個重要的限制:作為一個整體的路徑對于動畫的不同關鍵幀不能有不同的路徑命令序列,否則平滑的動畫將失敗。換個號碼應該沒問題。

在 goo 的后面是一個不透明的矩形,它最初隱藏了內容。當 goo 在屏幕上運行時,它會在適當的時間隱藏。

動畫的時間在<set><animate>元素的屬性中定義。請注意 goo 動畫運行了 6 秒,而背景矩形的隱藏發生在 3 秒后。此分布匹配屬性的值<animate keyTimes>0;0.5;1,您可以將其讀作 0%、50%、100% 作為關鍵幀的計時。觸發器必須與中間關鍵幀匹配的時間<set>,因為那是 goo 覆蓋整個客戶區域的時間。

const

? rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min,

? flatten = (x, y) => `${x.toFixed(2)},${y.toFixed(2)}`


function randomPoints(width, height) {

? const

? ? from = [],

? ? to = []


? let x = 0, old_extent = 0

? while (x + old_extent < width) {

? ? //width of a single goo tongue

? ? const extent = rand(5, 20)

? ? // rand() part: distance between tongues

? ? x += (from.length ? 1.5 : 0) * (old_extent + extent) + rand(0, 5)

? ? const data = {

? ? ? ? x1: x - extent,

? ? ? ? x2: x + extent,

? ? ? ? // "roundness": how far will the lowest point of the tongue

? ? ? ? // stretch below its defining line (qualitative value)

? ? ? ? dty: extent * rand(0.4, 1.4)

? ? ? }


? ? // y: tongue postition above screen border at start

? ? // Note the -20 gives space for the "roundness" not to cross the threshold

? ? from.push({ ...data, y: rand(-50, -20) })

? ? // y: tongue postition below screen border at end

? ? // Note the 10 gives space for the "roundness" not to cross the threshold

? ? to.push({ ...data, y: rand(10, 105) + height })


? ? old_extent = extent

? }


? return { from, to }

}


function generatePath(points, path, back) {

? const qti = points.length

? let old_dtx, old_dty


? if (back) points.reverse()


? for (let i = 0; i < qti; i++) {

? ? const

? ? ? x1 = back ? points[i].x2 : points[i].x1,

? ? ? x2 = back ? points[i].x1 : points[i].x2,

? ? ? dtx = (x2 - x1) / 2

? ? let dty = 0


? ? if (i == 0) {

? ? ? path.push(

? ? ? ? back ? 'L' : 'M',?

? ? ? ? flatten(x1, points[i].y),?

? ? ? ? 'Q',

? ? ? ? flatten(x1 + dtx, points[i].y),? ? ? ??

? ? ? ? flatten(x2, points[i].y)

? ? ? );

? ? } else {

? ? ? if (i !== qti - 1) {

? ? ? ? const

? ? ? ? ? y0 = points[i - 1].y,

? ? ? ? ? y1 = points[i].y,

? ? ? ? ? y2 = points[i + 1].y,

? ? ? ? ? // the numbers give a weight to the "roundness" value for different cases:

? ? ? ? ? // a tongue stretching below its neighbors = 1 (rounding downwards)

? ? ? ? ? // a tongue laging behind below its neighbors = -0.1 (rounding upwards)

? ? ? ? ? // other cases = 0.5

? ? ? ? ? down = y1 > y0 ? y1 > y2 ? 1 : 0.5 : y1 > y2 ? 0.5 : -0.1

? ? ? ? dty = points[i].dty * down //min absichern

? ? ? }


? ? ? path.push(

? ? ? ? 'C',?

? ? ? ? flatten(points[i - 1][back ? 'x1' : 'x2'] + old_dtx / 2, points[i - 1].y - old_dty / 2),

? ? ? ? flatten(x1 - dtx / 2, points[i].y - dty / 2),

? ? ? ? flatten(x1, points[i].y),?

? ? ? ? 'Q',

? ? ? ? flatten(x1 + dtx, points[i].y + dty),

? ? ? ? flatten(x2, points[i].y)

? ? ? );

? ? }

? ? old_dtx = dtx, old_dty = dty

? }


? if (back) {?

? ? points.reverse()

? ? path.push('Z')

? }

}


function generateArea(width, height) {

? const

? ? // tongue control points for first wave

? ? firstPoints = randomPoints(width, height),

? ? // tongue control points for second wave

? ? secondPoints = randomPoints(width, height),

? ? start = [],

? ? mid = [],

? ? end = []


? // first keyframe

? generatePath(firstPoints.from, start, false)

? generatePath(secondPoints.from, start, true)


? // second keyframe

? generatePath(firstPoints.to, mid, false)

? generatePath(secondPoints.from, mid, true)


? // third keyframe

? generatePath(firstPoints.to, end, false)

? generatePath(secondPoints.to, end, true)

??

? return [

? ? start.join(' '),?

? ? mid.join(' '),?

? ? end.join(' ')

? ]

}


const rect = document.querySelector('svg').getBoundingClientRect()

const animate = document.querySelector('#gooAnimate')

const areas = generateArea(rect.width, rect.height)


animate.setAttribute('values', areas.join(';'))

animate.beginElement() // trigger animation start

body {

? position: relative;

? margin: 0;

}

#content {

? position: relative;

? box-sizing: border-box;

? background: #faa;

? width: 100vw;

? height: 100vh;

? padding: 1em;

}

svg {

? position: absolute;

? width: 100%;

? height: 100%;

? top: 0%;

? pointer-events: none;

}

#veil {

? fill: skyblue;

}

#goo {

? fill: #5b534a;

}

<div id="content">

? <h1>Lorem ipsum dolor sit amet</h1>

? <p>Lorem ipsum dolor sit amet, <a href="">consectetur</a> adipiscing elit. Nam eu sodales lectus. Sed non erat accumsan, placerat purus quis, sodales mi. Suspendisse potenti. Sed eu viverra odio. </p>


</div>

<svg xmlns="http://www.w3.org/2000/svg">

? <rect id="veil" width="100%" height="100%">

? ? <!-- background animation start time is relative to goo animation start time -->

? ? <set attributeName="display" to="none" begin="gooAnimate.begin+3s" fill="freeze" />

? </rect>

? <path id="goo" d="" >

? ? <animate id="gooAnimate" attributeName="d"

? ? ? ? ? ? ?begin="indefinite" dur="6s" fill="freeze" keyTimes="0;0.5;1" />

? </path>

</svg>


查看完整回答
反對 回復 2023-06-15
  • 3 回答
  • 0 關注
  • 169 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號