Skip to content

Commit fffabe9

Browse files
Denis-GHskorobaeussolarrust
authored
Дополняет доку про perspective (#5437)
* Добавляет раздел На практике, исправляет демку и формулировку в доке про perspective * ~~Баба Яга~~ пунктуация против :) * repspective -> perspective * Отбивает математические операторы пробелами Co-authored-by: Alena Batitskaia <[email protected]> * Добавляет демку в совет * добавляет пустую строку * удаляет пробел * Добавляет overflow: hidden * Дарит значок --------- Co-authored-by: Svetlana Korobtseva <[email protected]> Co-authored-by: Alena Batitskaia <[email protected]> Co-authored-by: Alena Batitskaia <[email protected]>
1 parent 41bc198 commit fffabe9

File tree

5 files changed

+210
-39
lines changed

5 files changed

+210
-39
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
<!DOCTYPE html>
2+
<html lang="ru">
3+
<head>
4+
<title>Интерактивная песочница — perspective — Дока</title>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<link rel="preconnect" href="https://fonts.googleapis.com">
8+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto&display=swap">
10+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&display=swap">
11+
<style>
12+
*, *::before, *::after {
13+
margin: 0;
14+
padding: 0;
15+
box-sizing: border-box;
16+
}
17+
18+
html {
19+
color-scheme: dark;
20+
accent-color: #2E9AFF;
21+
}
22+
23+
body {
24+
min-height: 100vh;
25+
padding: 50px;
26+
display: flex;
27+
align-items: center;
28+
justify-content: center;
29+
background-color: #18191C;
30+
color: #FFFFFF;
31+
font-family: "Roboto", sans-serif;
32+
font-size: 18px;
33+
overflow: hidden;
34+
}
35+
36+
code {
37+
font-family: "Roboto Mono", monospace;
38+
font-size: calc(1em - 1px);
39+
}
40+
41+
.container {
42+
width: 500px;
43+
margin: 0 auto;
44+
}
45+
46+
.controls {
47+
margin-bottom: 25px;
48+
text-align: center;
49+
text-transform: lowercase;
50+
}
51+
52+
.value {
53+
font-size: 40px;
54+
font-weight: 500;
55+
}
56+
57+
.slider {
58+
display: block;
59+
width: 100%;
60+
margin: 5px 0;
61+
}
62+
63+
.plane {
64+
width: 500px;
65+
height: 250px;
66+
perspective: 500px;
67+
transform-style: preserve-3d;
68+
background-color: #2e9aff80;
69+
display: grid;
70+
grid-template-rows: 40px 1fr 40px;
71+
justify-items: center;
72+
align-items: center;
73+
}
74+
75+
.element {
76+
text-align: left;
77+
width: 500px;
78+
height: 150px;
79+
background-color: #F498AD;
80+
transform: rotateY(45deg);
81+
position: relative;
82+
}
83+
84+
.line {
85+
width: 1px;
86+
height: calc(100% - 2px);
87+
position: absolute;
88+
top: 0;
89+
left: -10px;
90+
background-color: #fff;
91+
}
92+
93+
.line::before,
94+
.line::after {
95+
content: "";
96+
position: absolute;
97+
top: 0;
98+
height: 1px;
99+
left: -4px;
100+
width: 10px;
101+
background-color: #fff;
102+
}
103+
104+
.line::after {
105+
top: 100%;
106+
}
107+
108+
.height-calc {
109+
transform: rotateZ(-90deg);
110+
position: absolute;
111+
left: -35px;
112+
top: 44%;
113+
}
114+
115+
@media (max-width: 768px) {
116+
body {
117+
padding: 30px;
118+
}
119+
120+
.container, .plane, .element {
121+
width: 300px;
122+
}
123+
}
124+
</style>
125+
</head>
126+
<body>
127+
<div class="container">
128+
<div class="controls">
129+
<label>
130+
<code class="value"><span id="demo"></span></code>
131+
<input type="range" min="200" max="1000" value="500" class="slider" id="myRange">
132+
</label>
133+
<p>Значение свойства <code>perspective</code></p>
134+
</div>
135+
<div class="plane">
136+
Плоскость экрана
137+
<div class="element">
138+
<pre>
139+
<code>
140+
.pink-element {
141+
width: 500px;
142+
height: 150px;
143+
transform: rotateY(45deg);
144+
}
145+
</code>
146+
</pre>
147+
<div class="line">
148+
<code class="height-calc"></code>
149+
</div>
150+
</div>
151+
</div>
152+
</div>
153+
154+
<script>
155+
const myRange = document.getElementById('myRange')
156+
const output = document.getElementById('demo')
157+
const plane = document.querySelector('.plane')
158+
const element = document.querySelector('.element')
159+
const heightCalc = document.querySelector('.height-calc')
160+
const height = element.clientHeight
161+
output.textContent = myRange.value + 'px'
162+
heightCalc.textContent = "232px"
163+
164+
myRange.onchange = myRange.oninput = function () {
165+
let value = myRange.value
166+
167+
plane.style.perspective = `${+value}px`
168+
output.textContent = `${+value}px`
169+
170+
let multiplier = value / (value - (Math.sin(Math.PI / 4) * 250))
171+
172+
heightCalc.textContent = Math.round(height * multiplier) + "px"
173+
}
174+
</script>
175+
</body>
176+
</html>

css/perspective/demos/dynamic/index.html

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -59,45 +59,33 @@
5959
margin: 5px 0;
6060
}
6161

62-
.scene {
63-
position: absolute;
62+
.plane {
6463
width: 500px;
6564
height: 250px;
6665
perspective: 500px;
67-
}
68-
69-
.scene-wrapper {
70-
width: 500px;
71-
height: 250px;
7266
transform-style: preserve-3d;
67+
background-color: #2e9aff80;
68+
display: grid;
69+
grid-template-rows: 40px 1fr 40px;
70+
justify-items: center;
71+
align-items: center;
7372
}
7473

7574
.element {
76-
display: flex;
77-
justify-content: center;
75+
text-align: center;
7876
width: 500px;
79-
height: 250px;
77+
height: 150px;
8078
padding: 15px;
81-
}
82-
83-
.element--front {
84-
align-items: end;
85-
background-color: #2e9aff80;
86-
transform: rotateY(0) translateZ(100px);
87-
}
88-
89-
.element--back {
90-
align-items: start;
9179
background-color: #F498AD;
92-
transform: rotateY(180deg) translateZ(100px);
80+
transform: rotateY(45deg);
9381
}
9482

9583
@media (max-width: 768px) {
9684
body {
9785
padding: 30px;
9886
}
9987

100-
.container, .scene, .scene-wrapper, .element {
88+
.container, .plane, .element {
10189
width: 300px;
10290
}
10391
}
@@ -108,36 +96,28 @@
10896
<div class="controls">
10997
<label>
11098
<code class="value"><span id="demo"></span></code>
111-
<input type="range" min="100" max="1000" value="500" class="slider" id="myRange">
99+
<input type="range" min="200" max="1000" value="500" class="slider" id="myRange">
112100
</label>
113101
<p>Значение свойства <code>perspective</code></p>
114102
</div>
115-
<div class="scene">
116-
<div class="scene-wrapper">
117-
<div class="element element--back">Задняя стенка экрана</div>
118-
</div>
103+
<div class="plane">
104+
Плоскость экрана
105+
<div class="element">Элемент с <code>transform: rotateY(45deg)</code></div>
119106
</div>
120-
<div class="element element--front">Пользователь</div>
121107
</div>
122108

123109
<script>
124110
const myRange = document.getElementById('myRange')
125111
const output = document.getElementById('demo')
126-
const scene = document.querySelector('.scene')
127-
const elementBack = document.querySelector('.element--back')
112+
const plane = document.querySelector('.plane')
113+
const element = document.querySelector('.element')
128114
output.textContent = myRange.value + 'px'
129115

130116
myRange.onchange = myRange.oninput = function() {
131117
let value = myRange.value
132-
elementBack.style.transform='rotateY(180deg) translateZ(100px)'
133-
134-
if (value === '1000') {
135-
value = 'none'
136-
elementBack.style.transform='rotateY(180deg) translateZ(0)'
137-
}
138118

139-
scene.style.perspective = value === 'none' ? 'none' : `${ +value}px`
140-
output.textContent = value === 'none' ? 'none' : `${ +value}px`
119+
plane.style.perspective = `${ +value}px`
120+
output.textContent = `${ +value}px`
141121
}
142122
</script>
143123
</body>

css/perspective/index.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ title: "`perspective`"
33
description: "Перспектива есть всегда, даже в двумерном вебе."
44
authors:
55
- sqlzzy
6+
contributors:
7+
- denis-gh
68
related:
79
- css/transform
810
- css/transition
@@ -13,7 +15,7 @@ tags:
1315

1416
## Кратко
1517

16-
Свойство `perspective` определяет расстояние от пользователя до _задней стенки_ экрана по оси _z_. Таким образом можно придать глубину элементу, к которому применяется свойство [`transform`](/css/transform/). Эффект заметен только при 3D-трансформациях.
18+
Свойство `perspective` определяет расстояние от пользователя до плоскости экрана по оси _z_. При уменьшении значения свойства `perspective` элементы (или части элементов), расположенные выше плоскости экрана по оси _z_ (ближе к зрителю) увеличиваются в размерах, а те, что дальше — уменьшаются. Таким образом можно придать глубину элементу, к которому применяется свойство [`transform`](/css/transform/). Эффект заметен только при 3D-трансформациях.
1719

1820
Свойство `perspective` влияет на _вложенные элементы_ контейнера, для которого указано, а не на сам контейнер.
1921

css/perspective/practice/denis-gh.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
🛠 Для точного масштабирования в перспективе мы можем определить, во сколько раз увеличится элемент, по формуле _d/(d-z)_, где _d_ — значение свойства `perspective`, _z_ — смещение элемента отностительно плоскости экрана по оси _z_. Смещение по оси _z_ определяем следующим образом: если задали элементу `transform: translateZ(100px)`, то параметр _z_ равен 100px, а если задали элементу `transform: rotateY(20deg)`, то для крайней левой точки элемента смещение по оси _z_ определяется как _sin(20)_, умноженный на половину изначальной ширины элемента.
2+
3+
Рассмотрим на конкретном примере: изначальная ширина элемента — 500px, высота — 150px, элемент повёрнут на 45°, родителю зададим `perspective: 700px`. Применяем формулу: 700 / (700 - sin(45) * 250) = 1,3379 — во столько раз увеличится высота элемента в крайней левой точке. Подставляя разные значения в формулу можем «на бумаге» рассчитать эффект перспективы.
4+
5+
<iframe title="Интерактивная песочница" src="../demos/dynamic-practice/" height="500"></iframe>

people/denis-gh/index.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
name: 'Денис Вакуленко'
3+
url: https://github.com/Denis-GH
4+
badges:
5+
- first-contribution-small
6+
---
7+
8+
Начинающий фронтендер

0 commit comments

Comments
 (0)