import { Base64 } from "js-base64"; export const getRealativeMosePosition = ( dom: HTMLElement, mousePosition: number[] ) => { const rect = dom.getBoundingClientRect(); return [mousePosition[0] - rect.left, mousePosition[1] - rect.top]; }; // 节流 export const throttle = any>( fn: T, delay: number = 160 ) => { let previous = 0; return function (this: This, ...args: Parameters) { const now = Date.now(); if (now - previous >= delay) { fn.apply(this, args); previous = now; } }; }; // 防抖 export const debounce = any>( fn: T, delay: number = 160 ) => { let timeout: any; return function (this: This, ...args: Parameters) { clearTimeout(timeout); timeout = setTimeout(() => { fn.apply(this, args); }, delay); }; }; export const loadImage = (src: string): Promise => { const img = new Image(); img.src = src; img.crossOrigin = "anonymous"; return new Promise((resolve) => { img.onload = () => resolve(img); }); }; export const mergeFuns = (...fns: (() => void)[]) => { return () => { fns.forEach((fn) => fn()); }; }; // 四舍五入保留指定位数 export const round = (num: number, index: number = 2) => { const s = Math.pow(10, index); return Math.round(num * s) / s; }; export const numberSplice = (val: number) => { const integer = Math.floor(val); const decimal = val - integer; return [integer, decimal]; }; //经纬度转度°分′秒″ export const toDegrees = (val: number, retain = 2) => { let temps = numberSplice(val); const d = temps[0]; temps = numberSplice(temps[1] * 60); const m = temps[0]; const s = round(temps[1] * 60, retain); return `${d}°${m}′${s.toFixed(2)}″`; }; export const copyText = async ( text: string, fallback?: boolean ): Promise => { if (navigator.clipboard && !fallback) { let permiss: any; try { permiss = await navigator.permissions.query({ name: "geolocation", }); permiss.state === "denied"; } catch (e) { console.error(e); } if (permiss && permiss.state === "denied") { console.error(permiss); throw new Error("请授予写入粘贴板权限!"); } else { try { await navigator.clipboard.writeText(text); } catch (e) { console.error("不支持navigator.clipboard.writeText 开启回退"); return await copyText(text, true); } } } else { const textarea = document.createElement("textarea"); document.body.appendChild(textarea); // 隐藏此输入框 textarea.style.position = "fixed"; textarea.style.clip = "rect(0 0 0 0)"; textarea.style.top = "10px"; // 赋值 textarea.value = text; // 选中 textarea.select(); // 复制 document.execCommand("copy", true); // 移除输入框 document.body.removeChild(textarea); } }; function randomWord(randomFlag: boolean, min: number, max?: number) { let str = ""; let range = min; const arr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", ]; // 随机产生 if (randomFlag && max) { range = Math.round(Math.random() * (max - min)) + min; } for (let i = 0; i < range; i++) { const pos = Math.round(Math.random() * (arr.length - 1)); str += arr[pos]; } return str; } export function encodePwd(str: string) { str = Base64.encode(str); const NUM = 2; const front = randomWord(false, 8); const middle = randomWord(false, 8); const end = randomWord(false, 8); const str1 = str.substring(0, NUM); const str2 = str.substring(NUM); return front + str2 + middle + str1 + end; } const place = /(?:\/:([^/]*))/g; // 生成/:id 类真实url export const gendUrl = (tempUrl: string, params: { [key: string]: any }) => { let url = ""; let preIndex = 0; let m; while ((m = place.exec(tempUrl))) { url += tempUrl.substring(preIndex, m.index + 1) + (params[m[1]] || "null"); preIndex = m.index + m[0].length; } url += tempUrl.substr(preIndex); return url; }; export const dateFormat = (date: Date, fmt: string) => { var o: any = { "M+": date.getMonth() + 1, //月份 "d+": date.getDate(), //日 "h+": date.getHours(), //小时 "m+": date.getMinutes(), //分 "s+": date.getSeconds(), //秒 "q+": Math.floor((date.getMonth() + 3) / 3), //季度 S: date.getMilliseconds(), //毫秒 }; if (/(y+)/.test(fmt)) { fmt = fmt.replace( RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length) ); } for (var k in o) { if (new RegExp("(" + k + ")").test(fmt)) { fmt = fmt.replace( RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length) ); } } return fmt; }; let canvas: HTMLCanvasElement; let ctx: CanvasRenderingContext2D; export const getTextBound = ( text: string, font: string, padding: number[] = [0, 0], margin: number[] = [0, 0] ) => { if (!canvas) { canvas = document.createElement("canvas"); ctx = canvas.getContext("2d")!; } ctx.font = font; const textMetrics = ctx.measureText(text); const width = textMetrics.width + (padding[1] + margin[1]) * 2; const fontHeight = textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent; console.log(fontHeight); const height = fontHeight + (padding[0] + margin[0]) * 2; return { width, height }; }; export * from "./tree";