镂空的波浪动画组件
花式组件库
组件库:fancy-components,翻译过来就是花式组件库。光听名字也能猜得到:这不是像Element UI
、Ant Design
那类组件库一样,而是能够为我们提供一些较为复杂样式的组件库。
首先这是一款基于web components的组件库,无论你是vue
、react
、angular
还是svelte
等一些其他框架,它都能良好的与这些框架共存,因为这就是JS
原生的组件化技术。
现如今已经有很多组件库都采用了web components作为底层技术,已经可以看到这种趋势了。只不过web components在国内很少被人谈起,所以那些在国外还不错的一些组件库也就没能传到大家的耳朵里。
就连新发布的Vue3.2
也出了一个defineCustomElement方法,就是为了专门用来生成自定义元素(web components的其中一项技术)的。目前已经有趋势表明这门技术未来将会大展身手,以前它没能火起来的主要原因就是兼容性问题。
在普通项目中使用
普通项目指的是那种直接在文件夹里建个HTML
文件就开始写代码的那种项目,没有什么工程化、webpack、babel这些花里胡哨的东西。我们新建个HTML
然后在<script>
标签中写上type="module"
就能使用模块化的语法来加载fancy-components啦:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>公众号:前端学不动</title>
<style>
* {
padding: 0;
margin: 0;
}
html, body {
height: 100%;
display: grid;
place-items: center;
}
fc-wave-filter {
--width: 100px;
}
/* :defined 选择器会选择到已定义的元素 */
/* 但却没有 :undefined 这样的选择器 所以只能用 :not() 选择器来配合使用 */
/* 这个选择器具体是干嘛用的 可以B站搜索:前端学不动 这位up主 */
/* 找到他的《自定义元素基础篇》在第 17:25 的位置有讲 */
:not(:defined) {
display: none;
}
</style>
</head>
<body>
<!-- 需要在<fc-wave-filter>里指定color这个属性 默认为黑色 -->
<fc-wave-filter color="#047">
<!-- 在这里(slot里)放入img图片 -->
<img src="data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaWNvbiIgc3R5bGU9IndpZHRoOjFlbTtoZWlnaHQ6MWVtO3ZlcnRpY2FsLWFsaWduOm1pZGRsZSIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBmaWxsPSJjdXJyZW50Q29sb3IiIG92ZXJmbG93PSJoaWRkZW4iPjxwYXRoIGQ9Ik0yNjQuMTI5IDI2MS4yNjJjNS4wMjUtNS45NCA0LjI4NS0xNS4yNS0zLjAwOS0yMS40MS02LjQ3NS01LjQzNS0xNi4wODUtMy45MzgtMjAuMzU0IDEuMTk4bC0zOC4wNzcgNDUuMzIzIDIzLjY2MiAxOS44NjYgMzcuNzc4LTQ0Ljk3N3ptLTQzLjkzNy01MC4wMTljLTYuMTQ0LTUuMTA0LTE1LjU2NS01LjI3Ny0xOS43ODctLjMxNWwtMzYuMjAzIDQzLjE2NiAyMi40MDIgMTguNzk0IDM1Ljc5My00Mi42NjFjNC41MzctNS4zNTcgNC41MDYtMTMuMzQ0LTIuMjA1LTE4Ljk4NHptNTY2LjQxMyAxMzUuODE0bC0yMi40NDktMjcuOTE2IDQ0LjcyNS02NS4zNzgtLjI4My0uMzE1LTczLjIwOCAzMC4xMjEtMjIuNjg2LTI3Ljc1OCA3Ny40OTMtOTkuNzIyIDE5LjEyNSAyMy42My00OC41MjIgNjMuNTA1IDc0LjE4NS0zMS44NyAyMC41MTIgMjUuMzYzLTQ2LjU2OSA2NS45MyA3Mi4yLTM0LjI4IDE5LjEyNiAyMy41OTktMTEzLjY0OSA1NS4wOTF6TTUwNy4xNjQgODA3LjAzOGMtMTY1LjYwNSAwLTI5OS44NzUtMTM0LjI1NC0yOTkuODc1LTI5OS44NzQgMC0xNjUuNTczIDEzNC4yNy0yOTkuODQzIDI5OS44NzUtMjk5Ljg0MyAxNjUuNjIgMCAyOTkuODc0IDEzNC4yNTQgMjk5Ljg3NCAyOTkuODQzIDAgMTY1LjYyLTEzNC4yNTQgMjk5Ljg3NC0yOTkuODc0IDI5OS44NzR6TTEyNi45MjkgMjY0Ljk4bDYwLjI5LTcxLjgyMmMxMi41MDgtMTQuODg3IDI5Ljk2NC0yNi43ODIgNDYuNTUyLTEyLjg0IDUuMTA1IDQuMjcgNy4yOTQgNS42ODggMTMuNTAxIDE3LjA0NiAxLjQ2NSA0LjAwMiAyLjU4NCAxMS4yOTYtLjE4OSAxOC40NDggMTQuNDE1LTguOTY0IDI5Ljc5LTYuMDM0IDM5LjcxNiAzLjYyMyAxNS4yODEgMTQuODU2IDEzLjA2IDMxLjk5Ni0xLjQ2NSA0OS4zMjZsLTYzLjU4MyA3NS43NzYtOTQuODIyLTc5LjU1N3ptMzExLjYxLTIwMy4yNTZoMzcuMjI3bDMzLjYxOSA4OCAzMy42MTktODhoMzcuMTYzdjEyMy41NzNoLTI0LjczNHYtODYuM2wtMzIuNTQ3IDg2LjNoLTI3LjA1bC0zMi40ODQtODYuM3Y4Ni4zSDQzOC41NFY2MS43MjR6bTY4LjYyNS0yMy45OTRDMjQ3LjkxOCAzNy43MyAzNy43MyAyNDcuOTE4IDM3LjczIDUwNy4xNjRjMCAyNTkuMjc2IDIxMC4xODggNDY5LjQ4IDQ2OS40MzQgNDY5LjQ4IDI1OS4zMDggMCA0NjkuNDgtMjEwLjIwNCA0NjkuNDgtNDY5LjQ2NVM3NjYuNDcyIDM3LjcxNSA1MDcuMTY0IDM3LjcxNXptMCA3NDkuOTk0YzE1NC45ODYgMCAyODAuNjA3LTEyNS41OSAyODAuNjA3LTI4MC41Nkg1MDcuMTY0Vjc4Ny43NHptLTI4MC41NzYtMjgwLjU2aDI4MC41NzZWMjI2LjYxOWMtMTU0Ljk3MSAwLTI4MC41NzYgMTI1LjYwNS0yODAuNTc2IDI4MC41NDV6bTI4MC41NzYgNDg5LjYzYy0yNjkuOTU4IDAtNDg5LjY0Ni0yMTkuNjU3LTQ4OS42NDYtNDg5LjYzIDAtMjY5Ljk1OCAyMTkuNjg4LTQ4OS42MyA0ODkuNjQ2LTQ4OS42MyAyNzAuMDA1IDAgNDg5LjY0NSAyMTkuNjcyIDQ4OS42NDUgNDg5LjYzIDAgMjY5Ljk3My0yMTkuNjQgNDg5LjYzLTQ4OS42NDUgNDg5LjYzem0wLTk5Ni43OTRDMjI3LjUgMCAwIDIyNy41MDEgMCA1MDcuMTY0YzAgMjc5LjY2MiAyMjcuNTAxIDUwNy4xOTUgNTA3LjE2NCA1MDcuMTk1IDI3OS42OTMgMCA1MDcuMTc5LTIyNy41MzMgNTA3LjE3OS01MDcuMTk1QzEwMTQuMzQzIDIyNy41IDc4Ni44NTcgMCA1MDcuMTYzIDB6IiBmaWxsPSIjQjlCRUMzIi8+PC9zdmc+" />
</fc-wave-filter>
<script type="module">
// 从 fancy-components 中引入 FcWaveFilter(波浪滤镜)
import { FcWaveFilter } from 'https://unpkg.com/fancy-components'
// new 就相当于全局注册了这个组件,相当于 Vue 的 Vue.component('fc-wave-filter', FcWaveFilter)
new FcWaveFilter()
</script>
</body>
</html>
在线运行效果http://code.wubin.work/code/vue/bolang-logo/
在线的库:http://code.wubin.work/code/vue/bolang-logo/facy-components/index.js
在Vue中使用
vue2
Vue
组件既可以写成大写字母开头的驼峰形式,又可以写成小写字母开头的短横线形式。那么问题来了:当我们写了一个短横线连接的组件时,它怎么知道我们写的到底是组件还是标签呢?
它的做法是把所有HTML
以及SVG
标签全列举出来,只要你写的标签不在这个范围内,那么就默认你是组件了,如果你还没有在components
里注册过,那么就会在控制台打印一个警告。所以我们要告诉Vue
:对我这个既不在HTML
标签范围内,又不在SVG
标签范围内,同时还不是Vue
组件的标签来说就不要给我报警告啦,我确定一定以及肯定这不是个错误!
npm i fancy-components 安装
import Vue from 'vue'
import App from './App'
import { FcWaveFilter } from 'fancy-components'
/* eslint-disable no-new */
new FcWaveFilter()
new Vue({
render: h => h(App)
}).$mount('#app')
然后用Vue.config
来配置需要忽略哪些标签:
import Vue from 'vue'
import App from './App'
import { FcWaveFilter } from 'fancy-components'
/* eslint-disable no-new */
new FcWaveFilter()
// 配置忽略以 fc- 作为开头的元素
Vue.config.ignoredElements = [/^fc-/]
new Vue({
render: h => h(App)
}).$mount('#app')
在用的时候(xxx.vue):
<template>
<fc-wave-filter color="#047">
<img src="data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaWNvbiIgc3R5bGU9IndpZHRoOjFlbTtoZWlnaHQ6MWVtO3ZlcnRpY2FsLWFsaWduOm1pZGRsZSIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBmaWxsPSJjdXJyZW50Q29sb3IiIG92ZXJmbG93PSJoaWRkZW4iPjxwYXRoIGQ9Ik0yNjQuMTI5IDI2MS4yNjJjNS4wMjUtNS45NCA0LjI4NS0xNS4yNS0zLjAwOS0yMS40MS02LjQ3NS01LjQzNS0xNi4wODUtMy45MzgtMjAuMzU0IDEuMTk4bC0zOC4wNzcgNDUuMzIzIDIzLjY2MiAxOS44NjYgMzcuNzc4LTQ0Ljk3N3ptLTQzLjkzNy01MC4wMTljLTYuMTQ0LTUuMTA0LTE1LjU2NS01LjI3Ny0xOS43ODctLjMxNWwtMzYuMjAzIDQzLjE2NiAyMi40MDIgMTguNzk0IDM1Ljc5My00Mi42NjFjNC41MzctNS4zNTcgNC41MDYtMTMuMzQ0LTIuMjA1LTE4Ljk4NHptNTY2LjQxMyAxMzUuODE0bC0yMi40NDktMjcuOTE2IDQ0LjcyNS02NS4zNzgtLjI4My0uMzE1LTczLjIwOCAzMC4xMjEtMjIuNjg2LTI3Ljc1OCA3Ny40OTMtOTkuNzIyIDE5LjEyNSAyMy42My00OC41MjIgNjMuNTA1IDc0LjE4NS0zMS44NyAyMC41MTIgMjUuMzYzLTQ2LjU2OSA2NS45MyA3Mi4yLTM0LjI4IDE5LjEyNiAyMy41OTktMTEzLjY0OSA1NS4wOTF6TTUwNy4xNjQgODA3LjAzOGMtMTY1LjYwNSAwLTI5OS44NzUtMTM0LjI1NC0yOTkuODc1LTI5OS44NzQgMC0xNjUuNTczIDEzNC4yNy0yOTkuODQzIDI5OS44NzUtMjk5Ljg0MyAxNjUuNjIgMCAyOTkuODc0IDEzNC4yNTQgMjk5Ljg3NCAyOTkuODQzIDAgMTY1LjYyLTEzNC4yNTQgMjk5Ljg3NC0yOTkuODc0IDI5OS44NzR6TTEyNi45MjkgMjY0Ljk4bDYwLjI5LTcxLjgyMmMxMi41MDgtMTQuODg3IDI5Ljk2NC0yNi43ODIgNDYuNTUyLTEyLjg0IDUuMTA1IDQuMjcgNy4yOTQgNS42ODggMTMuNTAxIDE3LjA0NiAxLjQ2NSA0LjAwMiAyLjU4NCAxMS4yOTYtLjE4OSAxOC40NDggMTQuNDE1LTguOTY0IDI5Ljc5LTYuMDM0IDM5LjcxNiAzLjYyMyAxNS4yODEgMTQuODU2IDEzLjA2IDMxLjk5Ni0xLjQ2NSA0OS4zMjZsLTYzLjU4MyA3NS43NzYtOTQuODIyLTc5LjU1N3ptMzExLjYxLTIwMy4yNTZoMzcuMjI3bDMzLjYxOSA4OCAzMy42MTktODhoMzcuMTYzdjEyMy41NzNoLTI0LjczNHYtODYuM2wtMzIuNTQ3IDg2LjNoLTI3LjA1bC0zMi40ODQtODYuM3Y4Ni4zSDQzOC41NFY2MS43MjR6bTY4LjYyNS0yMy45OTRDMjQ3LjkxOCAzNy43MyAzNy43MyAyNDcuOTE4IDM3LjczIDUwNy4xNjRjMCAyNTkuMjc2IDIxMC4xODggNDY5LjQ4IDQ2OS40MzQgNDY5LjQ4IDI1OS4zMDggMCA0NjkuNDgtMjEwLjIwNCA0NjkuNDgtNDY5LjQ2NVM3NjYuNDcyIDM3LjcxNSA1MDcuMTY0IDM3LjcxNXptMCA3NDkuOTk0YzE1NC45ODYgMCAyODAuNjA3LTEyNS41OSAyODAuNjA3LTI4MC41Nkg1MDcuMTY0Vjc4Ny43NHptLTI4MC41NzYtMjgwLjU2aDI4MC41NzZWMjI2LjYxOWMtMTU0Ljk3MSAwLTI4MC41NzYgMTI1LjYwNS0yODAuNTc2IDI4MC41NDV6bTI4MC41NzYgNDg5LjYzYy0yNjkuOTU4IDAtNDg5LjY0Ni0yMTkuNjU3LTQ4OS42NDYtNDg5LjYzIDAtMjY5Ljk1OCAyMTkuNjg4LTQ4OS42MyA0ODkuNjQ2LTQ4OS42MyAyNzAuMDA1IDAgNDg5LjY0NSAyMTkuNjcyIDQ4OS42NDUgNDg5LjYzIDAgMjY5Ljk3My0yMTkuNjQgNDg5LjYzLTQ4OS42NDUgNDg5LjYzem0wLTk5Ni43OTRDMjI3LjUgMCAwIDIyNy41MDEgMCA1MDcuMTY0YzAgMjc5LjY2MiAyMjcuNTAxIDUwNy4xOTUgNTA3LjE2NCA1MDcuMTk1IDI3OS42OTMgMCA1MDcuMTc5LTIyNy41MzMgNTA3LjE3OS01MDcuMTk1QzEwMTQuMzQzIDIyNy41IDc4Ni44NTcgMCA1MDcuMTYzIDB6IiBmaWxsPSIjQjlCRUMzIi8+PC9zdmc+" />
</fc-wave-filter>
</template>
<script>
export default {
components: {
// 不需要在这里进行注册 就把 <fc-wave-filter> 当成一个浏览器原生标签就行
}
}
</script>
vue3中
Vue3 在写法上出现了很大的变化,没有Vue
了,取而代之的是app
:
import { createApp } from 'vue'
import App from './App'
import { FcWaveFilter } from 'fancy-components'
/* eslint-disable no-new */
new FcWaveFilter()
createApp(App).mount('#app')
Vue3处理起来相对要稍微麻烦一点,我们需要在根目录下的vue.config.js中(如果没有就自己新建一个):
module.exports = {
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
options.compilerOptions = {
...(options.compilerOptions || {}),
isCustomElement: tag => tag.startsWith('fc-')
}
return options
})
}
}
这样就可以啦!
基础用法
假设我们已经npm i fancy-components
安装过了,并且已经在主文件(main.js或index.js)注册过了:
import { FcWaveFilter } from 'fancy-components'
/* eslint-disable no-new */
new FcWaveFilter() // 相当于全局注册了组件 注:web components 没有局部注册组件这一说
而且如果是Vue
项目也已经配置过了忽略fc-
开头的web components了的话,那么我们只需要用<fc-wave-filter>
来包裹住一张浅灰色的(最好是纯色)镂空图片:
<template>
<fc-wave-filter>
<img src="xxx.png" />
</fc-wave-filter>
</template>
<style scoped>
fc-wave-filter {
--color: #dd1028;
}
</style>
除了在<fc-wave-filter>
标签里写color
属性,我们还可以在CSS
里写--color
属性:
效果也是一样的。不过有些人可能不太明白为什么要用--color
而不是color
属性,这是因为color
属性是控制字体颜色的,它控制不了我们的填充颜色。而前面带--
的属性叫自定义属性,是fancy-components内部为我们封装好要在哪用这个自定义属性的,自定义属性也叫CSS变量,如果不太清楚什么是CSS变量的话可以点击这个链接学习一下。
标签内的color
属性比--color
这个CSS变量的优先级要高,这两种写法最好不要混用。
更多的用法以及原理请参考下面的链接,这里再列举一些支持的API属性:
属性 | 中文含义 | 可选值 | 默认值 |
---|---|---|---|
color | 填充颜色 | 正常的CSS颜色值 | 'black' |
dur | 动画时长 | 大于0的数字(单位为秒) | 3 |
amplitude | 波浪幅度 | 数字(原波浪幅的倍数) | 1 |
delay | 填充后持续的时间 | 大于0的数字(单位为秒) | 0 |
mode | 动画模式 | 'alpha'(透明度)、'luminance'(亮度)、'img'(图片)、'slideshow'(幻灯片) | 'alpha' |
interval | 几秒一切换(适合幻灯片模式) | 大于0的数字(单位为秒) | 0 |
CSS属性 | 中文含义 | 可选值 | 默认值 |
---|---|---|---|
--color | 填充颜色 | 正常的CSS颜色值 | black |
--width | 组件的宽度 | 正常的CSS宽度值 | fit-content |
--height | 组件的高度 | 正常的CSS高度值 | 无 |
webkit-mask背景镂空
先来看一下案例效果:http://code.wubin.work/code/vue/bolang-logo/
我们想让这个图片变个形状,就变成桃心❤️状吧!那么我们先需要准备一张❤️心形图片, 注意这张图片需要是镂空的png
格式,就是心的那部分不透明,其他部分都透明,如链接:http://code.wubin.work/code/vue/bolang-logo/mask-bg.png
然后这样写代码:
<div>
<img src="girl.png" />
</div>
<style scoped>
img {
-webkit-mask: url(xxx/heart.png);
-webkit-mask-repeat: no-repeat;
}
</style>
注意,要想成功看到效果,必须要在服务器环境下查看,如果在本地环境,那么浏览器会报错。
因为mask
是一个类似于background
的属性,默认会平铺,如果不想平铺的话,要加上-webkit-mask-repeat: no-repeat;