云间玉兔,自出机抒,从零开始制作Web插件网页特效小兔子组件(小挂件widget),基于原生CSS/NPM

  • 云间玉兔,自出机抒,从零开始制作Web插件网页特效小兔子组件(小挂件widget),基于原生CSS/NPM已关闭评论
  • 124 次浏览
  • A+
所属分类:Web前端
摘要

著意登楼瞻玉兔,何人张幕遮银阙?又到了一年一度的网页小挂件环节,以往我们都是集成别人开源的组件,但所谓熟读唐诗三百首,不会做诗也会吟,熟读了别人的东西,做几首打油诗也是可以的,但若不能自出机抒,却也成不了大事,所以本次我们从零开始制作属于自己的网页小挂件,博君一晒。

著意登楼瞻玉兔,何人张幕遮银阙?又到了一年一度的网页小挂件环节,以往我们都是集成别人开源的组件,但所谓熟读唐诗三百首,不会做诗也会吟,熟读了别人的东西,做几首打油诗也是可以的,但若不能自出机抒,却也成不了大事,所以本次我们从零开始制作属于自己的网页小挂件,博君一晒。

玉兔主题元素绘制

成本最低的绘制方式是使用纯CSS,不依赖任何图片和三方库,首先创建绘制容器:

<div id="rabbit_box">              </div> 

由于是小挂件,我们首先将容器固定在右下角:

#rabbit_box{          position: fixed;       bottom: var(--pos,5%);        right: 35px;        z-index: 99;        border: none;        outline: none;        filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));        } 

这里加了一层filter滤镜,可以让玉兔更加立体。

考虑到复用性和可移植性,将主题元素动态添加到容器中:

function rabbit_init(){          var container = document.getElementById("rabbit_box");          container.innerHTML = '<div class="rabbit"><div class="rabbit__leg rabbit__leg--one"></div><div class="rabbit__leg rabbit__leg--two"></div><div class="rabbit__tail"></div><div class="rabbit__body"></div><div class="rabbit__leg rabbit__leg--three"></div><div class="rabbit__leg rabbit__leg--four"></div><div class="rabbit__ear rabbit__ear--right"></div><div class="rabbit__head"></div><div class="rabbit__ear rabbit__ear--left"></div></div>';               }      rabbit_init() 

这里玉兔元素由八个小组件构成,分别是头部,四肢,四爪,两只耳朵,眼睛,尾巴以及嘴。

随后设置CSS样式:

.rabbit .rabbit__body {       width: 4em;       height: 5.6em;       background: #F4F4F4;       border-radius: 50% 50% 50% 50%/60% 60% 40% 40%;       transform: rotate(-40deg);       box-shadow: inset -2.3em -2.7em 0 0 var(--theme-color,#D2DAEE);     } 

兔子身体元素通过border-radius来获得圆润的曲线,同时使用transform旋转元素得到一个适合的角度。最后通过box-shadow属性来设置颜色,颜色可以自定义,如果没有自定义则使用默认值#D2DAEE,注意旋转角度需要指定单位:deg。

接着绘制头部:

.rabbit .rabbit__head {       position: absolute;       width: 4em;       height: 4.6em;       top: -2.5em;       left: -2em;       background: var(--theme-color,#e1e6f4);       border-radius: 50% 50% 50% 50%/65% 60% 40% 35%;       transform: rotate(-120deg);       overflow: hidden;     }     .rabbit .rabbit__head:before {       content: "";       position: absolute;       width: 0.65em;       height: 0.5em;       top: -0.1em;       left: 1.8em;       background: #F97996;       border-radius: 50% 50% 50% 50%/30% 30% 70% 70%;       transform: rotate(130deg);     }     .rabbit .rabbit__head:after {       content: "";       position: absolute;       width: 1em;       height: 1em;       top: 1.5em;       left: 1.6em;       background: #F4F4F4;       border-radius: 50%;       box-shadow: inset 0.1em 0.15em 0 0.37em #e2262e;     } 

这里通过::before 和 ::after 伪元素在兔子头部元素的前面或后面插入内容,头部前面绘制兔嘴,后面则插入兔子眼睛,之所以这样控制,是因为可以灵活的使用box-shadow填充颜色。

接着绘制耳朵:

.rabbit .rabbit__ear {       position: absolute;       border-radius: 50% 50% 50% 50%/40% 40% 60% 60%;       transform-origin: 50% 100%;     }     .rabbit .rabbit__ear--left {       width: 2.2em;       height: 4.7em;       top: -5.7em;       left: -0.2em;       background: #F3E3DE;       transform: rotate(60deg);       box-shadow: inset 0.3em -0.4em 0 -0.1em var(--theme-color,#c7d1ea);       -webkit-animation: ear-left 3s infinite ease-out;               animation: ear-left 3s infinite ease-out;     }     .rabbit .rabbit__ear--right {       width: 2em;       height: 4.7em;       top: -5.5em;       left: -0.7em;       background: var(--theme-color,#D2DAEE);       transform: rotate(20deg);       -webkit-animation: ear-right 3s infinite ease-out;               animation: ear-right 3s infinite ease-out;     }  @-webkit-keyframes ear-left {       0%, 20%, 100% {         transform: rotate(40deg);       }       10%, 30%, 80% {         transform: rotate(45deg);       }       90% {         transform: rotate(50deg);       }     }          @keyframes ear-left {       0%, 20%, 100% {         transform: rotate(40deg);       }       10%, 30%, 80% {         transform: rotate(45deg);       }       90% {         transform: rotate(50deg);       }     }     @-webkit-keyframes ear-right {       0%, 20%, 100% {         transform: rotate(10deg);       }       10%, 30%, 80% {         transform: rotate(5deg);       }       90% {         transform: rotate(0deg);       }     }     @keyframes ear-right {       0%, 20%, 100% {         transform: rotate(10deg);       }       10%, 30%, 80% {         transform: rotate(5deg);       }       90% {         transform: rotate(0deg);       }     }  

这里通过-webkit-animation属性让兔子左右耳在3秒内进行来回摆动,达到一种动态效果,注意左耳内侧颜色固定为:#F3E3DE,同时动画会影响元素的布局,需要注意元素的宽高。

最后就是四肢和尾巴:

.rabbit .rabbit__leg {       position: absolute;     }     .rabbit .rabbit__leg--one {       width: 0.8em;       height: 3em;       top: 2.3em;       left: 0.2em;       background: var(--theme-color,#c7d1ea);       border-radius: 50% 50% 50% 50%/30% 30% 70% 70%;       transform-origin: 50% 0%;       transform: rotate(15deg);     }     .rabbit .rabbit__leg--one:before {       content: "";       position: absolute;       width: 0.8em;       height: 0.5em;       top: 2.6em;       left: -0.2em;       background: #f3f6ff;       border-radius: 50% 50% 50% 50%/70% 70% 30% 30%;       transform: rotate(-10deg);     }     .rabbit .rabbit__leg--three {       width: 0.9em;       height: 3em;       top: 2.4em;       left: 0.7em;       background: var(--theme-color,#e1e6f4);       border-radius: 50% 50% 50% 50%/30% 30% 70% 70%;       transform-origin: 50% 0%;       transform: rotate(10deg);     }     .rabbit .rabbit__leg--three:before {       content: "";       position: absolute;       width: 0.8em;       height: 0.5em;       top: 2.6em;       left: -0.2em;       background: #f3f6ff;       border-radius: 50% 50% 50% 50%/70% 70% 30% 30%;       transform: rotate(-10deg);     }     .rabbit .rabbit__leg--two {       width: 2.6em;       height: 3.6em;       top: 1.7em;       left: 1.6em;       background: #c7d1ea;       border-radius: 50% 50% 50% 50%/50% 50% 50% 50%;       transform-origin: 50% 0%;       transform: rotate(10deg);     }     .rabbit .rabbit__leg--two:before {       content: "";       position: absolute;       width: 1.6em;       height: 0.8em;       top: 3.05em;       left: 0em;       background: #f3f6ff;       border-radius: 50% 50% 50% 50%/70% 70% 30% 30%;       transform: rotate(-10deg);     }     .rabbit .rabbit__leg--four {       width: 2.6em;       height: 3.6em;       top: 1.8em;       left: 2.1em;       background: var(--theme-color,#e1e6f4);       border-radius: 50% 50% 50% 50%/50% 50% 50% 50%;       transform-origin: 50% 0%;       transform: rotate(10deg);     }     .rabbit .rabbit__leg--four:before {       content: "";       position: absolute;       width: 1.6em;       height: 0.8em;       top: 3.05em;       left: 0em;       background: #f3f6ff;       border-radius: 50% 50% 50% 50%/70% 70% 30% 30%;       transform: rotate(-10deg);     }     .rabbit .rabbit__tail {       position: absolute;       width: 0.9em;       height: 0.9em;       top: 3.7em;       left: 4em;       background: var(--theme-color,#D2DAEE);       transform: rotate(25deg);     }     .rabbit .rabbit__tail:after, .rabbit .rabbit__tail:before {       content: "";       position: absolute;       width: 100%;       height: 100%;       background: var(--theme-color,#D2DAEE);       border-radius: 50%;     }     .rabbit .rabbit__tail:before {       top: 0;       left: -50%;     }     .rabbit .rabbit__tail:after {       top: 50%;       left: 0;     } 

这里四肢和四爪的颜色应该有差异,四肢颜色可以自定义,四爪固定为白色,以达到“四蹄踏雪”的效果。

接着改造初始化函数,使其可以动态更改颜色:

function rabbit_init(color=null,pos=null){          var container = document.getElementById("rabbit_box");          container.innerHTML = '<div class="rabbit"><div class="rabbit__leg rabbit__leg--one"></div><div class="rabbit__leg rabbit__leg--two"></div><div class="rabbit__tail"></div><div class="rabbit__body"></div><div class="rabbit__leg rabbit__leg--three"></div><div class="rabbit__leg rabbit__leg--four"></div><div class="rabbit__ear rabbit__ear--right"></div><div class="rabbit__head"></div><div class="rabbit__ear rabbit__ear--left"></div></div>';          if(color != null){              document.documentElement.style.setProperty("--theme-color",color);          }       if(pos != null){              document.documentElement.style.setProperty("--pos",pos);          }      }      rabbit_init("pink") 

最终效果:

云间玉兔,自出机抒,从零开始制作Web插件网页特效小兔子组件(小挂件widget),基于原生CSS/NPM

开源发布

现在我们将这个开源特效打包上线,首先创建项目目录:

mkdir rabbit 

随后将特效的样式CSS代码以及JS代码分别抽离出来:rabbit.css:

.rabbit {       position: relative;     }     .rabbit .rabbit__body {       width: 4em;       height: 5.6em;       background: #F4F4F4;       border-radius: 50% 50% 50% 50%/60% 60% 40% 40%;       transform: rotate(-40deg);       box-shadow: inset -2.3em -2.7em 0 0 var(--theme-color,#D2DAEE);     }     .rabbit .rabbit__head {       position: absolute;       width: 4em;       height: 4.6em;       top: -2.5em;       left: -2em;       background: var(--theme-color,#e1e6f4);       border-radius: 50% 50% 50% 50%/65% 60% 40% 35%;       transform: rotate(-120deg);       overflow: hidden;     }     .rabbit .rabbit__head:before {       content: "";       position: absolute;       width: 0.65em;       height: 0.5em;       top: -0.1em;       left: 1.8em;       background: #F97996;       border-radius: 50% 50% 50% 50%/30% 30% 70% 70%;       transform: rotate(130deg);     }     .rabbit .rabbit__head:after {       content: "";       position: absolute;       width: 1em;       height: 1em;       top: 1.5em;       left: 1.6em;       background: #F4F4F4;       border-radius: 50%;       box-shadow: inset 0.1em 0.15em 0 0.37em #e2262e;     }     .rabbit .rabbit__ear {       position: absolute;       border-radius: 50% 50% 50% 50%/40% 40% 60% 60%;       transform-origin: 50% 100%;     }     .rabbit .rabbit__ear--left {       width: 2.2em;       height: 4.7em;       top: -5.7em;       left: -0.2em;       background: #F3E3DE;       transform: rotate(60deg);       box-shadow: inset 0.3em -0.4em 0 -0.1em var(--theme-color,#c7d1ea);       -webkit-animation: ear-left 3s infinite ease-out;               animation: ear-left 3s infinite ease-out;     }     .rabbit .rabbit__ear--right {       width: 2em;       height: 4.7em;       top: -5.5em;       left: -0.7em;       background: var(--theme-color,#D2DAEE);       transform: rotate(20deg);       -webkit-animation: ear-right 3s infinite ease-out;               animation: ear-right 3s infinite ease-out;     }     .rabbit .rabbit__leg {       position: absolute;     }     .rabbit .rabbit__leg--one {       width: 0.8em;       height: 3em;       top: 2.3em;       left: 0.2em;       background: var(--theme-color,#c7d1ea);       border-radius: 50% 50% 50% 50%/30% 30% 70% 70%;       transform-origin: 50% 0%;       transform: rotate(15deg);     }     .rabbit .rabbit__leg--one:before {       content: "";       position: absolute;       width: 0.8em;       height: 0.5em;       top: 2.6em;       left: -0.2em;       background: #f3f6ff;       border-radius: 50% 50% 50% 50%/70% 70% 30% 30%;       transform: rotate(-10deg);     }     .rabbit .rabbit__leg--three {       width: 0.9em;       height: 3em;       top: 2.4em;       left: 0.7em;       background: var(--theme-color,#e1e6f4);       border-radius: 50% 50% 50% 50%/30% 30% 70% 70%;       transform-origin: 50% 0%;       transform: rotate(10deg);     }     .rabbit .rabbit__leg--three:before {       content: "";       position: absolute;       width: 0.8em;       height: 0.5em;       top: 2.6em;       left: -0.2em;       background: #f3f6ff;       border-radius: 50% 50% 50% 50%/70% 70% 30% 30%;       transform: rotate(-10deg);     }     .rabbit .rabbit__leg--two {       width: 2.6em;       height: 3.6em;       top: 1.7em;       left: 1.6em;       background: #c7d1ea;       border-radius: 50% 50% 50% 50%/50% 50% 50% 50%;       transform-origin: 50% 0%;       transform: rotate(10deg);     }     .rabbit .rabbit__leg--two:before {       content: "";       position: absolute;       width: 1.6em;       height: 0.8em;       top: 3.05em;       left: 0em;       background: #f3f6ff;       border-radius: 50% 50% 50% 50%/70% 70% 30% 30%;       transform: rotate(-10deg);     }     .rabbit .rabbit__leg--four {       width: 2.6em;       height: 3.6em;       top: 1.8em;       left: 2.1em;       background: var(--theme-color,#e1e6f4);       border-radius: 50% 50% 50% 50%/50% 50% 50% 50%;       transform-origin: 50% 0%;       transform: rotate(10deg);     }     .rabbit .rabbit__leg--four:before {       content: "";       position: absolute;       width: 1.6em;       height: 0.8em;       top: 3.05em;       left: 0em;       background: #f3f6ff;       border-radius: 50% 50% 50% 50%/70% 70% 30% 30%;       transform: rotate(-10deg);     }     .rabbit .rabbit__tail {       position: absolute;       width: 0.9em;       height: 0.9em;       top: 3.7em;       left: 4em;       background: var(--theme-color,#D2DAEE);       transform: rotate(25deg);     }     .rabbit .rabbit__tail:after, .rabbit .rabbit__tail:before {       content: "";       position: absolute;       width: 100%;       height: 100%;       background: var(--theme-color,#D2DAEE);       border-radius: 50%;     }     .rabbit .rabbit__tail:before {       top: 0;       left: -50%;     }     .rabbit .rabbit__tail:after {       top: 50%;       left: 0;     }          @-webkit-keyframes ear-left {       0%, 20%, 100% {         transform: rotate(40deg);       }       10%, 30%, 80% {         transform: rotate(45deg);       }       90% {         transform: rotate(50deg);       }     }          @keyframes ear-left {       0%, 20%, 100% {         transform: rotate(40deg);       }       10%, 30%, 80% {         transform: rotate(45deg);       }       90% {         transform: rotate(50deg);       }     }     @-webkit-keyframes ear-right {       0%, 20%, 100% {         transform: rotate(10deg);       }       10%, 30%, 80% {         transform: rotate(5deg);       }       90% {         transform: rotate(0deg);       }     }     @keyframes ear-right {       0%, 20%, 100% {         transform: rotate(10deg);       }       10%, 30%, 80% {         transform: rotate(5deg);       }       90% {         transform: rotate(0deg);       }     }        #rabbit_box{          position: fixed;       bottom: var(--pos,5%);        right: 35px;        z-index: 99;        border: none;        outline: none;        filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));        } 

rabbit.js代码:

(function (name, context, fn) {       if (typeof module != 'undefined' && module.exports) {           // Node 环境           module.exports = fn();       } else if (typeof context['define'] == 'function' && (context['define']['amd'] || context['define']['cmd'])) {           // Require.js 或 Sea.js 环境           define(fn);       } else {           // client 环境           context[name] = fn();       }   })('rabbit_init', this, function () {       return function (color=null,pos=null) {                         var container = document.getElementById("rabbit_box");          container.innerHTML = '<div class="rabbit"><div class="rabbit__leg rabbit__leg--one"></div><div class="rabbit__leg rabbit__leg--two"></div><div class="rabbit__tail"></div><div class="rabbit__body"></div><div class="rabbit__leg rabbit__leg--three"></div><div class="rabbit__leg rabbit__leg--four"></div><div class="rabbit__ear rabbit__ear--right"></div><div class="rabbit__head"></div><div class="rabbit__ear rabbit__ear--left"></div></div>';          if(color != null){              document.documentElement.style.setProperty("--theme-color",color);          }       if(pos != null){              document.documentElement.style.setProperty("--pos",pos);          }             }   }); 

保存在项目的lib目录。

首先将项目提交到Github: https://github.com/zcxey2911/rabbit

随后运行命令填写NPM配置:

npm init 

entry point 配置项填写你的入口文件:

entry point: ./lib/rabbit.js 

登录NPM账号,随后发布:

npm login   npm publish 

登录之前,最好将切换回默认源,否则无法登录:

npm config set registry=https://registry.npmjs.com 

发布成功后,查看发布内容:https://www.npmjs.com/package/rabbit-widget

开源库引入和使用

首先需要引入模块,可以使用 CDN 直接引入或者通过 NPM 包的形式安装。

直接引入:

<!-- https://cdn.jsdelivr.net/gh/zcxey2911/rabbit@v1.0.0/lib/rabbit.css -->   <!-- https://cdn.jsdelivr.net/gh/zcxey2911/rabbit@v1.0.0/lib/rabbit.js -->      <link     rel="stylesheet"     href="https://cdn.jsdelivr.net/gh/zcxey2911/rabbit@v1.0.0/lib/rabbit.css"   />      <div id="rabbit_box">   </div>      <script>      function init_rabbit(){       rabbit_init("pink","20%");  // 粉色 高度20%       //rabbit_init(); //默认颜色 默认位置      }      </script>         <script     async     onload="init_rabbit()"     src="https://cdn.jsdelivr.net/gh/zcxey2911/rabbit@v1.0.0/lib/rabbit.js"   ></script> 

NPM 包的形式安装:

// npm install --save rabbit-widget   import 'rabbit-widget/lib/rabbit.css';      var rabbit_init = require('rabbit-widget');      rabbit_init(); 

如果使用NPM导入模块的形式引入,请确保页面加载完毕之后执行再执行rabbit_init();,否则会报错:Uncaught TypeError: Cannot set properties of null (setting 'innerHTML')。

这里以Vue.js3.0组件为例子:

<template>     <a-layout class="layout">       <a-layout-header>         <div class="logo" />            <ad_header />                      </a-layout-header>       <a-layout-content style="padding: 0 50px">         <a-breadcrumb style="margin: 16px 0">           <a-breadcrumb-item>广告平台</a-breadcrumb-item>           <a-breadcrumb-item>首页</a-breadcrumb-item>            </a-breadcrumb>         <div :style="{ background: '#fff', padding: '24px', minHeight: '280px' }">                 这里是首页                 <div id="rabbit_box"></div>             </div>       </a-layout-content>       <a-layout-footer style="text-align: center">         在线广告平台       </a-layout-footer>     </a-layout>   </template>      <script>      import ad_header from './ad_header';      import 'rabbit-widget/lib/rabbit.css';      var rabbit_init = require('rabbit-widget');         export default {    data() {       return {                     }     },     //声明子组件     components:{          'ad_header':ad_header           },     methods:{                    },     created(){             this.$nextTick(() => {       console.log("页面加载完啦~")          rabbit_init();   })           }      }   </script>   <style>   .site-layout-content {     min-height: 280px;     padding: 24px;     background: #fff;   }   #components-layout-demo-top .logo {     float: left;     width: 120px;     height: 31px;     margin: 16px 24px 16px 0;     background: rgba(255, 255, 255, 0.3);   }   .ant-row-rtl #components-layout-demo-top .logo {     float: right;     margin: 16px 0 16px 24px;   }      [data-theme='dark'] .site-layout-content {     background: #141414;   }   </style> 

项目中引入效果:

云间玉兔,自出机抒,从零开始制作Web插件网页特效小兔子组件(小挂件widget),基于原生CSS/NPM

结语

奉上项目代码,与众亲同飨:https://github.com/zcxey2911/rabbit https://www.npmjs.com/package/rabbit-widget ,最后祝各位乡亲祥瑞玉兔,人机平安,愿诸君2023年武运昌隆,前端一统。