月度归档:2021年09月

职业教育成风口,但困境难解决

来源:第一财经YiMagazine

  原标题:职业教育成风口,但困境难解决

  全社会都认同蓝领工人是刚需,可为何培养蓝领的职业教育始终地位尴尬?

  记者 | 文思敏

  编辑 | 孟佳丽

  张扬的最后一拨客人约在晚上9点。和徒弟柏小玲一起带着客人看完房子后,他到家已临近深夜。连轴转的日子每个月总会有那么几天。有时,他会从早上8点一直忙到晚上11点,期间带着不同的租房客在上海浦东的各个核心居住区穿梭。

  张扬出生于1998年,但少年老成,时常被认为比真实年龄大十来岁。柏小玲比他晚出生一年,因为刚到公司,不善言辞,两天前被派来跟着张扬学习。

  2016年高考过后,张扬考入江西应用技术学院,那是赣州当地一所公办高职院校。因为“觉得有意思”,张扬选了工业机器人专业,但后来他发现,这个专业要读下来其实很难,除了高数、C语言这些课程难,专业对英语的要求也很高,不少教材都是英译的。于是,他在学校度过了“翘课睡觉”的3年。

  毕业后,张扬没有选择专业相关工作。经历过一段短暂而枯燥的餐饮工作后,他就转做了房屋中介,因为收入不错且足够“自由”。

  实际上,在制造业推动数智化工厂的趋势下,张扬就读的“工业机器人”是一个相当热门的专业,行业人才紧缺。2019年,宁德时代曾为一位有6年工业机器人行业工作经验,并经过3个月专业培训的技术人才开出35万一年的高薪,岗位是资深技术管理岗。2015年教育部把工业机器人技术列入职业教育的专业目录,正是希望职业教育院校能填充这部分人才来源。

  “这些技术工人大概有三种来源,一种是工业机器人本体制造商和系统集成商里有经验的工程师,但存量很少;一种是工业机器人培训机构,可以提供一些人才来源;第三种是职业学校。”许辉对《第一财经》YiMagazine说,“岗位的需求量很大,所以会倒逼职业教育改革,提升教育质量。”

  许辉目前是德国耶拿大学的博士候选人,他的研究方向是劳动、产业与经济社会学。“这些工作与我们传统认知中单一操作的流水线工人不太一样。它需要你既有软件知识又有硬件知识,同时还要有通信和机械方面的经验,是很复合的人才需求。”许辉说。

  许辉去一些学校调查过,在这个领域,职业教育院校普遍没有足够的老师。因为是新专业,很多老师并非该专业出身,“如何让职业教育更贴近企业的实际需求,其实需要一些时间。当下正是缺人的时候,但教育是个长期性问题,要慢慢才能看到效果。”许辉说。

  而从现实情况来看,大多数职校毕业生从事的,是与自己专业并不相关的工作。和张扬一样,柏小玲也离自己就读的专业越来越远。从郑州一所高职的建筑设计专业毕业后,她做过老师,也去工厂当过文员。根据她的观察,身边真正去设计院的同学并不多,大多数都和自己一样,做着专业不对口的工作。这些工作往往是房产中介、销售、外卖员——随着互联网经济的蓬勃,大量门槛不高的工种出现。

  在1990年代以前,中专和大专曾经受到人们的青睐。作为干部的预备役,一些中专学校的分数线比普通高中甚至重点高中都要高。但在高等教育扩招后,这些学历失去了原本的光环。

  根据《全国教育事业发展统计公报》2019年的数据,中等职业学校比上年减少151所。近年来,高等教育的普及让职业学校的发展呈现低迷趋势。自2010年来,中职院校的招生人数逐年下降,直到2019年才有所回暖。然而,根据教育局统计,相比2010年,2019年中等职业学校的在校生数量也已经下降了29.6%。

  在企业需求和人才供给之间,存在一道鸿沟。一方面,毕业生因为训练不足被产业筛选,无法得到好的机会;另一方面,企业则因为招不到合适人才,一度用工紧缺——这是一种双输局面。

  2019年年初,国务院发布《国家职业教育改革实施方案》,正式对职业教育动刀。这一方案的指导意见一共20条,因此又被称为“职教20条”。文件强调“职业教育与普通教育具有同等重要地位”,并提出要在5至10年内让职业教育完成由“政府主导”向“政府统筹管理、社会多元化办学”的格局转变。

  可以说,产业侧的“用工荒”倒逼职业教育院校推进供给侧改革,蒙尘已久的职业教育又重新回到人们的视野中。

  提前分流,谁是受益者?

  在“职教20条”中,“保持高中阶段教育职普比大体相当”的口号再次被强调。“职普比相当”并非新政策,早在2002年,《国务院关于大力推进职业教育改革与发展的决定》中就首次提出了“职普比大体相当”的说法,只是之后这一目标始终维持地很艰难,大部分地区依然难以做到1:1。直到“职教20条”再次提起,家长们不得不认真思考对孩子未来道路的规划——在教育已经实现普及化的当下,一路高考、升学、换取好工作的路径已经不再那么理所当然。

  《文凭社会》一书中,社会学家Randall Collins认为,在现代社会,教育是一种通货,可以用来交换工作机会。与其他所有通货一样,当供给不断增加而货物却有限时,教育通货的购买力会下降,作者称之为“文凭的通货膨胀”。因此,面临学历贬值,人们所能做的是通过进一步提升学历,以增强个人的就业竞争力。

  要拿到高等院校门票,升入普通高中一度被视为唯一的机会,而普职比对半分导致高考的竞争压力进一步下移到初中,甚至小学。为了达成普职比例1:1的目标,一些地方政府在十多年前就划下严格的“中招红线”,只有达到一定的中考分数才能分流到普通高中。

  许辉的家乡江苏就是严格执行地区之一,多年以来“分流最为严格”。在许辉读书的年代,中考录取率就已经不到50%,他的初中同学毕业后有一半以上的人要么进入本地职校,要么直接开始工作。从社会经济角度看,江苏的分流给地方产业提供了很好的人才支持,但同时也成为初中毕业生向上升学的拦路虎,将一些渴望接受高等教育的初中毕业生拦在了普通高中的门外。

  中国对学生的分流设计来自于对德国职业教育体系的参考,后者有效运作的职业教育体系被认为是支撑德国制造业发展的根基。在中国发展制造业的纲领之下,德国的成功经验成为了很好的学习对象。“德国的职业教育特色概括起来就是三个关键词,分流、双元制和转轨。”许辉对《第一财经》YiMagazine说。

  德国的学生从小学四年级起便要开始第一次分流。在分流前,会有一些职业探索课程供学生选择,以判断学生的个人潜能。按照成绩和个人兴趣,在小学毕业后,学生会进入到职业预校、实科中学或者文理中学。

  按照对学生培养的不同定位,各类中学的学制、运作模式均有所不同。成绩稍弱的孩子会进入职业预校就读,学制5年,实科中学的学生可进可退,学制为6年。这两类学生是职业教育的主体,往上升学会进入应用类大学。文理中学学制最长,长达8年,学生毕业后会升入综合类大学。

  “早分流对于行业和企业来讲是好事,较早地锁定未来员工,企业可以较早介入,投入相应的培训成本。员工对企业的忠诚度也会更高。晚分流就需要在前期打好文化基础,才能有利于后续的发展。”匡瑛说。匡瑛是华东师范大学职业教育与成人教育研究所教授,研究方向是比较职业技术教育、职业教育政策等领域。

  北京大学社会学系教授郑也夫认为,分流制度是用“实惠置换梦想”,以实实在在的职业技能教育帮助学业稍弱的学生平稳过渡,进入职业社会,不用在无尽的考试中陪跑。虽然这一做法的代价有些残忍,它剪断了一些学生的高校梦想。

  德国的职业教育制度设计之所以为人称赞,有部分原因是,选择职业教育方向的学生,可以从中职、高职,走向应用型本科、硕士乃至博士——在升学路径上,职业性人才和研究性人才无异。

  上海市实行的中本贯通就是一种既满足职业教育需求,又满足学生及家长的升学需求的创新模式。匡瑛参与了上海市贯通教育培养模式(包括中高贯通和中本贯通)的设计和论证。其中,中本贯通就是以中职教育和应用本科教育联合培养初中毕业生的培养模式,开始于2014年。在参加完3年中职阶段学习后,通过转段甄别,学生就可以进入到为期4年的应用本科阶段。

  在培养方案中,中本贯通的中职不等同于普通中职,本科阶段也有别于普通本科。3年的中职阶段会加入本科的部分理论,4年本科阶段则会为学生延续中职贯穿的实践方式,二者共同构成一体化的培养体系。“7年培养出来的人才更具复合性和高端性,学生有更多机会跟企业合作,以及做工学交替。”匡瑛说。如今,这一模式正受到一些担心孩子被分流的家长的欢迎。

  据上海市临港科技学校校长张黎明的观察,近两年,招生情况明显好转,尤其在贯通教育模式的推动下,生源质量有了提升,“中本贯通的学生要达到区重点中学的分数线,中高贯通则要达到普通高中的分数线。”

  生源质量的提升打破了过去对职校的偏见。职业教育院校一度被认为是“差生”聚集地,分流则往往被外界误读为是一种学生的“被迫选择”。在过去20年间,缺乏好生源、没有完整的培养体系,职业院校的办学效果一直不佳,从而对学生和家长更加缺乏吸引力,形成恶性循环。

  但如今,在长三角和珠三角一些经济发达地区,新一批初中生和家长对职校的看法已经有了改观。除去中本贯通被一些上海家长认为是一种“曲线救国”式的本科升学通道,学生选择公立中职院校也会从性价比的角度来考量。

  深圳市第二职业技术学校的李宜珍正在备战明年的春季高考,这是属于高职类学生的高考,通过考试后她可以升入大专。李宜珍是随迁子女,3年前,由于没有深圳户口,在相同分数下,深户同学可以去公立高中,她却只能选择私立高中。

  私立高中费用昂贵,并且按照她的成绩,不一定能通过高考考上本科。春季高考比普通高中高考要简单很多,按照高考班的升学路径,只用考语数英三门,总分在250分以上就可以进入广州当地排名前列的大专。既然是同样的结果,为什么不选择一个更轻松的方式?再三考虑后,李宜珍说服了父母。

  但很多亲戚朋友不理解,“大家觉得我去读职校是因为考不上高中,但我的成绩在班上算比较前面的。只不过别人选择了私立高中,我选择了公办职校。因为读的是职校,别人就会觉得你就是不行了,你已经没有用了,我听到太多这种话,但其实不是这样的。”李宜珍说。

  通过教育部发布的统计数据可以看到,职校的招生人数在近两年有了突破性的上升。

  广州市城市建设职业学校教研室主任彭玉蓉告诉《第一财经》YiMagazine,她所在的广州市土房学校,去年来自广州市内的生源人数是300多人,今年这一数字超过了900,占据全部生源的近1/3。“很久没有看到这么高的比例了。”彭玉蓉说。

  可以看到,尽管选择职业教育,但学历依然是学生和家长看重的重点,在分流之后,是否还有机会重新选择,是未来职业教育制度改善的方向。在德国的教育体系设计中,除了分流,回流通道也随时敞开,学生有机会为自己调整选择,综合类大学和应用类大学之间并没有不可逾越的壁垒。

  “英国和澳大利亚也是一样的,也会有一些国家资格认证的框架,通过资格框架,你现有的职业资格可以等值于什么,然后通过等值可以申请上一级别的院校。”匡瑛说。“所以我们在做制度设计的时候,也希望以后能够融通,而不是一次分流。分流了以后还有机会再次选择,多次回流。”

  教育最终仍然无法割断与就业的联系。匡瑛认为,目前中国的教育体系中还缺的一块叫职业生涯规划。德国、美国以及欧洲一些国家,会投入比较大的精力帮助学生制定职业生涯规划。“在美国,从幼儿园到研究生都会有一揽子的生计教育,学校会有很多职业体验、职业启蒙和职业生涯规划,让他们接触到各种各样的职业,了解不同职业所面临的工作环境和所需具备的能力素质。”匡瑛说,“职业探索相当于是给学生多次职业模拟的机会。”

  校企合作的多种可能性

  “职业教育的衡量标准就是解决问题,我们培养的是应用型人才。就像医生一样,开药方或手术都是为了解决问题。”上海博世汽车职业技术培训学校的创始人刘勇对《第一财经》YiMagazine说。

  过去,单纯由学校提供的职业教育与社会的实际需求脱节,除了课程内容过时、难以与产业进步及时更新,教学内容往往也是通用版本,很难和企业的精细化需求对接。以汽车行业为例,“目前汽车专业普遍都是电喷电控和新能源智能化了,但一些学校还在考核化油器车型,这些东西你在市场上找都找不到。”刘勇说。

  双元制被认为是德国职业教育的精髓,即由学校、企业和行业协会共同为学生制定培育计划,甚至共同决定某种职业的具体技能要求。学生每周在学校上一天或两天理论课程,其余时间在企业做实操性训练。这种方式让德国的职业教育与社会实际需求挂钩,成为承接学生们顺利就业的安全网。

  该校理实一体化汽车整车实训中心,主要用于低中高端汽车机电检测与维修训练。图片/麻耀刚

  彭玉蓉介绍,校企合作大致有三种模式,由浅入深层层递进。最常见的是实习和就业人才输送的合作关系,在此基础上,部分企业会进一步深入,在学校开设“订单班”,先挑选适合培养的人,然后针对这部分人做针对性培养。更深度的融合模式是企业会介入招生阶段,并且在之后几年的就读过程中,更深层地培养学生,并提前锁定学生。

  刘勇创办的技术学校就以与保时捷的产教深度融合为特色。一方面,保时捷会与学校设置课程同步精准化,比如每一款车型的发动机该如何拆装,发动机检测该如何做,每一道工序有哪些技术操作要求等等。另一方面是课程的通用化,比如通用的轮胎拆装标准都是对角拆,这是通用技术。“但再细化一些,奔驰第8代是这样的,宝马第8代是那样的,还可以根据品牌来精细化。”刘勇告诉《第一财经》YiMagazine。

  作为校企深度合作的一种表现形式,在保时捷第一款电动车Taycan还没有上市的时候,学生和老师已经完成了培养。“如果你没有跟企业合作,等上市以后才能拿到资料,其实已经落后市场很多了。”刘勇说。

  上海博世汽车职业技术培训学校的一位汽车机电老师正在给学生讲解保时捷汽车机电核心课程。图片/麻耀刚

  刘勇创办的这所学校是一所成立于上海的民办职业技术学校,自负盈亏,因此需要敏捷地反映市场,才能获得竞争力。而对于公立职校来讲,受限于学校的吸纳能力、地方经济发展状况等现实条件,校企合作的阻碍也更大。企业在过程中的投入与产出的回报率不高,因此也不愿意多投入。

  更重要的是,中国技术人才的流动性大,企业不愿意做“亏本生意”。“企业要培养技术工人,其实投入并不小,这是一个长期的过程。但现在整体的跳槽率和流动率非常高,往往一个很小的原因就跳槽了,(学生)对企业缺乏忠诚度。”匡瑛说。

  而在双元制下,德国的企业鲜少有这样的顾虑。敢于投入的原因在于企业自身的利益有法律保障,比如会跟学生签约,学生如果失信可能会遭遇诉讼,面临赔钱甚至被行业拉入“黑名单”的后果。

  江苏太仓是300多家德资企业的聚集地,也采用以行业性合作的方式来同时保证培养方案和企业利益的运转。比如约束企业之间的薪资不能差异太多,不能高薪挖人等等——通过一些行业和法律规范来限制技术工人的流动性。如果企业没有投资过工人的培训费用,并且希望挖走一位技术工人,那么它需要向之前提供培训的企业支付数千元的人员培养费。“但是这一共识仅限于德资企业,德企之外的企业可能缺乏这样的行业共识。”许辉说。

  集聚式正越来越成为更多制造企业做校企合作项目的方向。一位中部地区的校企合作项目负责人告诉《第一财经》YiMagazine,其所在行业正在集合十来个代表企业与学校共建。合作会保证两个方面的筛选:首先是筛选生源,比如在10个学校里筛选100个合格学生,企业与学校共同在实战中培养这些学生;另外,企业与企业之间也会互相筛选,以保证集群企业的门槛。

  佛山指南车智能制造研究院的实训学员正在企业内部跟着技术服务工程师学习。

  该校培训基地内部,学员正在观摩学习机器人焊接操作。图片/许辉提供

  在这个案例中,不同企业的多样性还增加了学生的就业选择。比如同一行业的不同企业可以提供生产、研发、制造、销售、维修等各个环节的岗位。企业和学生之间就成为一种双向选择。这个项目目前运作刚满一年,还在观察期。这位负责人介绍,截至目前运作情况比较良性。

  “这样一来企业有大批学生可以挑选,学生自己的反馈也不错。”这位负责人说,“今年80%的学生都联系到了实习单位,剩下20%可能要去专升本或者有其他的打算。”

  不过,校企共育是长期性的过程,当企业看不到有利的投入产出比,中途退出的几率并不低。彭玉蓉认为,最后那些选择坚持下来的企业应该得到更多鼓励。“一些企业能够长期坚持下来,支持我们的专业建设,支持我们的教学,接纳我们的学生。这种责任感和使命感令人感动。”彭玉蓉说,“虽然我们的学生确实也能补充他们存在的人力缺口,但来自更高层面的,比如说政府、社会以及行业协会对企业在这方面投入的认可还有待体现。”

  从工厂“消失”的年轻人

  作为新一代职校毕业生,制造业已不在张扬和柏小玲的工作考虑范围内。互联网经济催生出更多灵活的工作机会,在疫情过渡期,张扬就当过一段时间的外卖骑手。

  剥削感重是年轻人不喜欢工厂的原因之一。柏小玲曾去一家喇叭生产厂做文职实习,偶尔也会因生产需要去流水线上帮忙。为了提高效率,流水线被要求以最高速运转,一旦产品因为做不过来而堆积,管理者就会训斥工人。

  除此之外,频繁换人是小工厂里经常发生的事,也是一些工厂的“省钱”方式。工厂一般会压10到15天的工资,不适应的人很快就会走,然后换新的人进来。柏小玲没有打算在工厂里长待,因为收入微薄,一个月只有不到4000元。

  “工厂里一般年轻人很少,要么年龄很小,比如零几年出生的,刚中专或高中毕业,要么就是年龄稍微大一点的阿姨,其他地方不愿意收她们。”柏小玲观察到。

  “‘缺工荒’倒不一定是个特别坏的事情,它可能会促进两个方面。第一是会让工厂考虑调整它的流水线和产能,因为招不到人,它的智能化水平就要提升。”匡瑛解释道,“第二是它未来需要的人才就要更符合复合型素质,这样企业要给的薪酬会更多,对人的吸引力会增强。从这个意义上来讲,应该会进入一个良性的循环。”

  10年前,许辉曾经“卧底”富士康,做过一次关于学生工的调查。学校将中职学生以实习名义“倒卖”给工厂,从中抽取佣金费用。从形式上来看,似乎是一种四方获益的局面——工厂解决了用人短缺的问题,学校完成了实习指标计划,政府获得了招商引资项目,学生则可以获取薄弱的薪水。但在这种情况下,学生们所做的是训练几个小时就可以胜任的简单重复劳动,既无利于职业教育的良性发展,也无益于学生未来的竞争力提升。

  如今,越来越多大型工厂在做数智化转型,原本由人工操作的重复劳作正在被机械臂取代,因此对人也有了更多的要求。

  “智能化以后,企业的组织方式也会发生变化。比如岗位更多是人机互动,人要赋予更多决策的功能,因此以往两三个岗位的工作,可能未来只要一个人就可以了。对技术人来说,他需要面对更多的不确定性,可能有工艺问题、技术问题、客户体验问题等,都要能独当一面。这对我们原来职业教育培养的人才提出了更高的要求。”匡瑛说。

  产线改造过后,制造业对人力的需求会大幅降低。溢出的人力就会被新的服务业形态承接。“外卖骑手中可能有30%到40%是原来制造业退出来的人。等于说,中国用了新的服务业经济吸纳制造业的失业。另一方面,从劳动关系来讲,制造业经过过去20多年的发展,有比较完整的劳动保障体系,但服务业的劳动关系和社会保障是比制造业要差的。”许辉对《第一财经》YiMagazine说。在上海的几份工作中,张扬和柏小玲都没有和公司签署过劳动合同,取而代之的是合作合同。这意味着公司不会为他们承担任何社会保障,公司与个人之间也只是合作形式。

  新职业教育需要什么?

  1980年代,德国的职业教育曾因理论内容过多且脱离实际而饱受业界批评。德国职业教育学者Felix Raune提出“以工作过程为导向的新职业教育理论”,对职业教育界影响深远。Raune认为,现代企业人才要拥有的不仅仅是适应工作世界的能力,还要具有“从对经济、社会和生态负责的角度,建构工作世界的能力”。其中强调的是人在生产活动中不断运用认知能力解决问题,不断重新表达的过程。

  职业教育研究者们达成的一个共识是,职业教育不能与真实世界脱钩,需要的是一种终身学习能力的培养。“职业教育要跟经济需求挂钩,不能所有学校都开出一堆实用性不高的专业,学生毕业后找不到对口的工作。”许辉对《第一财经》YiMagazine说,“另一方面是社会观念问题,如何重塑社会观念,这个社会身份是需要被重构的。并且,社会要能弥补工人社会身份的落差。”

  许辉在自己的研究中建构的一个词叫“新技术工人”,指的是在某一领域——比如工业机器人——有技能偏好的新工人群体。“从出路来讲,好的职业前景、好的社会身份、好的声誉以及户口,这些制度性问题是不是能配套。如果不做这些制度性的安排,光是花钱买设备,职业学校其实对大部分人仍然没有吸引力。”许辉说。

  回到最本质的问题,如何提升职业教育的质量是保障生态良性运行的关键。匡瑛认为,现在职业教育改革最核心的是三教改革,也就是教师、教学和教材。这些最核心的部分直接涉及到职业教育的质量,“课堂里老师有没有专业实践能力、钻研精神和工匠精神?能不能研发出适合某个专业学生又快又好的教学方法?有没有适合这个类型学生的教学材料,让学生看到就想学?只有这些都做好了,才能使职业教育的整体质量有所提升。”

  在专业教学法和教师培养培训方面,德国已经探索了很多年,才能培养出一大批高水平的产业工人。“课堂变革才是真正意义上动真格的职业教育的改革。”匡瑛说。如何重建家长和孩子对职业教育的信心和期待,如何让走出校园的技术人才满足企业不断变化的发展需求,这条路还很长。

  (应采访对象要求,文中张扬和柏小玲为化名

原文阅读

教育部24365为大学生引领理想职业之路

9月12日,教育部24365系列“互联网+”就业指导新学期第二期全国公益直播课程《大学生理想职业之路》,为全国高校师生讲解了大学生职业发展最优精细规划。主讲老师为教育部创新创业教育委员会委员、万学教育张锐老师。他深度分析了社会组织选拔大学生的核心指标、高阶能力的先进训练方案、关键资历的高效获取方案、就业重要人脉系统的快速构建、职业发展目标的最优选择、连通社会的深度实践模式和高质量求职核心实施步骤等与大学生职业发展密切相关的专题。张锐认为,大学在教育价值链的最高端,连通了职业与学业两个重要人生阶段,同学们在大学时光中不仅要寻找心灵深处的梦想,还要探索通达梦想的航向,更要锤炼乘风远航的力量,为人生发展赋予新的高度与速度。

当天,学习强国等平台同步直播,总观看量超过1100万人次。直播课程结束后,活动在广大师生中引发了持续和热烈的讨论。

本次课程在高校学生中反响热烈。兰州大学学生蔡得昱表示:“这次直播内容完全超出正常学业认知,张锐老师传授的三大高端能力受益匪浅。期待自己认真完成各项高价值活动,实现自己的人生价值。”天津大学学生田雨说:“没听张锐老师讲座前,我对职业发展只是一个概念词,这次讲座打开了求职的局限性,对于未来就业发展也有了系统化的路径,期待能沿着张锐老师传授的这条理想职业之路走到自身期待的新高度。”

课程也在高校就业指导老师之间引发讨论。中国人民大学招生就业处副处长陈姚认为:“大学生理想职业之路”讲座不仅阐明了大学生涯与职业发展的最优路径及核心原理,还提供了科学可行的执行方案,对大一新生和应届毕业生都很有价值。”。中央民族大学教务处副处长,教师教学发展中心主任马映君说:“这次讲座为大学生提供了从职业规划到毕业工作的专业建议。这是目前为止,为大学生提供的从职业规划到毕业工作的最全面、最专业、最系统指导。”

据悉,“24365校园招聘服务”活动是教育部应对新冠肺炎疫情影响推出的创新举措,活动平台24小时不打烊,全年365天随时“云”就业。9月还将推出多堂课程,给大学生提供不出家门的就业指导服务,提升大学生求职能力,助力高校大学生走上理想职业之路。

来源:中国网

原文:https://m.gmw.cn/baijia/2021-09/15/1302582402.html

运动生理学六原则

  1. 个体差异原理:尊重每一个个体去发展
  2. 超负荷原理:每天进步一点点,超出一点点
  3. 循序渐进原理:为一个目标,每天分解,逐步达到
  4. 适应原理:慢慢地适应强度,习惯成为状态
  5. 用进废退原理
  6. 休息原理:合理作息,保证睡眠质量

Tips:
没有专业度,就谈不上自由。
系统信息优于碎片信息。

自行翻书特效,纯CSS+HTML

效果见下:

代码:

<!DOCTYPE html>
<html>

<head>

  <meta charset="UTF-8">
    <style>

::before,
::after {
	content: "";
}

.component{
	background: #deebef;
	color: #34495e;
	font-family: 'Lato', 'Arial', sans-serif;
	font-weight: 400;
	line-height: 1.2;
}

ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

a {
	color: #2c3e50;
	text-decoration: none;
}

.btn {
	display: inline-block;
	text-transform: uppercase;
	border: 2px solid #2c3e50;
	margin-top: 100px; 
	font-size: 0.7em;
	font-weight: 700;
	padding: 0.1em 0.4em;
	text-align: center;
	-webkit-transition: color 0.3s, border-color 0.3s;
	-moz-transition: color 0.3s, border-color 0.3s;
	transition: color 0.3s, border-color 0.3s;
}

.btn:hover {
	border-color: #16a085;
	color: #16a085;
}

/* basic grid, only for this demo */

.align {
	clear: both;
	margin: 90px auto 20px;
	width: 100%;
	max-width: 1170px;
	text-align: center;
}

.align > li {
	width: 500px;
	min-height: 300px;
	display: inline-block;
	margin: 30px 20px 30px 30px;
	padding: 0 0 0 60px;
	vertical-align: top;
}

/* ///////////////////////////////////////////////////

HARDCOVER
Table of Contents

1. container
2. background & color
3. opening cover, back cover and pages
4. position, transform y transition
5. events
6. Bonus
	- Cover design
	- Ribbon
	- Figcaption
7. mini-reset

/////////////////////////////////////////////////////*/

/*
	1. container
*/

.book {
	position: relative;
	width: 160px; 
	height: 220px;
	-webkit-perspective: 1000px;
	-moz-perspective: 1000px;
	perspective: 1000px;
	-webkit-transform-style: preserve-3d;
	-moz-transform-style: preserve-3d;
	transform-style: preserve-3d;
}

/*
	2. background & color
*/

/* HARDCOVER FRONT */
.hardcover_front li:first-child {
	background-color: #eee;
	-webkit-backface-visibility: hidden;
	-moz-backface-visibility: hidden;
	backface-visibility: hidden;
}

/* reverse */
.hardcover_front li:last-child {
	background: #fffbec;
}

/* HARDCOVER BACK */
.hardcover_back li:first-child {
	background: #fffbec;
}

/* reverse */
.hardcover_back li:last-child {
	background: #fffbec;
}

.book_spine li:first-child {
	background: #eee;
}
.book_spine li:last-child {
	background: #333;
}

/* thickness of cover */

.hardcover_front li:first-child:after,
.hardcover_front li:first-child:before,
.hardcover_front li:last-child:after,
.hardcover_front li:last-child:before,
.hardcover_back li:first-child:after,
.hardcover_back li:first-child:before,
.hardcover_back li:last-child:after,
.hardcover_back li:last-child:before,
.book_spine li:first-child:after,
.book_spine li:first-child:before,
.book_spine li:last-child:after,
.book_spine li:last-child:before {
	background: #999;
}

/* page */

.page > li {
	background: -webkit-linear-gradient(left, #e1ddd8 0%, #fffbf6 100%);
	background: -moz-linear-gradient(left, #e1ddd8 0%, #fffbf6 100%);
	background: -ms-linear-gradient(left, #e1ddd8 0%, #fffbf6 100%);
	background: linear-gradient(left, #e1ddd8 0%, #fffbf6 100%);
	box-shadow: inset 0px -1px 2px rgba(50, 50, 50, 0.1), inset -1px 0px 1px rgba(150, 150, 150, 0.2);
	border-radius: 0px 5px 5px 0px;
}

/*
	3. opening cover, back cover and pages
*/

.hardcover_front {
	-webkit-transform: rotateY(-34deg) translateZ(8px);
	-moz-transform: rotateY(-34deg) translateZ(8px);
	transform: rotateY(-34deg) translateZ(8px);
	z-index: 100;
}

.hardcover_back {
	-webkit-transform: rotateY(-15deg) translateZ(-8px);
	-moz-transform: rotateY(-15deg) translateZ(-8px);
	transform: rotateY(-15deg) translateZ(-8px);
}

.page li:nth-child(1) {
	-webkit-transform: rotateY(-28deg);
	-moz-transform: rotateY(-28deg);
	transform: rotateY(-28deg);
}

.page li:nth-child(2) {
	-webkit-transform: rotateY(-30deg);
	-moz-transform: rotateY(-30deg);
	transform: rotateY(-30deg);
}

.page li:nth-child(3) {
	-webkit-transform: rotateY(-32deg);
	-moz-transform: rotateY(-32deg);
	transform: rotateY(-32deg);
}

.page li:nth-child(4) {
	-webkit-transform: rotateY(-34deg);
	-moz-transform: rotateY(-34deg);
	transform: rotateY(-34deg);
}

.page li:nth-child(5) {
	-webkit-transform: rotateY(-36deg);
	-moz-transform: rotateY(-36deg);
	transform: rotateY(-36deg);
}

/*
	4. position, transform & transition
*/

.hardcover_front,
.hardcover_back,
.book_spine,
.hardcover_front li,
.hardcover_back li,
.book_spine li {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	-webkit-transform-style: preserve-3d;
	-moz-transform-style: preserve-3d;
	transform-style: preserve-3d;
}

.hardcover_front,
.hardcover_back {
	-webkit-transform-origin: 0% 100%;
	-moz-transform-origin: 0% 100%;
	transform-origin: 0% 100%;
}

.hardcover_front {
	-webkit-transition: all 0.8s ease, z-index 0.6s;
	-moz-transition: all 0.8s ease, z-index 0.6s;
	transition: all 0.8s ease, z-index 0.6s;
}

/* HARDCOVER front */
.hardcover_front li:first-child {
	cursor: default;
	-webkit-user-select: none;
	-moz-user-select: none;
	user-select: none;
	-webkit-transform: translateZ(2px);
	-moz-transform: translateZ(2px);
	transform: translateZ(2px);
}

.hardcover_front li:last-child {
	-webkit-transform: rotateY(180deg) translateZ(2px);
	-moz-transform: rotateY(180deg) translateZ(2px);
	transform: rotateY(180deg) translateZ(2px);
}

/* HARDCOVER back */
.hardcover_back li:first-child {
	-webkit-transform: translateZ(2px);
	-moz-transform: translateZ(2px);
	transform: translateZ(2px);
}

.hardcover_back li:last-child {
	-webkit-transform: translateZ(-2px);
	-moz-transform: translateZ(-2px);
	transform: translateZ(-2px);
}

/* thickness of cover */
.hardcover_front li:first-child:after,
.hardcover_front li:first-child:before,
.hardcover_front li:last-child:after,
.hardcover_front li:last-child:before,
.hardcover_back li:first-child:after,
.hardcover_back li:first-child:before,
.hardcover_back li:last-child:after,
.hardcover_back li:last-child:before,
.book_spine li:first-child:after,
.book_spine li:first-child:before,
.book_spine li:last-child:after,
.book_spine li:last-child:before {
	position: absolute;
	top: 0;
	left: 0;
}

/* HARDCOVER front */
.hardcover_front li:first-child:after,
.hardcover_front li:first-child:before {
	width: 4px;
	height: 100%;
}

.hardcover_front li:first-child:after {
	-webkit-transform: rotateY(90deg) translateZ(-2px) translateX(2px);
	-moz-transform: rotateY(90deg) translateZ(-2px) translateX(2px);
	transform: rotateY(90deg) translateZ(-2px) translateX(2px);
}

.hardcover_front li:first-child:before {
	-webkit-transform: rotateY(90deg) translateZ(158px) translateX(2px);
	-moz-transform: rotateY(90deg) translateZ(158px) translateX(2px);
	transform: rotateY(90deg) translateZ(158px) translateX(2px);
}

.hardcover_front li:last-child:after,
.hardcover_front li:last-child:before {
	width: 4px;
	height: 160px;
}

.hardcover_front li:last-child:after {
	-webkit-transform: rotateX(90deg) rotateZ(90deg) translateZ(80px) translateX(-2px) translateY(-78px);
	-moz-transform: rotateX(90deg) rotateZ(90deg) translateZ(80px) translateX(-2px) translateY(-78px);
	transform: rotateX(90deg) rotateZ(90deg) translateZ(80px) translateX(-2px) translateY(-78px);
}
.hardcover_front li:last-child:before {
	box-shadow: 0px 0px 30px 5px #333;
	-webkit-transform: rotateX(90deg) rotateZ(90deg) translateZ(-140px) translateX(-2px) translateY(-78px);
	-moz-transform: rotateX(90deg) rotateZ(90deg) translateZ(-140px) translateX(-2px) translateY(-78px);
	transform: rotateX(90deg) rotateZ(90deg) translateZ(-140px) translateX(-2px) translateY(-78px);
}

/* thickness of cover */

.hardcover_back li:first-child:after,
.hardcover_back li:first-child:before {
	width: 4px;
	height: 100%;
}

.hardcover_back li:first-child:after {
	-webkit-transform: rotateY(90deg) translateZ(-2px) translateX(2px);
	-moz-transform: rotateY(90deg) translateZ(-2px) translateX(2px);
	transform: rotateY(90deg) translateZ(-2px) translateX(2px);
}
.hardcover_back li:first-child:before {
	-webkit-transform: rotateY(90deg) translateZ(158px) translateX(2px);
	-moz-transform: rotateY(90deg) translateZ(158px) translateX(2px);
	transform: rotateY(90deg) translateZ(158px) translateX(2px);
}

.hardcover_back li:last-child:after,
.hardcover_back li:last-child:before {
	width: 4px;
	height: 160px;
}

.hardcover_back li:last-child:after {
	-webkit-transform: rotateX(90deg) rotateZ(90deg) translateZ(80px) translateX(2px) translateY(-78px);
	-moz-transform: rotateX(90deg) rotateZ(90deg) translateZ(80px) translateX(2px) translateY(-78px);
	transform: rotateX(90deg) rotateZ(90deg) translateZ(80px) translateX(2px) translateY(-78px);
}

.hardcover_back li:last-child:before {
	box-shadow: 10px -1px 80px 20px #666;
	-webkit-transform: rotateX(90deg) rotateZ(90deg) translateZ(-140px) translateX(2px) translateY(-78px);
	-moz-transform: rotateX(90deg) rotateZ(90deg) translateZ(-140px) translateX(2px) translateY(-78px);
	transform: rotateX(90deg) rotateZ(90deg) translateZ(-140px) translateX(2px) translateY(-78px);
}

/* BOOK SPINE */
.book_spine {
	-webkit-transform: rotateY(60deg) translateX(-5px) translateZ(-12px);
	-moz-transform: rotateY(60deg) translateX(-5px) translateZ(-12px);
	transform: rotateY(60deg) translateX(-5px) translateZ(-12px);
	width: 16px;
	z-index: 0;
}

.book_spine li:first-child {
	-webkit-transform: translateZ(2px);
	-moz-transform: translateZ(2px);
	transform: translateZ(2px);
}

.book_spine li:last-child {
	-webkit-transform: translateZ(-2px);
	-moz-transform: translateZ(-2px);
	transform: translateZ(-2px);
}

/* thickness of book spine */
.book_spine li:first-child:after,
.book_spine li:first-child:before {
	width: 4px;
	height: 100%;
}

.book_spine li:first-child:after {
	-webkit-transform: rotateY(90deg) translateZ(-2px) translateX(2px);
	-moz-transform: rotateY(90deg) translateZ(-2px) translateX(2px);
	transform: rotateY(90deg) translateZ(-2px) translateX(2px);
}

.book_spine li:first-child:before {
	-webkit-transform: rotateY(-90deg) translateZ(-12px);
	-moz-transform: rotateY(-90deg) translateZ(-12px);
	transform: rotateY(-90deg) translateZ(-12px);
}

.book_spine li:last-child:after,
.book_spine li:last-child:before {
	width: 4px;
	height: 16px;
}

.book_spine li:last-child:after {
	-webkit-transform: rotateX(90deg) rotateZ(90deg) translateZ(8px) translateX(2px) translateY(-6px);
	-moz-transform: rotateX(90deg) rotateZ(90deg) translateZ(8px) translateX(2px) translateY(-6px);
	transform: rotateX(90deg) rotateZ(90deg) translateZ(8px) translateX(2px) translateY(-6px);
}

.book_spine li:last-child:before {
	box-shadow: 5px -1px 100px 40px rgba(0, 0, 0, 0.2);
	-webkit-transform: rotateX(90deg) rotateZ(90deg) translateZ(-210px) translateX(2px) translateY(-6px);
	-moz-transform: rotateX(90deg) rotateZ(90deg) translateZ(-210px) translateX(2px) translateY(-6px);
	transform: rotateX(90deg) rotateZ(90deg) translateZ(-210px) translateX(2px) translateY(-6px);
}

.page,
.page > li {
	position: absolute;
	top: 0;
	left: 0;
	-webkit-transform-style: preserve-3d;
	-moz-transform-style: preserve-3d;
	transform-style: preserve-3d;
}

.page {
	width: 100%;
	height: 98%;
	top: 1%;
	left: 3%;
	z-index: 10;
}

.page > li {
	width: 100%;
	height: 100%;
	-webkit-transform-origin: left center;
	-moz-transform-origin: left center;
	transform-origin: left center;
	-webkit-transition-property: transform;
	-moz-transition-property: transform;
	transition-property: transform;
	-webkit-transition-timing-function: ease;
	-moz-transition-timing-function: ease;
	transition-timing-function: ease;
}

.page > li:nth-child(1) {
	-webkit-transition-duration: 0.6s;
	-moz-transition-duration: 0.6s;
	transition-duration: 0.6s;
}

.page > li:nth-child(2) {
	-webkit-transition-duration: 0.6s;
	-moz-transition-duration: 0.6s;
	transition-duration: 0.6s;
}

.page > li:nth-child(3) {
	-webkit-transition-duration: 0.4s;
	-moz-transition-duration: 0.4s;
	transition-duration: 0.4s;
}

.page > li:nth-child(4) {
	-webkit-transition-duration: 0.5s;
	-moz-transition-duration: 0.5s;
	transition-duration: 0.5s;
}

.page > li:nth-child(5) {
	-webkit-transition-duration: 0.6s;
	-moz-transition-duration: 0.6s;
	transition-duration: 0.6s;
}

/*
	5. events
*/

.book:hover > .hardcover_front {
	-webkit-transform: rotateY(-145deg) translateZ(0);
	-moz-transform: rotateY(-145deg) translateZ(0);
	transform: rotateY(-145deg) translateZ(0);
	z-index: 0;
}

.book:hover > .page li:nth-child(1) {
	-webkit-transform: rotateY(-30deg);
	-moz-transform: rotateY(-30deg);
	transform: rotateY(-30deg);
	-webkit-transition-duration: 1.5s;
	-moz-transition-duration: 1.5s;
	transition-duration: 1.5s;
}

.book:hover > .page li:nth-child(2) {
	-webkit-transform: rotateY(-35deg);
	-moz-transform: rotateY(-35deg);
	transform: rotateY(-35deg);
	-webkit-transition-duration: 1.8s;
	-moz-transition-duration: 1.8s;
	transition-duration: 1.8s;
}

.book:hover > .page li:nth-child(3) {
	-webkit-transform: rotateY(-118deg);
	-moz-transform: rotateY(-118deg);
	transform: rotateY(-118deg);
	-webkit-transition-duration: 1.6s;
	-moz-transition-duration: 1.6s;
	transition-duration: 1.6s;
}

.book:hover > .page li:nth-child(4) {
	-webkit-transform: rotateY(-130deg);
	-moz-transform: rotateY(-130deg);
	transform: rotateY(-130deg);
	-webkit-transition-duration: 1.4s;
	-moz-transition-duration: 1.4s;
	transition-duration: 1.4s;
}

.book:hover > .page li:nth-child(5) {
	-webkit-transform: rotateY(-140deg);
	-moz-transform: rotateY(-140deg);
	transform: rotateY(-140deg);
	-webkit-transition-duration: 1.2s;
	-moz-transition-duration: 1.2s;
	transition-duration: 1.2s;
}

/*
	6. Bonus
*/

/* cover CSS */

.coverDesign {
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	right: 0;
	overflow: hidden;
	-webkit-backface-visibility: hidden;
	-moz-backface-visibility: hidden;
	backface-visibility: hidden;
}

.coverDesign::after {
	background-image: -webkit-linear-gradient( -135deg, rgba(255, 255, 255, 0.45) 0%, transparent 100%);
	background-image: -moz-linear-gradient( -135deg, rgba(255, 255, 255, 0.45) 0%, transparent 100%);
	background-image: linear-gradient( -135deg, rgba(255, 255, 255, 0.45) 0%, transparent 100%);
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	right: 0;
}

.coverDesign h1 {
	color: #fff;
	font-size: 2.2em;
	letter-spacing: 0.05em;
	text-align: center;
	margin: 54% 0 0 0;
	text-shadow: -1px -1px 0 rgba(0,0,0,0.1);
}

.coverDesign p {
	color: #f8f8f8;
	font-size: 1em;
	text-align: center;
	text-shadow: -1px -1px 0 rgba(0,0,0,0.1);
}

.yellow {
	background-color: #f1c40f;
	background-image: -webkit-linear-gradient(top, #f1c40f 58%, #e7ba07 0%);
	background-image: -moz-linear-gradient(top, #f1c40f 58%, #e7ba07 0%);
	background-image: linear-gradient(top, #f1c40f 58%, #e7ba07 0%);
}

.blue {
	background-color: #3498db;
	background-image: -webkit-linear-gradient(top, #3498db 58%, #2a90d4 0%);
	background-image: -moz-linear-gradient(top, #3498db 58%, #2a90d4 0%);
	background-image: linear-gradient(top, #3498db 58%, #2a90d4 0%);
}

.grey {
	background-color: #f8e9d1;
	background-image: -webkit-linear-gradient(top, #f8e9d1 58%, #e7d5b7 0%);
	background-image: -moz-linear-gradient(top, #f8e9d1 58%, #e7d5b7 0%);
	background-image: linear-gradient(top, #f8e9d1 58%, #e7d5b7 0%);
}

/* Basic ribbon */

.ribbon {
	background: #c0392b;
	color: #fff;
	display: block;
	font-size: 0.7em;
	position: absolute;
	top: 11px;
	right: 1px;
	width: 40px;
	height: 20px;
	line-height: 20px;
	letter-spacing: 0.15em; 
	text-align: center;
	-webkit-transform: rotateZ(45deg) translateZ(1px);
	-moz-transform: rotateZ(45deg) translateZ(1px);
	transform: rotateZ(45deg) translateZ(1px);
	-webkit-backface-visibility: hidden;
	-moz-backface-visibility: hidden;
	backface-visibility: hidden;
	z-index: 10;
}

.ribbon::before,
.ribbon::after{
	position: absolute;
	top: -20px;
	width: 0;
	height: 0;
	border-bottom: 20px solid #c0392b;
	border-top: 20px solid transparent;
}

.ribbon::before{
	left: -20px;
	border-left: 20px solid transparent;
}

.ribbon::after{
	right: -20px;
	border-right: 20px solid transparent;
}

/* figcaption */

figcaption {
	padding-left: 40px;
	text-align: left;
	position: absolute;
	top: 0%;
	left: 160px;
	width: 310px;
}

figcaption h1 {
	margin: 0;
}

figcaption span {
	color: #16a085;
	padding: 0.6em 0 1em 0;
	display: block;
}

figcaption p {
	color: #63707d;
	line-height: 1.3;
}

/* Media Queries */
@media screen and (max-width: 37.8125em) {
	.align > li {
		width: 100%;
		min-height: 440px;
		height: auto;
		padding: 0;
		margin: 0 0 30px 0;
	}

	.book {
		margin: 0 auto;
	}

	figcaption {
		text-align: center;
		width: 320px;
		top: 250px;
		padding-left: 0;
		left: -80px;
		font-size: 90%;
	}
}

</style>

</head>

<body>

  <div class="component">
				<ul class="align">
					<li>
						<figure class='book'>

							<!-- Front -->

							<ul class='hardcover_front'>
								<li>
									<div class="coverDesign blue">
										<h1>Felicity</h1>
										<p>cool</p>
									</div>
								</li>
								<li></li>
							</ul>

							<!-- Pages -->

							<ul class='page'>
								<li></li>
								<li>
									<a class="btn"  >你在闲逛</a>
								</li>
								<li></li>
								<li></li>
								<li></li>
							</ul>

							<!-- Back -->

							<ul class='hardcover_back'>
								<li></li>
								<li></li>
							</ul>
							<ul class='book_spine'>
								<li></li>
								<li></li>
							</ul>
							 
						</figure>
					</li>
				</ul>
			</div>
<div style="text-align:center;clear:both"></div>
</body>

</html>

参考原文:www.html5tricks.com

首页蜡烛代码

老版(无数字):

<!doctype html>
<html>
<head>
<meta charset="utf-8">

<style>
.outerme {
  width: 10vw;
  height: 5px;
  margin-left: 0;
  margin-top: 10px;  
  margin-bottom: 150px;
  /*background:#de38a0;*/
  transform: scale(0.7, 0.7);
  -ms-transform: scale(0.7, 0.7);    /* IE 9 */
  -webkit-transform: scale(0.7, 0.7);      /* Safari and Chrome */
}

.thefloor {
  /*position: absolute;*/
  left: 50%;
  top: 50%;
  width: 280px;
  height: 5px;
  background: #673C63;
  transform: translate(0, -50%);
  box-shadow: 0px 2px 5px #111;
  z-index: 2;
}

.candles {
  /*position: absolute;*/
  left: 50%;
  top: 50%;
  width: 250px;
  height: 150px;
  transform: translate(0, 0);
  z-index: 1;
  /*background-color:#fff;
  animation: change-background 3s infinite linear;*/
}

.candle1 {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 35px;
  height: 100px;
  background: #fff;
  border: 3px solid #673C63;
  border-bottom: 0px;
  border-radius: 3px;
  transform-origin: center right;
  transform: translate(60%, -25%);
  box-shadow: -2px 0px 0px #95c6f2 inset;
  animation: expand-body 3s infinite linear;
}

.candle1__stick, .candle2__stick {
  position: absolute;
  left: 50%;
  top: 0%;
  width: 3px;
  height: 15px;
  background: #673C63;
  border-radius: 8px;
  transform: translate(-50%, -100%);
}

.candle2__stick {
  height: 12px;
  transform-origin: bottom center;
  animation: stick-animation 3s infinite linear;
}

.candle1__eyes, .candle2__eyes {
  position: absolute;
  left: 50%;
  top: 0%;
  width: 35px;
  height: 30px;
  transform: translate(-50%, 0%);
}

.candle1__eyes-one {
  position: absolute;
  left: 30%;
  top: 20%;
  width: 5px;
  height: 5px;
  border-radius: 100%;
  background: #673C63;
  transform: translate(-70%, 0%);
  animation: blink-eyes 3s infinite linear;
}

.candle1__eyes-two {
  position: absolute;
  left: 70%;
  top: 20%;
  width: 5px;
  height: 5px;
  border-radius: 100%;
  background: #673C63;
  transform: translate(-70%, 0%);
  animation: blink-eyes 3s infinite linear;
}

.candle1__mouth {
  position: absolute;
  left: 40%;
  top: 20%;
  width: 0px;
  height: 0px;
  border-radius: 20px;
  background: #673C63;
  transform: translate(-50%, -50%);
  animation: uff 3s infinite linear;
}

.candle__smoke-one {
  position: absolute;
  left: 30%;
  top: 50%;
  width: 30px;
  height: 3px;
  background: grey;
  transform: translate(-50%, -50%);
  animation: move-left 3s infinite linear;
}

.candle__smoke-two {
  position: absolute;
  left: 30%;
  top: 40%;
  width: 10px;
  height: 10px;
  border-radius: 10px;
  background: grey;
  transform: translate(-50%, -50%);
  animation: move-top 3s infinite linear;
}

.candle2 {
  position: absolute;
  left: 20%;
  top: 65%;
  width: 42px;
  height: 60px;
  background: #fff;
  border: 3px solid #673C63;
  border-bottom: 0px;
  border-radius: 3px;
  transform: translate(60%, -15%);
  transform-origin: center right;
  box-shadow: -2px 0px 0px #95c6f2 inset;
  animation: shake-left 3s infinite linear;
}

.candle2__eyes-one {
  position: absolute;
  left: 30%;
  top: 50%;
  width: 5px;
  height: 5px;
  display: inline-block;
  border: 0px solid #673C63;
  border-radius: 100%;
  float: left;
  background: #673C63;
  transform: translate(-80%, 0%);
  animation: changeto-lower 3s infinite linear;
}

.candle2__eyes-two {
  position: absolute;
  left: 70%;
  top: 50%;
  width: 5px;
  height: 5px;
  display: inline-block;
  border: 0px solid #673C63;
  border-radius: 100%;
  float: left;
  background: #673C63;
  transform: translate(-80%, 0%);
  animation: changeto-greater 3s infinite linear;
}

.light__wave {
  position: absolute;
  top: 35%;
  left: 35%;
  width: 75px;
  height: 75px;
  border-radius: 100%;
  z-index: 0;
  transform: translate(-25%, -50%) scale(2.5, 2.5);
  border: 2px solid rgba(255, 255, 255, 0.2);
  animation: expand-light 3s infinite linear;
}

.candle2__fire {
  position: absolute;
  top: 50%;
  left: 40%;
  display: block;
  width: 16px;
  height: 20px;
  background-color: red;
  border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
  background: #FF9800;
  transform: translate(-50%, -50%);
  animation: dance-fire 3s infinite linear;
}

@keyframes blink-eyes {
  0%,35% {
    opacity: 1;
    transform: translate(-70%, 0%);
  }
  36%,39% {
    opacity: 0;
    transform: translate(-70%, 0%);
  }
  40% {
    opacity: 1;
    transform: translate(-70%, 0%);
  }
  50%,65% {
    transform: translate(-140%, 0%);
  }
  66% {
    transform: translate(-70%, 0%);
  }
}
@keyframes expand-body {
  0%,40% {
    transform: scale(1, 1) translate(60%, -25%);
  }
  45%,55% {
    transform: scale(1.1, 1.1) translate(60%, -28%);
  }
  60% {
    transform: scale(0.89, 0.89) translate(60%, -25%);
  }
  65% {
    transform: scale(1, 1) translate(60%, -25%);
  }
  70% {
    transform: scale(0.95, 0.95) translate(60%, -25%);
  }
  75% {
    transform: scale(1, 1) translate(60%, -25%);
  }
}
@keyframes uff {
  0%,40% {
    width: 0px;
    height: 0px;
  }
  50%,54% {
    width: 15px;
    height: 15px;
    left: 30%;
  }
  59% {
    width: 5px;
    height: 5px;
    left: 20%;
  }
  62% {
    width: 2px;
    height: 2px;
    left: 20%;
  }
  67% {
    width: 0px;
    height: 0px;
    left: 30%;
  }
}
@keyframes change-background{
  0%,59%,98%,100% {
    background: #fff;
  }
  61%,97% {
    background: #b3afcc;   /* 原色:f8ae39 */
  }
}
@keyframes move-left {
  0%,59%,100% {
    width: 0px;
    left: 40%;
  }
  60% {
    width: 30px;
    left: 30%;
  }
  68% {
    width: 0px;
    left: 20%;
  }
}
@keyframes move-top {
  0%,64%,100% {
    width: 0px;
    height: 0px;
    top: 0%;
  }
  65% {
    width: 10px;
    height: 10px;
    top: 40%;
    left: 40%;
  }
  80% {
    width: 0px;
    height: 0px;
    top: 20%;
  }
}
@keyframes shake-left {
  0%,40% {
    left: 20%;
    transform: translate(60%, -15%);
  }
  50%,54% {
    left: 20%;
    transform: translate(60%, -15%);
  }
  59% {
    left: 20%;
    transform: translate(60%, -15%);
  }
  62% {
    left: 18%;
    transform: translate(60%, -15%);
  }
  65% {
    left: 21%;
    transform: translate(60%, -15%);
  }
  67% {
    left: 20%;
    transform: translate(60%, -15%);
  }
  75% {
    left: 20%;
    transform: scale(1.15, 0.85) translate(60%, -15%);
    background: #fff;
    border-color: #673C63;
  }
  91% {
    left: 20%;
    transform: scale(1.18, 0.82) translate(60%, -10%);
    background: #F44336;
    border-color: #F44336;
    box-shadow: -2px 0px 0px #F44336 inset;
  }
  92% {
    left: 20%;
    transform: scale(0.85, 1.15) translate(60%, -15%);
  }
  95% {
    left: 20%;
    transform: scale(1.05, 0.95) translate(60%, -15%);
  }
  97% {
    left: 20%;
    transform: scale(1, 1) translate(60%, -15%);
  }
}
@keyframes stick-animation {
  0%,40% {
    left: 50%;
    top: 0%;
    transform: translate(-50%, -100%);
  }
  50%,54% {
    left: 50%;
    top: 0%;
    transform: translate(-50%, -100%);
  }
  59% {
    left: 50%;
    top: 0%;
    transform: translate(-50%, -100%);
  }
  62% {
    left: 50%;
    top: 0%;
    transform: rotateZ(-15deg) translate(-50%, -100%);
  }
  65% {
    left: 50%;
    top: 0%;
    transform: rotateZ(15deg) translate(-50%, -100%);
  }
  70% {
    left: 50%;
    top: 0%;
    transform: rotateZ(-5deg) translate(-50%, -100%);
  }
  72% {
    left: 50%;
    top: 0%;
    transform: rotateZ(5deg) translate(-50%, -100%);
  }
  74%,84% {
    left: 50%;
    top: 0%;
    transform: rotateZ(0deg) translate(-50%, -100%);
  }
  85% {
    transform: rotateZ(180deg) translate(0%, 120%);
  }
  92% {
    left: 50%;
    top: 0%;
    transform: translate(-50%, -100%);
  }
}
@keyframes expand-light {
  10%,29%,59%,89% {
    transform: translate(-25%, -50%) scale(0, 0);
    border: 2px solid rgba(255, 255, 191, 0);
  }
  90%,20%,50% {
    transform: translate(-25%, -50%) scale(1, 1);
  }
  95%,96%,26%,27%,56%,57% {
    transform: translate(-25%, -50%) scale(2, 2);
    border: 2px solid rgba(255, 255,191, 0.5);
  }
  0%,28%,58%,100% {
    transform: translate(-25%, -50%) scale(2.5, 2.5);
    border: 2px solid rgba(255, 255, 191, 0.2);
  }
}
@keyframes dance-fire {
  59%,89% {
    left: 40%;
    width: 0px;
    height: 0px;
  }
  90%,0%,7%,15%,23%,31%,39%,47%,55% {
    left: 40.8%;
    width: 16px;
    height: 20px;
    background: #FFC107;
  }
  94%,3%,11%,19%,27%,35%,43%,51%,58% {
    left: 41.2%;
    width: 16px;
    height: 20px;
    background: #FF9800;
  }
}
@keyframes changeto-lower {
  0%,70%,90% {
    padding: 0px;
    display: inline-block;
    border-radius: 100%;
    background: #673C63;
    border-width: 0 0 0 0;
    border: 0px solid #673C63;
    transform: translate(-90%, 0%);
  }
  71%,89% {
    background: none;
    border: solid #673C63;
    border-radius: 0px;
    border-width: 0 2px 2px 0;
    display: inline-block;
    padding: 1px;
    float: left;
    transform-origin: bottom left;
    transform: rotate(-45deg) translate(-50%, -65%);
    -webkit-transform: rotate(-45deg) translate(-50%, -65%);
  }
}
@keyframes changeto-greater {
  0%,70%,90% {
    top: 50%;
    padding: 0px;
    display: inline-block;
    border-radius: 100%;
    background: #673C63;
    border-width: 0 0 0 0;
    border: 0px solid #673C63;
    transform: translate(-80%, 0%);
  }
  71%,89% {
    top: 30%;
    background: none;
    border: solid #673C63;
    border-radius: 0px;
    border-width: 0 2px 2px 0;
    display: inline-block;
    padding: 1px;
    float: left;
    transform-origin: bottom left;
    transform: rotate(135deg) translate(-80%, 20%);
    -webkit-transform: rotate(135deg) translate(-80%, 20%);
  }
}
</style>

</head>
<body>

<div  class="outerme">
  <div class="candles">
    <div class="light__wave"></div>
    <div class="candle1">
      <div class="candle1__body">
        <div class="candle1__eyes">
          <span class="candle1__eyes-one"></span>
          <span class="candle1__eyes-two"></span>
        </div>
        <div class="candle1__mouth"></div>
      </div>
      <div class="candle1__stick"></div>
    </div>
    
    <div class="candle2">
      <div class="candle2__body">
        <div class="candle2__eyes">
          <div class="candle2__eyes-one"></div>
          <div class="candle2__eyes-two"></div>
        </div>
      </div>
      <div class="candle2__stick"></div>
    </div>
    <div class="candle2__fire"></div>
    <div class="sparkles-one"></div>
    <div class="sparkles-two"></div>
    <div class="candle__smoke-one">

    </div>
    <div class="candle__smoke-two">

    </div>
    
  </div>
  <div class="thefloor">
  </div>

</div>


</body>
</html>

新版(有数字):

<!doctype html>
<html>
<head>
<meta charset="utf-8">

<style>
.outerme {
  width: 10vw;
  height: 5px;
  margin-left: 0;
  margin-top: 10px;  
  margin-bottom: 150px;
  /*background:#de38a0;*/
  transform: scale(0.7, 0.7);
  -ms-transform: scale(0.7, 0.7);    /* IE 9 */
  -webkit-transform: scale(0.7, 0.7);      /* Safari and Chrome */
}

.thefloor {
  /*position: absolute;*/
  left: 50%;
  top: 50%;
  width: 280px;
  height: 5px;
  background: #673C63;
  transform: translate(0, -50%);
  box-shadow: 0px 2px 5px #111;
  z-index: 2;
}

.candles {
  /*position: absolute;*/
  left: 50%;
  top: 50%;
  width: 250px;
  height: 150px;
  transform: translate(-5%, 0);
  z-index: 1;
  /*background-color:#fff;
  animation: change-background 3s infinite linear;*/
}

.candle-text {
  position: absolute;
  left: 72%;
  bottom: -13%;
  width: 50px;
  /*background: #ddd;*/
  transform-origin: center right;
  transform: translate(70%,0);
  text-align: center;
  font-size: 28pt;
  color: #673C63;
  font-family: "Helvetica", Serif,  "Times New Roman";
}

.candle1 {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 35px;
  height: 100px;
  background: #fff;
  border: 3px solid #673C63;
  border-bottom: 0px;
  border-radius: 3px;
  transform-origin: center right;
  transform: translate(60%, -25%);
  box-shadow: -2px 0px 0px #95c6f2 inset;
  animation: expand-body 3s infinite linear;
}

.candle1__stick, .candle2__stick {
  position: absolute;
  left: 50%;
  top: 0%;
  width: 3px;
  height: 15px;
  background: #673C63;
  border-radius: 8px;
  transform: translate(-50%, -100%);
}

.candle2__stick {
  height: 12px;
  transform-origin: bottom center;
  animation: stick-animation 3s infinite linear;
}

.candle1__eyes, .candle2__eyes {
  position: absolute;
  left: 50%;
  top: 0%;
  width: 35px;
  height: 30px;
  transform: translate(-50%, 0%);
}

.candle1__eyes-one {
  position: absolute;
  left: 30%;
  top: 20%;
  width: 5px;
  height: 5px;
  border-radius: 100%;
  background: #673C63;
  transform: translate(-70%, 0%);
  animation: blink-eyes 3s infinite linear;
}

.candle1__eyes-two {
  position: absolute;
  left: 70%;
  top: 20%;
  width: 5px;
  height: 5px;
  border-radius: 100%;
  background: #673C63;
  transform: translate(-70%, 0%);
  animation: blink-eyes 3s infinite linear;
}

.candle1__mouth {
  position: absolute;
  left: 40%;
  top: 20%;
  width: 0px;
  height: 0px;
  border-radius: 20px;
  background: #673C63;
  transform: translate(-50%, -50%);
  animation: uff 3s infinite linear;
}

.candle__smoke-one {
  position: absolute;
  left: 30%;
  top: 50%;
  width: 30px;
  height: 3px;
  background: grey;
  transform: translate(-50%, -50%);
  animation: move-left 3s infinite linear;
}

.candle__smoke-two {
  position: absolute;
  left: 30%;
  top: 40%;
  width: 10px;
  height: 10px;
  border-radius: 10px;
  background: grey;
  transform: translate(-50%, -50%);
  animation: move-top 3s infinite linear;
}

.candle2 {
  position: absolute;
  left: 20%;
  top: 65%;
  width: 42px;
  height: 60px;
  background: #fff;
  border: 3px solid #673C63;
  border-bottom: 0px;
  border-radius: 3px;
  transform: translate(60%, -15%);
  transform-origin: center right;
  box-shadow: -2px 0px 0px #95c6f2 inset;
  animation: shake-left 3s infinite linear;
}

.candle2__eyes-one {
  position: absolute;
  left: 30%;
  top: 50%;
  width: 5px;
  height: 5px;
  display: inline-block;
  border: 0px solid #673C63;
  border-radius: 100%;
  float: left;
  background: #673C63;
  transform: translate(-80%, 0%);
  animation: changeto-lower 3s infinite linear;
}

.candle2__eyes-two {
  position: absolute;
  left: 70%;
  top: 50%;
  width: 5px;
  height: 5px;
  display: inline-block;
  border: 0px solid #673C63;
  border-radius: 100%;
  float: left;
  background: #673C63;
  transform: translate(-80%, 0%);
  animation: changeto-greater 3s infinite linear;
}

.light__wave {
  position: absolute;
  top: 35%;
  left: 35%;
  width: 75px;
  height: 75px;
  border-radius: 100%;
  z-index: 0;
  transform: translate(-25%, -50%) scale(2.5, 2.5);
  border: 2px solid rgba(255, 255, 255, 0.2);
  animation: expand-light 3s infinite linear;
}

.candle2__fire {
  position: absolute;
  top: 50%;
  left: 40%;
  display: block;
  width: 16px;
  height: 20px;
  background-color: red;
  border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
  background: #FF9800;
  transform: translate(-50%, -50%);
  animation: dance-fire 3s infinite linear;
}

@keyframes blink-eyes {
  0%,35% {
    opacity: 1;
    transform: translate(-70%, 0%);
  }
  36%,39% {
    opacity: 0;
    transform: translate(-70%, 0%);
  }
  40% {
    opacity: 1;
    transform: translate(-70%, 0%);
  }
  50%,65% {
    transform: translate(-140%, 0%);
  }
  66% {
    transform: translate(-70%, 0%);
  }
}
@keyframes expand-body {
  0%,40% {
    transform: scale(1, 1) translate(60%, -25%);
  }
  45%,55% {
    transform: scale(1.1, 1.1) translate(60%, -28%);
  }
  60% {
    transform: scale(0.89, 0.89) translate(60%, -25%);
  }
  65% {
    transform: scale(1, 1) translate(60%, -25%);
  }
  70% {
    transform: scale(0.95, 0.95) translate(60%, -25%);
  }
  75% {
    transform: scale(1, 1) translate(60%, -25%);
  }
}
@keyframes uff {
  0%,40% {
    width: 0px;
    height: 0px;
  }
  50%,54% {
    width: 15px;
    height: 15px;
    left: 30%;
  }
  59% {
    width: 5px;
    height: 5px;
    left: 20%;
  }
  62% {
    width: 2px;
    height: 2px;
    left: 20%;
  }
  67% {
    width: 0px;
    height: 0px;
    left: 30%;
  }
}
@keyframes change-background{
  0%,59%,98%,100% {
    background: #fff;
  }
  61%,97% {
    background: #b3afcc;   /* 原色:f8ae39 */
  }
}
@keyframes move-left {
  0%,59%,100% {
    width: 0px;
    left: 40%;
  }
  60% {
    width: 30px;
    left: 30%;
  }
  68% {
    width: 0px;
    left: 20%;
  }
}
@keyframes move-top {
  0%,64%,100% {
    width: 0px;
    height: 0px;
    top: 0%;
  }
  65% {
    width: 10px;
    height: 10px;
    top: 40%;
    left: 40%;
  }
  80% {
    width: 0px;
    height: 0px;
    top: 20%;
  }
}
@keyframes shake-left {
  0%,40% {
    left: 20%;
    transform: translate(60%, -15%);
  }
  50%,54% {
    left: 20%;
    transform: translate(60%, -15%);
  }
  59% {
    left: 20%;
    transform: translate(60%, -15%);
  }
  62% {
    left: 18%;
    transform: translate(60%, -15%);
  }
  65% {
    left: 21%;
    transform: translate(60%, -15%);
  }
  67% {
    left: 20%;
    transform: translate(60%, -15%);
  }
  75% {
    left: 20%;
    transform: scale(1.15, 0.85) translate(60%, -15%);
    background: #fff;
    border-color: #673C63;
  }
  91% {
    left: 20%;
    transform: scale(1.18, 0.82) translate(60%, -10%);
    background: #F44336;
    border-color: #F44336;
    box-shadow: -2px 0px 0px #F44336 inset;
  }
  92% {
    left: 20%;
    transform: scale(0.85, 1.15) translate(60%, -15%);
  }
  95% {
    left: 20%;
    transform: scale(1.05, 0.95) translate(60%, -15%);
  }
  97% {
    left: 20%;
    transform: scale(1, 1) translate(60%, -15%);
  }
}
@keyframes stick-animation {
  0%,40% {
    left: 50%;
    top: 0%;
    transform: translate(-50%, -100%);
  }
  50%,54% {
    left: 50%;
    top: 0%;
    transform: translate(-50%, -100%);
  }
  59% {
    left: 50%;
    top: 0%;
    transform: translate(-50%, -100%);
  }
  62% {
    left: 50%;
    top: 0%;
    transform: rotateZ(-15deg) translate(-50%, -100%);
  }
  65% {
    left: 50%;
    top: 0%;
    transform: rotateZ(15deg) translate(-50%, -100%);
  }
  70% {
    left: 50%;
    top: 0%;
    transform: rotateZ(-5deg) translate(-50%, -100%);
  }
  72% {
    left: 50%;
    top: 0%;
    transform: rotateZ(5deg) translate(-50%, -100%);
  }
  74%,84% {
    left: 50%;
    top: 0%;
    transform: rotateZ(0deg) translate(-50%, -100%);
  }
  85% {
    transform: rotateZ(180deg) translate(0%, 120%);
  }
  92% {
    left: 50%;
    top: 0%;
    transform: translate(-50%, -100%);
  }
}
@keyframes expand-light {
  10%,29%,59%,89% {
    transform: translate(-25%, -50%) scale(0, 0);
    border: 2px solid rgba(255, 255, 191, 0);
  }
  90%,20%,50% {
    transform: translate(-25%, -50%) scale(1, 1);
  }
  95%,96%,26%,27%,56%,57% {
    transform: translate(-25%, -50%) scale(2, 2);
    border: 2px solid rgba(255, 255,191, 0.5);
  }
  0%,28%,58%,100% {
    transform: translate(-25%, -50%) scale(2.5, 2.5);
    border: 2px solid rgba(255, 255, 191, 0.2);
  }
}
@keyframes dance-fire {
  59%,89% {
    left: 40%;
    width: 0px;
    height: 0px;
  }
  90%,0%,7%,15%,23%,31%,39%,47%,55% {
    left: 40.8%;
    width: 16px;
    height: 20px;
    background: #FFC107;
  }
  94%,3%,11%,19%,27%,35%,43%,51%,58% {
    left: 41.2%;
    width: 16px;
    height: 20px;
    background: #FF9800;
  }
}
@keyframes changeto-lower {
  0%,70%,90% {
    padding: 0px;
    display: inline-block;
    border-radius: 100%;
    background: #673C63;
    border-width: 0 0 0 0;
    border: 0px solid #673C63;
    transform: translate(-90%, 0%);
  }
  71%,89% {
    background: none;
    border: solid #673C63;
    border-radius: 0px;
    border-width: 0 2px 2px 0;
    display: inline-block;
    padding: 1px;
    float: left;
    transform-origin: bottom left;
    transform: rotate(-45deg) translate(-50%, -65%);
    -webkit-transform: rotate(-45deg) translate(-50%, -65%);
  }
}
@keyframes changeto-greater {
  0%,70%,90% {
    top: 50%;
    padding: 0px;
    display: inline-block;
    border-radius: 100%;
    background: #673C63;
    border-width: 0 0 0 0;
    border: 0px solid #673C63;
    transform: translate(-80%, 0%);
  }
  71%,89% {
    top: 30%;
    background: none;
    border: solid #673C63;
    border-radius: 0px;
    border-width: 0 2px 2px 0;
    display: inline-block;
    padding: 1px;
    float: left;
    transform-origin: bottom left;
    transform: rotate(135deg) translate(-80%, 20%);
    -webkit-transform: rotate(135deg) translate(-80%, 20%);
  }
}
</style>

</head>
<body>

<div  class="outerme">
  <div class="candles">
    <div class="light__wave"></div>
    <div class="candle1">
      <div class="candle1__body">
        <div class="candle1__eyes">
          <span class="candle1__eyes-one"></span>
          <span class="candle1__eyes-two"></span>
        </div>
        <div class="candle1__mouth"></div>
      </div>
      <div class="candle1__stick"></div>
    </div>
		   <!-- 在这里改数字 -->
    <div class="candle-text"> 0 </div>
    
    <div class="candle2">
      <div class="candle2__body">
        <div class="candle2__eyes">
          <div class="candle2__eyes-one"></div>
          <div class="candle2__eyes-two"></div>
        </div>
      </div>
      <div class="candle2__stick"></div>
    </div>
    <div class="candle2__fire"></div>
    <div class="sparkles-one"></div>
    <div class="sparkles-two"></div>
    <div class="candle__smoke-one">

    </div>
    <div class="candle__smoke-two">

    </div>
    
  </div>
  <div class="thefloor">
  </div>

</div>


</body>
</html>

用h5的canvas实现动画的泡沫

效果图1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
            background-color: pink;
        }
        canvas{
            position: absolute;
            left: 0;
            top: 0;
            right: 0;
            bottom: 0;
            margin: auto;
            background-color: white;
        }
    </style>
</head>
<body>
    <canvas width="400" height="400"></canvas>
    <script>
        var oC = document.querySelector("canvas");
        if(oC.getContext){
            var ctx = oC.getContext("2d");
            var arr = [];
            //将数组中的圆绘制到画布上
            setInterval(function(){
                ctx.clearRect(0,0,oC.width,oC.height);
                for(i=0;i<arr.length;i++){
                    ctx.save();
                    ctx.beginPath();
                    ctx.fillStyle = "rgba("+arr[i].red+","+arr[i].blue+","+arr[i].yellow+","+arr[i].alp+")";
                    ctx.arc(arr[i].x,arr[i].y,arr[i].r,0,2*Math.PI);
                    ctx.fill();
                    ctx.restore();
                    if(arr[i].alp<=0){
                        arr.splice(i,1);
                    }
                    arr[i].r++;
                    arr[i].alp -=0.01;
                }
            },1000/60)
             //往arr中注入随机圆的信息
            setInterval(function(){
                var x = Math.random()*oC.width;
                var y = Math.random()*oC.height;
                var r = 10;
                var red = Math.round(Math.random()*255);
                var blue = Math.round(Math.random()*255);
                var yellow = Math.round(Math.random()*255);
                var alp = 1;
                arr.push({
                    x:x,
                    y:y,
                    r:r,
                    red:red,
                    blue:blue,
                    yellow:yellow,
                    alp:alp,
                })
            },100)
        }
    </script>
</body>
</html>

效果图2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
            background-color: pink;
        }
        canvas{
            position: absolute;
            left: 0;
            top: 0;
            right: 0;
            bottom: 0;
            margin: auto;
            background-color: white;
        }
    </style>
</head>
<body>
    <canvas width="150" height="400"></canvas>
    <script>
        var oC = document.querySelector("canvas");
        if(oC.getContext){
            var ctx = oC.getContext("2d");
            var arr = [];
            //将数组中的圆绘制到画布上
            setInterval(function(){
                ctx.clearRect(0,0,oC.width,oC.height);
                for(i=0;i<arr.length;i++){
                    ctx.save();
                    ctx.beginPath();
                    ctx.fillStyle = "rgba("+arr[i].red+","+arr[i].blue+","+arr[i].yellow+","+arr[i].alp+")";
                    ctx.arc(arr[i].x,arr[i].y,arr[i].r,0,2*Math.PI);
                    ctx.fill();
                    ctx.restore();
                    arr[i].deg +=6;
                    arr[i].x = arr[i].startX + Math.sin(arr[i].deg*Math.PI/180)*arr[i].step*2;
                    arr[i].y = arr[i].startY - (arr[i].deg*Math.PI/180)*arr[i].step;
                    if(arr[i].Y<=50){
                        arr.splice(i,1);
                    }
                }
            },1000/60)
             //往arr中注入随机圆的信息
            setInterval(function(){
                var x = Math.random()*oC.width;
                var r = Math.random()*6+2;
                var y = oC.height-r;
                var startX = x;
                var startY = y;
                var red = Math.round(Math.random()*255);
                var blue = Math.round(Math.random()*255);
                var yellow = Math.round(Math.random()*255);
                var step = Math.random()*20+10;
                var alp = 1;
                var deg = 0;
                arr.push({
                    x:x,
                    y:y,
                    r:r,
                    red:red,
                    blue:blue,
                    yellow:yellow,
                    alp:alp,
                    step:step,
                    startX:startX,
                    startY:startY,
                    deg:deg
                })
            },100)
        }
    </script>
</body>
</html>

用到的知识点:

 h5中canvas相关的知识点:

  save()      canvas2D API通过将当前状态放入栈中,保存canvas全部状态的方法,调用sava时,将样式容器里的状态压入样式表。

restore()   调用restore时,将样式栈的栈顶状态弹出到样式容器里进行覆盖。

clearRect(x,y,width,height)    清楚指定矩形区域,让清除部分完全透明。

                x与y指定了画布上所绘制的矩形的左上角(相对于原点)的坐标。

fillStyle   设置图形的填充颜色。

closePath()  此方法会通过绘制一条从当前点到开始点的直线来闭合图形。

stroke()    通过线条来绘制图形轮廓。(不会自动调用closePath())

fill()      通过填充区域的内容区域生成实心的图形。(会自动调用closePath())

arc(x,y,radius,startAngle,endAngle,anticlockwise)      画一个以(x,y)为圆心的以radius为半径的圆弧,从startAngle开始到endAngle 结束,按照anticlockwise给定的方向(默认为顺时针)生成。

JS中用到的知识点

 Math.round()   可对一个数进四舍五入取整。

 Math.random() 可生成一个0~1之间的随机数。

 Math.sin()  正弦函数。

 Math.PI()圆周率。

 splice()  可用于删除数组中指定的元素。

                   两个参数:参数一:删除数组第几个。

                                     参数二:删除几个数据。

————————————————

原文链接:https://blog.csdn.net/weixin_43571052/article/details/90233193

首页花瓣代码

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
.container {
  width: 10vw;
  height: 5vw;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  margin: auto;
}

.outme{
transform: scale(0.5, 0.5);
-ms-transform: scale(0.5, 0.5); /* IE 9 */
-webkit-transform: scale(0.5, 0.5); /* Safari and Chrome */
margin-left: -50px;
}

.common {
  height: 5vw;
  max-height: 100%;
  overflow: auto;
  width: 2vw;
  margin: auto;
  max-width: 100%;
  position: absolute;
  background-color: ;
  border-radius: 0vw 10vw 0vw 10vw;
  box-shadow: inset 0vw 0vw 0vw .1vw #E645D0, 0vw 0vw 1.5vw 0vw #E645D0;
}

.one {
  transform: rotate(45deg);
  left: 0;
  right: 0;
  top: 0;
  bottom: 7.5vw;
}

.two {
  transform: rotate(90deg);
  left: 5.5vw;
  right: 0;
  top: 0;
  bottom: 5.5vw;
}

.three {
  transform: rotate(135deg);
  left: 7.5vw;
  right: 0;
  top: 0;
  bottom: 0;
}

.four {
  transform: rotate(180deg);
  left: 5.5vw;
  right: 0;
  top: 5.5vw;
  bottom: 0;
}

.five {
  transform: rotate(225deg);
  left: 0;
  right: 0;
  top: 7.5vw;
  bottom: 0;
}

.six {
  transform: rotate(270deg);
  left: 0;
  right: 5.5vw;
  top: 5.5vw;
  bottom: 0;
}

.seven {
  transform: rotate(315deg);
  left: 0;
  right: 7.5vw;
  top: 0;
  bottom: 0;
}

.eight {
  transform: rotate(360deg);
  left: 0;
  right: 5.5vw;
  top: 0;
  bottom: 5.5vw;
}

 
 
.one {
  animation: one 1s ease infinite;
  -moz-animation: one 1s ease infinite;
  /* Firefox */
  -webkit-animation: one 1s ease infinite;
  /* Safari and Chrome */
  -o-animation: one 1s ease infinite;
  /* Opera */
}

@keyframes one {
  0%,
  100% {}
  50% {
    background: ;
    box-shadow: inset 0vw 0vw 0vw .1vw #17E1E6, 0vw 0vw 1.5vw 0vw #17E1E6;
  }
}

.two {
  animation: two 1s .125s ease infinite;
  -moz-animation: two 1s .125s ease infinite;
  /* Firefox */
  -webkit-animation: two 1s .125s ease infinite;
  /* Safari and Chrome */
  -o-animation: two 1s .125s ease infinite;
  /* Opera */
}

@keyframes two {
  0%,
  100% {}
  50% {
    background: ;
    box-shadow: inset 0vw 0vw 0vw .1vw #17E1E6, 0vw 0vw 1.5vw 0vw #17E1E6;
  }
}

.three {
  animation: three 1s .25s ease infinite;
  -moz-animation: three 1s .25s ease infinite;
  /* Firefox */
  -webkit-animation: three 1s .25s ease infinite;
  /* Safari and Chrome */
  -o-animation: three 1s .25s ease infinite;
  /* Opera */
}

@keyframes three {
  0%,
  100% {}
  50% {
    background: ;
    box-shadow: inset 0vw 0vw 0vw .1vw #17E1E6, 0vw 0vw 1.5vw 0vw #17E1E6;
  }
}

.four {
  animation: four 1s .375s ease infinite;
  -moz-animation: four 1s .375s ease infinite;
  /* Firefox */
  -webkit-animation: four 1s .375s ease infinite;
  /* Safari and Chrome */
  -o-animation: four 1s .375s ease infinite;
  /* Opera */
}

@keyframes four {
  0%,
  100% {}
  50% {
    background: ;
    box-shadow: inset 0vw 0vw 0vw .1vw #17E1E6, 0vw 0vw 1.5vw 0vw #17E1E6;
  }
}

.five {
  animation: five 1s .5s ease infinite;
  -moz-animation: five 1s .5s ease infinite;
  /* Firefox */
  -webkit-animation: five 1s .5s ease infinite;
  /* Safari and Chrome */
  -o-animation: five 1s .5s ease infinite;
  /* Opera */
}

@keyframes five {
  0%,
  100% {}
  50% {
    background: ;
    box-shadow: inset 0vw 0vw 0vw .1vw #17E1E6, 0vw 0vw 1.5vw 0vw #17E1E6;
  }
}

.six {
  animation: six 1s .625s ease infinite;
  -moz-animation: six 1s .625s ease infinite;
  /* Firefox */
  -webkit-animation: six 1s .625s ease infinite;
  /* Safari and Chrome */
  -o-animation: six 1s .625s ease infinite;
  /* Opera */
}

@keyframes six {
  0%,
  100% {}
  50% {
    background: ;
    box-shadow: inset 0vw 0vw 0vw .1vw #17E1E6, 0vw 0vw 1.5vw 0vw #17E1E6;
  }
}

.seven {
  animation: seven 1s .750s ease infinite;
  -moz-animation: seven 1s .750s ease infinite;
  /* Firefox */
  -webkit-animation: seven 1s .750s ease infinite;
  /* Safari and Chrome */
  -o-animation: seven 1s .750s ease infinite;
  /* Opera */
}

@keyframes seven {
  0%,
  100% {}
  50% {
    background: ;
    box-shadow: inset 0vw 0vw 0vw .1vw #17E1E6, 0vw 0vw 1.5vw 0vw #17E1E6;
  }
}

.eight {
  animation: eight 1s .875s ease infinite;
  -moz-animation: eight 1s .875s ease infinite;
  /* Firefox */
  -webkit-animation: eight 1s .875s ease infinite;
  /* Safari and Chrome */
  -o-animation: eight 1s .875s ease infinite;
  /* Opera */
}

@keyframes eight {
  0%,
  100% {}
  50% {
    background: ;
    box-shadow: inset 0vw 0vw 0vw .1vw #17E1E6, 0vw 0vw 1.5vw 0vw #17E1E6;
  }
}

.container {
  animation: container 5s linear infinite;
  -moz-animation: container 5s linear infinite;
  /* Firefox */
  -webkit-animation: container 5s linear infinite;
  /* Safari and Chrome */
  -o-animation: container 5s linear infinite;
  /* Opera */
}

@keyframes container {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(-360deg);
  }
}

.progress {
  animation: progress 15s ease;
  -moz-animation: progress 15s ease;
  /* Firefox */
  -webkit-animation: progress 15s ease;
  /* Safari and Chrome */
  -o-animation: progress 15s ease;
  /* Opera */
}

@keyframes progress {
  0% {
    left: -24vw;
  }
  10% {
    left: -20vw;
  }
  30% {
    left: -16vw;
  }
  50% {
    left: -12vw;
  }
  65% {
    left: -10vw;
  }
  80% {
    left: -4vw;
  }
  100% {
    left: 0;
  }
}

.fade-in {
  animation: fade-in 2s ease;
  -moz-animation: fade-in 2s ease;
  /* Firefox */
  -webkit-animation: fade-in 2s ease;
  /* Safari and Chrome */
  -o-animation: fade-in 2s ease;
  /* Opera */
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.out {
  animation: out 2s 15s ease;
  -moz-animation: out 2s 15s ease;
  /* Firefox */
  -webkit-animation: out 2s 15s ease;
  /* Safari and Chrome */
  -o-animation: out 2s 15s ease;
  /* Opera */
}

@keyframes out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
</style>

</head>
<body>

<div class="outme">
	<div class="fade-in">
		<div class="container">
			<div class="one common"></div>
			<div class="two common"></div>
			<div class="three common"></div>
			<div class="four common"></div>
			<div class="five common"></div>
			<div class="six common"></div>
			<div class="seven common"></div>
			<div class="eight common"></div>
		</div>
		 
	</div>
</div>

</body>
</html>

H5 – canvas实现帧动画

前言
相信大家小时候一定玩过这样的小人书:

原理是快速切换图片,利用人眼的 视觉暂留(Persistenceofvision)现象,脑补产生动画效果。其实我们的 vedio、GIF 等也是这样实现的,只是它的帧速可能更高。

下面我们就利用 爱奇艺万能播放器 拆分一张GIF图

获得 timg_vedio
显示本地图片
先将照片显示至 Web上,HTML5 中有两种标签可实现:

img
canvas
img
可使用其 src 指定图片,支持 .jpg、.png、.bmp

canvas
canvas 是画布,我们可通过 drawImage() 令其绘制图像:

drawImage(mixed image, int x, int y)
以canvas上指定的坐标点开始,按照图像的原始尺寸大小绘制整个图像。这里的image可以是Image对象,也可以是Canvas对象(下同)。

drawImage(mixed image, int x, int y, int width, int height)
以canvas上指定的坐标点开始,以指定的大小(width和height)绘制整个图像,图像将根据指定的尺寸自动进行相应的缩放。

drawImage(mixed image, int imageX, int imageY, int imageWidth, int imageHeight, int canvasX, int canvasY, int canvasWidth, int canvasHeight)
将指定图像的局部图像(以(imageX, imageY)为左上角、宽度为imageWidth、高度为imageHeight的矩形部分)绘制到canvas中以(canvasX,canvasY)为左上角坐标、宽度为canvasWidth、高度为canvasHeight的矩形区域中


var imge=document.getElementById(“bmp-test1”);

var cjpg=document.getElementById(“c-jpg”);
var cjpg_tx=cjpg.getContext(“2d”);

// onload 图片加载完后执行
imge.onload=function(){
// 图像偏移x50 y50 图像大小110*110
cjpg_tx.drawImage(imge,50,50,110,110);
}

值得注意的是 JS 中图片为 异步加载,所以我们必须等图片加载完后我们使用 drawImage( )才有效。

canvas实现动画效果
遍历
for (let index = 1; index < 20; index++) {
let testimge=new Image();
let imagename=”timg_vedio/timg_”+index+”.jpg”;
testimge.src=imagename;
testimge.onload=function(){
cjpg_tx.drawImage(testimge,50,50,110,110);
}
}

Q&A
Q: 由于JS 异步机制,无法保证 drawImage( ) 按顺序执行
A: 预加载 策略

var imgWrap = [];
//预加载
for (let i = 1; i < 20; i++) {

let imagename="timg_vedio/timg_"+i+".jpg";
imgWrap[i]=new Image();
imgWrap[i].src=imagename;

}
//定时循环显示
var index = 1;
window.setInterval(function() {
if(index < imgWrap.length-1){
index++;
}
else{
index = 1
}
cjpg_tx.drawImage(imgWrap[index],20,20,110,110);
},80);

代码及图片资源可至百度云 下载(请戳) 提取码: 33xq
————————————————


原文链接:https://blog.csdn.net/weixin_40774605/article/details/106627696