123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- export function isValidUrl(url) {
- return isOnlineUrl(url) || isDataUrl(url);
- }
- export function isOnlineUrl(url) {
- return /(ht|f)tp(s?):\/\/([^ \\/]*\.)+[^ \\/]*(:[0-9]+)?\/?/.test(url);
- }
- export function isDataUrl(url) {
- return /data:image\/(\w+);base64,(.*)/.test(url);
- }
- /**
- * 深度对比两个对象是否一致
- * from: https://github.com/epoberezkin/fast-deep-equal
- * @param {Object} a 对象a
- * @param {Object} b 对象b
- * @return {Boolean} 是否相同
- */
- /* eslint-disable */
- export function equal(a, b) {
- if (a === b) {
- return true;
- }
- if (a && b && typeof a == 'object' && typeof b == 'object') {
- var arrA = Array.isArray(a);
- var arrB = Array.isArray(b);
- var i;
- var length;
- var key;
- if (arrA && arrB) {
- length = a.length;
- if (length != b.length) {
- return false;
- }
- for (i = length; i-- !== 0; ) {
- if (!equal(a[i], b[i])) {
- return false;
- }
- }
- return true;
- }
- if (arrA != arrB) {
- return false;
- }
- var dateA = a instanceof Date;
- var dateB = b instanceof Date;
- if (dateA != dateB) {
- return false;
- }
- if (dateA && dateB) {
- return a.getTime() == b.getTime();
- }
- var regexpA = a instanceof RegExp;
- var regexpB = b instanceof RegExp;
- if (regexpA != regexpB) {
- return false;
- }
- if (regexpA && regexpB) {
- return a.toString() == b.toString();
- }
- var keys = Object.keys(a);
- length = keys.length;
- if (length !== Object.keys(b).length) {
- return false;
- }
- for (i = length; i-- !== 0; ) {
- if (!Object.prototype.hasOwnProperty.call(b, keys[i])) {
- return false;
- }
- }
- for (i = length; i-- !== 0; ) {
- key = keys[i];
- if (!equal(a[key], b[key])) {
- return false;
- }
- }
- return true;
- }
- return a !== a && b !== b;
- }
- /**
- * 简单的四则运算计算函数
- * @param {String} expression 数学表达式字符串
- * @return {Number} 计算结果
- */
- export function calc(expression) {
- try {
- // 移除所有空格
- expression = expression.replace(/\s/g, '');
-
- // 简单的四则运算实现
- const tokens = expression.match(/(\d+\.?\d*|\+|\-|\*|\/|\(|\))/g) || [];
- const output = [];
- const operators = [];
-
- const precedence = {
- '+': 1,
- '-': 1,
- '*': 2,
- '/': 2
- };
-
- for (let token of tokens) {
- if (/\d/.test(token)) {
- output.push(parseFloat(token));
- } else if (token === '(') {
- operators.push(token);
- } else if (token === ')') {
- while (operators.length > 0 && operators[operators.length - 1] !== '(') {
- output.push(operators.pop());
- }
- if (operators.length > 0 && operators[operators.length - 1] === '(') {
- operators.pop();
- }
- } else if (['+', '-', '*', '/'].includes(token)) {
- while (operators.length > 0 &&
- operators[operators.length - 1] !== '(' &&
- precedence[operators[operators.length - 1]] >= precedence[token]) {
- output.push(operators.pop());
- }
- operators.push(token);
- }
- }
-
- while (operators.length > 0) {
- output.push(operators.pop());
- }
-
- // 计算后缀表达式
- const stack = [];
- for (let token of output) {
- if (typeof token === 'number') {
- stack.push(token);
- } else {
- const b = stack.pop();
- const a = stack.pop();
- switch (token) {
- case '+': stack.push(a + b); break;
- case '-': stack.push(a - b); break;
- case '*': stack.push(a * b); break;
- case '/': stack.push(a / b); break;
- }
- }
- }
-
- return stack[0] || 0;
- } catch (error) {
- console.error('Calc error:', error);
- return 0;
- }
- }
- /**
- * 将带单位的字符串转换为像素值
- * @param {String} origin 原始字符串,支持 rpx、px、% 单位和 calc() 表达式
- * @param {Number} screenK 屏幕比例,默认为 0.5
- * @param {Number} scale 缩放比例,默认为 1
- * @param {Number} baseSize 当设置了 % 号时,设置的基准值
- * @param {Object} viewRect 视图矩形信息,用于 calc() 表达式中的属性引用
- * @return {Number} 转换后的像素值
- */
- export function toPx(origin, screenK = 0.5, scale = 1, baseSize = 0, viewRect = {}) {
- const REG = /-?[0-9]+(\.[0-9]+)?(rpx|px|%)/;
-
- const parsePx = (origin) => {
- const results = new RegExp(REG).exec(origin);
- if (!origin || !results) {
- return origin;
- }
- const unit = results[2];
- const value = parseFloat(origin);
- let res = 0;
- if (unit === 'rpx' || unit === 'px') {
- res = Math.round(value * (screenK || 0.5) * (scale || 1));
- } else if (unit === '%') {
- res = Math.round((value * baseSize) / 100);
- }
- return res;
- };
- const formula = /^calc\((.+)\)$/.exec(origin);
- if (formula && formula[1]) {
- // 进行 calc 计算
- const afterOne = formula[1].replace(
- /([^\s\(\+\-\*\/]+)\.(left|right|bottom|top|width|height)/g,
- (word) => {
- const [id, attr] = word.split('.');
- return viewRect[id][attr] || 0;
- }
- );
- const afterTwo = afterOne.replace(new RegExp(REG, 'g'), parsePx);
- return calc(afterTwo);
- } else {
- return parsePx(origin);
- }
- }
|