Возможно ли реализовать такой эффект плавной смены изображений на чистом css?
Увидел сайт с очень интересным эффектом: https://travelshift.com/
В правом верхнем углу есть круглая кнопка со стрелкой, если нажать на неё начинается нужный эффект, все мои попытки провальные и кода нету.
Может быть у кого то не будет это отображаться и по этому скину ссылкы на видео в dropbox: видео
Сам эффект начинается после того как нажать на кнопку мышки ..
Можно ли на css получить хотя бы частичную копию ?
Ответы на шейдерах на javascript не нужны
Ответы (2 шт):
У меня получился следующий эффект, реализация которого на основе заготовки автора вопроса. Возможно, что это не совсем именно то, что требуется в вопросе. Сайт по ссылке открыть не могу (санкции), поэтому ориентировался по видео. Чтобы решить задачу полностью и с точностью, готов и дальше двигаться в нужном направлении. И конечно же, коллеги, присоединяйтесь :)
jQuery(document).ready(function($) {
$('.circle').hover(function() {
$('.circle__inner').addClass('circle__inner__on');
$('.before').addClass('before__on');
$('.after').addClass('after__on');
}, function() {
$('.circle__inner').addClass('circle__inner__off');
$('.before').addClass('before__off');
$('.after').addClass('after__off');
});
$('button').click(function() {
$('.circle__inner').removeClass('circle__inner__off').removeClass('circle__inner__on');
$('.before').removeClass('before__off').removeClass('before__on');
$('.after').removeClass('after__off').removeClass('after__on');
});
});
* {
margin: 0;
padding: 0;
}
/*Background*/
.item {
position: relative;
overflow: hidden;
width: 100%;
height: 100vh;
opacity: 0.8;
}
.before {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('https://www.nastol.com.ua/pic/201704/1920x1200/nastol.com.ua-216880.jpg') center center no-repeat;
background-size: cover;
transition: 0.34s linear;
}
.after {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('https://tapety.tja.pl/obrazki/tja_normalne/208831.jpg') center center no-repeat;
background-size: cover;
transition: 0.34s linear;
transform: translate(-100%) scale(5) rotate(45deg);
opacity: 0;
filter: blur(10px);
}
.before__on {
transform: translate(-100%) scale(5) rotate(-45deg);
opacity: 0;
filter: blur(10px);
animation: animate__before__on 8s ease;
}
.after__on {
transform: translate(0) scale(1) rotate(0deg);
opacity: 1;
filter: blur(0px);
animation: animate__after__on 8s ease;
}
.before__off {
transform: translate(0) scale(1) rotate(0deg);
opacity: 1;
filter: blur(0px);
animation: animate__before__off 8s ease;
}
.after__off {
transform: translate(-100%) scale(5) rotate(-45deg);
opacity: 0;
filter: blur(10px);
animation: animate__after__off 8s ease;
}
@keyframes animate__before__on {
0% {
transform: translate(0) scale(1) rotate(0deg);
opacity: 1;
filter: blur(0px);
}
100% {
transform: translate(-100%) scale(5) rotate(-45deg);
opacity: 0;
filter: blur(10px);
}
}
@keyframes animate__after__on {
0% {
transform: translate(0) scale(5) rotate(45deg);
opacity: 0;
filter: blur(10px);
}
100% {
transform: translate(0) scale(1) rotate(0deg);
opacity: 1;
filter: blur(0px);
}
}
@keyframes animate__before__off {
0% {
transform: translate(0) scale(5) rotate(45deg);
opacity: 0;
filter: blur(10px);
}
100% {
transform: translate(0) scale(1) rotate(0deg);
opacity: 1;
filter: blur(0px);
}
}
@keyframes animate__after__off {
0% {
transform: translate(0) scale(1) rotate(0deg);
opacity: 1;
filter: blur(0px);
}
100% {
transform: translate(-100%) scale(5) rotate(-45deg);
opacity: 0;
filter: blur(10px);
}
}
/*Progress*/
.circle-size,
.circle,
.circle__mask,
.circle__inner {
width: 3em;
height: 3em;
border-radius: 50%;
}
.clip-show-left,
.circle__mask.on-left,
.on-right .circle__inner {
clip: rect(0, 1.5em, 3em, 0);
}
.clip-show-right,
.circle__mask.on-right,
.on-left .circle__inner {
clip: rect(0, 3em, 3em, 1.5em);
}
.circle {
position: absolute;
top: 20px;
left: 20px;
font-size: 30px;
border: 2px solid aliceblue;
}
.circle__mask {
position: absolute;
left: 0;
top: 0;
}
.circle__holder {
position: absolute;
width: 80%;
height: 80%;
left: 10%;
top: 10%;
border-radius: 50%;
}
.circle__inner {
position: absolute;
width: 100%;
height: 100%;
background-color: lightsteelblue;
}
.on-left .circle__inner__on {
animation: circle-left__on 16s linear;
}
.on-right .circle__inner__on {
animation: circle-right__on 16s linear;
}
.on-left .circle__inner__off {
animation: circle-left__off 16s linear;
}
.on-right .circle__inner__off {
animation: circle-right__off 16s linear;
}
@keyframes circle-left__on {
0% {
transform: rotate(0);
}
25% {
transform: rotate(0);
}
50% {
transform: rotate(180deg);
}
75% {
transform: rotate(180deg);
}
100% {
transform: rotate(180deg);
}
}
@keyframes circle-right__on {
0% {
transform: rotate(0);
}
25% {
transform: rotate(180deg);
}
50% {
transform: rotate(180deg);
}
75% {
transform: rotate(180deg);
}
100% {
transform: rotate(180deg);
}
}
@keyframes circle-left__off {
0% {
transform: rotate(180deg);
}
25% {
transform: rotate(180deg);
}
50% {
transform: rotate(360deg);
}
75% {
transform: rotate(360deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes circle-right__off {
0% {
transform: rotate(180deg);
}
25% {
transform: rotate(360deg);
}
50% {
transform: rotate(360deg);
}
75% {
transform: rotate(360deg);
}
100% {
transform: rotate(360deg);
}
}
.circle>span {
position: absolute;
top: 45%;
left: 0;
right: 0;
bottom: 0;
transform: translateY(-25%);
text-align: center;
font-size: 16px;
color: aliceblue;
text-shadow: 2px 1px 4px rgba(0, 0, 0, 0.5);
}
button {
outline: none;
border: none;
display: block;
position: absolute;
top: 120px;
left: 33px;
padding: 3px 6px;
border-radius: 2px;
background-color: aliceblue;
color: #111;
}
button:active {
background-color: #111;
color: aliceblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item">
<div class="after"></div>
<div class="before"></div>
</div>
<div class="circle">
<div class="circle__mask on-left">
<div class="circle__inner"></div>
</div>
<div class="circle__mask on-right">
<div class="circle__inner"></div>
</div>
<div class="circle__holder"></div>
<span>Наведи <br> и подержи</span>
</div>
<button>Сбросить</button>
Ещё один вариант. Сценарий анимации максимально постарался приблизить к оригиналу в вопросе. Но это лишь сценарий, и чего-то мне кажется здесь ещё не хватает. Конечно, такие эффекты с помощью WebGL повторить на CSS вероятнее всего невозможно. Но, есть ещё над чем подумать и работать :))
jQuery(document).ready(function($) {
$('.circle').hover(function() {
$('.circle__inner').addClass('circle__inner__on');
$('.before').addClass('before__on');
$('.after').addClass('after__on');
}, function() {
$('.circle__inner').addClass('circle__inner__off');
$('.before').addClass('before__off');
$('.after').addClass('after__off');
});
$('button').click(function() {
$('.circle__inner').removeClass('circle__inner__off').removeClass('circle__inner__on');
$('.before').removeClass('before__off').removeClass('before__on');
$('.after').removeClass('after__off').removeClass('after__on');
});
});
* {
margin: 0;
padding: 0;
}
/*Background*/
.item {
position: relative;
overflow: hidden;
width: 100%;
height: 100vh;
opacity: 0.8;
}
.before {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('https://www.nastol.com.ua/pic/201704/1920x1200/nastol.com.ua-216880.jpg') center center no-repeat;
background-size: cover;
transition: 0.34s linear;
}
.after {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('https://tapety.tja.pl/obrazki/tja_normalne/208831.jpg') center center no-repeat;
background-size: cover;
transition: 0.34s linear;
transform: scale(5) rotate(90deg);
opacity: 0;
filter: blur(30px);
z-index: -1;
}
.before__on {
transform: scale(0.5) rotate(-90deg);
opacity: 0;
filter: blur(30px);
z-index: -1;
animation: animate__before__on 2s ease;
}
.after__on {
transform: scale(1) rotate(0deg);
opacity: 1;
filter: blur(0);
z-index: 1;
animation: animate__after__on 2s ease;
}
.before__off {
transform: scale(1) rotate(0deg);
opacity: 1;
filter: blur(0);
z-index: 1;
animation: animate__before__off 2s ease;
}
.after__off {
transform: scale(0.5) rotate(-90deg);
opacity: 0;
filter: blur(30px);
z-index: -1;
animation: animate__after__off 2s ease;
}
@keyframes animate__before__on {
0% {
transform: scale(1) rotate(0deg);
opacity: 1;
filter: blur(0);
z-index: 1;
}
20% {
transform: scale(1.2) rotate(0deg);
opacity: 1;
filter: blur(0);
z-index: 1;
}
100% {
transform: scale(0.1) rotate(-90deg);
opacity: 0;
filter: blur(30px);
z-index: -1;
}
}
@keyframes animate__after__on {
0% {
transform: scale(5) rotate(90deg);
opacity: 0;
filter: blur(30px);
z-index: -1;
}
100% {
transform: scale(1) rotate(0deg);
opacity: 1;
filter: blur(0);
z-index: 1;
}
}
@keyframes animate__before__off {
0% {
transform: scale(5) rotate(90deg);
opacity: 0;
filter: blur(30px);
z-index: -1;
}
100% {
transform: scale(1) rotate(0deg);
opacity: 1;
filter: blur(0);
z-index: 1;
}
}
@keyframes animate__after__off {
0% {
transform: scale(1) rotate(0deg);
opacity: 1;
filter: blur(0);
z-index: 1;
}
20% {
transform: scale(1.2) rotate(0deg);
opacity: 1;
filter: blur(0);
z-index: 1;
}
100% {
transform: scale(0.1) rotate(-90deg);
opacity: 0;
filter: blur(30px);
z-index: -1;
}
}
/*Progress*/
.circle-size,
.circle,
.circle__mask,
.circle__inner {
width: 3em;
height: 3em;
border-radius: 50%;
}
.clip-show-left,
.circle__mask.on-left,
.on-right .circle__inner {
clip: rect(0, 1.5em, 3em, 0);
}
.clip-show-right,
.circle__mask.on-right,
.on-left .circle__inner {
clip: rect(0, 3em, 3em, 1.5em);
}
.circle {
position: absolute;
top: 20px;
left: 20px;
font-size: 30px;
border: 2px solid aliceblue;
}
.circle__mask {
position: absolute;
left: 0;
top: 0;
}
.circle__holder {
position: absolute;
width: 80%;
height: 80%;
left: 10%;
top: 10%;
border-radius: 50%;
}
.circle__inner {
position: absolute;
width: 100%;
height: 100%;
background-color: lightsteelblue;
}
.on-left .circle__inner__on {
animation: circle-left__on 4s linear;
}
.on-right .circle__inner__on {
animation: circle-right__on 4s linear;
}
.on-left .circle__inner__off {
animation: circle-left__off 4s linear;
}
.on-right .circle__inner__off {
animation: circle-right__off 4s linear;
}
@keyframes circle-left__on {
0% {
transform: rotate(0);
}
25% {
transform: rotate(0);
}
50% {
transform: rotate(180deg);
}
75% {
transform: rotate(180deg);
}
100% {
transform: rotate(180deg);
}
}
@keyframes circle-right__on {
0% {
transform: rotate(0);
}
25% {
transform: rotate(180deg);
}
50% {
transform: rotate(180deg);
}
75% {
transform: rotate(180deg);
}
100% {
transform: rotate(180deg);
}
}
@keyframes circle-left__off {
0% {
transform: rotate(180deg);
}
25% {
transform: rotate(180deg);
}
50% {
transform: rotate(360deg);
}
75% {
transform: rotate(360deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes circle-right__off {
0% {
transform: rotate(180deg);
}
25% {
transform: rotate(360deg);
}
50% {
transform: rotate(360deg);
}
75% {
transform: rotate(360deg);
}
100% {
transform: rotate(360deg);
}
}
.circle>span {
position: absolute;
top: 45%;
left: 0;
right: 0;
bottom: 0;
transform: translateY(-25%);
text-align: center;
font-size: 16px;
color: aliceblue;
text-shadow: 2px 1px 4px rgba(0, 0, 0, 0.5);
}
button {
outline: none;
border: none;
display: block;
position: absolute;
top: 120px;
left: 33px;
padding: 3px 6px;
border-radius: 2px;
background-color: aliceblue;
color: #111;
}
button:active {
background-color: #111;
color: aliceblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item">
<div class="after"></div>
<div class="before"></div>
</div>
<div class="circle">
<div class="circle__mask on-left">
<div class="circle__inner"></div>
</div>
<div class="circle__mask on-right">
<div class="circle__inner"></div>
</div>
<div class="circle__holder"></div>
<span>Наведи <br> и подержи</span>
</div>
<button>Сбросить</button>