Как сделать плавную выпуклость?
Ответы (3 шт):
Вариант на чистом CSS
Здесь можно найти множество других вариантов плавных переходов, в том числе и решения на CSS.
body {margin: 0; background-image: -webkit-repeating-radial-gradient(center center, rgba(0, 0, 0, .2), rgba(0, 0, 0, .2) 1px, transparent 1px, transparent 100%); background-image: repeating-radial-gradient(center center, rgba(0, 0, 0, .2), rgba(0, 0, 0, .2) 1px, transparent 1px, transparent 100%); -webkit-background-size: 3px 3px; background-size: 3px 3px;}
.container {position: relative; width: 150px; height: 100vh; background-color: lightgray;}
.elem {display: block; position: absolute; width: 100px; height: 100px; right: -30px; top: 50%; margin-top: -50px; border-radius: 100%; background-color: lightgray;}
.elem__t,.elem__b {overflow: hidden; position: absolute; padding: 40px 20px; width: 4px;}
.elem__t {top: 0%; right: 26px; margin-top: -40px; transform: rotate(-70deg);}
.elem__b {top: 0%; right: 26px; margin-top: 60px; transform: rotate(-108deg) scale(-1, 1);}
.elem__t-top,.elem__b-bottom {position: absolute; left: 100%; width: 400%; border-radius: 100%;}
.elem__t-top {top: 50%; box-shadow: 0 0 0 50px lightgray; transform: translate(-50%, 1%);}
.elem__b-bottom {top: 50%; box-shadow: 0 0 0 50px lightgray; transform: translate(-50%, 1%);}
.elem__t-top:before,.elem__b-bottom:before {content: ""; display: block;}
.elem__t-top:before {padding: 100% 0 1000px 0;}
.elem__b-bottom:before {padding: 100% 0 1000px 0;}
<div class="container"><div class="elem"><div class="elem__t"><div class="elem__t-top"></div></div><div class="elem__b"><div class="elem__b-bottom"></div></div></div></div>
В качестве бонуса пример оживим, сделаем из него выдвижной блок:
$('.elem').hover(function() {$('.container').addClass('container__hover');}, function() {$('.container').removeClass('container__hover');});
$('.elem').click(function() {$('.container').toggleClass('container__active');});
body {margin: 0; background-image: -webkit-repeating-radial-gradient(center center, rgba(0, 0, 0, .2), rgba(0, 0, 0, .2) 1px, transparent 1px, transparent 100%); background-image: repeating-radial-gradient(center center, rgba(0, 0, 0, .2), rgba(0, 0, 0, .2) 1px, transparent 1px, transparent 100%); -webkit-background-size: 3px 3px; background-size: 3px 3px;}
.container {position: relative; width: 1px; height: 100vh; background-color: lightgray; transition: width 0.25s ease-in-out;}
.elem {display: block; position: absolute; width: 100px; height: 100px; right: -30px; top: 50%; margin-top: -50px; border-radius: 100%; background-color: lightgray; cursor: pointer;}
.elem__t,.elem__b {overflow: hidden; position: absolute; padding: 40px 20px; width: 4px;}
.elem__t {top: 0%; right: 26px; margin-top: -40px; transform: rotate(-70deg);}
.elem__b {top: 0%; right: 26px; margin-top: 60px; transform: rotate(-108deg) scale(-1, 1);}
.elem__t-top,.elem__b-bottom {position: absolute; left: 100%; width: 400%; border-radius: 100%;}
.elem__t-top {top: 50%; box-shadow: 0 0 0 50px lightgray; transform: translate(-50%, 1%);}
.elem__b-bottom {top: 50%; box-shadow: 0 0 0 50px lightgray; transform: translate(-50%, 1%);}
.elem__t-top:before,.elem__b-bottom:before {content: ""; display: block;}
.elem__t-top:before {padding: 100% 0 1000px 0;}
.elem__b-bottom:before {padding: 100% 0 1000px 0;}
.container__hover {width: 15px;}
.container__active {width: 50%;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container"><div class="elem"><div class="elem__t"><div class="elem__t-top"></div></div><div class="elem__b"><div class="elem__b-bottom"></div></div></div></div>
тут меня вдруг осенило - а можно так сделать что бы эта выпуклость появилась при hover ? – MaximLensky
Вариант с анимацией при наведении. Как говорится, любой каприз за ваши деньги :)
$('.elem').hover(function() {$('.container').addClass('container__hover');}, function(){$('.container').removeClass('container__hover');});$('.elem').click(function() {$('.overlay').toggleClass('overlay__active');$('.container').toggleClass('container__active');$('.elem').toggleClass('elem__active');});
body {margin: 0; background-image: -webkit-repeating-radial-gradient(center center, rgba(0, 0, 0, .2), rgba(0, 0, 0, .2) 1px, transparent 1px, transparent 100%); background-image: repeating-radial-gradient(center center, rgba(0, 0, 0, .2), rgba(0, 0, 0, .2) 1px, transparent 1px, transparent 100%); -webkit-background-size: 3px 3px; background-size: 3px 3px; z-index: 0;}
.container {position: relative; width: 2px; height: 100vh; background-color: lightgray; transition: width 0.25s ease-in-out; z-index: 2;}
.container:before {content: ""; display: block; position: absolute; top: 0; bottom: 0; right: -30px; width: 30px;}
.elem {display: block; position: absolute; width: 100px; height: 100px; right: -30px; top: 50%; margin-top: -50px; border-radius: 100%; background-color: lightgray; cursor: pointer; transform: scale(0); transition: all 0.25s ease-in-out;}.elem__t,.elem__b {overflow: hidden; position: absolute; padding: 40px 20px; width: 4px;}.elem__t {top: 0%; right: 26px; margin-top: -40px; transform: rotate(-70deg);}.elem__b {top: 0%; right: 26px; margin-top: 60px; transform: rotate(-108deg) scale(-1, 1);}.elem__t-top,.elem__b-bottom {position: absolute; left: 100%; width: 400%; border-radius: 100%;}.elem__t-top {top: 50%; box-shadow: 0 0 0 50px lightgray; transform: translate(-50%, 1%);}.elem__b-bottom {top: 50%; box-shadow: 0 0 0 50px lightgray; transform: translate(-50%, 1%);}.elem__t-top:before,.elem__b-bottom:before {content: ""; display: block;}.elem__t-top:before {padding: 100% 0 1000px 0;}.elem__b-bottom:before {padding: 100% 0 1000px 0;}.container__hover {width: 15px;}.container__active {width: 50%; box-shadow: 5px 0px 8px 0px rgba(34, 60, 80, 0.1); animation-name: Open; animation-duration: 1.5s; animation-iteration-count: 1; animation-direction: normal;}@keyframes Open {from { width: 2px; } 50% { width: 60%; } to { width: 50%; }}.overlay__active {position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.15); z-index: -1; animation-name: Overlay; animation-duration: 1.5s; animation-iteration-count: 1; animation-direction: normal;}@keyframes Overlay { from { background-color: rgba(0, 0, 0, 0); } to { background-color: rgba(0, 0, 0, 0.15); }}
.container:hover .elem {transform: scale(1);}.elem__active {transform: scale(1)!important; box-shadow: 10px 0px 8px 0px rgba(34, 60, 80, 0.1);}
span {position: absolute; top: 50%; margin-top: -8px; left: 49px; font-size: 14px; color: gray;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>← наведи</span><div class="container"><div class="elem"><div class="elem__t"><div class="elem__t-top"></div></div><div class="elem__b"><div class="elem__b-bottom"></div></div></div></div><div class="overlay"></div>
Изначально, если какой то объект в svg сложнее чем можно сделать руками то рисуют уже в графическом редакторе как и я в этом примере, открыл inkscape и дальше скрины по шагам
1) Выбирает инструмент Рисовать прямоугольники и квадраты на панеле инструментов
2) Потом в меню программы находим Контур и нажимает Оконтурить объект
3) Выбираем инструмент Редактировать узлы контуром и рычаги контуров и
4) ставим точки и выравниваем как душе угодно но согласно макета у меня получилось вот это
5) Выдеяем эти три точки и нажмём на дополнительном меню программы на Сделать выделенные узлы автоматически сглаженными
6) Выравниваем лишнее инструментом из третьего пункта и получаем вот это
Последнее : Сохраняем как простой svg чистим от не нужного и пользуемся кодом - превью в снипете
.item{
height: 100vh;
}
.item svg{
height: 100%;
}
<div class="item">
<svg viewBox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">
<path d="m0 0.66666663h83.910713s-2.882957 72.709545 4.264202 108.03266c3.315168 16.38442 17.307115 30.22482 17.658415 46.93757 0.36654 17.43751-13.077122 32.57246-16.349987 49.70399-5.83825 30.55981-5.57263 93.17099-5.57263 93.17099h-83.910713z" fill="#666"/>
</svg>
</div>
На самом деле, для svg эта форма - не сложная, описывается двумя кривыми Безье, координаты для которых очень просто вычислить в уме или на бумаге:
<svg width=300 height=300>
<path d="
m 0 0
h 125
v 50
c 0 50 50 50 50 100
c 0 50 -50 50 -50 100
v 50
h -125
" /></svg>
Как видите, одна команда “c” сопровождается 3 мя точками, первые 2 из них - контрольные точки кривой Безье, а третья - конечная точка, если все эти точки нарисовать - получится очень незамысловатая картина:
<svg viewbox="-50 -10 150 150" height=100vh>
<circle r=3 cx=0 cy=0 />
<circle r=3 cx=0 cy=50 />
<circle r=3 cx=50 cy=50 />
<circle r=3 cx=50 cy=100 />
<path d="
m 0 0
c 0 50 50 50 50 100
" stroke=red fill=none />
</svg>
BONUS:
let dir = -1, p = 0;
let elastic = t => Math.pow(2,-10*t) *
Math.sin((t-0.2/4)*(2*Math.PI)/0.2) + 1
addEventListener('mousemove', e => {
let r = svg.getBoundingClientRect();
let dx = e.x - r.x - r.width/2;
let dy = e.y - r.y - r.height/2;
dir = Math.sqrt(dx*dx+dy*dy) > 50 ? -1 : 1;
});
function draw(t) {
p = Math.max(0, Math.min(p+(dir>0?0.02:-0.1), 1));
let pt = (dir>0?elastic(p):Math.sqrt(p))*25;
path.setAttribute('d', `m 0 0 h 125 v 25
c 0 30 ${pt} 30 ${pt} 60
c 0 30 -${pt} 30 -${pt} 60
v 25 h -125`)
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
<svg id=svg width=250 height=170><path id=path /></svg>







