右上角的切换开关按钮可从亮模式切换到暗模式,反之亦然。背景是一张放大的图像。
目前,它从转移
切换到暗模式时从左到右但我希望它自己朝一个方向移动。比如,假设它处于亮模式,当我将其切换到暗模式时,背景图像会像预期的那样向右移动(左>右(,然后当我将它切换到亮模式时,我希望背景图像再次从左向右移动(左>右(。
有点像一个连续的循环,但有一个切换按钮。
我有什么办法做到这一点吗?
我想它可能适用于不确定的关键帧和动画。但是有没有一种方法可以在JS中做到这一点而不需要关键帧?
不要介意下面的代码,因为我不得不从我的react项目中截取它,所以可能不需要一些CSS属性。
let Dark = false
const DarkOrLight = () => {
const container = document.getElementsByClassName('Login-container')[0]
if (!Dark) {
container.style.backgroundPosition = 'right'
} else {
container.style.backgroundPosition = 'left'
}
Dark = !Dark
}
.toggle-container {
position: fixed;
top: 5px;
right: 5%;
}
.toggle {
appearance: none;
width: 50px;
height: 30px;
background-image: linear-gradient(120deg, #383030 0%, #22282e 100%);
cursor: pointer;
border-radius: 20px;
}
.toggle:focus {
outline: 0;
}
.toggle::after {
content: '';
background-image: linear-gradient(120deg, rgb(182, 244, 146), rgb(51, 139, 147));
position: absolute;
top: 5px;
left: 5px;
width: 25px;
height: 25px;
border-radius: 50%;
transition: all 1s ease;
}
.toggle:checked {
background-color: #b6f492;
background-image: linear-gradient(120deg, #b6f492, rgb(51, 139, 147));
}
.toggle:checked::after {
transform: translateX(23px);
background-image: linear-gradient(120deg, #383030 0%, #22282e 100%);
}
.Login-container {
position: relative;
background-image: linear-gradient(120deg, #b6f492, #338b93, #383030, #22282e);
background-size: 400%;
background-position: left;
width: 100%;
height: 100vh;
display: flex;
justify-content: end;
transition: all 1s ease;
font-family: Merriweather;
}
<div class="Login-container">
<div class="toggle-container">
<input class="toggle" type="checkbox" onClick=DarkOrLight()></input>
</div>
</div>
修复颜色停止:
- 您的背景大小为400%
- 但您只使用4颜色停止(而不是5(
问题是:通过简单地从左到右设置动画,您当前的代码就会发生这种情况:
|left right| bg-position left-to-right
|#1 |#2 |#3 |#4 4 colors-stops
|0% |100% |200% |300% |400% bg-size
| light | (anim) | dark | mode
|░░░░░░░░|▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒|▓▓▓▓▓▓▓▓|
你知道100%的颜色是什么吗没有
你知道300%的确切颜色是什么吗没有
是否看到不一致?颜色停止被关闭一个。
上述问题的一些可能解决方案:
- 再添加一个颜色停止-或
- 将宽度减小到300%-或
- 使用CSS
linear-gradient()
停止在所需的%位置
建议
为具有所需背景的子元素制作动画:
- 宽度400%
- 5个颜色停止,其中最后一个与第一个匹配
|0% |200% |400% animate left by -%
|#1 |#2 |#3 |#4 |#1 5 colors-stops
|0% |100% |200% |300% |400% width
| light | (anim) | dark | (anim) | mode
|░░░░░░░░|▒▒▒▒▒▒▒▒|▓▓▓▓▓▓▓▓|▒▒▒▒▒▒▒▒|░░...
正如您所看到的,在400%时,我们又回到了颜色#1
-非常适合循环逻辑!并且通过";向左动画化-%">我的意思是动画GPU加速的transform: translateX()
属性值。
但是等等!如果我想设置背景位置的动画而不是Element子对象,该怎么办
不是background-position: 100% 0
吗;与background-position: right 0
完全相同
很遗憾,是的。100%不会将其设置在其初始状态(0%
(。如果我们将子元素设置为-200%left
位置的步长,则上表将是有意义的
有关此(背景位置(问题的深入解释,请阅读:在线性梯度上使用具有背景位置的百分比值。
解决方案
你可以:
使用设置为4×父元素(
width: 400%;
(宽度的子元素(背景(。然后在JS中,将其向左移动-200%
,在transitionend
事件中,您可以使用Modulo(Reminder(运算符%
将其位置重置为0(如果返回到Light模式(。否则,移动背景的数学运算实际上是三分之一:
公式:100 / 3 * totModes * counter
下表中为bgX = 100 / 3 * 2 * (1) = 66.66666666666667
等…
|0% |66.66% |133.33% bg-position by %
|#1 |#2 |#3 |#4 |#1 5 colors-stops
|0% |100% |200% |300% |400% bg-size
| light | (anim) | dark | (anim) | mode
|░░░░░░░░|▒▒▒▒▒▒▒▒|▓▓▓▓▓▓▓▓|▒▒▒▒▒▒▒▒|░░...
示例:
// DOM utility functions:
const find = (selector, parent) => (parent || document).querySelector(selector);
// Task:
const elContainer = find("#login");
let c = 0; // position counter
const toggleDarkMode = () => {
c += 1;
const bgX = 100 / 3 * 2 * c;
console.log(bgX)
elContainer.style.backgroundPosition = `${bgX}%`;
};
find("#toggleMode").addEventListener("input", toggleDarkMode);
* {
margin: 0;
}
.toggle-container {
position: fixed;
z-index: 1000;
top: 20px;
left: 20px;
}
.Login-container {
background-image: linear-gradient(to right,
#fff,
red,
#000,
blue,
#fff /*back to home*/
);
background-size: 400%;
background-position: 0% 0;
background-repeat: repeat-x;
height: 100vh;
transition: background 1s ease;
}
<label class="toggle-container">
DARK MODE: <input id="toggleMode" class="toggle" type="checkbox">
</label>
<div id="login" class="Login-container"></div>
对角线坡度
正如您所看到的,只有当背景图像的linear-gradient()
设置为90deg
、270deg
、to right
或to left
时,以上操作才会起作用。
对于对角线渐变任何其他度数,您可以复制值并移动一半。但在这种情况下,背景图像应该以负偏移进行定位。再说一遍,我认为animationend
最终会发挥作用。
不确定以上是否有帮助,但希望它能澄清一些想法,帮助你找到一个可行的解决方案。