Skip to content

Instantly share code, notes, and snippets.

@xhsdnn
Last active December 21, 2023 07:11
Show Gist options
  • Save xhsdnn/b1bf54d2960b5daf342e0299592113a2 to your computer and use it in GitHub Desktop.
Save xhsdnn/b1bf54d2960b5daf342e0299592113a2 to your computer and use it in GitHub Desktop.
js工具方法
/**
* 正则字符串去重
*
* @param {string} str —— 需要去重的字符串
* @returns
*/
function clearRepeat(str) {
let regex = /(.)?/g;
return str.replace(regex, function($1, $2, $3, $4) {
return $4.indexOf($2) === $3 ? $2 : '';
});
}
/**
* canvas导出图片
*
* @param {*} canvas —— canvas元素
* @param {string} [filename='canvas'] —— 导出文件名
* @param {string} [type='png'] —— 图片类型
*/
function canvasToImg(canvas, filename = 'canvas',type = 'png') {
let canvasdata = canvas.toDataURL(`image/${type}`),
a = document.createElement('a');
a.download = `${filename}.${type}`;
a.href = canvasdata;
a.click();
}
/**
* 获取两个元素的重叠部分相对于‘被覆盖元素’的数据
*
* @param {*} el —— 被覆盖元素
* @param {*} popEl —— 元素(覆盖元素,即定位在被覆盖元素上的元素)
* @returns
*/
getOverData(el, popEl) {
let { width: Wi, height: Hi, top: Ti, left: Li } = el.getBoundingClientRect();
let { width: We, height: He, top: Te, left: Le } = popEl.getBoundingClientRect();
let centerXi = Li + Wi/2,
centerYi = Ti + Hi/2,
centerXe = Le + We/2,
centerYe = Te + He/2,
top = 0, // 生成遮挡元素的top
left = 0, // 生成遮挡元素的left
width = 0, // 生成遮挡元素的width
height = 0, // 生成遮挡元素的height
borderTopWidth = getBorder('borderTopWidth'), // 被遮挡元素上边框宽度
borderLeftWidth = getBorder('borderLeftWidth'); // 被遮挡元素左边框宽度
// 无重叠部分
if(Math.abs(centerXi - centerXe) >= (Wi/2 + We/2) || Math.abs(centerYi - centerYe) >= (Hi/2 + He/2)) return {};
// 有重叠部分
top = (Te - Ti) < 0 ? 0 : (Te - Ti); // 元素上边界超出top为0
if(Ti > Te) { // 元素上边界超出被覆盖元素上边界
height = (Te + He - Ti) > Hi ? Hi : (Te + He - Ti);
} else if(Te + He > Ti + Hi) { // 元素下边界超出被覆盖元素下边界
height = Ti + Hi - Te;
} else { // 元素边界全部在被覆盖元素内部/外部
height = He > Hi ? Hi : He;
}
// 1.从左侧遮盖
// ________
// __|__ |
// | | | |
// |__|__| |
// |________|
if(Li > Le && Li + Wi > Le) {
left = 0;
width = (Le + We - Li) > Wi ? Wi : (Le + We - Li); // 宽度超出被覆盖元素宽度为被覆盖元素宽度
}
// 2.从右侧遮盖
// ________
// | __|__
// | | | |
// | |__|__|
// |________|
if(Le + We > Li + Wi && Le < Li + Wi) {
left = Le - Li;
width = Li + Hi - Li;
}
// 3.从上/下遮盖
// ____
// __|____|__
// | |____| |
// | |
// | |
// |__________|
if(Le > Li && Le + He < Li + Hi) {
left = Le - Li;
width = We;
let heightNum = Te + He - Ti;
if(heightNum > Hi) { // 下边界超出
height = Ti + Hi - Te;
} else if(heightNum > He) { // 全部在内部
height = He;
} else { // 下边界超出
height = heightNum;
}
}
// 根据边框宽度对数据做修正
top -= borderTopWidth;
left -= borderLeftWidth;
return { top, left, width, height };
function getBorder(type, dom = el) {
return Number(getComputedStyle(dom)[type].replace('px', ''));
}
}
/**
* 简单生成随机32位字符
*
* @returns
*/
function getNonce() {
let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < 32; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
/**
* 生成uuid
* reference: https://github.com/remesh-js/remesh/blob/main/projects/domains/src/todo-mvc/uuid.ts
*
* @returns
*/
export const uuid = () =>
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment