镂空的波浪动画组件

10356次阅读 940人点赞 作者: WuBin 发布时间: 2021-09-15 17:05:59
扫码到手机查看

花式组件库

组件库:fancy-components,翻译过来就是花式组件库。光听名字也能猜得到:这不是像Element UIAnt Design那类组件库一样,而是能够为我们提供一些较为复杂样式的组件库。

首先这是一款基于web components的组件库,无论你是vuereactangular还是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;

相关资料

点赞 支持一下 觉得不错?客官您就稍微鼓励一下吧!
关键词:fancy-components
推荐阅读
  • uniapp实现被浏览器唤起的功能

    当用户打开h5链接时候,点击打开app若用户在已经安装过app的情况下直接打开app,若未安装过跳到应用市场下载安装这个功能在实现上主要分为两种场景,从普通浏览器唤醒以及从微信唤醒。

    9094次阅读 588人点赞 发布时间: 2022-12-14 16:34:53 立即查看
  • Vue

    盘点Vue2和Vue3的10种组件通信方式

    Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异;本文将通过选项式API组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式。

    3843次阅读 286人点赞 发布时间: 2022-08-19 09:40:16 立即查看
  • JS

    几个高级前端常用的API

    推荐4个前端开发中常用的高端API,分别是MutationObserver、IntersectionObserver、getComputedstyle、getBoundingClientRect、requ...

    14071次阅读 914人点赞 发布时间: 2021-11-11 09:39:54 立即查看
  • PHP

    【正则】一些常用的正则表达式总结

    在日常开发中,正则表达式是非常有用的,正则表达式在每个语言中都是可以使用的,他就跟JSON一样,是通用的。了解一些常用的正则表达式,能大大提高你的工作效率。

    12908次阅读 442人点赞 发布时间: 2021-10-09 15:58:58 立即查看
  • 【中文】免费可商用字体下载与考证

    65款免费、可商用、无任何限制中文字体打包下载,这些字体都是经过长期验证,经得住市场考验的,让您规避被无良厂商起诉的风险。

    11469次阅读 920人点赞 发布时间: 2021-07-05 15:28:45 立即查看
  • Vue

    Vue3开发一个v-loading的自定义指令

    在vue3中实现一个自定义的指令,有助于我们简化开发,简化复用,通过一个指令的调用即可实现一些可高度复用的交互。

    15588次阅读 1244人点赞 发布时间: 2021-07-02 15:58:35 立即查看
  • JS

    关于手机上滚动穿透问题的解决

    当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。在PC上使用css即可解决,但是在手机端,情况就变的比较复杂,就需要禁止触摸事件才可以。

    14795次阅读 1205人点赞 发布时间: 2021-05-31 09:25:50 立即查看
  • Vue

    Vue+html2canvas截图空白的问题

    在使用vue做信网单页专题时,有海报生成的功能,这里推荐2个插件:一个是html2canvas,构造好DOM然后转canvas进行截图;另外使用vue-canvas-poster(这个截止到2021年3月...

    28950次阅读 2273人点赞 发布时间: 2021-03-02 09:04:51 立即查看
  • Vue

    vue-router4过度动画无效解决方案

    在初次使用vue3+vue-router4时候,先后遇到了过度动画transition进入和退出分别无效的情况,搜遍百度没没找到合适解决方法,包括vue-route4有一些API都进行了变化,以前的一些操...

    24982次阅读 1925人点赞 发布时间: 2021-02-23 13:37:20 立即查看
交流 收藏 目录