Как сделать, чтобы третье условие работало?
const rectLeftTop = [ 50, 50 ];
const rectSize = 450;
const step = 15;
let [ x, y ] = rectLeftTop;
setInterval(() => {
if (rectLeftTop[1] <= y && x === rectLeftTop[0]) {
y = Math.min(y + step, rectLeftTop[1] + rectSize);
}
if (rectLeftTop[0] <= x && y === rectLeftTop[1] + rectSize) {
x = Math.min(x + step, rectLeftTop[0] + rectSize);
}
if (rectLeftTop[1] < y && x === rectLeftTop[0] + rectSize) {
y = Math.max(y - step, rectLeftTop[1]);
}
if (rectLeftTop[0] < x && y === rectLeftTop[1]) {
x = Math.max(x - step, rectLeftTop[0]);
}
block.style.left = `${x}px`;
block.style.top = `${y}px`;
}, rectSize / step);
const directions = [
[ 0, -1 ],
[ -1, 0 ],
[ 0, 1 ],
[ 1, 0 ],
];
let iDirection = 0;
const coords = [ 50, 50 ];
const step = 15;
const rectSize = 450;
const rect = [ [...coords], coords.map(n => n + rectSize) ];
(function move() {
const d = directions[iDirection].map(n => n * step);
coords.forEach((n, i, a) => a[i] = Math.max(rect[0][i], Math.min(rect[1][i], n + d[i])));
if (coords.every((n, i) => rect.some(m => m[i] === n))) {
iDirection = (iDirection + 1) % directions.length;
}
block.style.left = `${coords[0]}px`;
block.style.top = `${coords[1]}px`;
requestAnimationFrame(move);
})();
.block {
transition: all 750ms linear;
}
const positions = [
[ 50, 50 ],
[ 50, 500 ],
[ 500, 500 ],
[ 500, 50 ],
];
let iPosition = -1;
move();
block.addEventListener('transitionend', move);
setTimeout(move, 0);
function move() {
iPosition = (iPosition + 1) % positions.length;
const [ x, y ] = positions[iPosition].map(n => `${n}px`);
block.style.left = x;
block.style.top = y;
}
.block {
animation: move 3s infinite linear;
}
@keyframes move {
0%, 100% {
left: 50px;
top: 50px;
}
25% {
left: 50px;
top: 500px;
}
50% {
left: 500px;
top: 500px;
}
75% {
left: 500px;
top: 50px;
}
}
<svg viewBox="0 0 550 550" xmlns="http://www.w3.org/2000/svg" width="550" height="550">
<rect width="50" height="50" fill="red">
<animateMotion
dur="3s"
repeatCount="indefinite"
path="M50,50 L50,500 L500,500 L500,50 L50,50 z"
/>
</rect>
</svg>
<div class="players">
<div class="player">
<input placeholder="*Введите псевдоним" data-type="name">
<br>
<input placeholder="*Введите рейтинг" data-type="rating">
</div>
<div class="player">
<input placeholder="*Введите псевдоним" data-type="name">
<br>
<input placeholder="*Введите рейтинг" data-type="rating">
</div>
</div>
<h1 class="message hidden">HELLO, WORLD!!</h1>
true
или false
:const validations = {
name: val => /\D/.test(val),
rating: val => /^\d+$/.test(val),
};
input
, внутри которого перебираются элементы формы, из них извлекается имя типа данных, по имени типа данных из объекта с валидаторами извлекается функция проверки, ей передаётся значение элемента, введённое пользователем. Чтобы форма в целом была признана корректно заполненной, каждая из проверок должна оказаться успешной, в зависимости от полученного результата показываем или прячем дополнительный контент. Ну и ещё тот элемент, который пользователь только что редактировал, обрабатывается в особом порядке - в зависимости от результата его проверки у него добавляется или снимается класс, предназначенный для выделения некорректно заполненного элемента:document.querySelector('.players').addEventListener('input', function(e) {
const error = Array.from(this.querySelectorAll('[data-type]'), n => {
const error = !validations[n.dataset.type](n.value);
if (n === e.target) {
n.classList.toggle('error', error);
}
return error;
}).some(Boolean);
document.querySelector('.message').classList.toggle('hidden', error);
});
.error {
color: white;
background: red;
}
.hidden {
display: none;
}
<div class="spinner"><div>
.spinner {
color: black;
font-size: 5rem;
}
.spinner::before {
display: inline-block;
text-align: center;
font-family: monospace;
width: 5rem;
content: "";
animation: spinner .8s infinite steps(4);
}
@keyframes spinner {
0%, 100% { content: "\2014"; }
25% { content: "\\"; }
50% { content: "|"; }
75% { content: "/"; }
}
<div class="spinner"><div>
.spinner {
color: black;
font-size: 5rem;
font-family: monospace;
}
const block = document.querySelector('.spinner');
const text = [ '\u2014', '\\', '|', '/' ];
let index = -1;
setInterval(() => {
index = (index + 1) % text.length;
block.textContent = text[index];
}, 200);
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<g font-size="60" font-family="monospace" fill="black" visibility="hidden">
<text x="30" y="60">
—
<animate attributeName="visibility" from="hidden" to="visible" begin="0.2s; hide4.begin" dur="0.2s" id="show1" />
<animate attributeName="visibility" from="visible" to="hidden" begin="show1.begin + 0.2s" dur="0.2s" id="hide1" />
</text>
<text x="30" y="60">
\
<animate attributeName="visibility" from="hidden" to="visible" begin="hide1.begin" dur="0.2s" id="show2" />
<animate attributeName="visibility" from="visible" to="hidden" begin="hide1.begin + 0.2s" dur="0.2s" id="hide2" />
</text>
<text x="30" y="60">
|
<animate attributeName="visibility" from="hidden" to="visible" begin="hide2.begin" dur="0.2s" id="show3" />
<animate attributeName="visibility" from="visible" to="hidden" begin="hide2.begin + 0.2s" dur="0.2s" id="hide3" />
</text>
<text x="30" y="60">
/
<animate attributeName="visibility" from="hidden" to="visible" begin="hide3.begin" dur="0.2s" id="show4" />
<animate attributeName="visibility" from="visible" to="hidden" begin="hide3.begin + 0.2s" dur="0.2s" id="hide4" />
</text>
</g>
</svg>
.wrap
:.wrap-active {
transform: translateY(-100%);
}
$('.wrap').on('click', 'a', function(e) {
e.preventDefault();
$(e.delegateTarget).toggleClass('wrap-active');
});
.wrap
добавляем скрытый чекбокс:<input type="checkbox" id="toggle" hidden>
<a href="#">Day</a>
---> <label for="toggle">Day</label>
<a href="#">Night</a>
---> <label for="toggle">Night</label>
.wrap
не при наличии дополнительного класса, а если чекбокс перед ним выставлен:.wrap-active {
---> #toggle:checked + .wrap {