1. 3D转换

transform:不仅可以2D转换,还可以进行3D转换

1.1 坐标轴

用X、Y、Z分别表示空间的3个维度,三条轴互相垂直。注意+Y是向下的

1.2 perspective透视

电脑显示屏是一个2D的平面,因为我们看不出来旋转的方向,通过perspective属性,可以定义3D 元素距视图的距离,单位是px。

说白了,设置了perspective属性后,就有了进大远小的效果了,在视觉上,让我们能看出来3d的效果。

注意:当为元素定义 perspective 属性时,其子元素会获得透视效果,而不是元素本身。

需要添加透视:perspective

1.)添加给父盒子, 让子盒子拥有近大远小的透视效果

2. )1000px 指的是观察者到盒子的距离

1.3 rotate旋转

左手定则:

伸出左手握拳, 心中自有三根轴,

大拇指指向轴的正方向, 手指头卷曲的方向, 就是旋转的正方向

transform: rotate(45deg);// 让元素在平面2D中旋转
transform: rotateX(45deg);// 让元素沿着X轴转45度
transform: rotateY(45deg);// 让元素沿着Y轴转45度
transform: rotateZ(45deg);// 让元素沿着Z轴转45度

1.4 translate平移

/*沿着X轴的正方向移动45px*/
transform: translateX(45px);
/*沿着Y轴的正方向移动45px*/
transform: translateY(45px);
/*沿着Z轴的正方向移动45px*/
transform: translateZ(45px);

 <style>body {perspective: 1000px;}img {display: block;margin: 100px auto;transition: all 4s;}img:hover {/*transform: translateX(-100px);*//*transform: translateY(-100px);*/transform: translateZ(-500px);}</style>

1.5 transform-style

transform-style 属性规定如何在 3D 空间中呈现被嵌套的元素。注意这个属性只能给父元素添加。

flat:默认值,2d显示
preserve-3d: 3d显示

transform-style与perspective的区别 :

/*透视:透视只是相当于设置了一个距离,辅助我们查看3D效果的工具,*/
/*preserve-3d:给父盒子添加,让子元素保留3D的位置,说白了,只有设置了preserve-3d,这个元素才能被称之为3d元素。 */

//一个3d元素可以没有perspective,但是不能没有transform-style

/立方体效果/
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>Title</title><style>* {margin: 0;padding: 0;list-style: none;}ul {width: 200px;height: 200px;margin: 100px auto;position: relative;/* 真 3 d */transform-style: preserve-3d;transition: all 20s;/* 只是用于辅助布局的, 布局完成可以拿掉 *//*perspective: 1000px;*/}ul:hover {transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);}li {position: absolute;left: 0;top: 0;width: 100%;height: 100%;transition: all 1s;}/* 前面 */li:nth-child(1) {background-color: pink;transform: translateZ(100px);}/* 上面 */li:nth-child(2) {background-color: green;transform: rotateX(90deg) translateZ(100px);}/* 后面 */li:nth-child(3) {background-color: orange;transform: rotateX(180deg) translateZ(100px);}/* 下面 */li:nth-child(4) {background-color: brown;transform: rotateX(270deg) translateZ(100px);}/* 左面 */li:nth-child(5) {background-color: lime;transform: rotateY(-90deg) translateZ(100px);}/* 右面 */li:nth-child(6) {background-color: blue;transform: rotateY(90deg) translateZ(100px);}/* 炸开的效果 */ul:hover li:nth-child(1) {transform: translateZ(200px);}ul:hover li:nth-child(2) {transform: rotateX(90deg) translateZ(200px);}ul:hover li:nth-child(3) {transform: rotateX(180deg) translateZ(200px);}ul:hover li:nth-child(4) {transform: rotateX(270deg) translateZ(200px);}ul:hover li:nth-child(5) {transform: rotateY(-90deg) translateZ(200px);}ul:hover li:nth-child(6) {transform: rotateY(90deg) translateZ(200px);}</style>
</head>
<body>
<ul><li></li><li></li><li></li><li></li><li></li><li></li>
</ul>
</body>
</html>
<script>// transitionend事件, 可以添加 transition 动画完成的事件监听// 在transition动画执行完成时调用var div = document.querySelector("div");// div.addEventListener( "事件名称", function() { ... })div.addEventListener("transitionend", function() {console.log("呵呵");})
</script>

2.动画

动画可以通过设置多个节点来精确控制一个或者一组动画,常用来实现复杂的动画效果

动画与过渡的区别:

1. 过渡必须触发,需要两个状态的改变。
2. 动画可以一直运行下去,不需要触发。实现效果与过渡差不多

使用一个动画的基本步骤:

//1.通过@keyframes指定动画序列
//2.通过百分比或者from/to将动画分割成多个节点
//3.在各个节点中分别定义样式
//4.通过animation将动画应用于相应的元素

2.1 animation详解

animation是一个复合属性,一共有8个参数

animation-name:动画名称,由@keyframes定义的
animation-duration:动画的持续时间
animation-timing-function:动画的过渡类型
animation-delay:动画的延迟时间
animation-iteration-count:动画的循环次数
animation-direction:设置动画在循环中是否反向运动:alternate(from,to,to,from)、normal(from,to)
animation-fill-mode:设置动画时间之外的状态:forwards(让动画停留在最终的位置)
animattion-play-state:设置动画的状态:paused(让动画停止)

  <style>div {width: 200px;height: 200px;border: 10px solid blue;margin: 100px auto;/* 使用动画 *//* animation: 动画名称 动画时间 动画次数 *//* infinite 无限次 */animation: play 2s infinite;}/* 使用动画1. 声明动画序列2. 使用动画*//* 声明动画序列 *//* @keyframes 动画名称 { ... }from to  从哪个状态到哪个状态from to 只能设置两个状态的变化, 满足不了复杂动画的要求, 复杂使用 百分比*/@keyframes zhuan {from {width: 200px;height: 200px;transform: rotate(0deg);}to {width: 300px;height: 300px;transform: rotate(360deg);}}@keyframes play {0% {width: 200px;height: 200px;}50% {width: 400px;height: 200px;}100% {width: 400px;height: 400px;}}</style>

2.2动画库的使用

https://daneden.github.io/animate.css/

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="./animate.css"><style>div {width: 200px;height: 200px;margin: 100px auto;background-color: pink;/* 使用动画 *//*animation: flash 2s infinite;*/}</style>
</head>
<body><!-- 通过添加类名来使用动画函数库1. animated  添加动画时间, 让动画停留在最终状态2. 添加动画类, 指定具体动画的名称
-->
<div class="animated bounceInUp"></div></body>
</html>

3. 字体图标

我们经常把网页常用的一些小的图标,做成精灵图,然后通过background-position去调整位置,但是这个需要引入图片,并且图片大小改变之后如果失真。在CSS3中可以使用字体图片,即使用图标跟使用文字一样。

优点:

1)将所有图标打包成字体库,减少请求;

2)具有矢量性,可保证清晰度;

3)使用灵活,便于维护;

阿里巴巴矢量图标:(可以自己定制) http://www.iconfont.cn/plus/collections/index?type=1

Font Awesome 使用 http://fontawesome.dashgame.com/

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="./fonts/iconfont.css"><style>/*小图片特别多, 请求次数很多 => 通过精灵图解决, 只需要加载一张精灵图缺点: 1. 使用起来麻烦 (算位置)2. 精灵图可能会失真字体图标: 本质上字体好处: 1. 不会失真, 可以任意缩放  font-size2. 可以任意控制颜色 color3. 可以节约网络请求次数*//* 原理: 通过 @font-face 定义一个字体, 并引入对应的字体文件, 供用户使用 */</style>
</head>
<body><!-- iconfont 指定字体icon-wechat 指定的是具体哪个图标
-->
<span class="iconfont icon-wechat"></span>
<span class="iconfont icon-bofang"></span>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>Title</title><!-- 1. 引包 --><link rel="stylesheet" href="./fa/css/font-awesome.css"><style>.my {font-size: 200px;color: red;text-shadow: 2px 2px 2px blue, 4px 4px 4px green;}</style>
</head>
<body>
<!--2. fa 指定字体3. fa-gratipay 指定具体哪个图标
-->
<span class="fa fa-gratipay my"></span>
<span class="fa fa-ge my"></span>
</body>
</html>

4. 弹性布局(伸缩布局)

Flex是Flexible Box的缩写,翻译成中文就是“弹性盒子”,用来为盒装模型提供最大的灵活性。任何一个容器都可以指定为Flex布局

CSS3在布局方面做了非常大的改进,使得我们对块级元素的布局排列变得十分灵活,适应性非常强,其强大的伸缩性,在响应式开中可以发挥极大的作用。

display: 设置元素的显示模式

1) none 隐藏                                        2) block 块级, 独占一整行, 可设宽高

3)inline-block 行内块, 一行可以显示多个, 可设宽高

4)inline: 行内, 一行可以显示多个, 宽高内容撑开, 不可设宽高

5)flex 让盒子变成一个伸缩盒子

当给一个盒子设置了display:flex之后,这个盒子就有了主轴侧轴 的概念。主轴:Flex容器的主轴主要用来配置Flex项目,默认是水平方向侧轴:与主轴垂直的轴称作侧轴,默认是垂直方向的 。

方向:默认主轴从左向右 ,默认侧轴从上到下。

4.1 给容器设置的样式

4.1.1 flex-direction

flex-diretion主要是用来调整主轴的方向的,默认是水平方向

了解即可,一般来说,很少调整主轴的方向。

row:主轴方向为水平向右
column:主轴方向为竖直向下
row-reverse:主轴方向为水平向左
column-reverse:主轴方向是竖直向上。

4.1.2 justify-content(重点)

justify-content主要用来设置主轴方向的对齐方式 ,可选的值有:

flex-start: 弹性盒子元素将向起始位置对齐
flex-end: 弹性盒子元素将向结束位置对齐。
center: 弹性盒子元素将向行中间位置对齐
space-around: 弹性盒子元素会平均地分布在行里
space-between:第一个贴左边,最后一个贴右边,其他盒子均分,保证每个盒子之间的空隙是相等的。

4.1.3 align-items(重点)

align-items用于调整侧轴的对其方式 ,可选的值有:

flex-start: 元素在侧轴的起始位置对其。 
flex-end: 元素在侧轴的结束位置对其。
center: 元素在侧轴上居中对其。
stretch: 元素的高度会被拉伸到最大(不能给死高度)。

4.1.4 align-content

align-content用来设置多行的flex容器的排列方式

flex-start: 各行向侧轴的起始位置堆叠。 
flex-end: 各行向弹性盒容器的结束位置堆叠。
center: 各行向弹性盒容器的中间位置堆叠。
space-between: 各行在侧轴中平均分布。 
space-around: 第一行贴上边,最后一个行贴下边,其他行在弹性盒容器中平均分布。 
stretch:拉伸,不设置高度的情况下。

align-items与align-content的区别 :

align-items调整的是侧轴的对其方式,不换行一般用align-items
align-content:必须是多行才生效,如果单行,没有效果。换行了就用align-content。

4.1.5 flex-wrap

flex-wrap属性控制flex容器是单行或者多行,默认不换行

nowrap: 不换行(默认),会压缩子盒子的宽度。
wrap: 当宽度不够的时候,会换行。

      /* 只要给盒子指定 display: flex; 这个盒子就成为了伸缩盒子就拥有了主轴和侧轴的概念,默认主轴水平往右, 侧轴垂直往下, 盒子在主轴方向从左往右进行排布1. flex-direction: 控制主轴方向row 主轴水平往右  默认值column 主轴垂直往下2. justify-content: 主轴方向对齐方式flex-start: 往主轴开始位置对齐 (左对齐)flex-end: 往主轴结束位置对齐 (右对齐)center: 居中对齐space-around: 让盒子让主轴方向平均分布space-between: 让盒子进行平均分布, 只不过两端不留间隙3. align-items: 侧轴方向对齐方式flex-start: 往侧轴开始位置对齐, 默认值flex-end: 往侧轴结束位置对齐center: 在侧轴方向, 垂直居中stretch: 在侧轴方向上拉伸, 盒子不能设高*/
      参数整理1. 控制主轴方向: flex-direction:row/column2. 控制主轴对齐方式: justify-content: flex-start/flex-end/center/space-between/space-around3. 控制侧轴对齐方式:(1) 控制单行对齐方式align-items: flex-start/flex-end/center/stretch(2) 控制多行侧轴对齐方式align-content: flex-start/flex-end/center/space-between/space-around/stretch4. 换行: 默认nowrap不换行, flex-wrap: wrap; 进行换行

4.2 给子元素设置的样式

上述给容器设置的样式,都是用于对子元素进行排列的

下列的属性更多的是用于设置子元素自身的样式。

4.2.1 flex属性

flex属性与用于子元素分配主轴的空间。

flex:1;

4.2.2 order属性

order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。

order:1;

4.2.3 align-self

用于设置在侧轴的位置,但是align-self给子元素设置,优先级比align-items的优先级高。

取值与align-items的取值一样。

  给子元素设置的属性1. flex: 可以按份数分配主轴的剩余空间, 在排布完设置了宽度的盒子之后, 再分配空间2. order: 控制子元素的排布顺序, 数值越小, 越靠前3. align-self: 控制自己在侧轴的对齐方式属性值和 align-items 一样, 区别就在于, 这个是给子元素设置的(1) flex-start(2) flex-end(3) center(4) stretch

5.img标签留白问题

  <style>div {border: 1px solid #000;background-color: pink;}img {width: 100%;/* 原因: img标签是行内块元素, 默认基线对齐 *//*vertical-align: bottom;*//* 块级元素对 vertical-align 无感 */display: block;}</style>

6.监听鼠标滚轮的滚动

<script>// mousewheel 事件, 可以监听鼠标滚轮的滚动window.addEventListener("mousewheel", function( e ) {console.log( e.wheelDelta );if (e.wheelDelta > 0) {console.log( "滚轮往上滚动" );}else {console.log( "滚轮往下滚动" );}})
</script>

7.360浏览器——fullpage的使用

fullPage.js 是一个基于 jQuery 的插件,它能够很方便、很轻松的制作出全屏网站。

参考文档 http://www.dowebok.com/77.html

下载地址 https://github.com/alvarotrigo/fullPage.js

基本使用

  1. 引入jQuery文件,因为fullpage是jquery插件

  2. 引入fullpage的js文件

  3. 页面结构

  4. 编写js代码

<!-- 页面结构 -->
<div id="box"><!--每一个class为section的div都是一屏,section这个类是固定的--><div class="section">我是内容1</div><div class="section">我是内容2</div><div class="section">我是内容3</div><div class="section">我是内容4</div>
</div>
//编写js代码
$(function () {$("#box").fullpage();
});

常用参数

属性名称 描述
sectionsColor 设置每一个section的背景颜色
verticalCentered 设定每一个section的内容是否垂直居中,默认true,
scrollingSpeed 设置滚动的速度,默认700毫秒
easing 设置动画的方式,一般不修改, 默认是easeInOutCubic, 如果想要修改此参数,需要引入jquery.easing.js
css3 是否使用css3 transform来实现滚动效果,默认true,不用修改,CSS3的动画效率比较js高。
loopTop 滚动到顶部后是否连续滚动到底部,默认false
loopBottom 滚动到底部后是否连续滚动到顶部,默认false
continuousVertical 是否循环滚动,默认为false,如果设置为true,则页面会循环滚动,不会出现loopTop与loopBottom那样的跳动。
autoScrolling 是否使用插件的滚动方式,默认true,如果选择false,会出现浏览器子代的滚动条,将不会按页滚动,按照滚动进行滚动。
scrollBar 是否包含滚动条,默认false,如果设置为true,那么浏览器自定的滚动条会出现,这个时候,页面滚动还是按页滚动,但是浏览器也能滚动。不建议开启,不然会不同步。
paddingTop/paddingBottom 给每一个section设置一个paddingTop或者paddingBottom,默认值为0,如果需要给页面设置一个固定定位的头部菜单或者底部菜单的时候,可以使用这两个选项。
keyboardScrolling 是否可以使用键盘方向键导航,默认true
navigation 是否显示导航,默认为false,设置为true,会显示小圆点,作为导航
navigationPositon 导航小圆点的位置,设置left或者right,默认是right
navigationTooltips 小圆点的提示信息,鼠标一上去能看到提示信息
showActiveTooltip 是否显示当前页面的导航的tooltip信息,默认是false
slidesNavigation 是否显示横向幻灯片的导航,默认为false
slidesNavPosition 设置横向幻灯片的位置,top或者bottom,默认bottom
sectionSelector section的选择器,默认是.section
slideSelector slide的选择器,默认是.slide

常用回调函数

方法名 描述
afterLoad(anchorLink, index) 滚动到某一个section,当滚动结束后,会触发一次这个回调函数,anchorLink是锚链接的名称,index从1开始计算
onLeave(index,nextIndex,diretion) 当我们离开一个section时,会触发这个函数,index是离开的页面的序号,从1开始计算。 nextIndex是滚动到的页面的序号,direction是往上还是往下滚动,值是up或者down. return false可以取消滚动
afterResize() 窗口大小发生改变后会触发的回调函数
afterSlideLoad(anchor,index, slideAnchor,slideIndex) 页面滚动到某一个幻灯片的时候会触发这个回调函数
afterSlideLeave(anchor,index,slideIndex, diretion,nextSlideIndex) 当离开某一个幻灯片的时候会触发一次这个回调函数。
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>360浏览器</title><link rel="stylesheet" href="./css/jquery.fullPage.css"><style>.section {overflow: hidden;}/*----------------------- 第 1 屏 ------------------------- */.one .logo {width: 251px;height: 186px;background-image: url("./images/1_logo.png");margin: 80px auto;}.one .info {width: 772px;height: 49px;background-image: url("./images/1_info.png");margin: 20px auto;}.one .text {text-align: center;}/* 第一个状态 */.one .text img {margin: 0 30px;opacity: 0.2;}/* 第二个状态 */.one.now .text img {margin: 0;opacity: 1;transition: all 1s;}</style>
</head>
<body><div id="box"><div class="section one"><div class="logo"></div><div class="text"><img src="./images/1_text_1.png" alt=""><img src="./images/1_text_2.png" alt=""><img src="./images/1_text_3.png" alt=""><img src="./images/1_text_4.png" alt=""><img src="./images/1_text_5.png" alt=""><img src="./images/1_text_6.png" alt=""><img src="./images/1_text_7.png" alt=""><img src="./images/1_text_8.png" alt=""></div><div class="info"></div></div><div class="section two">2</div><div class="section three">3</div><div class="section four">4</div><div class="section five">5</div>
</div><script src="js/jquery.min.js"></script>
<script src="js/jquery.fullPage.min.js"></script>
<script>// 实现动画// 1. 需要知道滚动到的是第几屏, 需要一个回调函数, 在完全滚动到对应屏幕时调用// 2. 过渡动画需要有两个状态, 进入屏幕前一个状态, 进入屏幕后一个状态//    通过 transition 来过渡, 实现动画$(function(){$('#box').fullpage({// 配置每一屏幕的颜色sectionsColor: ['#0DA5D6', '#2AB561', '#DE8910', '#16BA9D', '#0DA5D6'],// 配置内容默认不垂直居中verticalCentered: false,// 显示导航navigation: true,// 滚动结束, 到达某一屏触发afterLoad: function( a, index ) {// index 表示第几屏, 从 1 开始console.log( index );// $('.one').addClass("now");// 动态维护了一个 now类, 进入屏幕加上now, 并且移除其他屏幕的 now类// 1. 让对应屏幕 加上 now 类, 实现动画, eq接收的是索引(下标)// 2. 给当前屏加上now类后, 将其他屏幕的 now 类移除, 这样其他屏可以再次执行动画$('.section').eq(index-1).addClass("now").siblings().removeClass("now");}})})</script></body>
</html>

前端之CSS3知识整理2相关推荐

  1. 前端开发基础知识整理--web综合篇

    该篇是web综合部分,主要包含了HTML(HTML5).http.页面优化及其他一些概念性的问题 doctype是什么?标准模式与兼容模式各有什么区别? <!doctype>声明必须处于H ...

  2. web前端开发基础知识整理以及前端视频教程

    随着移动互联网的发展和越来越多创业公司的加入,Web前端工程师的岗位空缺越来越大,薪资迅速上涨.Web前端工程师比以往更具有号召力. 想要自学成为炙手可热的Web前端工程师?靠零碎化的短视频可不行,你 ...

  3. 高级前端软件工程师知识整理之Vue技术栈篇

    1. 什么是MVVM? MVVM是Model-View-ViewModel的简写,它本质上就是MVC的改进版.MVVM就是将View的状态和行为抽象化,将视图UI和业务逻辑分开,View和Model之 ...

  4. Web前端基础知识整理

    1. 前端基础知识 文件分类 XML(扩展标记语言) 装载有格式的数据信息,用于各个框架和技术的配置文件描述 特点: 扩展名为.xml 内容区分大小写 标签要成对出现,形成容器,只能有一个 标签按正确 ...

  5. 2022前端知识整理:十、vue基础

    十.vue基础 2022前端知识整理:第十部分.vue基础,仅包含vue2.0相关知识,建议先完成html5.css3和JavaScript ES6之后再学习.部分图片未上传成功,稍后完善,请见谅. ...

  6. html5 css3思维导图,手把手整理CSS3知识汇总【思维导图】

    手把手整理CSS3知识汇总[思维导图] CSS3知识汇总思维导图请见文章底部 这两天总结了一下CSS3中的基本知识点,没有做到很全面,因为之前也记过一些笔记,就没有再整理成文档.这里我会把之前的笔记拍 ...

  7. 前端基础知识整理汇总(中)

    前端基础知识整理汇总(中) Call, bind, apply实现 // call Function.prototype.myCall = function (context) {context = ...

  8. 前端基础知识整理汇总(上)

    前端基础知识整理汇总(上) HTML页面的生命周期 HTML页面的生命周期有以下三个重要事件: 1.DOMContentLoaded -- 浏览器已经完全加载了 HTML,DOM 树已经构建完毕,但是 ...

  9. 前端入门知识整理(1)Vscode使用

    前端入门(1) 最近社团需要,所以整理了一下从0开始学习前端的一些知识. 安装软件 (VScode)以及对应插件的安装,相关配置. 介绍vscode常用快捷键 初始化第一个html程序 1.软件以及插 ...

最新文章

  1. 添加Net4CollectionTypeFactory的原因
  2. SQL Server查询性能优化——堆表、碎片与索引(一)
  3. Interesting Finds: 2008.03.17
  4. 关于异步IO与同步IO的写操作区别
  5. centos(7) 使用yum进行安装lamp环境
  6. 07 | 卷积神经网络:给你的模型一双可以看到世界的眼睛
  7. 递归查找所有子代id php,PHP递归函数:从父ID获取子ID
  8. 超声波机行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  9. 深圳卫视 - 饭没了秀
  10. list自定义排序工具类
  11. C#限制float有两位小数
  12. mybatis对mysql进行分页
  13. IIC加载以及存在的问题---lattice XO3
  14. CSS之颜色和背景的属性设置
  15. 统一资源定位符URL和统一资源标识符URI
  16. 不用U盘从linux重装win系统,不用U盘和光盘安装win7旗舰版系统
  17. 从青云上市,看中国云计算小巨头的“屠龙”之路
  18. 浅谈UEBA基本实现步骤
  19. 通过银联跨行转账、转接的交易手续费用——2358原则
  20. YbtOj#20073. 「NOIP2020 模拟赛 B 组 Day6」钻石守卫

热门文章

  1. Oculus VR设备账号登陆
  2. YOLOv5(v6.1)解析(四)超参数进化
  3. oracle 启动停用索引,oracle全文索引之停用词的通配符功能
  4. 自助去除APK的广告!(整理、修改、简化版)
  5. 基于MATLAB的SVM的交通标志识别
  6. 图片排版——让你的课件更生动的技巧 - [PPT|设计]
  7. matlab实现五子棋,matlab编程(五子棋
  8. android 红米拍照问题,拍照表现中规中矩_小米 红米_手机Android频道-中关村在线...
  9. 汽车OTA技术原理剖析
  10. 【AD-Studio - 无法识别Module - 个人成功解决的方式】