J'essaie de convertir un div carré avec une image d'arrière-plan en trapèze.
Je voulais le réaliser en 2D, de la même manière que l'outil "déformation" de Photoshop.
En gros, tout ce que je veux, c'est réduire le bord supérieur du carré et déformer l'image en conséquence.
La conversion 3D "semble" faire l'affaire :
transform: rotateX(30deg);
Cela fonctionne pour la plupart des cas d'utilisation, mais pas pour tous. En fait, il s'agit d'un carré pivoté de 30 degrés qui "ressemble" à un trapèze vu de face/arrière, mais qui reste un carré pivoté de 30 degrés vu de n'importe quel autre côté.
Ce que je veux, c'est obtenir un vrai trapèze. Je souhaite que l'image carrée soit déformée en 2D afin que la forme et l'image changent réellement sans impliquer de rotation.
J'ai essayé ça et ça marche en terme de forme (trapèze) :
border-style: solid; height: 0; border-color: transparent transparent red transparent; border-width: 0 100px 100px 100px;
Mais je ne peux pas remplacer la zone rouge par l'image d'arrière-plan déformée. Cela va à l’encontre de mon objectif. Tout ce que j'essaie garde l'image intacte.
Existe-t-il des astuces CSS/html5/javascript pour obtenir ce que je veux ?
Merci.
Vous pouvez obtenir l'effet en appliquant une transformation 3D au pseudo-élément (vous pouvez également définir
background-image
dessus) et en vous assurant qu'il est aplati sur son plan d'origine (le plan de son élément parent). Cela signifie que si vous souhaitez faire pivoter quelque chose en 3D, vous devez faire pivoter l'objet parent.Étape n°1 : Créez un carré
div
, ajoutez une variable factice (ou sous-variable) avec exactement les mêmes dimensions et définissezdiv
,添加一个具有完全相同尺寸的伪变量(或子变量),并在该伪变量上设置background-image
sur cette variable factice.Étape n°2 : Placez la valeur factice sur le
transform-origin
设置为底部边缘的中间 (100% 50%
) - cela garantit que le bord inférieur reste en place après l'application de la transformation 3D.Étape n°3 : Étendez le bord le long de l'axe
z
轴应用 3D 倾斜,沿y
.Oui, nous n'avons pas de fonction d'inclinaison 3D en CSS. Mais nous avons
matrix3d()
, qui peut être utilisé pour exprimer n'importe quelle rotation, mise à l'échelle, inclinaison et translation !Commençons donc par comprendre comment fonctionne l’inclinaison.
L'inclinaison se produit le long de l'axe.
Il s'agit d'une démo interactive qui illustre le fonctionnement de la fonction d'inclinaison 2D.
Considérez cet exemple où nous inclinons le long de l'axe x, lorsque l'axe y s'éloigne de sa position initiale, les bords le long de l'axe y sont allongés - cet angle est l'angle d'inclinaison. L'axe z est perpendiculaire au plan que nous inclinons (dans ce cas xOy) et n'est pas affecté :
Eh bien, dans notre cas, nous avons fait quelque chose de similaire, mais l'inclinaison s'est produite dans le plan yOz, pas dans le plan xOy, car nous avons plutôt incliné le long du plan yOz > z le long de l'axe x.
Puisque nous avons déjà utilisé
transform-origin
pour ancrer le milieu du bord inférieur de la pseudo-valeur en place, et que cette inclinaison se produit le long de l'axe z (perpendiculaire à l'écran), nous tirons essentiellement notre pseudo-arrière vers l'arrière de l'écran, en conservant toutes les coordonnées x et y d'un point, mais en modifiant les coordonnées z.En gros, si nous le visualisons en 3D sans l'aplatir sur le plan parent (le parent est limité par le contour), il ressemblera à ceci.
Vous pouvez voir comment la ligne de guidage horizontale en haut montre comment le haut de la pseudo-valeur inclinée conserve ses coordonnées x et y, c'est juste le long de l'axe z.
D'accord, comment pouvons-nous faire cela en utilisant CSS ?
Comme mentionné ci-dessus, il n'y a pas d'inclinaison 3D, mais nous pouvons construire nous-mêmes la matrice de transformation. Puisqu'il s'agit d'une inclinaison le long de l'axe z (le troisième axe) et que le bord est étiré le long de l'axe y (le deuxième axe), la seule chose dans la matrice qui ressemble à la matrice d'identité ( le
1
,其他地方的0
)将位于第 3 行第 2 行柱子。我们将在那里得到倾斜角的正切。在 MDN 上,您也可以在skewX()
和skewY()
le long de la diagonale principale) jusqu'à ce pointEn effet, chaque point le long de l'axe d'inclinaison est déplacé de sa coordonnée le long de l'axe allongé multipliée par la tangente de l'angle d'inclinaison - vous pouvez le voir dans la première illustration si vous tracez une ligne parallèle à l'axe (l'axe x , l'axe y (incliné vers l'avant et vers l'arrière) passe par la position d'origine (gris) et la position finale (noire) du point d'exemple. Dessiner ces lignes parallèles crée un triangle rectangle avec la coordonnée y sur le déplacement x . est la tangente de l'angle d'inclinaison
.D'accord, revenons à la matrice, ça ressemble à ça.
Pour obtenir
matrix3d()
值,我们再添加一行和一列,与4x4
les mêmes valeurs dans la matrice identité, puis lister les valeurs colonne par colonne ( pas ) > ligne par ligne !). Jusqu'à présent, nous avons :Notez que nous avons également ajouté
perspective
pour obtenir une vue déformée (plus petite en haut/plus en arrière).Le code jusqu'à présent nous donne la version aplatie vue dans le gif ci-dessus. Je dis version aplatie car, pour autant que nous en soyons ici, les pseudo-objets sont toujours aplatis sur le plan de leur parent.
Lorsque le parent
div
n'a pas de transformation 3D, et qu'on le regarde de face, l'aspect pseudo-évident est plat.Lorsqu'un parent
div
确实具有 3D 变换时,其 3D 变换伪值会展平到其平面中,因为默认transform-style
值为flat
。这意味着 3D 变换父级的任何 3D 变换子级/伪对象都会在父级平面中展平。如果我们将div的transform-style
设置为preserve-3d
a une transformation 3D, sa pseudo-valeur de transformation 3D est aplatie dans son plan, car la valeur par défaut detransform-style
estflat
. Cela signifie que tous les enfants/pseudo-objets de transformation 3D d'un parent de transformation 3D seront aplatis dans le plan parent. Ce paramètre peut être modifié si nous définissons letransform-style
du div surpreserve-3d
. Mais nous ne voulons pas de cela.Étape 4 : Sécurisez le bord supérieur !
Encore une chose qui ne semble toujours pas correcte :
transform
Le bord supérieur est maintenant en dessous du bord d'origine.C'est à cause de la façon dont nous l'avons configuré
), àperspective
以及它的工作原理。默认情况下,perspective-origin
死在我们设置它的元素的中间(在本例中是我们的div
),水平方向为50%
,垂直方向为50%
et de son fonctionnement. Par défaut,perspective-origin
meurt au milieu de l'élément sur lequel nous l'avons placé (dans ce cas notre50%
horizontalement et verticalement50%
.perspective-origin
(50% 50%
),只有div
正中间垂直于屏幕平面的线上的点才会被投影到屏幕平面上的某个点:考虑视角后,与自己的 x,y 坐标相同的 x,y 坐标。考虑透视后,只有垂直于屏幕并沿div
En utilisant laperspective-origin
par défaut (50% 50%
), seuls lesseront projetés sur cette ligne médiane horizontale.
Savez-vous ce qui se passe ? Si nous bougeonsperspective-origin
使其位于 div 顶部边缘的中间 (50% 0
), alors les points dans un plan perpendiculaire à l'écran le long de ce bord supérieur seront projetés le long de ce bord supérieur - c'est-à-dire que le bord supérieur du pseudo-objet incliné 3D sera dans la même ligne que le bord supérieur. de son parent.
🎜Notre code final est donc : 🎜Voici une vue comparative en direct entre nos résultats et leur version pré-conversion car les deux divs sont pivotés en 3D pour montrer qu'ils sont à plat sur le plan xOy.
Vous ne souhaitez pas utiliser de préprocesseur pour gérer les valeurs tangentes ? Firefox et Safari prennent déjà en charge les fonctions trigonométriques par défaut, et Chrome 111+ prend en charge les fonctions trigonométriques en activant le drapeau
chrome://flags
Fonctionnalités expérimentales de la plateforme Web dans le .Vous ne voulez pas attendre le support de Chromium ? Vous n'avez même pas besoin d'utiliser le calcul de la tangente, vous pouvez utiliser n'importe quel nombre positif - plus le nombre est grand, plus le bord supérieur sera petit. J'utilise la valeur tangente pour illustrer d'où elle vient, mais ce n'est pas obligatoire. Notre tangente est pour la tangente de
0°
到90°
的角度计算的。这为我们提供了从0
到+Infinity
. Alors oui, n’importe quel nombre positif peut apparaître dans une matrice.