Я пытаюсь создать экран ожидания c цифрами обратного отсчета, который показывает глаз вместе с веком, и глазное яблоко с эффектом радужной оболочки.
Учитывая, что многие из нас бессмысленно проводят время, глядя на такие лоадеры
, я хочу создать такой эффект лоадера, при котором вращающийся "глаз" смотрит на зрителя и мигает.
document.getElementById('waitDia').showModal();
var ticks = 300,
ticker = setInterval(changeTick,1000);
function changeTick()
{
document.getElementById('spnTick').innerText = --ticks;
if (0 === ticks) clearInterval(ticker);
}
#waitDia
{
position:absolute;
left:0 !important;
top:0 !important;
width:100vw !important;
height:100vh !important;
padding:0;
min-width:100vw;
min-height:100vh;
background-color:transparent !important;
}
#waitDia::backdrop{background-color:rgba(127,127,127,0.2);}
#spnTick
{
position:absolute;
display:inline-block;
width:100%;
left:0;
top:0;
}
#waitbox
{
left:0 !important;
top:0 !important;
width:100vw !important;
height:100vh !important;
position:absolute;
overflow:hidden;
}
#eyeball
{
position:relative;
top:-10vh;
left:-6px;
width:calc(24vh + 12px);
height:calc(24vh + 12px);
box-sizing:border-box;
background:rgba(0,128,128,0.5);
border-radius:100%;
border:1px solid transparent;
box-shadow:inset 0 0 18px 2px blue;
z-index:99999998;
}
#waitsecs
{
position:absolute;
left:calc(50vw - 12vh);
top:46vh;
width:24vh;
height:24vh;
font-size:8vh;
text-align:center;
display:block;
}
#waitEye
{
position:absolute;
top:27vh;
left:calc(50vw - 23vh);
width: 46vh;
height: 46vh;
background-color: rgba(255,255,255,.9);
border-radius: 100% 0px;
transform: rotate(45deg);
mix-blend-mode:overlay;
z-index:199999999;
box-shadow:0 -0.5vh 0 2px #f1c27d,inset 0 6px 4px 4px black;
}
body,html
{
background:black;
font-family:arial;
}
<dialog id='waitDia' class='waitdia'>
<div id='waitbox'>
<div id='waitsecs'><span id='spnTick'>300</span><div id='eyeball'></div></div>
<div id='waitEye'></div>
</div>
</dialog>
То, чего я смог достичь к настоящему времени, показано ниже - я установил здесь тикер на 300 секунд, просто в качестве иллюстрации, чтобы он продолжал работать в течение долгого времени - в реальном приложении время ожидания, вероятно, будет значительно меньше.
Пока этот эффект движется в правильном направлении, но ему все еще не хватает эффекта моргания века. Я подозреваю, что это легко выполнимо с помощью правильной манипуляцией box-shadow
и простой анимацией.
Я был бы очень признателен всем, кто мог бы предложить улучшения для завершения этой реализации.
Свободный перевод вопроса Creating a CSS blinking eyelid effect от участника @DroidOS.
Двигаем 2 опорные точки в кривой Безье в зависимости от времени :
requestAnimationFrame(draw);
function draw(t) {
// двигаем зрачок
circle.setAttribute('cx', Math.sin(t/1000)*2);
// анимируем градиент
grad.setAttribute('offset', 40 + Math.sin(t/3000)*20 + '%');
// сглаживаем время по формуле easeInOutQuint
t = Math.max(0, Math.sin(t/300));
t = (t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t)*6-3;
// кривая Безье в зависимости от сглаженного значения времени
let d = `-7 0C-2 ${t} 2 ${t} 7 0`;
mask.setAttribute('d', `M-7 -7${d}L7 -7z`);
eyelid.setAttribute('d', `M${d}`);
requestAnimationFrame(draw);
}
<svg viewbox="-10 -10 20 20" height="90vh">
<defs><radialGradient id="g1" cx="50%" cy="50%" r="50%">
<stop stop-color="black" offset="0%"/>
<stop id="grad" stop-color="teal" offset="30%"/>
<stop stop-color="white" offset="100%"/>
</radialGradient></defs>
<circle id="circle" r="2.4" stroke="black" fill="url(#g1)" stroke-width="0.2"></circle>
<path id="mask" stroke="none" fill="white"></path>
<path id="eyelid" stroke="black" fill="none"></path>
</svg>
let rnd = (a, b) => (a||0) + ((b-a)||1) * Math.random();
let eyes = Array(22).fill(0).map((e, i) => ({
i,
t: rnd(1, 10),
x: rnd(-96, 96),
y: rnd(-46, 46),
k: rnd(0.05,0.2),
r: rnd(-33,33)
}))
defs.innerHTML = eyes.map(e => `
<radialGradient id="gradient_${e.i}" cx="50%" cy="50%" r="50%">
<stop stop-color="black" offset="0%"/>
<stop id="color_${e.i}" stop-color="hsl(${rnd(0, 360)},55%,35%)" offset="30%"/>
<stop stop-color="white" offset="100%"/>
</radialGradient>
<clipPath id="clip_${e.i}">
<path></path>
</clipPath>
`).join('');
g.innerHTML = eyes.map(e => `
<g id="eye_${e.i}" transform="rotate(${e.r})scale(${e.k})translate(${e.x},${e.y})">
<circle r="2.4" stroke="black" fill="url(#gradient_${e.i})" stroke-width="0.2" clip-path="url(#clip_${e.i})"></circle>
<path stroke="black" fill="none"></path>
</g>
`).join('');
eyes.forEach(e => e.elements = {
circle: document.querySelector(`#eye_${e.i} circle`),
clipPath: document.querySelector(`#clip_${e.i} path`),
eyelid: document.querySelector(`#eye_${e.i} path`),
gradient: document.querySelector(`#color_${e.i}`)
})
requestAnimationFrame(draw);
function draw(t) {
eyes.forEach(e => {
e.elements.circle.setAttribute('cx', Math.sin(t/100/(e.t+e.i))*2);
e.elements.gradient.setAttribute('offset', 40 + Math.sin(t/300/(e.t+e.i))*20 + '%');
let T = Math.max(0, Math.sin(t/50/(e.t+e.i)));
T = (T<.5 ? 16*T*T*T*T*T : 1+16*(--T)*T*T*T*T)*6-3;
let d = `-7 0C-2 ${T} 2 ${T} 7 0`;
e.elements.clipPath.setAttribute('d', `M-7 3${d}L7 3z`);
e.elements.eyelid.setAttribute('d', `M${d}`);
})
requestAnimationFrame(draw);
}
<svg viewbox="-20 -10 40 20" height="90vh">
<defs id="defs"></defs>
<g id="g"></g>
</svg>
PS: функция сглаживания взята отсюда: https://gist.github.com/gre/1650294
Версия на Smil
<svg width="300px" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(-8,-121)">
<g id="eye">
<ellipse cx="106.2113" cy="150.72321" rx="27.59226" ry="22.300594"/>
<ellipse cx="108.47916" cy="149.58928" rx="10.205358" ry="8.3154764" fill="#fff"/>
<animateTransform
attributeName="transform"
attributeType="XML"
type="translate"
from="-5 0"
to="5 0"
dur="6s"
repeatCount="indefinite"/>
<animate
attributeName="fill"
dur="3000ms"
repeatCount="indefinite"
values="#1eb287;
#1eb287;
#1ca69e;
#188fc2;
#188fc2;
#bb625e;
#ca5f52;
#1eb287;"/>
</g>
<path d="" fill="#fff" stroke="#000" stroke-width="12" stroke-linecap="round">
<animate
attributeName="d"
dur="1.8s"
repeatCount="indefinite"
values=
"m195.79166 129.17857c-59.10423 2.90575-116.58946 5.9255-177.6488-3.02381;
M 195.79166,129.17857 C 140.04024,174.83267 83.866918,194.57929 18.142857,126.15476;
M 195.79166,129.17857 C 140.04024,174.83267 83.866918,194.57929 18.142857,126.15476;
M 195.79166,129.17857 C 140.04024,174.83267 83.866918,194.57929 18.142857,126.15476;
m195.79166 129.17857c-59.10423 2.90575-116.58946 5.9255-177.6488-3.02381;"
keyTimes="0; 0.11; 0.21; 0.72; 1"
/>
<animate
attributeName="stroke"
dur="8000ms"
repeatCount="indefinite"
keyTimes="0;
.0625;
.208333333;
.3125;
1"
values="red;
green;
blue;
yellow;
pink;"/>
</path>
</g>
</svg>
<path>
с
помощью перехода из верхнего положения вниз. Паузы в верхнем и нижнем положении века достигаются повторением позиций
Более подробно об анимациях с паузами - Как в SVG реализовать анимацию туда и обратно
Вариант решения без счётчика
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="25%" height="25%" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet">
<defs>
<radialGradient id="grad1" cx="40%" cy="20%" r="100%" fx="45%" fy="20%">
<stop stop-color="#B7B3B8" offset="10%"/>
<stop stop-color="#CDC9D0" offset="65%"/>
<stop stop-color="#9D90A2" offset="85%"/>
<stop stop-color="#CDBED3" offset="100%"/>
</radialGradient>
</defs>
<image xlink:href="https://i.stack.imgur.com/gDG2U.jpg" width="100%" height="100%" />
<path id="veko" fill="url(#grad1)" stroke="#B9B5BB" stroke-width="4" d="m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 4.9 2.6 6.4 4.9 0.4 0.6 1.1 2.4 0.4 2.1-6.7-2.5-17.2-10.3-26.1-14.8-6.6-3.3-13.1-6.8-20.1-9.1-5.2-1.7-10.6-2.9-16.1-3.4-8.6-0.8-17.5-1.3-26.1 0.4-12.4 2.5-24 8.4-35.4 14-14.6 7.1-42.2 24.6-42.2 24.6z" >
<animate attributeName="d" dur="4s" repeatCount="indefinite" values="
m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 4.9 2.6 6.4 4.9 0.4 0.6 1.1 2.4 0.4 2.1-6.7-2.5-17.2-10.3-26.1-14.8-6.6-3.3-13.1-6.8-20.1-9.1-5.2-1.7-10.6-2.9-16.1-3.4-8.6-0.8-17.5-1.3-26.1 0.4-12.4 2.5-24 8.4-35.4 14-14.6 7.1-42.2 24.6-42.2 24.6z;
m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 4.9 2.6 6.4 4.9 0.4 0.6 1.1 2.4 0.4 2.1-6.7-2.5-17.2-10.3-26.1-14.8-6.6-3.3-13.1-6.8-20.1-9.1-5.2-1.7-10.6-2.9-16.1-3.4-8.6-0.8-17.5-1.3-26.1 0.4-12.4 2.5-24 8.4-35.4 14-14.6 7.1-42.2 24.6-42.2 24.6z;
m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 6.4 4.9 6.4 4.9-0.1 0.7 2.8-0.5 0.4 2.1-4.7 5.2-11 10.6-17.4 14.6-6 3.8-12.7 6.5-19.5 8.9-6.1 2.1-12.4 3.9-18.9 4.7-8.3 1-16.8 0.5-25.2 0-13-0.8-26-2.3-38.8-4.7-15.6-2.9-46.2-11.9-46.2-11.9z;
m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 6.4 4.9 6.4 4.9-0.1 0.7 2.8-0.5 0.4 2.1-4.7 5.2-11 10.6-17.4 14.6-6 3.8-12.7 6.5-19.5 8.9-6.1 2.1-12.4 3.9-18.9 4.7-8.3 1-16.8 0.5-25.2 0-13-0.8-26-2.3-38.8-4.7-15.6-2.9-46.2-11.9-46.2-11.9z;
m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 4.9 2.6 6.4 4.9 0.4 0.6 1.1 2.4 0.4 2.1-6.7-2.5-17.2-10.3-26.1-14.8-6.6-3.3-13.1-6.8-20.1-9.1-5.2-1.7-10.6-2.9-16.1-3.4-8.6-0.8-17.5-1.3-26.1 0.4-12.4 2.5-24 8.4-35.4 14-14.6 7.1-42.2 24.6-42.2 24.6z" />
</path>
</svg>
var checks = 100,
checker = setInterval(Count, 2100);
function Count() {
document.getElementById('txt1').textContent = --checks;
if (0 === checks) clearInterval(checker);
}
.container {
background:silver;
}
svg {
display:block;
width:15%;
height:23%;
padding-left:0.5em;
padding-bottom:1.5em;
margin:1em;
border-radius:50%;
-webkit-box-shadow: 7px 7px 5px 0px rgba(50, 50, 50, 0.75);
-moz-box-shadow: 7px 7px 5px 0px rgba(50, 50, 50, 0.75);
box-shadow: 7px 7px 5px 0px rgba(50, 50, 50, 0.75);
background:#8C6282;
}
#txt1 {
font-size: 40px;
font-weight:bold;
fill:#FFDD00;
stroke:#917E00;
text-anchor:middle;
}
<div class="container">
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="50%" height="50%" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet">
<defs>
<radialGradient id="grad1" cx="40%" cy="20%" r="100%" fx="45%" fy="20%">
<stop stop-color="#B7B3B8" offset="10%"/>
<stop stop-color="#CDC9D0" offset="65%"/>
<stop stop-color="#9D90A2" offset="85%"/>
<stop stop-color="#CDBED3" offset="100%"/>
</radialGradient>
<mask id="msk1" >
<path fill="white" d="M0.9 129.9C10.6 74.7 114.5 44.3 176.2 88.8c8 5.1 16.2 15.8 16.8 23.4C200 200 1.1 166.8 0.9 129.9" />
</mask>
</defs>
<g mask="url(#msk1)" >
<image xlink:href="https://i.stack.imgur.com/gDG2U.jpg" width="100%" height="100%" />
<text id="txt1" x="98" y="130" >100</text>
<path id="veko" fill="url(#grad1)" stroke="#B9B5BB" stroke-width="1" d="m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 4.9 2.6 6.4 4.9 0.4 0.6 1.1 2.4 0.4 2.1-6.7-2.5-17.2-10.3-26.1-14.8-6.6-3.3-13.1-6.8-20.1-9.1-5.2-1.7-10.6-2.9-16.1-3.4-8.6-0.8-17.5-1.3-26.1 0.4-12.4 2.5-24 8.4-35.4 14-14.6 7.1-42.2 24.6-42.2 24.6z" >
<animate attributeName="d" dur="2.4s" repeatCount="indefinite" values="
m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 4.9 2.6 6.4 4.9 0.4 0.6 1.1 2.4 0.4 2.1-6.7-2.5-17.2-10.3-26.1-14.8-6.6-3.3-13.1-6.8-20.1-9.1-5.2-1.7-10.6-2.9-16.1-3.4-8.6-0.8-17.5-1.3-26.1 0.4-12.4 2.5-24 8.4-35.4 14-14.6 7.1-42.2 24.6-42.2 24.6z;
m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 4.9 2.6 6.4 4.9 0.4 0.6 1.1 2.4 0.4 2.1-6.7-2.5-17.2-10.3-26.1-14.8-6.6-3.3-13.1-6.8-20.1-9.1-5.2-1.7-10.6-2.9-16.1-3.4-8.6-0.8-17.5-1.3-26.1 0.4-12.4 2.5-24 8.4-35.4 14-14.6 7.1-42.2 24.6-42.2 24.6z;
m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 6.4 4.9 6.4 4.9-0.1 0.7 2.8-0.5 0.4 2.1-4.7 5.2-11 10.6-17.4 14.6-6 3.8-12.7 6.5-19.5 8.9-6.1 2.1-12.4 3.9-18.9 4.7-8.3 1-16.8 0.5-25.2 0-13-0.8-26-2.3-38.8-4.7-15.6-2.9-46.2-11.9-46.2-11.9z;
m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 6.4 4.9 6.4 4.9-0.1 0.7 2.8-0.5 0.4 2.1-4.7 5.2-11 10.6-17.4 14.6-6 3.8-12.7 6.5-19.5 8.9-6.1 2.1-12.4 3.9-18.9 4.7-8.3 1-16.8 0.5-25.2 0-13-0.8-26-2.3-38.8-4.7-15.6-2.9-46.2-11.9-46.2-11.9z;
m12.7 132c0 0 25.6-19.6 39.8-27.1 11.7-6.2 23.9-11.9 36.9-14.4 10.7-2.1 21.9-2 32.6-0.4 8.5 1.3 16.8 4.3 24.6 7.8 9 4.1 17.1 9.9 25.2 15.5 2.2 1.5 4.9 2.6 6.4 4.9 0.4 0.6 1.1 2.4 0.4 2.1-6.7-2.5-17.2-10.3-26.1-14.8-6.6-3.3-13.1-6.8-20.1-9.1-5.2-1.7-10.6-2.9-16.1-3.4-8.6-0.8-17.5-1.3-26.1 0.4-12.4 2.5-24 8.4-35.4 14-14.6 7.1-42.2 24.6-42.2 24.6z" />
</path>
</g>
</svg>
</div>
Связанный вопрос: Анимация svg глаз кролика с помощью атрибутов path “d” и “keyTimes”
Я сделал бы это по-другому и рассмотрел бы вращение для получения эффекта мерцания. Трюк заключается в том, чтобы создать глаз с двумя элементами (веко), чтобы они имели возможность моргать.
Вот код только с анимацией мерцания:
.eye {
width: 250px;
height: 80px;
margin: 50px;
display:inline-block;
perspective: 200px;
background:
radial-gradient(circle 100px at 50% 250%,#f1c27d 99% ,transparent 100%) top/100% 50%,
radial-gradient(circle 100px at 50% -150%,#f1c27d 99% ,transparent 100%) bottom/100% 50%;
background-repeat:no-repeat
}
.eye>div {
height: 50%;
position:relative;
overflow:hidden;
transform-origin:bottom;
animation:b1 0.8s infinite ease-out alternate;
}
.eye>div:last-child {
transform-origin:top;
animation-name:b2;
}
.eye>div:before {
content: "";
position: absolute;
top:0;
left:10%;
right:10%;
padding-top:80%;
border-radius:50%;
background:#fff;
box-shadow:
-2px 0 0 3px inset #f1c27d,
inset -5px 5px 2px 4px black;
}
.eye>div:last-child:before {
bottom:0;
top:auto;
box-shadow:
-2px 0 0 3px inset #f1c27d,
inset -6px -4px 2px 4px black;
}
body {
background:#000;
}
@keyframes b1{
to { transform:rotateX(-88deg);}
}
@keyframes b2{
to {transform:rotateX(88deg);}
}
<div class="eye">
<div></div>
<div></div>
</div>
Вот более реалистичное мигание век у всего глаза:
var ticks = 300,ticker;
setTimeout(function() { ticker = setInterval(changeTick,1600);},500);
function changeTick()
{
document.querySelector('.eye span').setAttribute('data-text', --ticks);
if (0 === ticks) clearInterval(ticker);
}
.eye {
width: 250px;
height: 80px;
margin: 50px;
display:inline-block;
perspective: 200px;
background:
radial-gradient(circle 100px at 50% 250%,#f1c27d 99% ,transparent 100%) top/100% 50%,
radial-gradient(circle 100px at 50% -150%,#f1c27d 99% ,transparent 100%) bottom/100% 50%;
background-repeat:no-repeat;
transform-style:preserve-3d;
position:relative;
}
.eye>div {
height: 50%;
position:relative;
overflow:hidden;
transform-origin:bottom;
z-index:1;
animation:b1 0.8s infinite ease-out alternate;
}
.eye>div:last-child {
transform-origin:top;
animation:none;
}
.eye>div:before {
content: "";
position: absolute;
top:0;
left:10%;
right:10%;
padding-top:80%;
border-radius:50%;
background:#fff;
box-shadow:
-2px 0 0 3px inset #f1c27d,
inset -5px 5px 2px 4px black;
animation:inherit;
animation-name:color;
}
.eye>div:last-child:before {
bottom:0;
top:auto;
box-shadow:
-2px 0 0 3px inset #f1c27d,
inset -6px -4px 2px 4px black;
}
.eye > span {
position:absolute;
width:45px;
height:45px;
bottom:18px;
left:50%;
transform:translateX(-50%) translateZ(55px);
overflow:hidden;
border-radius:20% 20% 0 0;
z-index:2;
animation:b2 0.8s infinite ease-out alternate;
}
.eye > span:before {
position:absolute;
left:0;
bottom:0;
height:45px;
width:100%;
content:attr(data-text);
border-radius:50%;
background:#000;
color:#fff;
text-align:center;
line-height:45px;
}
body {
background:#000;
}
@keyframes b1{
to {
transform:rotateX(-170deg);
}
}
@keyframes b2{
50% {
height:20px;
}
60%,100% {
height:0px;
}
}
@keyframes color{
0%,40% {
background:#fff;
box-shadow:
-2px 0 0 3px inset #f1c27d,
inset -5px 5px 2px 4px black;
}
40.1%,100% {
background:#f1c27d;
box-shadow:none;
}
}
<div class="eye">
<div></div>
<span data-text="300"></span>
<div></div>
</div>
Свободный перевод ответа Creating a CSS blinking eyelid effect от участника @Temani Afif.
Размер зрачка зависит от расстояния до мышки.
Глаз поворачивается в направлении указателя.
Процент загрузки выражается размером сектора радужной оболочки.
let mouse = {x:0, y:0},
progress = 0;
setInterval(e => progress = (progress + Math.random()/100)%1, 100)
requestAnimationFrame(draw);
addEventListener('pointermove', e => {mouse.x = e.x, mouse.y = e.y})
function draw(t) {
requestAnimationFrame(draw);
// двигаем зрачок
let dx = mouse.x - innerWidth/2,
dy = mouse.y - innerHeight/2,
len = Math.sqrt(dx*dx + dy*dy),
ml = Math.min(len*10/innerHeight, 1),
a = Math.atan2(dy, dx),
x = Math.cos(a) * ml,
y = Math.sin(a)/2 * ml;
circle1.setAttribute('cx', x);
circle1.setAttribute('cy', y);
circle2.setAttribute('cx', x);
circle2.setAttribute('cy', y);
// процент загрузки
let r = 1.8,
p = progress *2 * Math.PI,
px = r*Math.cos(p),
py = r*Math.sin(p),
arc = 1-Math.round(progress);
load.setAttribute('d', `M${r},0 A${r},${r},0,${arc},0,${px},${py}L0,0z`)
load.setAttribute('transform', `translate(${x}, ${y})`)
// анимируем градиент
let offset = Math.max(0.2, (0.5 - len/2/innerHeight))*100 + "%";
grad1.setAttribute('offset', offset);
grad2.setAttribute('offset', offset);
// сглаживаем время по формуле easeInOutQuint
t = Math.max(0, Math.sin(t/300));
t = (t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t)*6-3;
// кривая Безье в зависимости от сглаженного значения времени
let d = `-7 0C-2 ${t} 2 ${t} 7 0`;
mask.setAttribute('d', `M-7 -7${d}L7 -7z`);
eyelid.setAttribute('d', `M${d}`);
}
<body style="margin:0 calc(50vw - 50vh); overflow:hidden;">
<svg viewbox="-10 -10 20 20" height="100vh">
<defs>
<radialGradient id="g1" cx="50%" cy="50%" r="50%">
<stop stop-color="black" offset="0%"/>
<stop id="grad1" stop-color="#4f899d" offset="30%"/>
<stop stop-color="white" offset="100%"/>
</radialGradient>
<radialGradient id="g2" cx="50%" cy="50%" r="50%">
<stop stop-color="black" offset="0%"/>
<stop id="grad2" stop-color="#885d33" offset="30%"/>
<stop stop-color="white" offset="100%"/>
</radialGradient>
<mask id="m1">
<path id="load" fill="#fff"></path>
</mask>
</defs>
<circle id="circle1" r="2" stroke="black" stroke-width="0.2" fill="url(#g2)"></circle>
<circle id="circle2" r="2" fill="url(#g1)" mask="url(#m1)"></circle>
<path id="mask" stroke="none" fill="white"></path>
<path id="eyelid" stroke="black" fill="none"></path>
</svg>
</body>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
У меня есть валидация с помощью регулярки, где я проверяю совпадают ли условия с введенными даннымиСейчас показан пример где нужно ввести...
В Java есть функцияsplit которая разделяет строку вокруг регулярного выражения и возвращает массив строк, так вот есть ли в C++ (стандартной библиотеке)...
Пытаюсь подключиться к базе данных, созданной через Visual Studio (Средства -> Подключиться к базе данных)