/** * 验证码组件工具函数 */ /** * 生成随机整数 * @param {number} min 最小值 * @param {number} max 最大值 * @returns {number} 随机整数 */ export function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } /** * 生成随机颜色 * @returns {string} 十六进制颜色值 */ export function randomColor() { const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#98D8C8']; return colors[Math.floor(Math.random() * colors.length)]; } /** * 生成随机字符串 * @param {number} length 字符串长度 * @param {string} chars 字符集 * @returns {string} 随机字符串 */ export function randomString(length = 4, chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678') { let result = ''; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } /** * 计算两点距离 * @param {number} x1 点1 x坐标 * @param {number} y1 点1 y坐标 * @param {number} x2 点2 x坐标 * @param {number} y2 点2 y坐标 * @returns {number} 距离 */ export function getDistance(x1, y1, x2, y2) { return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); } /** * 判断点是否在矩形区域内 * @param {number} x 点x坐标 * @param {number} y 点y坐标 * @param {Object} rect 矩形对象 {x, y, width, height} * @returns {boolean} 是否在区域内 */ export function isPointInRect(x, y, rect) { return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height; } /** * 生成验证码图片拼图 * @param {CanvasRenderingContext2D} ctx Canvas上下文 * @param {number} x x坐标 * @param {number} y y坐标 * @param {number} r 圆角半径 * @param {number} PI 圆周率 */ export function drawPath(ctx, x, y, r, PI) { ctx.beginPath(); ctx.moveTo(x, y); ctx.arc(x + r / 2, y - r + 2, r, 0, 2 * PI); ctx.lineTo(x + r, y); ctx.arc(x + r + r / 2, y + r / 2, r, 1.5 * PI, 0.5 * PI); ctx.lineTo(x + r, y + r); ctx.lineTo(x, y + r); ctx.arc(x + r / 2, y + r + r / 2, r, PI, 0); ctx.closePath(); } /** * 获取图片像素数据 * @param {string} imgSrc 图片源 * @returns {Promise} 图片像素数据 */ export function getImageData(imgSrc) { return new Promise((resolve, reject) => { const img = new Image(); img.onload = function() { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); resolve(ctx.getImageData(0, 0, canvas.width, canvas.height)); }; img.onerror = reject; img.crossOrigin = 'anonymous'; img.src = imgSrc; }); } /** * 创建干扰线 * @param {CanvasRenderingContext2D} ctx Canvas上下文 * @param {number} width 画布宽度 * @param {number} height 画布高度 * @param {number} lineCount 干扰线数量 */ export function drawInterferenceLines(ctx, width, height, lineCount = 8) { for (let i = 0; i < lineCount; i++) { ctx.strokeStyle = randomColor(); ctx.lineWidth = randomInt(1, 3); ctx.beginPath(); ctx.moveTo(randomInt(0, width), randomInt(0, height)); ctx.lineTo(randomInt(0, width), randomInt(0, height)); ctx.stroke(); } } /** * 创建干扰点 * @param {CanvasRenderingContext2D} ctx Canvas上下文 * @param {number} width 画布宽度 * @param {number} height 画布高度 * @param {number} pointCount 干扰点数量 */ export function drawInterferencePoints(ctx, width, height, pointCount = 100) { for (let i = 0; i < pointCount; i++) { ctx.fillStyle = randomColor(); ctx.beginPath(); ctx.arc(randomInt(0, width), randomInt(0, height), randomInt(1, 2), 0, 2 * Math.PI); ctx.fill(); } } /** * 节流函数 * @param {Function} func 要执行的函数 * @param {number} delay 延迟时间 * @returns {Function} 节流后的函数 */ export function throttle(func, delay) { let timer = null; return function(...args) { if (!timer) { timer = setTimeout(() => { func.apply(this, args); timer = null; }, delay); } }; } /** * 防抖函数 * @param {Function} func 要执行的函数 * @param {number} delay 延迟时间 * @returns {Function} 防抖后的函数 */ export function debounce(func, delay) { let timer = null; return function(...args) { if (timer) clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); }, delay); }; } /** * 重置画布 * @param {CanvasRenderingContext2D} ctx Canvas上下文 * @param {number} width 画布宽度 * @param {number} height 画布高度 */ export function resetCanvas(ctx, width, height) { ctx.clearRect(0, 0, width, height); } /** * 获取元素的绝对位置 * @param {Element} element DOM元素 * @returns {Object} {left, top} */ export function getElementPosition(element) { let left = 0; let top = 0; while (element) { left += element.offsetLeft; top += element.offsetTop; element = element.offsetParent; } return { left, top }; } /** * 移动端触摸事件坐标获取 * @param {Event} e 事件对象 * @returns {Object} {x, y} */ export function getTouchPosition(e) { const touch = e.touches && e.touches.length > 0 ? e.touches[0] : e.changedTouches[0]; return { x: touch.clientX, y: touch.clientY }; } /** * 获取鼠标或触摸位置 * @param {Event} e 事件对象 * @returns {Object} {x, y} */ export function getEventPosition(e) { if (e.touches) { return getTouchPosition(e); } return { x: e.clientX, y: e.clientY }; } export { aesEncrypt } from './aes';