工作中老是会使用到一些常用的工具函数,如对象克隆,文件流下载等,每次都重新写就很烦还浪费时间,直接影响下班时间,今儿记录一下个人平时常用的一些工具函数。
文章目录
- 判断是否为IE浏览器
- 判断是否为全屏显示
- 退出全屏
- 全屏显示
- 触发window.resize事件
- 文件流下载
- 文件压缩
- 导出Excel
- crypto-js加密解密
- 判断原始类型,Object.prototype.toString.apply([]) '[object Array]'
- 对象深度拷贝
- 对象深度拷贝方案二
- 数据校验
- 时间转换
- 获取某月共有多少天
- 数组对象去重
- 防抖
- 节流
- 多维数组扁平化
- 数组转tree
- tree转数组(递归)
- tree转数组(循环)
- Base64加密解密
- 判断当前设备是否属于移动端
- 手机号加敏
- 身份证加敏
- 获取某月共有多少天
- 处理+ - * / 运算精度丢失
- 内容复制
- H5环境判断(判断是微信/支付宝/云闪付)
- 从身份证中提取出生日
- 获取小程序状态栏及右上角胶囊位置信息(uni)
- 平滑的滚动到页面指定位置
- 深度合并对象
- canvas绘制星空背景(星星会动)
- 欢迎随时CV,持续更新中,关注不迷路
判断是否为IE浏览器
export function isIE () {
const bw = window.navigator.userAgent
const compare = (s) => bw.indexOf(s) >= 0
const ie11 = (() => 'ActiveXObject' in window)()
return compare('MSIE') || ie11
}
判断是否为全屏显示
/**
* @function 判断是否处于全屏显示
* @returns {boolean}
*/
export function isFullScreen () {
if (document.fullscreen) {
return true;
} else if (document.mozFullScreen) {
return true;
} else if (document.webkitIsFullScreen) {
return true;
} else if (document.msFullscreenElement) {
return true;
} else if (window.fullScreen) {
return true;
}
return false;
}
退出全屏
/**
* @function 退出全屏
* @returns {undefined}
*/
export function exitFullscreen () {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
}
全屏显示
/**
* @function 全屏显示 如果已是全屏显示则退出全屏
* @param {HTMLElement} element
* @returns {boolean}
* launchFullScreen(document.documentElement); // 整个网页
* launchFullScreen(document.getElementById("videoElement")); // 某个页面元素
*/
export function launchFullscreen (element) {
if (isFullScreen()) {// 如果用户在全屏模式下测退出全屏
exitFullscreen()
return false
}
if (element.requestFullscreen) {
element.requestFullscreen();
return true
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
return true
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
return true
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
return true
}
}
触发window.resize事件
export function triggerWindowResizeEvent () {
const event = document.createEvent('HTMLEvents')
event.initEvent('resize', true, true)
event.eventType = 'message'
window.dispatchEvent(event)
}
文件流下载
/**
* @function 下载文件
* @param {object} data 文件对象
* @param {string} original 下载文件名称
* @param {string} msg 消息
* @param {Function} callback 回调
* @returns {undefined}
* @type {undefined}
* @version 1.0
* @author 小明
*/
export function exportNetdot (data, original, msg = '导出成功', callback) {
try {
if (data.fileName) {
original = decodeURI(data.fileName).split('=')
original = original[original.length - 1]
}
} catch (error) {
console.error(error)
}
const typeObj = {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
}
const url = window.URL.createObjectURL(new Blob([data.data], typeObj));
console.log(url);
const link = document.createElement('a');
link.href = url
link.download = original;
document.body.appendChild(link);
link.click();
window.setTimeout(() => {
if (this) this.$message.success(msg)
document.body.removeChild(link);
callback && callback()
}, 0);
}
文件压缩
// 安装 npm i jszip
const JSZip = require('jszip');
/**
* 依赖 npm i jszip
* @function 文件压缩
* @param {object} file
* @param {string} zipName
* @returns {undefined}
* @version 1.0
* @author 小明
*/
export function exportZip (file, zipName) {
const zip = new JSZip();
zip.file(file.name, file);
zip.generateAsync({ type: 'blob' }).then((content) => {
// content 压缩文件流
exportNetdot({ data: content }, zipName)
});
}
导出Excel
/**
* 依赖 npm i js-export-excel
* @function 导出excel
* @param {object} option excel配置对象
* 具体可以参考:https://blog.youkuaiyun.com/weixin_43376417/article/details/124665752?spm=1001.2014.3001.5501
* @returns {undefined}
* @version 1.0
* @author 小明
*/
export function exportExcelMode (option) {
var toExcel = new ExportJsonExcel(option);
const file = toExcel.saveExcel()
// 如果有返回则是一个文件流
if (!file) return
exportZip(file, option.zipFileName || 'test-zip.zip')
}
crypto-js加密解密
/**
* 依赖 npm i crypto-js
* @function 基于crypto-js的加解密
* @property genKey,encrypt,decrypt
*/
let CryptoJS = require('crypto-js')
export const aesUtil = {
/**
* @function 生成key 如果在不需要解密的情况可以直接使用这个获取key
* @param {number} length 需要生成key的长度
* @returns {string} key
*/
genKey: function (length = 16) {
let random = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let str = "";
for (let i = 0; i < length; i++) {
str = str + random.charAt(Math.random() * random.length)
}
return str;
},
/**
* @function 完成加密
* @param {any} plaintext 需要加密的数据
* @param {string} key 参与加密的key,
* @returns {string} 生成得加密字符串
*/
encrypt: function (plaintext, key = 'MIGfMA0GCSqGSIb3') {
if (plaintext instanceof Object) {
plaintext = JSON.stringify(plaintext)
}
let encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(plaintext), CryptoJS.enc.Utf8.parse(key), { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
return encrypted.toString();
},
/**
* @function 解密 解密key必须与加密保存一致
* @param {string} ciphertext 要解密的字符串
* @param {strign} key 参与加密的key
* @returns {any} 解密成功的数据
*/
decrypt: function (ciphertext, key = 'MIGfMA0GCSqGSIb3') {
try {
let decrypt = CryptoJS.AES.decrypt(ciphertext, CryptoJS.enc.Utf8.parse(key), { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
let decString = CryptoJS.enc.Utf8.stringify(decrypt).toString();
if (decString.charAt(0) === "{" || decString.charAt(0) === "[") {
decString = JSON.parse(decString);
}
return decString;
} catch (err) {
return { msg: '解密失败' }
}
}
}
判断原始类型,Object.prototype.toString.apply([]) ‘[object Array]’
/**
* @function 判断数据的类型
* @param {object} prop 需要判断类型的参数
* @returns {string}
* @version 1.0
* @author 小明
*/
export function getObjType (prop) {
const map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object'
}
return map[Object.prototype.toString.call(prop)]
}
对象深度拷贝
/**
* @function 对象深度克隆
* @param {any} data 要克隆的参数
* @returns {any}
*/
export function deepClone (data) {
var type = getObjType(data)
var obj
if (type === 'array') {
obj = []
} else if (type === 'object') {
obj = {}
} else {
// 不再具有下一层次
return data
}
if (type === 'array') {
for (var i = 0, len = data.length; i < len; i++) {
obj.push(deepClone(data[i]))
}
} else if (type === 'object') {
for (var key in data) {
obj[key] = deepClone(data[key])
}
}
return obj
}
对象深度拷贝方案二
/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
* @param {Object} source
* @returns {Object}
*/
export function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone');
}
const targetObj = source.constructor === Array ? [] : {};
Object.keys(source).forEach((keys) => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys]);
} else {
targetObj[keys] = source[keys];
}
});
return targetObj;
}
数据校验
/**
* @function 校验数据
* @param {object} info 需要校验的数据
* @param {object} rule 校验规则
* @returns {boolean || string}
* info={ticketPrice:'',adjustPrice:''}
* rule={
ticketPrice: [
{ required: true, message: '请输入票面金额' },
{ pattern: /^[0-9.]{1,50}$/, message: '必须是0以上的数字' },
],
adjustPrice: [
{ required: true, message: '请输入上浮金额' },
{ pattern: /^[0-9.]{1,50}$/, message: '必须是0以上的数字' },
],
}
*/
export function rules (info, rule) {
for (var i in rule) {
if (info[i] === undefined) {
console.log('没有' + info[i])
return false // 没有就不校验
}
for (let j = 0; j < rule[i].length; j++) {
// 判断是否是必填项
if (rule[i][j].required) {
if (info[i] == '') {
return rule[i][j].message
}
}
//判断最小输入值min
if (rule[i][j].min) {
if (info[i].length < rule[i][j].min) {
return rule[i][j].message
}
}
//判断最大输入值max
if (rule[i][j].max) {
if (info[i].length > rule[i][j].max) {
return rule[i][j].message
}
}
// 判断是否相同
if (rule[i][j].equal) {
const str = rule[i][j].equal
if (info[i] !== info[str]) {
return rule[i][j].message
}
}
// 正则判断pattern
if (rule[i][j].pattern) {
if (!rule[i][j].pattern.test(info[i])) {
return rule[i][j].message
}
}
// 判断数组长度
if (rule[i][j].arrlength) {
if (rule[i][j].arrlength != info[i].length) {
return rule[i][j].message
}
}
}
}
return false
}
时间转换
这里是用ts写的,如果是js的话删除类型标注就可以了。
class newData extends Date {
/**
* 格式转换
* @param day 日期格式 YYYY-MM-DD hh:mm:ss 大写HH是12小时制,小写hh是24小时
* @returns
*/
format(day = 'YYYY-MM-DD'){
const date = this
let y = date.getFullYear();
let MM = date.getMonth() + 1 as number;
MM = MM < 10 ? "0" + MM : MM;
let d = date.getDate();
d = d < 10 ? "0" + d : d;
let h = date.getHours();
h = h < 10 ? "0" + h : h;
let h12 = h > 12 ? h - 12 : Number(h);
h12 = h12 < 10 ? "0" + h12 : h12;
let m = date.getMinutes();
m = m < 10 ? "0" + m : m;
let s = date.getSeconds();
s = s < 10 ? "0" + s : s;
const str = day.replace('YYYY', y).replace('MM', MM).replace('DD', d).replace('HH', h12).replace('hh', h).replace('mm', m).replace('ss',s)
.replace('ss', s)
return str
}
}
/**
* 日期格式转换
* @param value date
* @returns
*/
export function moment(value:Date|string|number) {
if (typeof value === 'string') value = Number(value)
let date = value ? new newData(value) : new newData();
return date
}
获取某月共有多少天
/**
* 获取某月共有多少天-不传参数就是获取当月
* @param year 年份
* @param month 月份
*/
export function getMonthDayNum(year,month){
let date = null
if(year && month){
date = new Date(year,month,0)
}else{
const d = new Date()
date = new Date(d.getFullYear(),d.getMonth()+1,0)
}
return date.getDate()
}
数组对象去重
/**
* 对象数组去重
* @param Arr 要去重的数组
* @param key 去重的key
* @return Array
*/
export const objArrSet = (Arr, key) => {
let obj = {}
return Arr.reduce((setArr, item) => {
obj[item[key]] ? '' : (obj[item[key]] = setArr.push(item))
return setArr
}, [])
}
防抖
/**
* 使用闭包封装防抖函数
* @param {*} Callback
* @param {*} delayTime
* @returns
*/
export const debounceEvent = (Callback, delayTime) => {
let timer = null
return function (...agmes) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
Callback.apply(this, [...agmes])
}, delayTime)
}
}
节流
/**
* 使用闭包封装节流函数
* @param {*} Callback
* @param {*} delayTime
* @returns
*/
export const throttleEvent = (Callback, delayTime) => {
// 上一次执行的时间,
let constTime = 0
// 可以认为是节流的阀门。
let valve = false
return function (...agmes) {
let createTime = new Date().getTime()
let day = (createTime - constTime) / 1000
valve = !constTime || day > delayTime ? true : false
if (valve) {
Callback.apply(this, [...agmes])
constTime = createTime
}
}
}
多维数组扁平化
/**
* 多维数组扁平化
* @param {*} arr
* @returns
*/
export const arrDelayering = (arr) => {
if (!Array.isArray(arr)) return []
let newarr = new Array()
arr.forEach(item => Array.isArray(item) ? newarr = newarr.concat(arrpnh(item)) : newarr.push(item));
return newarr
}
数组转tree
/**
* 数组转tree
* @param {*} arr
* @param {*} nodeid
* @returns
*/
export const toTree = (arr,pid='pid',nodeid=null)=>{
if(!Array.isArray(arr))return []
let newarr = new Array()
arr.forEach(item => item[pid]===nodeid && newarr.push({...item,children:toTree(arr,pid,item.id)}));
return newarr
}
tree转数组(递归)
/**
* tree转数组 递归法 --转为数组后会按树形的顺序排序
* @param {*} data
* @returns
*/
export const treeArrdg = (data)=>{
let newarr = new Array()
data.forEach((item) => {
if (!item instanceof Object) return []
if (item.children && item.children.length) {
let children = item.children
delete item.children
newarr.push(item)
newarr = newarr.concat(treeArrdg(children))
} else {
newarr.push(item)
}
})
return newarr
}
/**
* tree转数组 非递归法-- 会按树形结构排序,先进2先出
* @param {*} data
* @returns
*/
export const treeArr = (data)=>{
if (!Array.isArray(data) || !data.length) return []
for (let i = 0; i < data.length; i++) {
let item = data[i]
if (item.children && item.children.length) {
data = data.concat(item.children)
delete item.children
}
}
return data
}
tree转数组(循环)
/**
* tree转数组 非递归法-- 会按树形结构排序,先进先出
* @param {*} data
* @returns
*/
export const treeArr = (data) => {
if (!Array.isArray(data) || !data.length) return []
for (let i = 0; i < data.length; i++) {
let item = data[i]
if (item.children && item.children.length) {
data = data.concat(item.children)
delete item.children
}
}
return data
}
Base64加密解密
/**
* Base64加密解密
* 构造函数-需要new创建实例
*/
export const Base64 = function () {
// private property
var _keyStr =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
// public method for encoding
this.encode = function (input) {
if (typeof input == 'object') {
input = JSON.stringify(input)
}
input = input + ''
var output = ''
var chr1, chr2, chr3, enc1, enc2, enc3, enc4
var i = 0
input = _utf8_encode(input)
while (i < input.length) {
chr1 = input.charCodeAt(i++)
chr2 = input.charCodeAt(i++)
chr3 = input.charCodeAt(i++)
enc1 = chr1 >> 2
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4)
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6)
enc4 = chr3 & 63
if (isNaN(chr2)) {
enc3 = enc4 = 64
} else if (isNaN(chr3)) {
enc4 = 64
}
output =
output +
_keyStr.charAt(enc1) +
_keyStr.charAt(enc2) +
_keyStr.charAt(enc3) +
_keyStr.charAt(enc4)
}
return output
}
// public method for decoding
this.decode = function (input) {
var output = ''
var chr1, chr2, chr3
var enc1, enc2, enc3, enc4
var i = 0
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '')
while (i < input.length) {
enc1 = _keyStr.indexOf(input.charAt(i++))
enc2 = _keyStr.indexOf(input.charAt(i++))
enc3 = _keyStr.indexOf(input.charAt(i++))
enc4 = _keyStr.indexOf(input.charAt(i++))
chr1 = (enc1 << 2) | (enc2 >> 4)
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2)
chr3 = ((enc3 & 3) << 6) | enc4
output = output + String.fromCharCode(chr1)
if (enc3 != 64) {
output = output + String.fromCharCode(chr2)
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3)
}
}
output = _utf8_decode(output)
return output
}
// private method for UTF-8 encoding
var _utf8_encode = function (string) {
string = string.replace(/\r\n/g, '\n')
var utftext = ''
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n)
if (c < 128) {
utftext += String.fromCharCode(c)
} else if (c > 127 && c < 2048) {
utftext += String.fromCharCode((c >> 6) | 192)
utftext += String.fromCharCode((c & 63) | 128)
} else {
utftext += String.fromCharCode((c >> 12) | 224)
utftext += String.fromCharCode(((c >> 6) & 63) | 128)
utftext += String.fromCharCode((c & 63) | 128)
}
}
return utftext
}
// private method for UTF-8 decoding
var _utf8_decode = function (utftext) {
var string = ''
var i = 0
var c = 0,
c1 = 0,
c2 = 0
while (i < utftext.length) {
c = utftext.charCodeAt(i)
if (c < 128) {
string += String.fromCharCode(c)
i++
} else if (c > 191 && c < 224) {
c2 = utftext.charCodeAt(i + 1)
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63))
i += 2
} else {
c2 = utftext.charCodeAt(i + 1)
c3 = utftext.charCodeAt(i + 2)
string += String.fromCharCode(
((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)
)
i += 3
}
}
return string
}
}
判断当前设备是否属于移动端
/**
* 判断当前设备是否属于移动端
* @returns bool|object
*/
export const equipmentType = ()=>{
var UA = window.navigator.userAgent.toLowerCase()
var isAndroid = UA.indexOf('android') > 0
var isIOS = /iphone|ipad|ipod|ios/.test(UA)
if (isAndroid || isIOS) {
return {
isPhone: isAndroid || isIOS,
isAndroid,
isIOS,
}
} else {
return false
}
}
手机号加敏
/**
* 手机号加敏
* @param {手机号} str
* @returns string
*/
export const phoneDesion = (str='')=>{
str+=''
return str.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
身份证加敏
/**
* 身份证加敏
* @param {身份证号} str
* @returns string
*/
export const codeDesion = (str='')=>{
str+=''
return str.replace(/^(.{6})(?:\d+)(.{4})$/, '$1********$2')
}
获取某月共有多少天
/**
* 获取某月共有多少天-不传参数就是获取当月
* @param year 年份
* @param month 月份
*/
export function getMonthDayNum(year,month){
let date = null
if(year && month){
date = new Date(year,month,0)
}else{
const d = new Date()
date = new Date(d.getFullYear(),d.getMonth()+1,0)
}
return date.getDate()
}
处理+ - * / 运算精度丢失
/**
* 解决js计算的精度问题
*/
const fn = {
countDecimals(num) {
let len = 0
try {
num = Number(num)
let str = num.toString().toUpperCase()
if (str.split('E').length === 2) { // scientific notation
let isDecimal = false
if (str.split('.').length === 2) {
str = str.split('.')[1]
if (parseInt(str.split('E')[0]) !== 0) {
isDecimal = true
}
}
let x = str.split('E')
if (isDecimal) {
len = x[0].length
}
len -= parseInt(x[1])
} else if (str.split('.').length === 2) { // decimal
if (parseInt(str.split('.')[1]) !== 0) {
len = str.split('.')[1].length
}
}
} catch (e) {
throw e
} finally {
if (isNaN(len) || len < 0) {
len = 0
}
// eslint-disable-next-line no-unsafe-finally
return len
}
},
convertToInt(num) {
num = Number(num)
let newNum = num
let times = this.countDecimals(num)
let tempNum = num.toString().toUpperCase()
if (tempNum.split('E').length === 2) {
newNum = Math.round(num * Math.pow(10, times))
} else {
newNum = Number(tempNum.replace('.', ''))
}
return newNum
},
getCorrectResult(type, num1, num2, result) {
let tempResult = 0
switch (type) {
case 'add':
tempResult = num1 + num2
break
case 'sub':
tempResult = num1 - num2
break
case 'div':
tempResult = num1 / num2
break
case 'mul':
tempResult = num1 * num2
break
}
if (Math.abs(result - tempResult) > 1) {
return Number(tempResult)
}
return Number(result)
}
}
const calculation = {
// 加法
add(num1, num2) {
num1 = Number(num1)
num2 = Number(num2)
let dec1, dec2, times
try { dec1 = fn.countDecimals(num1) + 1 } catch (e) { dec1 = 0 }
try { dec2 = fn.countDecimals(num2) + 1 } catch (e) { dec2 = 0 }
times = Math.pow(10, Math.max(dec1, dec2))
// let result = (num1 * times + num2 * times) / times
let result = (this.mul(num1, times) + this.mul(num2, times)) / times
return fn.getCorrectResult('add', num1, num2, result)
// return result
},
// 减法
sub(num1, num2) {
num1 = Number(num1)
num2 = Number(num2)
let dec1, dec2, times
try { dec1 = fn.countDecimals(num1) + 1 } catch (e) { dec1 = 0 }
try { dec2 = fn.countDecimals(num2) + 1 } catch (e) { dec2 = 0 }
times = Math.pow(10, Math.max(dec1, dec2))
// let result = Number(((num1 * times - num2 * times) / times)
let result = Number((this.mul(num1, times) - this.mul(num2, times)) / times)
return fn.getCorrectResult('sub', num1, num2, result)
// return result
},
// 乘法
mul(num1, num2) {
num1 = Number(num1)
num2 = Number(num2)
let times = 0
let s1 = num1.toString()
let s2 = num2.toString()
try { times += fn.countDecimals(s1) } catch (e) { }
try { times += fn.countDecimals(s2) } catch (e) { }
let result = fn.convertToInt(s1) * fn.convertToInt(s2) / Math.pow(10, times)
return fn.getCorrectResult('mul', num1, num2, result)
// return result
},
// 除法
div(num1, num2) {
num1 = Number(num1)
num2 = Number(num2)
let t1 = 0
let t2 = 0
let dec1, dec2
try { t1 = fn.countDecimals(num1) } catch (e) { }
try { t2 = fn.countDecimals(num2) } catch (e) { }
dec1 = fn.convertToInt(num1)
dec2 = fn.convertToInt(num2)
let result = this.mul((dec1 / dec2), Math.pow(10, t2 - t1))
return fn.getCorrectResult('div', num1, num2, result)
// return result
}
}
export default calculation
内容复制
/**
*
* @param {string} text
* @param {string} msg
*/
export async function cloneText(text,msg){
try {
// 在非https下不支持
if(navigator.clipboard && window.isSecureContext) {
const clipboardObj = navigator.clipboard
await clipboardObj.writeText(text)
ElMessage.success(msg || '复制成功')
}else{
let textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.position = "absolute";
textArea.style.opacity = '0';
textArea.style.left = "-999999px";
textArea.style.top = "-999999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
document.execCommand('copy') ? ElMessage.success(msg || '复制成功') : ElMessage.warning('复制失败')
textArea.remove();
}
} catch (error) {
ElMessage.warning('复制失败')
}
}
H5环境判断(判断是微信/支付宝/云闪付)
export function equipmentType() {
var UA = window.navigator.userAgent.toLowerCase();
var isAndroid = UA.indexOf('android') > 0;
var isIOS = /iphone|ipad|ipod|ios/.test(UA);
if (isAndroid || isIOS) {
const obj = {
isPhone: isAndroid || isIOS,
isAndroid,
isIOS,
// 微信环境
isWechat:UA.match(/MicroMessenger/i) == 'micromessenger',
// 支付宝环境
isAli:UA.match(/AlipayClient/i) == 'alipayclient',
// 云闪付环境
isYun:UA.match(/com.unionpay.chsp/i) == 'com.unionpay.chsp' || UA.match(/com.unionpay.mobilepay/i) == 'com.unionpay.mobilepay'
}
return obj
} else {
return false
}
}
从身份证中提取出生日
/**
* 从身份证中提取出生日
* @param value 身份证号码
* @returns String
*/
export function getBirthday(value){
let reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
let birthday = '';
value = value.toString()
if (reg.test(value)) {
let data = value.slice(6, 14);
let y = data.slice(0, 4);
let m = data.slice(4, 6);
let d = data.slice(6, 8);
birthday = y + '-' + m + '-' + d;
}
return birthday
}
获取小程序状态栏及右上角胶囊位置信息(uni)
/**
* 获取小程序状态栏及右上角胶囊位置信息
* @returns {Object} 返回参数
* @returns {Number} Object.statusBarHeight 状态栏高度
*/
export function getNavWHdata(){
let obj = {}
// 获取手机系统信息
const info = uni.getSystemInfoSync()
// 设置状态栏高度(H5顶部无状态栏小程序有状态栏需要撑起高度)
obj.statusBarHeight = info.statusBarHeight
obj.windowWidth = info.windowWidth
// 获取胶囊的位置
const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
// (胶囊底部高度 - 状态栏的高度) + (胶囊顶部高度 - 状态栏内的高度) = 导航栏的高度
obj.navBarHeight = (menuButtonInfo.bottom - info.statusBarHeight) + (menuButtonInfo.top - info
.statusBarHeight)
// 导航宽度等于出左上角菜单按钮宽度
obj.windowWidth = menuButtonInfo.left
obj.navHeight = obj.navBarHeight + obj.statusBarHeight
return obj
}
平滑的滚动到页面指定位置
Math.easeInOutQuad = function (t, b, c, d) {
t /= d / 2;
if (t < 1) {
return (c / 2) * t * t + b;
}
t--;
return (-c / 2) * (t * (t - 2) - 1) + b;
};
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
var requestAnimFrame = (function () {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
}
);
})();
/**
* Because it's so fucking difficult to detect the scrolling element, just move them all
* @param {number} amount
*/
function move(amount) {
document.documentElement.scrollTop = amount;
document.body.parentNode.scrollTop = amount;
document.body.scrollTop = amount;
}
function position() {
return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop;
}
/**
* @param {number} to
* @param {number} duration
* @param {Function} callback
*/
export function scrollTo(to, duration, callback) {
const start = position();
const change = to - start;
const increment = 20;
let currentTime = 0;
duration = typeof duration === 'undefined' ? 500 : duration;
var animateScroll = function () {
// increment the time
currentTime += increment;
// find the value with the quadratic in-out easing function
var val = Math.easeInOutQuad(currentTime, start, change, duration);
// move the document.body
move(val);
// do the animation unless its over
if (currentTime < duration) {
requestAnimFrame(animateScroll);
} else {
if (callback && typeof callback === 'function') {
// the animation is done so lets callback
callback();
}
}
};
animateScroll();
}
深度合并对象
// 深度合并对象
function deepAssign(obj1, obj2) {
for (let key in obj2) {
obj1[key] = obj1[key] && obj1[key].toString() === "[object Object]" ?
deepAssign(obj1[key], obj2[key]) : obj1[key] = obj2[key];
}
return obj1;
}
canvas绘制星空背景(星星会动)
export default function initLoginBg() {
var windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
// var windowWidth = window.clientWidth;
// var windowHeight = window.clientHeight;
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
w = canvas.width = windowWidth,
h = canvas.height = windowHeight,
hue = 217,
stars = [],
count = 0,
maxStars = 500;//星星数量
var canvas2 = document.createElement('canvas'),
ctx2 = canvas2.getContext('2d');
canvas2.width = 120;
canvas2.height = 120;
var half = canvas2.width / 2,
gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half);
gradient2.addColorStop(0.025, '#CCC');
gradient2.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)');
gradient2.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)');
gradient2.addColorStop(1, 'transparent');
ctx2.fillStyle = gradient2;
ctx2.beginPath();
ctx2.arc(half, half, half, 0, Math.PI * 2);
ctx2.fill();
// End cache
function random(min, max = 0) {
if (arguments.length < 2) {
max = min;
min = 0;
}
if (min > max) {
var hold = max;
max = min;
min = hold;
}
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function maxOrbit(x, y) {
var max = Math.max(x, y),
diameter = Math.round(Math.sqrt(max * max + max * max));
return diameter / 2;
//星星移动范围,值越大范围越小,
}
var Star = function () {
this.orbitRadius = random(maxOrbit(w, h));
this.radius = random(60, this.orbitRadius) / 18;
//星星大小
this.orbitX = w / 2;
this.orbitY = h / 2;
this.timePassed = random(0, maxStars);
this.speed = random(this.orbitRadius) / 500000;
//星星移动速度
this.alpha = random(2, 10) / 10;
count++;
stars[count] = this;
}
Star.prototype.draw = function () {
var x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX,
y = Math.cos(this.timePassed) * this.orbitRadius + this.orbitY,
twinkle = random(10);
if (twinkle === 1 && this.alpha > 0) {
this.alpha -= 0.05;
} else if (twinkle === 2 && this.alpha < 1) {
this.alpha += 0.05;
}
ctx.globalAlpha = this.alpha;
ctx.drawImage(canvas2, x - this.radius / 2, y - this.radius / 2, this.radius, this.radius);
this.timePassed += this.speed;
}
for (var i = 0; i < maxStars; i++) {
new Star.prototype.constructor();
}
function animation() {
ctx.globalCompositeOperation = 'source-over';
ctx.globalAlpha = 0.5; //尾巴
ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 2)';
ctx.fillRect(0, 0, w, h)
ctx.globalCompositeOperation = 'lighter';
for (var i = 1, l = stars.length; i < l; i++) {
stars[i].draw();
};
window.requestAnimationFrame(animation);
}
animation();
}