玉兔和云怎么画(云间玉兔,自出机抒,从零开始制作Web插件网页特效小兔子组件(小挂件widget),基于原生CSS/NPM)
著意登楼瞻玉兔 ,何人张幕遮银阙?又到了一年一度的网页小挂件环节 ,以往我们都是集成别人开源的组件 ,但所谓熟读唐诗三百首 ,不会做诗也会吟 ,熟读了别人的东西 ,做几首打油诗也是可以的 ,但若不能自出机抒 ,却也成不了大事 ,所以本次我们从零开始制作属于自己的网页小挂件 ,博君一晒 。
玉兔主题元素绘制
成本最低的绘制方式是使用纯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")最终效果:
开源发布
现在我们将这个开源特效打包上线 ,首先创建项目目录:
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 initentry 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> <a-breadcrumb> <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> 在线广告平台 </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年武运昌隆 ,前端一统 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!