#javascript #css #css-transitions #css-transforms
#javascript #css #css-переходы #css-преобразования
Вопрос:
Я работаю над свойством перехода CSS, и у меня возникает проблема, когда мой JavaScript обновляет то же значение CSS.
Я привел простой пример для понимания.
document.addEventListener('DOMContentLoaded', function() {
let container = document.getElementById("container")
let hovercontainer = document.getElementById("hover-container")
let square = document.getElementById("square")
let mouseMove = function (e) {
let el = e.currentTarget;
let delta_x = parseFloat(e.offsetX / el.offsetWidth).toFixed(2)
square.style = "transform: translateX(" parseInt(delta_x * 400) "px);"
}
let mouseLeave = function(e) {
square.style = ""
}
hovercontainer.addEventListener("mousemove", mouseMove)
hovercontainer.addEventListener("mouseleave", mouseLeave)
}, false);
html, body, #wrapper {
height: 100%;
margin: 0;
padding: 0;
}
#wrapper {
background: #a4d24b;
display: flex;
}
#container {
width: 600px;
height: 200px;
margin: auto;
box-shadow: 0 2px 4px rgba(34, 25, 25, 0.4);
background: #FFF;
display: flex;
}
#hover-container {
width: 500px;
height: 100px;
margin: auto;
background: #EEE;
border-top: 1px solid #DDD;
border-bottom: 1px solid #CCC;
display: flex;
}
#square {
pointer-events: none;
width: 90px;
height: 90px;
background: #a4d24b;
margin: auto 5px;
box-shadow: 2px 2px 4px rgba(34, 25, 25, 0.4) inset;
transform: translateX(0);
transition: all 3s;
}
#container:hover #square {
transform: translateX(400px);
box-shadow: 0px 2px 4px rgba(34, 25, 25, 0.4) inset;
}
<div id="wrapper"> <!-- background -->
<div id="container"> <!-- white -->
<div id="hover-container"> <!-- gray -->
<div id="square"></div> <!-- square -->
</div>
</div>
</div>
В этом коде transform:translateX()
позиция #square
обновляется с 0 до 400 пикселей в зависимости от положения мыши:
- сделано с помощью CSS: при наведении курсора мыши на белое поле свойство CSS
transform
обновляется с 0 (слева) до 400 (справа), и переход выполняется за 3 секунды. - сделано с помощью JS: когда мышь попадает на серую линию,
transform
свойство обновляется непосредственно в теге, чтобы «следовать за мышью».
Проблема: когда мышь вводится на серой линии, куб красиво появляется (с переходом) под мышью. Но когда мышь перемещается (быстро), атрибут меняется каждый раз, а квадрат вообще не перемещается (вызвано transition
свойством)
Другая попытка Я также пытаюсь добавить transition: all 0s
с помощью Javascript для временного «отключения», но теперь квадрат телепортируется сам, когда мышь вводится на серой линии.
(тот же код с обновлением)
document.addEventListener('DOMContentLoaded', function() {
let container = document.getElementById("container")
let hovercontainer = document.getElementById("hover-container")
let square = document.getElementById("square")
let mouseMove = function (e) {
let el = e.currentTarget;
let delta_x = parseFloat(e.offsetX / el.offsetWidth).toFixed(2)
square.style = "transform: translateX(" parseInt(delta_x * 400) "px); transition: all 0s;"
}
let mouseLeave = function(e) {
square.style = ""
}
hovercontainer.addEventListener("mousemove", mouseMove)
hovercontainer.addEventListener("mouseleave", mouseLeave)
}, false);
html, body, #wrapper {
height: 100%;
margin: 0;
padding: 0;
}
#wrapper {
background: #a4d24b;
display: flex;
}
#container {
width: 600px;
height: 200px;
margin: auto;
box-shadow: 0 2px 4px rgba(34, 25, 25, 0.4);
background: #FFF;
display: flex;
}
#hover-container {
width: 500px;
height: 100px;
margin: auto;
background: #EEE;
border-top: 1px solid #DDD;
border-bottom: 1px solid #CCC;
display: flex;
}
#square {
pointer-events: none;
width: 90px;
height: 90px;
background: #a4d24b;
margin: auto 5px;
box-shadow: 2px 2px 4px rgba(34, 25, 25, 0.4) inset;
transform: translateX(0);
transition: all 3s;
}
#container:hover #square {
transform: translateX(400px);
box-shadow: 0px 2px 4px rgba(34, 25, 25, 0.4) inset;
}
<div id="wrapper"> <!-- background -->
<div id="container"> <!-- white -->
<div id="hover-container"> <!-- gray -->
<div id="square"></div> <!-- square -->
</div>
</div>
</div>
Как я могу объединить оба решения, чтобы получить красивый и плавный движущийся квадрат?
Ответ №1:
Это действительно сложно. Из этого я понял, что вы хотите иметь возможность перемещать мышь без заметного изменения скорости и чтобы она достигала указателя примерно в то же время, как если бы мышь никогда не двигалась. Для этого вам в основном нужно прослушивать в первый раз, когда мышь попадает в целевую область, и обновлять назначение и задержку перехода, чтобы она не сбрасывалась через 3 секунды. Вот демонстрация, которая делает то, что вы просите. Он использует javascript для определения того, каким должно быть время задержки, и обновляет его при обновлении целевого значения X. Однако мне пришлось отключить ослабление перехода, чтобы не выглядеть таким резким. Надеюсь, это поможет вам немного лучше понять проблему и, возможно, ее можно превратить в решение для ваших нужд.
document.addEventListener('DOMContentLoaded', function() {
let container = document.getElementById("container")
let hovercontainer = document.getElementById("hover-container")
let square = document.getElementById("square")
let ts = null
let mouseMove = function (e) {
let el = e.currentTarget;
let delta_x = parseFloat(e.offsetX / el.offsetWidth).toFixed(2)
if(!ts) ts = new Date().getTime() 3000;
let d = Math.max(0, ts - new Date().getTime()) / 1000 's';
square.style.transitionDuration = d;
square.style.transform = "translateX(" parseInt(delta_x * 400) "px)";
if(d === '0s') ts = null;
}
let mouseLeave = function(e) {
square.style.transition = null;
square.style.transform = null;
ts = null;
}
hovercontainer.addEventListener("mousemove", mouseMove)
hovercontainer.addEventListener("mouseleave", mouseLeave)
}, false);
html, body, #wrapper {
height: 100%;
margin: 0;
padding: 0;
}
#wrapper {
background: #a4d24b;
display: flex;
}
#container {
width: 600px;
height: 200px;
margin: auto;
box-shadow: 0 2px 4px rgba(34, 25, 25, 0.4);
background: #FFF;
display: flex;
}
#hover-container {
width: 500px;
height: 100px;
margin: auto;
background: #EEE;
border-top: 1px solid #DDD;
border-bottom: 1px solid #CCC;
display: flex;
}
#square {
pointer-events: none;
width: 90px;
height: 90px;
background: #a4d24b;
margin: auto 5px;
box-shadow: 2px 2px 4px rgba(34, 25, 25, 0.4) inset;
transform: translateX(0);
transition: all 3s linear;
}
#container:hover #square {
transform: translateX(400px);
box-shadow: 0px 2px 4px rgba(34, 25, 25, 0.4) inset;
}
<div id="wrapper"> <!-- background -->
<div id="container"> <!-- white -->
<div id="hover-container"> <!-- gray -->
<div id="square"></div> <!-- square -->
</div>
</div>
</div>