Размер прямоугольника внутри перекошенного контейнера - PullRequest
2 голосов
/ 22 марта 2019

Есть ли способ или расчет, чтобы узнать размер блока контейнера с transform: skew();?

Вот чего я хочу достичь:

enter image description here

То, что я делал до сих пор методом проб и ошибок, но, как вы видите, оно не динамично, а иногда оно идет дальше, чем края.

body,
html {
  width: 100vw;
  height: 100vh;
  position: relative;
}

.container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) skew(-20deg);
  background: lime;
  width: 50%;
  height: 50%;
}

.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) skew(20deg);
  height: 100%;
  width: 81%;
  background: pink;
  opacity: 0.5
}
<div class="container">
  <div class="child"></div>
</div>

Ответы [ 2 ]

0 голосов
/ 22 марта 2019

Сначала давайте оставим ширину равной 100% и просто скорректируем начало преобразования, чтобы оно было:

body,
html {
  width: 100vw;
  height: 100vh;
  position: relative;
}

.container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) skew(-20deg);
  background: lime;
  width: 50%;
  height: 50%;
}

.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) skew(20deg);
  transform-origin:top left;
  height: 100%;
  width: 100%;
  background: pink;
  opacity: 0.5
}
<div class="container">
  <div class="child"></div>
</div>

Теперь часть, которую мы должны удалить, это та, которая показана красным, как показано ниже:

enter image description here

Рассматривая иллюстрацию, мы имеем tan(angle) = X/H, где angle - угол перекоса (20deg), а H - высота и X, что мы ищем.Поэтому нам нужно удалить H*tan(20deg) = 0.36369*H:

body,
html {
  width: 100vw;
  height: 100vh;
  position: relative;
}

.container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) skew(-20deg);
  background: lime;
  width: 50%;
  height: 50%;
}

.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) skew(20deg);
  transform-origin:top left;
  height: 100%;
  width: calc(100% - 0.3639*50vh);
  background: pink;
  opacity: 0.5
}
<div class="container">
  <div class="child"></div>
</div>

Теперь, когда у нас есть хорошая ширина, мы исправляем положение:

body,
html {
  width: 100vw;
  height: 100vh;
  position: relative;
}

.container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) skew(-20deg);
  background: lime;
  width: 50%;
  height: 50%;
}

.child {
  position: absolute;
  top: 0;
  left: 0;
  transform: skew(20deg);
  transform-origin:top left;
  height: 100%;
  width: calc(100% - 0.3639*50vh);
  background: pink;
  opacity: 0.5
}
<div class="container">
  <div class="child"></div>
</div>

Я не совсем уверен в назначении этой фигуры, но вот еще одна идея создать ее без сложных вычислений:

body,
html {
  width: 100vw;
  height: 100vh;
  position: relative;
}

.container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: 
    linear-gradient(to bottom right,transparent 49.8%,lime 50%) left/15% 100%,
    linear-gradient(to top    left ,transparent 49.8%,lime 50%) right/15% 100%,
    linear-gradient(lime,lime) center/70% 100%;
  background-repeat:no-repeat;
  width: 50%;
  height: 50%;
}

.child {;
  height: 100%;
  width:70%;
  margin:auto;
  background: pink;
  opacity: 0.5
}
<div class="container">
  <div class="child"></div>
</div>

Вам просто нужно сделать внутренний прямоугольник такой же ширины, что и центрированный градиент (в данном случае 70%), а затем разделить оставшееся влево /правый градиент, который создаст треугольную форму.

Вы также можете легко применить анимацию:

body,
html {
  margin:0;
}

.container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: 
    linear-gradient(to bottom right,transparent 49.8%,lime 50%) left/15% 100%,
    linear-gradient(to top    left ,transparent 49.8%,lime 50%) right/15% 100%,
    linear-gradient(lime,lime) center/70% 100%;
  background-repeat:no-repeat;
  width: 50%;
  height: 50%;
  transition:1s;
}

.child {;
  height: 100%;
  width:70%;
  margin:auto;
  background: pink;
  opacity: 0.5;
  transition:1s;
}

.container:hover {
  background-size:0% 100%,0% 100%,100% 100%;
}

.container:hover .child{
  width:100%;
}
<div class="container">
  <div class="child"></div>
</div>
0 голосов
/ 22 марта 2019

Это не совсем та структура, о которой вы просили, но похожая, и она не требует сложных вычислений.

Принцип будет заключаться в том, чтобы не помещать ребенка в наклонный блок, а сверху, как вынаходятся на абсолютной позиции.Таким образом, у нас будет 3 блока одинакового размера.Если вы наклоните 2 блока позади, вы получите только половину треугольников.Чтобы получить полные треугольники, вы можете играть с transform-origin, и вы можете достичь следующего:

body,
html {
  width: 100vw;
  height: 100vh;
  position: relative;
}

.container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: pink;
  width: 50%;
  height: 50%;
  opacity:0.7;
}

.container-l,
.container-r {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) skew(-20deg);
  transform-origin:50% 0%;
  width: 50%;
  height: 50%;
}
.container-l {
  transform-origin:50% 100%;
  background: lime;
}
.container-r {
  transform-origin:50% 0%;
  background: green;
}
<div class="container-r">
</div>
<div class="container-l">
</div>
<div class="container">
  <div class="child"></div>
</div>
...