【项目实战】Vue自定义指令-水波纹效果&水印效果(三)

1,911 阅读4分钟

【专栏-效率工具】系列文章,从开发工具、版本控制工具、接口调试工具 到 开发规范,再到博客搭建工具等等,工作学习中用到的工具,分别一一作了介绍,养成习惯,提高开发效率。

记录提高日常码字幸福感的【实测能用】自用效率工具,持续更新、记录

仅当参考,按需食用,不足之处,欢迎各路大佬不吝赐教,补充完善,欢迎分享

  • 工欲善其事,必先利其器。实践(巧偷懒)促进科技发展-_-!
  • 本文及后续更文将为大家分享日常开发用到的一些工具函数,总结的样式,代码规范(CodeStyle),代码段等。为刚融入团队的新同学可以迅速 follow 团队的开发规范,快速融入到项目开发中,提高我们的工作效率,减少累赘代码,提高代码质量,减少bug.
  • 这里接着昨天更文 Vue 自定义指令(二) 继续为大家分享学习一些 Vue 自定义指令代码段: Vue-Directives

自定义指令(二) Vue Directives

① 统一注册指令 抽离模块,方便管理

  1. 引入指令 && 注册指令
// directives/index.js
import copy from './copy'
import color from './color'
import emoji from './emoji'
import waves from './waves'
import debounce from './debounce'
import lazyLoad from './lazyLoad'
import draggable from './draggable'
import longpress from './longpress'
import permission from './permission'
import waterMarker from './waterMarker'
...

// 自定义指令 对象,方便注册
const directives = {
  copy,
  color,
  emoji,
  waves,
  debounce,
  lazyLoad,
  longpress,
  draggable,
  permission,
  waterMarker,
  ...
}
// >--> 批量注册指令
export default {
  install(Vue) {
    Object.keys(directives).forEach((key) => {
      Vue.directive(key, directives[key])
    })
  }
}
  1. 指令在逻辑 js 文件中已注册,然后在 main.js 中引入 use 即可
// main.js
import install from './directives'
Vue.use(install)

三、点击水波纹指令 v-waves

3.1 效果

这个效果用的挺多的吧,先上效果图,请看

v-waves-xn213

3.2 具体逻辑如下:

js

// src/directives/waves.js
import './waves.css'

export default {
  bind(el, binding) {
    el.addEventListener(
      'click',
      (e) => {
        const customOpts = Object.assign({}, binding.value)
        const opts = Object.assign(
          {
            ele: el, // 波纹作用的目标元素
            type: 'hit', // hit 点击位置扩散 center中心点扩展
            // color: '#b45dea', // 波纹颜色
            color: 'rgba(0, 0, 0, 0.15)', // 波纹颜色
          },
          customOpts
        )
        const target = opts.ele
        if (target) {
          target.style.position = 'relative'
          target.style.overflow = 'hidden'
          const rect = target.getBoundingClientRect()
          let ripple = target.querySelector('.waves-ripple')
          if (!ripple) {
            ripple = document.createElement('span')
            ripple.className = 'waves-ripple'
            ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
            target.appendChild(ripple)
          } else {
            ripple.className = 'waves-ripple'
          }
          switch (opts.type) {
            case 'center':
              ripple.style.top = rect.height / 2 - ripple.offsetHeight / 2 + 'px'
              ripple.style.left = rect.width / 2 - ripple.offsetWidth / 2 + 'px'
              break
            default:
              ripple.style.top =
                (e.pageY -
                  rect.top -
                  ripple.offsetHeight / 2 -
                  document.documentElement.scrollTop || document.body.scrollTop) + 'px'
              ripple.style.left =
                (e.pageX -
                  rect.left -
                  ripple.offsetWidth / 2 -
                  document.documentElement.scrollLeft || document.body.scrollLeft) + 'px'
          }
          ripple.style.backgroundColor = opts.color
          ripple.className = 'waves-ripple z-active'
          return false
        }
      },
      false
    )
  },
}

3.3 CSS 样式: src/directives/waves.css

涉及到样式兼容,比较多,可根据兼容需求自行省去

/** src/directives/waves.css */
.waves-ripple {
  position: absolute;
  border-radius: 100%;
  background-color: rgba(0, 0, 0, 0.15);
  background-clip: padding-box;
  pointer-events: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -webkit-transform: scale(0);
  -ms-transform: scale(0);
  transform: scale(0);
  opacity: 1;
}

.waves-ripple.z-active {
  opacity: 0;
  -webkit-transform: scale(2);
  -ms-transform: scale(2);
  transform: scale(2);
  -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
  transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
  transition: opacity 1.2s ease-out, transform 0.6s ease-out;
  transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
}

3.4 使用:

使用特别简单,只需在容器标签上加上 v-waves 即可:

<div v-waves style="width: 213px;height: 100px">test v-waves</div>

四、 指定 div 添加指定内容样式水印 v-waterMark

4.1 具体逻辑

这里作简单的逻辑介绍, 通过 canvas 绘制 传入内容控制水印的内容,

此方案使用 canvas 绘制水印图片 添加到背景, 可在控制台取消 仅作实践

具体逻辑如下:

// directives/permission.js
//! 此方案使用 canvas 绘制水印图片 添加到背景, 可在控制台取消 仅作为学习实践

function addWaterMarker(str, parentNode, font, textColor) {
  // 水印文字,父元素,字体,文字颜色
  var canvas = document.createElement('canvas')
  parentNode.appendChild(canvas)
  canvas.width = 200
  canvas.height = 150
  canvas.style.display = 'none'
  var cvs = canvas.getContext('2d')
  cvs.rotate((-20 * Math.PI) / 180)
  cvs.font = font || '16px Microsoft JhengHei'
  cvs.fillStyle = textColor || 'rgba(180, 180, 180, 0.3)'
  cvs.textAlign = 'left'
  cvs.textBaseline = 'Middle'
  cvs.fillText(str, canvas.width / 10, canvas.height / 2)
  parentNode.style.backgroundImage = 'url(' + canvas.toDataURL('image/png') + ')'
}

const waterMarker = {
  bind: function (el, binding) {
    addWaterMarker(binding.value.text, el, binding.value.font, binding.value.textColor)
  },
}

export default waterMarker

4.2 注册: main.js

import install from './directives'
Vue.use(install)

4.3 使用:

昨天更文中有一个截图就用到了这个指令,如下图:

v-perssion-btn

<!-- 这是个容器,在这上面使用指令,则给此容器加上水印 -->

<div v-waterMarker="{text:'这里是水印',textColor:'red'}">
  <h1>1. test v-watermarker</h1>
</div>

<div v-waterMarker="{text:'版权所有 ©xn213',textColor:'blue'}">
  <h1>2. test v-watermarker</h1>
</div>

4.4 水印效果:

同一页面,不同容器定制显示不同水印内容:

v-watermarker-1


这里列举部分自定义指令仅作参考学习,抛砖引玉, 其他文章: 【效率工具】【接口调试工具-Insomnia】

优化美丽舒适的开发环境

下一代接口模拟工具-mock service worker

【Utils】那些常用的 JavaScript 工具函数(一)...-,-、

有没有 get 到呢?

欢迎各路大神评论出你的私藏工具, 把你的好用的【效率工具】分享给大家=,=

今日份预告不出来了:

明天继续更新技术文 分享一些积累的 codesutils/components/styles 等等吧

下一篇敬请期待! hahah~