前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从零开始制作Web插件网页特效小兔子组件(小挂件widget),基于原生CSS/NPM

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

作者头像
用户9127725
发布2023-01-13 13:55:45
6120
发布2023-01-13 13:55:45
举报

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

    玉兔主题元素绘制

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

代码语言:javascript
复制
<div id="rabbit_box">
  


</div>

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

代码语言:javascript
复制
#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滤镜,可以让玉兔更加立体。

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

代码语言:javascript
复制
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样式:

代码语言:javascript
复制
.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。

    接着绘制头部:

代码语言:javascript
复制
.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填充颜色。

    接着绘制耳朵:

代码语言:javascript
复制
.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,同时动画会影响元素的布局,需要注意元素的宽高。

    最后就是四肢和尾巴:

代码语言:javascript
复制
.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;
  }

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

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

代码语言:javascript
复制
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")

    最终效果:

   开源发布

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

代码语言:javascript
复制
mkdir rabbit

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

代码语言:javascript
复制
.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代码:

代码语言:javascript
复制
(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配置:

代码语言:javascript
复制
npm init

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

代码语言:javascript
复制
entry point: ./lib/rabbit.js

    登录NPM账号,随后发布:

代码语言:javascript
复制
npm login
npm publish

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

代码语言:javascript
复制
npm config set registry=https://registry.npmjs.com

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

   开源库引入和使用

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

    直接引入:

代码语言:javascript
复制
<!-- 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 包的形式安装:

代码语言:javascript
复制
// 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组件为例子:

代码语言:javascript
复制
<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>

    项目中引入效果:

    结语

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-01-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  •     玉兔主题元素绘制
  •    开源发布
  •    开源库引入和使用
  •     结语
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档