CSS 中的模糊文本动画
Blurry text animation in CSS
当我查看 three.js
的示例时,我看到了 Lusion 的页面。
标题为“实现您的创意”的动画显示文本先模糊后清晰。
我试图重现这个:
@keyframes test {
from {
opacity: 0;
visibility: hidden;
filter: blur(0.2ex);
}
to {
opacity: 1;
visibility: visible;
filter: blur(0ex);
}
}
body p {
font-size: 32px;
text-align: center;
}
body #one {
animation: test 2.6s linear;
}
body #two {
animation: test 2s linear;
}
body #three {
animation: test 1.5s linear;
}
body #four {
animation: test 2s linear;
}
body #five {
animation: test 2.6s linear;
}
<p>
<span id="one">T</span>
<span id="two">i</span>
<span id="three">t</span>
<span id="four">l</span>
<span id="five">e</span>
</p>
但是整个事情有点烦人,因为你必须对每个字母都这样做。
此外,我的结果看起来没有 Lusion 的好。
是否可以做得更容易/更好?也许使用 JS 库(也许 three.js)?
或者唯一的解决办法是通过CSS keyframes
?
使用javascript:
"use strict";
document.addEventListener("DOMContentLoaded", e =>
{
randBlur(document.getElementsByClassName("randBlur"));
setTimeout(()=>randBlur([document.getElementById("delayed")]), 3000);
});
function randBlur(els, randDurationMin, randDurationMax)
{
if (!els)
return;
if (randDurationMin === undefined)
randDurationMin = 0.7; //min animation duration (in sec)
if (randDurationMax === undefined)
randDurationMax = 1.7; //min animation duration (in sec)
if (randBlur.list === undefined)
{
randBlur.style = document.createElement("style");
document.head.appendChild(randBlur.style);
randBlur.list = {};
randBlur.applyStyle = () =>
{
randBlur.style.innerHTML = "";
for(let i in randBlur.list)
randBlur.style.textContent += '[randBlur="' + i + '"]{animation:randblur ' + i + 's linear}';
}
}
const span = document.createElement("span"),
text = document.createTextNode(""),
rand = () =>
{
const duration = parseFloat((Math.random() * (randDurationMax - randDurationMin) + randDurationMin).toFixed(2));
randBlur.list[duration] = "";
return duration;
},
randBlurChildren = el =>
{
if (el.nodeType == el.TEXT_NODE)
{
for(let n = 0, ws, box; n < el.textContent.length; n++)
{
ws = el.textContent[n].match(/\s/);
box = (ws ? text : span).cloneNode(false);
box.textContent = el.textContent[n];
if (!ws)
{
box.setAttribute("randBlur", rand());
}
el.parentNode.insertBefore(box, el);
}
el.parentNode.removeChild(el);
}
else
{
const children = Object.assign([], el.childNodes);
for(let c = 0; c < children.length; c++)
{
if (!children[c].hasAttribute || !children[c].hasAttribute("randBlur"))
randBlurChildren(children[c]);
}
}
};
for (let i = 0; i < els.length; i++)
randBlurChildren(els[i]);
randBlur.applyStyle();
}
@keyframes randblur {
from {
opacity: 0;
visibility: hidden;
filter: blur(0.2ex);
}
to {
opacity: 1;
visibility: visible;
filter: blur(0ex);
}
}
body {
font-size: 1.1em;
text-align: center;
}
h2,h3
{
display: inline;
}
h2
{
color: green;
}
p
{
white-space: pre;
}
<p class="randBlur"><P> element with юникод text
and whitespaces</p>
<span class="randBlur">Even <h3> elements with <h2>children</h2></h3> animated.</span>
<span id="delayed">Can be applied at any time, but only once</span>
<h1 class="randBlur">Practically any HTML tag can be used</h1>
当我查看 three.js
的示例时,我看到了 Lusion 的页面。
标题为“实现您的创意”的动画显示文本先模糊后清晰。
我试图重现这个:
@keyframes test {
from {
opacity: 0;
visibility: hidden;
filter: blur(0.2ex);
}
to {
opacity: 1;
visibility: visible;
filter: blur(0ex);
}
}
body p {
font-size: 32px;
text-align: center;
}
body #one {
animation: test 2.6s linear;
}
body #two {
animation: test 2s linear;
}
body #three {
animation: test 1.5s linear;
}
body #four {
animation: test 2s linear;
}
body #five {
animation: test 2.6s linear;
}
<p>
<span id="one">T</span>
<span id="two">i</span>
<span id="three">t</span>
<span id="four">l</span>
<span id="five">e</span>
</p>
但是整个事情有点烦人,因为你必须对每个字母都这样做。
此外,我的结果看起来没有 Lusion 的好。
是否可以做得更容易/更好?也许使用 JS 库(也许 three.js)?
或者唯一的解决办法是通过CSS keyframes
?
使用javascript:
"use strict";
document.addEventListener("DOMContentLoaded", e =>
{
randBlur(document.getElementsByClassName("randBlur"));
setTimeout(()=>randBlur([document.getElementById("delayed")]), 3000);
});
function randBlur(els, randDurationMin, randDurationMax)
{
if (!els)
return;
if (randDurationMin === undefined)
randDurationMin = 0.7; //min animation duration (in sec)
if (randDurationMax === undefined)
randDurationMax = 1.7; //min animation duration (in sec)
if (randBlur.list === undefined)
{
randBlur.style = document.createElement("style");
document.head.appendChild(randBlur.style);
randBlur.list = {};
randBlur.applyStyle = () =>
{
randBlur.style.innerHTML = "";
for(let i in randBlur.list)
randBlur.style.textContent += '[randBlur="' + i + '"]{animation:randblur ' + i + 's linear}';
}
}
const span = document.createElement("span"),
text = document.createTextNode(""),
rand = () =>
{
const duration = parseFloat((Math.random() * (randDurationMax - randDurationMin) + randDurationMin).toFixed(2));
randBlur.list[duration] = "";
return duration;
},
randBlurChildren = el =>
{
if (el.nodeType == el.TEXT_NODE)
{
for(let n = 0, ws, box; n < el.textContent.length; n++)
{
ws = el.textContent[n].match(/\s/);
box = (ws ? text : span).cloneNode(false);
box.textContent = el.textContent[n];
if (!ws)
{
box.setAttribute("randBlur", rand());
}
el.parentNode.insertBefore(box, el);
}
el.parentNode.removeChild(el);
}
else
{
const children = Object.assign([], el.childNodes);
for(let c = 0; c < children.length; c++)
{
if (!children[c].hasAttribute || !children[c].hasAttribute("randBlur"))
randBlurChildren(children[c]);
}
}
};
for (let i = 0; i < els.length; i++)
randBlurChildren(els[i]);
randBlur.applyStyle();
}
@keyframes randblur {
from {
opacity: 0;
visibility: hidden;
filter: blur(0.2ex);
}
to {
opacity: 1;
visibility: visible;
filter: blur(0ex);
}
}
body {
font-size: 1.1em;
text-align: center;
}
h2,h3
{
display: inline;
}
h2
{
color: green;
}
p
{
white-space: pre;
}
<p class="randBlur"><P> element with юникод text
and whitespaces</p>
<span class="randBlur">Even <h3> elements with <h2>children</h2></h3> animated.</span>
<span id="delayed">Can be applied at any time, but only once</span>
<h1 class="randBlur">Practically any HTML tag can be used</h1>