Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

一个元素即可实现 3D 插图效果 #138

Open
reng99 opened this issue May 21, 2022 · 0 comments
Open

一个元素即可实现 3D 插图效果 #138

reng99 opened this issue May 21, 2022 · 0 comments
Labels
blog a single blog css 样式

Comments

@reng99
Copy link
Owner

reng99 commented May 21, 2022

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第22天,点击查看活动详情

仅使用一个 <img> 标签,使用一个小技巧就可以创建一个 3D 插图,没有为伪元素,没有其他其他标签,没使用 SVG。仅仅是一个标签配合一些 CSS 样式。

效果图如下:

result.gif

不错哦~

我们来看下代码,分解下:

<img src="https://picsum.photos/id/1069/500/300" >

html 代码没什么好说的了吧~ 就是一个 img 标签。

img {
  --x:10px;
  --y:20px;
  clip-path:polygon(
       var(--y)              var(--y),
       calc(100% - var(--y)) var(--y),
       calc(100% - var(--y)) calc(100% - var(--y)),
       var(--y)              calc(100% - var(--y)),
       0 calc(100% - var(--x) - var(--y)),
       0 calc(var(--x) + var(--y)));
  margin:30px;
  transform:perspective(1000px) rotateY(40deg);
  outline: var(--y) solid rgba(0,0,0,0.4);
  outline-offset: calc(-1*var(--y));
  padding:var(--y) var(--y) var(--y) 0;
  transition:1s all;
  max-width:100%;
  display:block;
  margin:auto;
}

img:hover {
  transform:perspective(1000px) rotateY(0deg);
  clip-path:polygon(
       var(--y)              var(--y),
       calc(100% - var(--y)) var(--y),
       calc(100% - var(--y)) calc(100% - var(--y)),
       var(--y)              calc(100% - var(--y)),
       var(--y)  calc(100% - var(--x) - var(--y)),
       var(--y)  calc(var(--x) + var(--y))
    );
}

我们先对 img 原始的样式了解~

我们先预设变量 --x: 10px;--y: 20px。然后第一步对 <img> 标签添加轮廓:

/* [1] outline */
outline: var(--y) solid rgba(0,0,0,0.4);

1.outline.png

第二步,添加轮廓的偏移:

/* [2] outline-offset */
outline-offset: calc(-1*var(--y));

相当于给图片添加了边框的遮罩层。

2.negative_offset.png

第三步,使用 padding 保留图片左侧的轮廓遮罩。

/* [3] padding */
padding:var(--y) var(--y) var(--y) 0;

3.padding.png

之后,我们使用路径裁切 clip-path,将图片裁剪出一个多边形 -- 使用 polygon

/* [4] clip-path */
clip-path:polygon(
       var(--y)              var(--y),  /* a 点 */
       calc(100% - var(--y)) var(--y),  /* b 点 */
       calc(100% - var(--y)) calc(100% - var(--y)), /* c 点 */
       var(--y)              calc(100% - var(--y)), /* d 点 */
       0 calc(100% - var(--x) - var(--y)), /* x 点 */
       0 calc(var(--x) + var(--y))); /* y 点 */

4.clip-path.png

咦,这样看着是不是像 3d 图片了呢~

为了更加逼真,我们加上 tranform 属性:

/* [5] transform */
transform:perspective(1000px) rotateY(40deg);

5.transform.png

这里我们使用了透视效果,相当于,我们在 Z 轴上距离原点 1000px 处防止了投影仪;让后我们将图在 y 轴上正向旋转 40 度。

下面我们加上 hover 效果,先上图:

6.hover.png

我们对裁切的路径的点做出了调整,上面是 hover 稳定后的效果图,更改了点 x -> x'y -> y' 两处,并恢复了图片在 y 恢复为 0,如下:

transform:perspective(1000px) rotateY(0deg);
clip-path:polygon(
       var(--y)              var(--y), /* a 点 */
       calc(100% - var(--y)) var(--y), /* b 点 */
       calc(100% - var(--y)) calc(100% - var(--y)), /* c 点 */
       var(--y)              calc(100% - var(--y)), /* d 点 */
       var(--y)  calc(100% - var(--x) - var(--y)), /* x' 点 */
       var(--y)  calc(var(--x) + var(--y))); /* y' 点 */

当然,为了动画更加平滑,需要添加 transition 效果,这里添加了:

transition:1s all;

表明所有的动画将在 1s 内平滑移动。

当然,上面只是对图片的左边进行 3D 透视效果而已,你可以对其底部进行透视,比如:

bottom-3d.gif

本文翻译自 3D image with one element,采用意译。

上面的知识点,你学废了没? 💨

【完】✅

@reng99 reng99 added blog a single blog css 样式 labels Jun 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blog a single blog css 样式
Projects
None yet
Development

No branches or pull requests

1 participant