gis-common 4.2.2 → 4.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/CanvasDrawer.d.ts +2 -2
- package/dist/gis-common.es.js +1127 -997
- package/dist/gis-common.umd.js +1 -1
- package/dist/utils/AssertUtil.d.ts +21 -0
- package/dist/utils/CommUtil.d.ts +0 -1
- package/dist/utils/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/gis-common.es.js
CHANGED
|
@@ -274,17 +274,14 @@ class CanvasDrawer {
|
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
static createCanvas(width = 1, height = 1) {
|
|
277
|
-
|
|
278
|
-
if (
|
|
279
|
-
canvas =
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if (height) {
|
|
284
|
-
canvas.height = height;
|
|
285
|
-
}
|
|
286
|
-
return canvas;
|
|
277
|
+
const canvas = document.createElement("canvas");
|
|
278
|
+
if (width) {
|
|
279
|
+
canvas.width = width;
|
|
280
|
+
}
|
|
281
|
+
if (height) {
|
|
282
|
+
canvas.height = height;
|
|
287
283
|
}
|
|
284
|
+
return canvas;
|
|
288
285
|
}
|
|
289
286
|
}
|
|
290
287
|
class EventDispatcher {
|
|
@@ -476,7 +473,7 @@ class WebSocketClient extends EventDispatcher {
|
|
|
476
473
|
}, 1e3);
|
|
477
474
|
}
|
|
478
475
|
}
|
|
479
|
-
const
|
|
476
|
+
const CommUtil = {
|
|
480
477
|
/**
|
|
481
478
|
* 获取数据类型
|
|
482
479
|
*
|
|
@@ -535,9 +532,6 @@ const CommUtils = {
|
|
|
535
532
|
return false;
|
|
536
533
|
}
|
|
537
534
|
},
|
|
538
|
-
isNotEmpty(val) {
|
|
539
|
-
return !this.isEmpty(val);
|
|
540
|
-
},
|
|
541
535
|
/**
|
|
542
536
|
* 将JSON对象转换为FormData对象
|
|
543
537
|
*
|
|
@@ -937,10 +931,10 @@ const _MqttClient = class _MqttClient extends EventDispatcher {
|
|
|
937
931
|
__publicField(this, "options");
|
|
938
932
|
__publicField(this, "client");
|
|
939
933
|
__publicField(this, "topics");
|
|
940
|
-
this.context =
|
|
934
|
+
this.context = CommUtil.extend(_MqttClient.defaultContext, config);
|
|
941
935
|
this.options = {
|
|
942
936
|
connectTimeout: this.context.MQTT_TIMEOUTM,
|
|
943
|
-
clientId:
|
|
937
|
+
clientId: CommUtil.guid(),
|
|
944
938
|
username: this.context.MQTT_USERNAME,
|
|
945
939
|
password: this.context.MQTT_PASSWORD,
|
|
946
940
|
clean: true
|
|
@@ -1247,7 +1241,7 @@ const AjaxUtil = {
|
|
|
1247
1241
|
* @param callback - callback function when completed
|
|
1248
1242
|
*/
|
|
1249
1243
|
jsonp(url, callback) {
|
|
1250
|
-
const name = "_jsonp_" +
|
|
1244
|
+
const name = "_jsonp_" + CommUtil.guid();
|
|
1251
1245
|
const head = document.getElementsByTagName("head")[0];
|
|
1252
1246
|
if (url.includes("?")) {
|
|
1253
1247
|
url += "&callback=" + name;
|
|
@@ -1286,7 +1280,7 @@ const AjaxUtil = {
|
|
|
1286
1280
|
* );
|
|
1287
1281
|
*/
|
|
1288
1282
|
get(url, options, cb) {
|
|
1289
|
-
if (
|
|
1283
|
+
if (CommUtil.isFunction(options)) {
|
|
1290
1284
|
const t = cb;
|
|
1291
1285
|
cb = options;
|
|
1292
1286
|
options = t;
|
|
@@ -1418,7 +1412,7 @@ const AjaxUtil = {
|
|
|
1418
1412
|
* );
|
|
1419
1413
|
*/
|
|
1420
1414
|
getArrayBuffer(url, options, cb) {
|
|
1421
|
-
if (
|
|
1415
|
+
if (CommUtil.isFunction(options)) {
|
|
1422
1416
|
const t = cb;
|
|
1423
1417
|
cb = options;
|
|
1424
1418
|
options = t;
|
|
@@ -1471,7 +1465,7 @@ const AjaxUtil = {
|
|
|
1471
1465
|
* );
|
|
1472
1466
|
*/
|
|
1473
1467
|
getJSON(url, options, cb) {
|
|
1474
|
-
if (
|
|
1468
|
+
if (CommUtil.isFunction(options)) {
|
|
1475
1469
|
const t = cb;
|
|
1476
1470
|
cb = options;
|
|
1477
1471
|
options = t;
|
|
@@ -1488,691 +1482,519 @@ const AjaxUtil = {
|
|
|
1488
1482
|
return this.get(url, options, callback);
|
|
1489
1483
|
}
|
|
1490
1484
|
};
|
|
1491
|
-
const
|
|
1485
|
+
const GeoUtil = {
|
|
1486
|
+
toRadian: Math.PI / 180,
|
|
1487
|
+
R: 6371393,
|
|
1492
1488
|
/**
|
|
1493
|
-
*
|
|
1489
|
+
* 判断给定的经纬度是否合法
|
|
1494
1490
|
*
|
|
1495
|
-
* @
|
|
1491
|
+
* @param lng 经度值
|
|
1492
|
+
* @param lat 纬度值
|
|
1493
|
+
* @returns 如果经纬度合法,返回true;否则返回false
|
|
1496
1494
|
*/
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
if (explorer.indexOf("MSIE") >= 0 || /Trident\//.test(explorer)) {
|
|
1500
|
-
return "IE";
|
|
1501
|
-
} else if (explorer.indexOf("Firefox") >= 0) {
|
|
1502
|
-
return "Firefox";
|
|
1503
|
-
} else if (explorer.indexOf("Chrome") >= 0) {
|
|
1504
|
-
return "Chrome";
|
|
1505
|
-
} else if (explorer.indexOf("Opera") >= 0) {
|
|
1506
|
-
return "Opera";
|
|
1507
|
-
} else if (explorer.indexOf("Safari") >= 0 && explorer.indexOf("Chrome") === -1) {
|
|
1508
|
-
return "Safari";
|
|
1509
|
-
}
|
|
1510
|
-
return "Unknown";
|
|
1495
|
+
isLnglat(lng, lat) {
|
|
1496
|
+
return !isNaN(lng) && !isNaN(lat) && !!(+lat > -90 && +lat < 90 && +lng > -180 && +lng < 180);
|
|
1511
1497
|
},
|
|
1512
1498
|
/**
|
|
1513
|
-
*
|
|
1499
|
+
* 计算两哥平面坐标点间的距离
|
|
1514
1500
|
*
|
|
1515
|
-
* @
|
|
1501
|
+
* @param p1 坐标点1,包含x和y属性
|
|
1502
|
+
* @param p2 坐标点2,包含x和y属性
|
|
1503
|
+
* @returns 返回两点间的欧几里得距离
|
|
1516
1504
|
*/
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
const windows = navigator.userAgent.indexOf("Windows", 0) != -1 ? 1 : 0;
|
|
1520
|
-
const mac = navigator.userAgent.indexOf("mac", 0) != -1 ? 1 : 0;
|
|
1521
|
-
const linux = navigator.userAgent.indexOf("Linux", 0) != -1 ? 1 : 0;
|
|
1522
|
-
const unix = navigator.userAgent.indexOf("X11", 0) != -1 ? 1 : 0;
|
|
1523
|
-
if (windows) os_type = "MS Windows";
|
|
1524
|
-
else if (mac) os_type = "Apple mac";
|
|
1525
|
-
else if (linux) os_type = "Linux";
|
|
1526
|
-
else if (unix) os_type = "Unix";
|
|
1527
|
-
return os_type;
|
|
1505
|
+
distance(p1, p2) {
|
|
1506
|
+
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
|
|
1528
1507
|
},
|
|
1529
1508
|
/**
|
|
1530
|
-
*
|
|
1509
|
+
* 计算两个经纬度点之间的距离
|
|
1531
1510
|
*
|
|
1532
|
-
* @param
|
|
1511
|
+
* @param A 经纬度点A,包含lng(经度)和lat(纬度)两个属性
|
|
1512
|
+
* @param B 经纬度点B,包含lng(经度)和lat(纬度)两个属性
|
|
1513
|
+
* @returns 返回两点之间的距离,单位为米
|
|
1533
1514
|
*/
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
} else {
|
|
1547
|
-
if (document.exitFullscreen) {
|
|
1548
|
-
document.exitFullscreen();
|
|
1549
|
-
} else if ("msExitFullscreen" in document) {
|
|
1550
|
-
document.msExitFullscreen();
|
|
1551
|
-
} else if ("mozCancelFullScreen" in document) {
|
|
1552
|
-
document.mozCancelFullScreen();
|
|
1553
|
-
} else if ("webkitExitFullscreen" in document) {
|
|
1554
|
-
document.webkitExitFullscreen();
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1515
|
+
distanceByPoints(A, B) {
|
|
1516
|
+
const { lng: lngA, lat: latA } = A;
|
|
1517
|
+
const { lng: lngB, lat: latB } = B;
|
|
1518
|
+
const earthR = 6371e3;
|
|
1519
|
+
const x = Math.cos(latA * Math.PI / 180) * Math.cos(latB * Math.PI / 180) * Math.cos((lngA - lngB) * Math.PI / 180);
|
|
1520
|
+
const y = Math.sin(latA * Math.PI / 180) * Math.sin(latB * Math.PI / 180);
|
|
1521
|
+
let s = x + y;
|
|
1522
|
+
if (s > 1) s = 1;
|
|
1523
|
+
if (s < -1) s = -1;
|
|
1524
|
+
const alpha = Math.acos(s);
|
|
1525
|
+
const distance = alpha * earthR;
|
|
1526
|
+
return distance;
|
|
1557
1527
|
},
|
|
1558
1528
|
/**
|
|
1559
|
-
*
|
|
1529
|
+
* 格式化经纬度为度分秒格式
|
|
1560
1530
|
*
|
|
1561
|
-
* @
|
|
1531
|
+
* @param lng 经度
|
|
1532
|
+
* @param lat 纬度
|
|
1533
|
+
* @returns 返回格式化后的经纬度字符串,格式为:经度度分秒,纬度度分秒
|
|
1562
1534
|
*/
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
const designRatio = 16 / 9;
|
|
1571
|
-
let scaleRate = baseWidth / 1920;
|
|
1572
|
-
if (realRatio > designRatio) {
|
|
1573
|
-
scaleRate = baseHeight / 1080;
|
|
1535
|
+
formatLnglat(lng, lat) {
|
|
1536
|
+
let res = "";
|
|
1537
|
+
function formatDegreeToDMS(valueInDegrees) {
|
|
1538
|
+
const degree = Math.floor(valueInDegrees);
|
|
1539
|
+
const minutes = Math.floor((valueInDegrees - degree) * 60);
|
|
1540
|
+
const seconds = (valueInDegrees - degree) * 3600 - minutes * 60;
|
|
1541
|
+
return `${degree}°${minutes}′${seconds.toFixed(2)}″`;
|
|
1574
1542
|
}
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1543
|
+
if (this.isLnglat(lng, lat)) {
|
|
1544
|
+
res = formatDegreeToDMS(lng) + "," + formatDegreeToDMS(lat);
|
|
1545
|
+
} else if (!isNaN(lng)) {
|
|
1546
|
+
res = formatDegreeToDMS(lng);
|
|
1547
|
+
} else if (!isNaN(lat)) {
|
|
1548
|
+
res = formatDegreeToDMS(lat);
|
|
1549
|
+
}
|
|
1550
|
+
return res;
|
|
1578
1551
|
},
|
|
1579
1552
|
/**
|
|
1580
|
-
*
|
|
1553
|
+
* 将经纬度字符串转换为度
|
|
1581
1554
|
*
|
|
1582
|
-
* @
|
|
1555
|
+
* @param lng 经度字符串
|
|
1556
|
+
* @param lat 纬度字符串
|
|
1557
|
+
* @returns 转换后的经纬度对象
|
|
1583
1558
|
*/
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1559
|
+
transformLnglat(lng, lat) {
|
|
1560
|
+
function dms2deg(dmsString) {
|
|
1561
|
+
const isNegative = /[sw]/i.test(dmsString);
|
|
1562
|
+
let factor = isNegative ? -1 : 1;
|
|
1563
|
+
const numericParts = dmsString.match(/[\d.]+/g) || [];
|
|
1564
|
+
let degrees = 0;
|
|
1565
|
+
for (let i = 0; i < numericParts.length; i++) {
|
|
1566
|
+
degrees += parseFloat(numericParts[i]) / factor;
|
|
1567
|
+
factor *= 60;
|
|
1568
|
+
}
|
|
1569
|
+
return degrees;
|
|
1570
|
+
}
|
|
1571
|
+
if (lng && lat) {
|
|
1572
|
+
return {
|
|
1573
|
+
lng: dms2deg(lng),
|
|
1574
|
+
lat: dms2deg(lat)
|
|
1575
|
+
};
|
|
1589
1576
|
}
|
|
1590
|
-
}
|
|
1591
|
-
};
|
|
1592
|
-
const CoordsUtil = {
|
|
1593
|
-
PI: 3.141592653589793,
|
|
1594
|
-
XPI: 3.141592653589793 * 3e3 / 180,
|
|
1595
|
-
delta(lat, lng) {
|
|
1596
|
-
const a = 6378245;
|
|
1597
|
-
const ee = 0.006693421622965943;
|
|
1598
|
-
let dLat = this.transformLat(lng - 105, lat - 35);
|
|
1599
|
-
let dLon = this.transformLon(lng - 105, lat - 35);
|
|
1600
|
-
const radLat = lat / 180 * this.PI;
|
|
1601
|
-
let magic = Math.sin(radLat);
|
|
1602
|
-
magic = 1 - ee * magic * magic;
|
|
1603
|
-
const sqrtMagic = Math.sqrt(magic);
|
|
1604
|
-
dLat = dLat * 180 / (a * (1 - ee) / (magic * sqrtMagic) * this.PI);
|
|
1605
|
-
dLon = dLon * 180 / (a / sqrtMagic * Math.cos(radLat) * this.PI);
|
|
1606
|
-
return { lat: dLat, lng: dLon };
|
|
1607
1577
|
},
|
|
1608
1578
|
/**
|
|
1609
|
-
*
|
|
1579
|
+
* 射线法判断点是否在多边形内
|
|
1610
1580
|
*
|
|
1611
|
-
* @param
|
|
1612
|
-
* @param
|
|
1613
|
-
* @returns
|
|
1581
|
+
* @param p 点对象,包含x和y属性
|
|
1582
|
+
* @param poly 多边形顶点数组,可以是字符串数组或对象数组
|
|
1583
|
+
* @returns 返回字符串,表示点相对于多边形的位置:'in'表示在多边形内,'out'表示在多边形外,'on'表示在多边形上
|
|
1614
1584
|
*/
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1585
|
+
rayCasting(p, poly) {
|
|
1586
|
+
var px = p.x, py = p.y, flag = false;
|
|
1587
|
+
for (var i = 0, l = poly.length, j = l - 1; i < l; j = i, i++) {
|
|
1588
|
+
var sx = poly[i].x, sy = poly[i].y, tx = poly[j].x, ty = poly[j].y;
|
|
1589
|
+
if (sx === px && sy === py || tx === px && ty === py) {
|
|
1590
|
+
return "on";
|
|
1591
|
+
}
|
|
1592
|
+
if (sy < py && ty >= py || sy >= py && ty < py) {
|
|
1593
|
+
var x = sx + (py - sy) * (tx - sx) / (ty - sy);
|
|
1594
|
+
if (x === px) {
|
|
1595
|
+
return "on";
|
|
1596
|
+
}
|
|
1597
|
+
if (x > px) {
|
|
1598
|
+
flag = !flag;
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1621
1601
|
}
|
|
1622
|
-
return
|
|
1602
|
+
return flag ? "in" : "out";
|
|
1623
1603
|
},
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1604
|
+
/**
|
|
1605
|
+
* 旋转点
|
|
1606
|
+
*
|
|
1607
|
+
* @param p1 旋转前点坐标
|
|
1608
|
+
* @param p2 旋转中心坐标
|
|
1609
|
+
* @param θ 旋转角度(顺时针旋转为正)
|
|
1610
|
+
* @returns 旋转后点坐标
|
|
1611
|
+
*/
|
|
1612
|
+
rotatePoint(p1, p2, θ) {
|
|
1613
|
+
const x = (p1.x - p2.x) * Math.cos(Math.PI / 180 * -θ) - (p1.y - p2.y) * Math.sin(Math.PI / 180 * -θ) + p2.x;
|
|
1614
|
+
const y = (p1.x - p2.x) * Math.sin(Math.PI / 180 * -θ) + (p1.y - p2.y) * Math.cos(Math.PI / 180 * -θ) + p2.y;
|
|
1615
|
+
return { x, y };
|
|
1631
1616
|
},
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
const
|
|
1643
|
-
const
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
let pLat = gcjLat + dLat;
|
|
1649
|
-
let pLon = gcjLon + dLon;
|
|
1650
|
-
let wgsLat = 0;
|
|
1651
|
-
let wgsLon = 0;
|
|
1652
|
-
let i = 0;
|
|
1653
|
-
while (1) {
|
|
1654
|
-
wgsLat = (mLat + pLat) / 2;
|
|
1655
|
-
wgsLon = (mLon + pLon) / 2;
|
|
1656
|
-
const tmp = this.gcjEncrypt(wgsLat, wgsLon);
|
|
1657
|
-
dLat = tmp.lat - gcjLat;
|
|
1658
|
-
dLon = tmp.lng - gcjLon;
|
|
1659
|
-
if (Math.abs(dLat) < threshold && Math.abs(dLon) < threshold) {
|
|
1660
|
-
break;
|
|
1661
|
-
}
|
|
1662
|
-
if (dLat > 0) pLat = wgsLat;
|
|
1663
|
-
else mLat = wgsLat;
|
|
1664
|
-
if (dLon > 0) pLon = wgsLon;
|
|
1665
|
-
else mLon = wgsLon;
|
|
1666
|
-
if (++i > 1e4) break;
|
|
1667
|
-
}
|
|
1668
|
-
return { lat: wgsLat, lng: wgsLon };
|
|
1669
|
-
},
|
|
1670
|
-
// GCJ-02 to BD-09
|
|
1671
|
-
bdEncrypt(gcjLat, gcjLon) {
|
|
1672
|
-
const x = gcjLon;
|
|
1673
|
-
const y = gcjLat;
|
|
1674
|
-
const z = Math.sqrt(x * x + y * y) + 2e-5 * Math.sin(y * this.XPI);
|
|
1675
|
-
const theta = Math.atan2(y, x) + 3e-6 * Math.cos(x * this.XPI);
|
|
1676
|
-
const bdLon = z * Math.cos(theta) + 65e-4;
|
|
1677
|
-
const bdLat = z * Math.sin(theta) + 6e-3;
|
|
1678
|
-
return { lat: bdLat, lng: bdLon };
|
|
1679
|
-
},
|
|
1680
|
-
// BD-09 to GCJ-02
|
|
1681
|
-
bdDecrypt(bdLat, bdLon) {
|
|
1682
|
-
const x = bdLon - 65e-4;
|
|
1683
|
-
const y = bdLat - 6e-3;
|
|
1684
|
-
const z = Math.sqrt(x * x + y * y) - 2e-5 * Math.sin(y * this.XPI);
|
|
1685
|
-
const theta = Math.atan2(y, x) - 3e-6 * Math.cos(x * this.XPI);
|
|
1686
|
-
const gcjLon = z * Math.cos(theta);
|
|
1687
|
-
const gcjLat = z * Math.sin(theta);
|
|
1688
|
-
return { lat: gcjLat, lng: gcjLon };
|
|
1689
|
-
},
|
|
1690
|
-
// WGS-84 to Web mercator
|
|
1691
|
-
// mercatorLat -> y mercatorLon -> x
|
|
1692
|
-
mercatorEncrypt(wgsLat, wgsLon) {
|
|
1693
|
-
const x = wgsLon * 2003750834e-2 / 180;
|
|
1694
|
-
let y = Math.log(Math.tan((90 + wgsLat) * this.PI / 360)) / (this.PI / 180);
|
|
1695
|
-
y = y * 2003750834e-2 / 180;
|
|
1696
|
-
return { lat: y, lng: x };
|
|
1697
|
-
},
|
|
1698
|
-
// Web mercator to WGS-84
|
|
1699
|
-
// mercatorLat -> y mercatorLon -> x
|
|
1700
|
-
mercatorDecrypt(mercatorLat, mercatorLon) {
|
|
1701
|
-
const x = mercatorLon / 2003750834e-2 * 180;
|
|
1702
|
-
let y = mercatorLat / 2003750834e-2 * 180;
|
|
1703
|
-
y = 180 / this.PI * (2 * Math.atan(Math.exp(y * this.PI / 180)) - this.PI / 2);
|
|
1704
|
-
return { lat: y, lng: x };
|
|
1705
|
-
},
|
|
1706
|
-
transformLat(x, y) {
|
|
1707
|
-
let ret = -100 + 2 * x + 3 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
|
1708
|
-
ret += (20 * Math.sin(6 * x * this.PI) + 20 * Math.sin(2 * x * this.PI)) * 2 / 3;
|
|
1709
|
-
ret += (20 * Math.sin(y * this.PI) + 40 * Math.sin(y / 3 * this.PI)) * 2 / 3;
|
|
1710
|
-
ret += (160 * Math.sin(y / 12 * this.PI) + 320 * Math.sin(y * this.PI / 30)) * 2 / 3;
|
|
1711
|
-
return ret;
|
|
1712
|
-
},
|
|
1713
|
-
transformLon(x, y) {
|
|
1714
|
-
let ret = 300 + x + 2 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
|
1715
|
-
ret += (20 * Math.sin(6 * x * this.PI) + 20 * Math.sin(2 * x * this.PI)) * 2 / 3;
|
|
1716
|
-
ret += (20 * Math.sin(x * this.PI) + 40 * Math.sin(x / 3 * this.PI)) * 2 / 3;
|
|
1717
|
-
ret += (150 * Math.sin(x / 12 * this.PI) + 300 * Math.sin(x / 30 * this.PI)) * 2 / 3;
|
|
1718
|
-
return ret;
|
|
1617
|
+
/**
|
|
1618
|
+
* 根据两个平面坐标点计算方位角和距离
|
|
1619
|
+
*
|
|
1620
|
+
* @param p1 第一个点的坐标对象
|
|
1621
|
+
* @param p2 第二个点的坐标对象
|
|
1622
|
+
* @returns 返回一个对象,包含angle和distance属性,分别表示两点之间的角度(以度为单位,取值范围为0~359)和距离
|
|
1623
|
+
*/
|
|
1624
|
+
calcBearAndDis(p1, p2) {
|
|
1625
|
+
const { x: x1, y: y1 } = p1;
|
|
1626
|
+
const { x: x2, y: y2 } = p2;
|
|
1627
|
+
const dx = x2 - x1;
|
|
1628
|
+
const dy = y2 - y1;
|
|
1629
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
1630
|
+
const angleInRadians = Math.atan2(dy, dx);
|
|
1631
|
+
const angle = (angleInRadians * (180 / Math.PI) + 360 + 90) % 360;
|
|
1632
|
+
return { angle, distance };
|
|
1719
1633
|
},
|
|
1720
1634
|
/**
|
|
1721
|
-
*
|
|
1635
|
+
* 根据两个经纬度点计算方位角和距离
|
|
1722
1636
|
*
|
|
1723
|
-
* @param
|
|
1724
|
-
* @param
|
|
1725
|
-
* @returns
|
|
1637
|
+
* @param latlng1 第一个经纬度点
|
|
1638
|
+
* @param latlng2 第二个经纬度点
|
|
1639
|
+
* @returns 包含方位角和距离的对象
|
|
1726
1640
|
*/
|
|
1727
|
-
|
|
1641
|
+
calcBearAndDisByPoints(latlng1, latlng2) {
|
|
1642
|
+
var f1 = latlng1.lat * 1, l1 = latlng1.lng * 1, f2 = latlng2.lat * 1, l2 = latlng2.lng * 1;
|
|
1643
|
+
var y = Math.sin((l2 - l1) * this.toRadian) * Math.cos(f2 * this.toRadian);
|
|
1644
|
+
var x = Math.cos(f1 * this.toRadian) * Math.sin(f2 * this.toRadian) - Math.sin(f1 * this.toRadian) * Math.cos(f2 * this.toRadian) * Math.cos((l2 - l1) * this.toRadian);
|
|
1645
|
+
var angle = Math.atan2(y, x) * (180 / Math.PI);
|
|
1646
|
+
var deltaF = (f2 - f1) * this.toRadian;
|
|
1647
|
+
var deltaL = (l2 - l1) * this.toRadian;
|
|
1648
|
+
var a = Math.sin(deltaF / 2) * Math.sin(deltaF / 2) + Math.cos(f1 * this.toRadian) * Math.cos(f2 * this.toRadian) * Math.sin(deltaL / 2) * Math.sin(deltaL / 2);
|
|
1649
|
+
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
1650
|
+
var distance = this.R * c;
|
|
1728
1651
|
return {
|
|
1729
|
-
|
|
1730
|
-
|
|
1652
|
+
angle,
|
|
1653
|
+
distance
|
|
1731
1654
|
};
|
|
1732
1655
|
},
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1656
|
+
/**
|
|
1657
|
+
* 计算点P到线段P1P2的最短距离
|
|
1658
|
+
*
|
|
1659
|
+
* @param p 点P的坐标
|
|
1660
|
+
* @param p1 线段起点P1的坐标
|
|
1661
|
+
* @param p2 线段终点P2的坐标
|
|
1662
|
+
* @returns 点P到线段P1P2的最短距离
|
|
1663
|
+
*/
|
|
1664
|
+
distanceToSegment(p, p1, p2) {
|
|
1665
|
+
const x = p.x, y = p.y, x1 = p1.x, y1 = p1.y, x2 = p2.x, y2 = p2.y;
|
|
1666
|
+
const cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
|
|
1667
|
+
if (cross <= 0) {
|
|
1668
|
+
return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
|
|
1736
1669
|
}
|
|
1737
|
-
const
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
p = arr[i];
|
|
1741
|
-
if (CommUtils.isNil(p)) {
|
|
1742
|
-
result.push(null);
|
|
1743
|
-
continue;
|
|
1744
|
-
}
|
|
1745
|
-
if (Array.isArray(p)) {
|
|
1746
|
-
result.push(this.deCompose(p, fn, context));
|
|
1747
|
-
} else {
|
|
1748
|
-
pp = context ? fn.call(context, p) : fn(p);
|
|
1749
|
-
result.push(pp);
|
|
1750
|
-
}
|
|
1670
|
+
const d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
|
|
1671
|
+
if (cross >= d2) {
|
|
1672
|
+
return Math.sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
|
|
1751
1673
|
}
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
random() {
|
|
1757
|
-
let r = Math.floor(Math.random() * 256).toString(16);
|
|
1758
|
-
let g = Math.floor(Math.random() * 256).toString(16);
|
|
1759
|
-
let b = Math.floor(Math.random() * 256).toString(16);
|
|
1760
|
-
r = r.length === 1 ? "0" + r : r;
|
|
1761
|
-
g = g.length === 1 ? "0" + g : g;
|
|
1762
|
-
b = b.length === 1 ? "0" + b : b;
|
|
1763
|
-
return "#" + r + g + b;
|
|
1674
|
+
const r = cross / d2;
|
|
1675
|
+
const px = x1 + (x2 - x1) * r;
|
|
1676
|
+
const py = y1 + (y2 - y1) * r;
|
|
1677
|
+
return Math.sqrt((x - px) * (x - px) + (y - py) * (y - py));
|
|
1764
1678
|
},
|
|
1765
1679
|
/**
|
|
1766
|
-
*
|
|
1680
|
+
* 根据给定的经纬度、角度和距离计算新的经纬度点
|
|
1767
1681
|
*
|
|
1768
|
-
* @param
|
|
1769
|
-
* @
|
|
1682
|
+
* @param latlng 给定的经纬度点,类型为LngLat
|
|
1683
|
+
* @param angle 角度值,单位为度,表示从当前点出发的方向
|
|
1684
|
+
* @param distance 距离值,单位为米,表示从当前点出发的距离
|
|
1685
|
+
* @returns 返回计算后的新经纬度点,类型为{lat: number, lng: number}
|
|
1770
1686
|
*/
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1687
|
+
calcPointByBearAndDis(latlng, angle, distance) {
|
|
1688
|
+
const sLat = MathUtils.deg2Rad(latlng.lat * 1);
|
|
1689
|
+
const sLng = MathUtils.deg2Rad(latlng.lng * 1);
|
|
1690
|
+
const d = distance / this.R;
|
|
1691
|
+
angle = MathUtils.deg2Rad(angle);
|
|
1692
|
+
const lat = Math.asin(Math.sin(sLat) * Math.cos(d) + Math.cos(sLat) * Math.sin(d) * Math.cos(angle));
|
|
1693
|
+
const lon = sLng + Math.atan2(Math.sin(angle) * Math.sin(d) * Math.cos(sLat), Math.cos(d) - Math.sin(sLat) * Math.sin(lat));
|
|
1694
|
+
return {
|
|
1695
|
+
lat: MathUtils.rad2Deg(lat),
|
|
1696
|
+
lng: MathUtils.rad2Deg(lon)
|
|
1697
|
+
};
|
|
1774
1698
|
},
|
|
1775
1699
|
/**
|
|
1776
|
-
*
|
|
1700
|
+
* 将墨卡托坐标转换为经纬度坐标
|
|
1777
1701
|
*
|
|
1778
|
-
* @param
|
|
1779
|
-
* @
|
|
1702
|
+
* @param x 墨卡托坐标的x值
|
|
1703
|
+
* @param y 墨卡托坐标的y值
|
|
1704
|
+
* @returns 返回包含转换后的经度lng和纬度lat的对象
|
|
1780
1705
|
*/
|
|
1781
|
-
|
|
1782
|
-
const
|
|
1783
|
-
|
|
1706
|
+
mercatorTolonlat(x, y) {
|
|
1707
|
+
const lng = x / 2003750834e-2 * 180;
|
|
1708
|
+
var mmy = y / 2003750834e-2 * 180;
|
|
1709
|
+
const lat = 180 / Math.PI * (2 * Math.atan(Math.exp(mmy * Math.PI / 180)) - Math.PI / 2);
|
|
1710
|
+
return { lng, lat };
|
|
1784
1711
|
},
|
|
1785
1712
|
/**
|
|
1786
|
-
*
|
|
1713
|
+
* 将经纬度坐标转换为墨卡托坐标
|
|
1787
1714
|
*
|
|
1788
|
-
* @param
|
|
1789
|
-
* @
|
|
1715
|
+
* @param lng 经度值
|
|
1716
|
+
* @param lat 纬度值
|
|
1717
|
+
* @returns 墨卡托坐标对象,包含x和y属性
|
|
1790
1718
|
*/
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
const
|
|
1794
|
-
|
|
1795
|
-
const
|
|
1796
|
-
|
|
1797
|
-
return hexValue;
|
|
1798
|
-
}
|
|
1799
|
-
const r = parseInt(rgb[1], 16);
|
|
1800
|
-
const g = parseInt(rgb[2], 16);
|
|
1801
|
-
const b = parseInt(rgb[3], 16);
|
|
1802
|
-
return `rgba(${r},${g},${b},1)`;
|
|
1719
|
+
lonlatToMercator(lng, lat) {
|
|
1720
|
+
var earthRad = 6378137;
|
|
1721
|
+
const x = lng * Math.PI / 180 * earthRad;
|
|
1722
|
+
var a = lat * Math.PI / 180;
|
|
1723
|
+
const y = earthRad / 2 * Math.log((1 + Math.sin(a)) / (1 - Math.sin(a)));
|
|
1724
|
+
return { x, y };
|
|
1803
1725
|
},
|
|
1804
1726
|
/**
|
|
1805
|
-
*
|
|
1727
|
+
* 根据百分比获取坐标
|
|
1806
1728
|
*
|
|
1807
|
-
* @param
|
|
1808
|
-
* @
|
|
1729
|
+
* @param start 起点坐标
|
|
1730
|
+
* @param end 终点坐标
|
|
1731
|
+
* @param percent 百分比,取值范围0-1
|
|
1732
|
+
* @returns 返回插值后的坐标
|
|
1809
1733
|
*/
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
}
|
|
1814
|
-
const hsl = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(hslValue) || /hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(hslValue);
|
|
1815
|
-
if (!hsl) {
|
|
1816
|
-
return null;
|
|
1817
|
-
}
|
|
1818
|
-
const h = parseInt(hsl[1], 10) / 360;
|
|
1819
|
-
const s = parseInt(hsl[2], 10) / 100;
|
|
1820
|
-
const l = parseInt(hsl[3], 10) / 100;
|
|
1821
|
-
const a = hsl[4] ? parseFloat(hsl[4]) : 1;
|
|
1822
|
-
function hue2rgb(p, q, t) {
|
|
1823
|
-
if (t < 0) t += 1;
|
|
1824
|
-
if (t > 1) t -= 1;
|
|
1825
|
-
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
1826
|
-
if (t < 1 / 2) return q;
|
|
1827
|
-
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
1828
|
-
return p;
|
|
1829
|
-
}
|
|
1830
|
-
let r, g, b;
|
|
1831
|
-
if (s === 0) {
|
|
1832
|
-
r = g = b = l;
|
|
1833
|
-
} else {
|
|
1834
|
-
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
1835
|
-
const p = 2 * l - q;
|
|
1836
|
-
r = hue2rgb(p, q, h + 1 / 3);
|
|
1837
|
-
g = hue2rgb(p, q, h);
|
|
1838
|
-
b = hue2rgb(p, q, h - 1 / 3);
|
|
1839
|
-
}
|
|
1840
|
-
return `rgba(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)},${a})`;
|
|
1841
|
-
},
|
|
1842
|
-
isHex(a) {
|
|
1843
|
-
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(a);
|
|
1844
|
-
},
|
|
1845
|
-
isRgb(a) {
|
|
1846
|
-
return /^rgb/.test(a);
|
|
1847
|
-
},
|
|
1848
|
-
isHsl(a) {
|
|
1849
|
-
return /^hsl/.test(a);
|
|
1850
|
-
},
|
|
1851
|
-
isColor(a) {
|
|
1852
|
-
return this.isHex(a) || this.isRgb(a) || this.isHsl(a);
|
|
1853
|
-
},
|
|
1854
|
-
colorToRgb(val) {
|
|
1855
|
-
if (this.isRgb(val)) return this.rgbToRgba(val);
|
|
1856
|
-
if (this.isHex(val)) return this.hexToRgba(val);
|
|
1857
|
-
if (this.isHsl(val)) return this.hslToRgba(val);
|
|
1858
|
-
}
|
|
1859
|
-
};
|
|
1860
|
-
const myDate = Object.create(Date);
|
|
1861
|
-
myDate.prototype.format = function(fmt = "yyyy-MM-dd hh:mm:ss") {
|
|
1862
|
-
const o = {
|
|
1863
|
-
"M+": this.getMonth() + 1,
|
|
1864
|
-
// 月份
|
|
1865
|
-
"d+": this.getDate(),
|
|
1866
|
-
// 日
|
|
1867
|
-
"h+": this.getHours() % 12,
|
|
1868
|
-
// 小时
|
|
1869
|
-
"H+": this.getHours(),
|
|
1870
|
-
// 小时 (24小时制)
|
|
1871
|
-
"m+": this.getMinutes(),
|
|
1872
|
-
// 分
|
|
1873
|
-
"s+": this.getSeconds(),
|
|
1874
|
-
// 秒
|
|
1875
|
-
"q+": Math.floor((this.getMonth() + 3) / 3),
|
|
1876
|
-
// 季度
|
|
1877
|
-
S: this.getMilliseconds()
|
|
1878
|
-
// 毫秒
|
|
1879
|
-
};
|
|
1880
|
-
if (/(y+)/.test(fmt)) {
|
|
1881
|
-
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
|
|
1882
|
-
}
|
|
1883
|
-
for (const k in o) {
|
|
1884
|
-
if (new RegExp("(" + k + ")").test(fmt)) {
|
|
1885
|
-
const len = k.length === 1 ? 1 : Number(k.slice(1));
|
|
1886
|
-
fmt = fmt.replace(RegExp.$1, ("00" + o[k]).substr(("" + o[k]).length + len - (o[k] + "").length));
|
|
1887
|
-
}
|
|
1888
|
-
}
|
|
1889
|
-
return fmt;
|
|
1890
|
-
};
|
|
1891
|
-
myDate.prototype.addDate = function(interval, number) {
|
|
1892
|
-
const date = new Date(this);
|
|
1893
|
-
switch (interval) {
|
|
1894
|
-
case "y":
|
|
1895
|
-
date.setFullYear(this.getFullYear() + number);
|
|
1896
|
-
break;
|
|
1897
|
-
case "q":
|
|
1898
|
-
date.setMonth(this.getMonth() + number * 3);
|
|
1899
|
-
break;
|
|
1900
|
-
case "M":
|
|
1901
|
-
date.setMonth(this.getMonth() + number);
|
|
1902
|
-
break;
|
|
1903
|
-
case "w":
|
|
1904
|
-
date.setDate(this.getDate() + number * 7);
|
|
1905
|
-
break;
|
|
1906
|
-
case "d":
|
|
1907
|
-
date.setDate(this.getDate() + number);
|
|
1908
|
-
break;
|
|
1909
|
-
case "h":
|
|
1910
|
-
date.setHours(this.getHours() + number);
|
|
1911
|
-
break;
|
|
1912
|
-
case "m":
|
|
1913
|
-
date.setMinutes(this.getMinutes() + number);
|
|
1914
|
-
break;
|
|
1915
|
-
case "s":
|
|
1916
|
-
date.setSeconds(this.getSeconds() + number);
|
|
1917
|
-
break;
|
|
1918
|
-
default:
|
|
1919
|
-
date.setDate(this.getDate() + number);
|
|
1920
|
-
break;
|
|
1734
|
+
interpolate({ x: x1, y: y1, z: z1 = 0 }, { x: x2, y: y2, z: z2 = 0 }, percent) {
|
|
1735
|
+
const dx = x2 - x1, dy = y2 - y1, dz = z2 - z1;
|
|
1736
|
+
return { x: x1 + dx * percent, y: y1 + dy * percent, z: z1 + dz * percent };
|
|
1921
1737
|
}
|
|
1922
|
-
return date;
|
|
1923
1738
|
};
|
|
1924
|
-
const
|
|
1925
|
-
lastMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth() - 1, 1),
|
|
1926
|
-
thisMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), 1),
|
|
1927
|
-
nextMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth() + 1, 1),
|
|
1928
|
-
lastWeekDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() + 1 - 7 - (/* @__PURE__ */ new Date()).getDay()),
|
|
1929
|
-
thisWeekDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() + 1 - (/* @__PURE__ */ new Date()).getDay()),
|
|
1930
|
-
nextWeekDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() + 1 + 7 - (/* @__PURE__ */ new Date()).getDay()),
|
|
1931
|
-
lastDayDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() - 1),
|
|
1932
|
-
thisDayDate: new Date((/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0)),
|
|
1933
|
-
nextDayDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() + 1),
|
|
1934
|
-
parseDate(str) {
|
|
1935
|
-
if (typeof str == "string") {
|
|
1936
|
-
var results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) *$/);
|
|
1937
|
-
if (results && results.length > 3) return new Date(parseInt(results[1]), parseInt(results[2]) - 1, parseInt(results[3]));
|
|
1938
|
-
results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) +(\d{1,2}):(\d{1,2}):(\d{1,2}) *$/);
|
|
1939
|
-
if (results && results.length > 6)
|
|
1940
|
-
return new Date(
|
|
1941
|
-
parseInt(results[1]),
|
|
1942
|
-
parseInt(results[2]) - 1,
|
|
1943
|
-
parseInt(results[3]),
|
|
1944
|
-
parseInt(results[4]),
|
|
1945
|
-
parseInt(results[5]),
|
|
1946
|
-
parseInt(results[6])
|
|
1947
|
-
);
|
|
1948
|
-
results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) +(\d{1,2}):(\d{1,2}):(\d{1,2})\.(\d{1,9}) *$/);
|
|
1949
|
-
if (results && results.length > 7)
|
|
1950
|
-
return new Date(
|
|
1951
|
-
parseInt(results[1]),
|
|
1952
|
-
parseInt(results[2]) - 1,
|
|
1953
|
-
parseInt(results[3]),
|
|
1954
|
-
parseInt(results[4]),
|
|
1955
|
-
parseInt(results[5]),
|
|
1956
|
-
parseInt(results[6]),
|
|
1957
|
-
parseInt(results[7])
|
|
1958
|
-
);
|
|
1959
|
-
}
|
|
1960
|
-
return null;
|
|
1961
|
-
},
|
|
1739
|
+
const StringUtil = {
|
|
1962
1740
|
/**
|
|
1963
|
-
*
|
|
1741
|
+
* 校验字符串是否符合指定类型
|
|
1964
1742
|
*
|
|
1965
|
-
* @param
|
|
1966
|
-
* @param
|
|
1967
|
-
*
|
|
1743
|
+
* @param str 待校验字符串
|
|
1744
|
+
* @param type 校验类型,可选值包括:
|
|
1745
|
+
* - 'phone': 手机号码
|
|
1746
|
+
* - 'tel': 座机
|
|
1747
|
+
* - 'card': 身份证
|
|
1748
|
+
* - 'pwd': 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线)
|
|
1749
|
+
* - 'postal': 邮政编码
|
|
1750
|
+
* - 'QQ': QQ号
|
|
1751
|
+
* - 'email': 邮箱
|
|
1752
|
+
* - 'money': 金额(小数点2位)
|
|
1753
|
+
* - 'URL': 网址
|
|
1754
|
+
* - 'IP': IP地址
|
|
1755
|
+
* - 'date': 日期时间
|
|
1756
|
+
* - 'number': 数字
|
|
1757
|
+
* - 'english': 英文
|
|
1758
|
+
* - 'chinese': 中文
|
|
1759
|
+
* - 'lower': 小写字母
|
|
1760
|
+
* - 'upper': 大写字母
|
|
1761
|
+
* - 'HTML': HTML标记
|
|
1762
|
+
* @returns 校验结果,符合返回true,否则返回false
|
|
1968
1763
|
*/
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1764
|
+
checkStr(str, type) {
|
|
1765
|
+
switch (type) {
|
|
1766
|
+
case "phone":
|
|
1767
|
+
return /^1[3|4|5|6|7|8|9][0-9]{9}$/.test(str);
|
|
1768
|
+
case "tel":
|
|
1769
|
+
return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);
|
|
1770
|
+
case "card":
|
|
1771
|
+
return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(str);
|
|
1772
|
+
case "pwd":
|
|
1773
|
+
return /^[a-zA-Z]\w{5,17}$/.test(str);
|
|
1774
|
+
case "postal":
|
|
1775
|
+
return /[1-9]\d{5}(?!\d)/.test(str);
|
|
1776
|
+
case "QQ":
|
|
1777
|
+
return /^[1-9][0-9]{4,9}$/.test(str);
|
|
1778
|
+
case "email":
|
|
1779
|
+
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
|
|
1780
|
+
case "money":
|
|
1781
|
+
return /^\d*(?:\.\d{0,2})?$/.test(str);
|
|
1782
|
+
case "URL":
|
|
1783
|
+
return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(str);
|
|
1784
|
+
case "IP":
|
|
1785
|
+
return /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/.test(str);
|
|
1786
|
+
case "date":
|
|
1787
|
+
return /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/.test(str) || /^(\d{4})\-(\d{2})\-(\d{2})$/.test(str);
|
|
1788
|
+
case "number":
|
|
1789
|
+
return /^[0-9]$/.test(str);
|
|
1790
|
+
case "english":
|
|
1791
|
+
return /^[a-zA-Z]+$/.test(str);
|
|
1792
|
+
case "chinese":
|
|
1793
|
+
return /^[\u4E00-\u9FA5]+$/.test(str);
|
|
1794
|
+
case "lower":
|
|
1795
|
+
return /^[a-z]+$/.test(str);
|
|
1796
|
+
case "upper":
|
|
1797
|
+
return /^[A-Z]+$/.test(str);
|
|
1798
|
+
case "HTML":
|
|
1799
|
+
return /<("[^"]*"|'[^']*'|[^'">])*>/.test(str);
|
|
1800
|
+
default:
|
|
1801
|
+
return true;
|
|
1995
1802
|
}
|
|
1996
|
-
return intervalDes;
|
|
1997
1803
|
},
|
|
1998
|
-
formatterCounter(times) {
|
|
1999
|
-
const checked = function(j) {
|
|
2000
|
-
return (j > 10 ? "" : "0") + (j || 0);
|
|
2001
|
-
};
|
|
2002
|
-
const houres = checked(Math.floor(times / 3600));
|
|
2003
|
-
const level1 = times % 3600;
|
|
2004
|
-
const minutes = checked(Math.floor(level1 / 60));
|
|
2005
|
-
const leave2 = level1 % 60;
|
|
2006
|
-
const seconds = checked(Math.round(leave2));
|
|
2007
|
-
return `${houres}:${minutes}:${seconds}`;
|
|
2008
|
-
},
|
|
2009
|
-
sleep(d) {
|
|
2010
|
-
}
|
|
2011
|
-
};
|
|
2012
|
-
function trim(str) {
|
|
2013
|
-
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, "");
|
|
2014
|
-
}
|
|
2015
|
-
function splitWords(str) {
|
|
2016
|
-
return trim(str).split(/\s+/);
|
|
2017
|
-
}
|
|
2018
|
-
const DomUtil = {
|
|
2019
1804
|
/**
|
|
2020
|
-
*
|
|
1805
|
+
* 转换字符串大小写
|
|
2021
1806
|
*
|
|
2022
|
-
* @param
|
|
2023
|
-
* @param
|
|
2024
|
-
*
|
|
1807
|
+
* @param str 待转换的字符串
|
|
1808
|
+
* @param type 转换类型,可选值为 1-5,默认为 4
|
|
1809
|
+
* 1:首字母大写,其余小写
|
|
1810
|
+
* 2:首字母小写,其余大写
|
|
1811
|
+
* 3:字母大小写反转
|
|
1812
|
+
* 4:全部大写
|
|
1813
|
+
* 5:全部小写
|
|
1814
|
+
* @returns 转换后的字符串
|
|
2025
1815
|
*/
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
1816
|
+
changeCase(str, type) {
|
|
1817
|
+
type = type || 4;
|
|
1818
|
+
switch (type) {
|
|
1819
|
+
case 1:
|
|
1820
|
+
return str.replace(/\b\w+\b/g, function(word) {
|
|
1821
|
+
return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase();
|
|
1822
|
+
});
|
|
1823
|
+
case 2:
|
|
1824
|
+
return str.replace(/\b\w+\b/g, function(word) {
|
|
1825
|
+
return word.substring(0, 1).toLowerCase() + word.substring(1).toUpperCase();
|
|
1826
|
+
});
|
|
1827
|
+
case 3:
|
|
1828
|
+
return str.split("").map(function(word) {
|
|
1829
|
+
if (/[a-z]/.test(word)) {
|
|
1830
|
+
return word.toUpperCase();
|
|
1831
|
+
} else {
|
|
1832
|
+
return word.toLowerCase();
|
|
1833
|
+
}
|
|
1834
|
+
}).join("");
|
|
1835
|
+
case 4:
|
|
1836
|
+
return str.toUpperCase();
|
|
1837
|
+
case 5:
|
|
1838
|
+
return str.toLowerCase();
|
|
1839
|
+
default:
|
|
1840
|
+
return str;
|
|
2033
1841
|
}
|
|
2034
|
-
return value;
|
|
2035
1842
|
},
|
|
2036
1843
|
/**
|
|
2037
|
-
*
|
|
1844
|
+
* 根据字符串数组和参数生成新的字符串
|
|
2038
1845
|
*
|
|
2039
|
-
* @param
|
|
2040
|
-
* @param
|
|
2041
|
-
* @
|
|
2042
|
-
* @returns 返回新创建的HTML元素
|
|
1846
|
+
* @param strArray 字符串数组
|
|
1847
|
+
* @param args 可变参数列表,支持 Object、Array 类型和任意其他类型,若为 null 或 undefined,则按类型默认转换为 '{}'、'[]' 或 ''
|
|
1848
|
+
* @returns 返回生成的新字符串
|
|
2043
1849
|
*/
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
1850
|
+
tag(strArray, ...args) {
|
|
1851
|
+
args = args.map((val) => {
|
|
1852
|
+
switch (CommUtil.getDataType(val)) {
|
|
1853
|
+
case "Object":
|
|
1854
|
+
return val || "{}";
|
|
1855
|
+
case "Array":
|
|
1856
|
+
return val || "[]";
|
|
1857
|
+
default:
|
|
1858
|
+
return val || "";
|
|
1859
|
+
}
|
|
1860
|
+
});
|
|
1861
|
+
return strArray.reduce((prev, next, index) => `${prev}${args[index - 1]}${next}`);
|
|
2051
1862
|
},
|
|
2052
1863
|
/**
|
|
2053
|
-
*
|
|
1864
|
+
* 计算字符串的字节长度
|
|
2054
1865
|
*
|
|
2055
|
-
* @param
|
|
1866
|
+
* @param str 需要计算字节长度的字符串
|
|
1867
|
+
* @returns 返回字符串的字节长度
|
|
2056
1868
|
*/
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
if (parent) {
|
|
2060
|
-
parent.removeChild(el);
|
|
2061
|
-
}
|
|
1869
|
+
getByteLength(str) {
|
|
1870
|
+
return str.replace(/[\u0391-\uFFE5]/g, "aa").length;
|
|
2062
1871
|
},
|
|
2063
1872
|
/**
|
|
2064
|
-
*
|
|
1873
|
+
* 截取字符串中指定字节长度的子串
|
|
2065
1874
|
*
|
|
2066
|
-
* @param
|
|
1875
|
+
* @param str 字符串对象,包含replace、length和substring方法
|
|
1876
|
+
* @param start 截取起始位置
|
|
1877
|
+
* @param n 截取字节长度
|
|
1878
|
+
* @returns 返回截取后的子串
|
|
2067
1879
|
*/
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
1880
|
+
subStringByte(str, start, n) {
|
|
1881
|
+
var r = /[^\x00-\xff]/g;
|
|
1882
|
+
if (str.replace(r, "mm").length <= n) {
|
|
1883
|
+
return str;
|
|
2071
1884
|
}
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
toFront(el) {
|
|
2079
|
-
const parent = el.parentNode;
|
|
2080
|
-
if (parent && parent.lastChild !== el) {
|
|
2081
|
-
parent.appendChild(el);
|
|
1885
|
+
var m = Math.floor(n / 2);
|
|
1886
|
+
for (var i = m; i < str.length; i++) {
|
|
1887
|
+
let sub = str.substring(start, i);
|
|
1888
|
+
if (sub.replace(r, "mm").length >= n) {
|
|
1889
|
+
return sub;
|
|
1890
|
+
}
|
|
2082
1891
|
}
|
|
1892
|
+
return str;
|
|
1893
|
+
}
|
|
1894
|
+
};
|
|
1895
|
+
const ColorUtil = {
|
|
1896
|
+
random() {
|
|
1897
|
+
let r = Math.floor(Math.random() * 256).toString(16);
|
|
1898
|
+
let g = Math.floor(Math.random() * 256).toString(16);
|
|
1899
|
+
let b = Math.floor(Math.random() * 256).toString(16);
|
|
1900
|
+
r = r.length === 1 ? "0" + r : r;
|
|
1901
|
+
g = g.length === 1 ? "0" + g : g;
|
|
1902
|
+
b = b.length === 1 ? "0" + b : b;
|
|
1903
|
+
return "#" + r + g + b;
|
|
2083
1904
|
},
|
|
2084
1905
|
/**
|
|
2085
|
-
*
|
|
1906
|
+
* 将RGB颜色值转换为十六进制颜色值
|
|
2086
1907
|
*
|
|
2087
|
-
* @param
|
|
1908
|
+
* @param rgb RGB颜色值数组,包含三个0-255之间的整数
|
|
1909
|
+
* @returns 转换后的十六进制颜色值,以#开头
|
|
2088
1910
|
*/
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
parent.insertBefore(el, parent.firstChild);
|
|
2093
|
-
}
|
|
1911
|
+
rgb2hex(rgb) {
|
|
1912
|
+
var hex = "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1);
|
|
1913
|
+
return hex;
|
|
2094
1914
|
},
|
|
2095
1915
|
/**
|
|
2096
|
-
*
|
|
1916
|
+
* 将RGB颜色值转换为RGBA颜色值,并返回转换后的颜色值。
|
|
2097
1917
|
*
|
|
2098
|
-
* @param
|
|
2099
|
-
* @
|
|
2100
|
-
* @param el.className 类名对象
|
|
2101
|
-
* @param el.className.baseVal 类名字符串
|
|
2102
|
-
* @returns 返回元素的类名字符串
|
|
1918
|
+
* @param rgbValue RGB颜色值,格式为"rgb(r, g, b)"。
|
|
1919
|
+
* @returns 转换后的RGBA颜色值,格式为"rgba(r, g, b, 1)"。如果输入值不符合RGB格式,则返回原值。
|
|
2103
1920
|
*/
|
|
2104
|
-
|
|
2105
|
-
const
|
|
2106
|
-
return
|
|
1921
|
+
rgbToRgba(rgbValue) {
|
|
1922
|
+
const rgb = /rgb\((\d+,\s*[\d]+,\s*[\d]+)\)/g.exec(rgbValue);
|
|
1923
|
+
return rgb ? `rgba(${rgb[1]}, 1)` : rgbValue;
|
|
2107
1924
|
},
|
|
2108
1925
|
/**
|
|
2109
|
-
*
|
|
1926
|
+
* 将十六进制颜色值转换为rgba格式的颜色值
|
|
2110
1927
|
*
|
|
2111
|
-
* @param
|
|
2112
|
-
* @
|
|
2113
|
-
* @returns 返回一个布尔值,表示元素是否包含指定类名
|
|
1928
|
+
* @param hexValue 十六进制颜色值,可带或不带#前缀,支持3位和6位表示
|
|
1929
|
+
* @returns 返回rgba格式的颜色值,格式为rgba(r,g,b,1)
|
|
2114
1930
|
*/
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
1931
|
+
hexToRgba(hexValue) {
|
|
1932
|
+
const rgxShort = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
|
1933
|
+
const hex = hexValue.replace(rgxShort, (m, r2, g2, b2) => r2 + r2 + g2 + g2 + b2 + b2);
|
|
1934
|
+
const rgx = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
|
|
1935
|
+
const rgb = rgx.exec(hex);
|
|
1936
|
+
if (!rgb) {
|
|
1937
|
+
return hexValue;
|
|
2119
1938
|
}
|
|
2120
|
-
const
|
|
2121
|
-
|
|
1939
|
+
const r = parseInt(rgb[1], 16);
|
|
1940
|
+
const g = parseInt(rgb[2], 16);
|
|
1941
|
+
const b = parseInt(rgb[3], 16);
|
|
1942
|
+
return `rgba(${r},${g},${b},1)`;
|
|
2122
1943
|
},
|
|
2123
1944
|
/**
|
|
2124
|
-
*
|
|
1945
|
+
* 将 HSL 颜色值转换为 RGBA 颜色值
|
|
2125
1946
|
*
|
|
2126
|
-
* @param
|
|
2127
|
-
* @
|
|
1947
|
+
* @param hslValue HSL 颜色值字符串,格式为 "hsl(h, s%, l%)" 或 "hsla(h, s%, l%, a)",其中 h 为色相,s 为饱和度,l 为亮度,a 为透明度(可选)。
|
|
1948
|
+
* @returns 转换后的 RGBA 颜色值字符串,格式为 "rgba(r, g, b, a)",其中 r、g、b 为红绿蓝分量,a 为透明度。若输入为空或无效,则返回 null。
|
|
2128
1949
|
*/
|
|
2129
|
-
|
|
2130
|
-
if (
|
|
2131
|
-
|
|
2132
|
-
for (let i = 0, len = classes.length; i < len; i++) {
|
|
2133
|
-
el.classList.add(classes[i]);
|
|
2134
|
-
}
|
|
2135
|
-
} else if (!this.hasClass(el, name)) {
|
|
2136
|
-
const className = this.getClass(el);
|
|
2137
|
-
this.setClass(el, (className ? className + " " : "") + name);
|
|
1950
|
+
hslToRgba(hslValue) {
|
|
1951
|
+
if (!hslValue) {
|
|
1952
|
+
return null;
|
|
2138
1953
|
}
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
1954
|
+
const hsl = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(hslValue) || /hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(hslValue);
|
|
1955
|
+
if (!hsl) {
|
|
1956
|
+
return null;
|
|
1957
|
+
}
|
|
1958
|
+
const h = parseInt(hsl[1], 10) / 360;
|
|
1959
|
+
const s = parseInt(hsl[2], 10) / 100;
|
|
1960
|
+
const l = parseInt(hsl[3], 10) / 100;
|
|
1961
|
+
const a = hsl[4] ? parseFloat(hsl[4]) : 1;
|
|
1962
|
+
function hue2rgb(p, q, t) {
|
|
1963
|
+
if (t < 0) t += 1;
|
|
1964
|
+
if (t > 1) t -= 1;
|
|
1965
|
+
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
1966
|
+
if (t < 1 / 2) return q;
|
|
1967
|
+
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
1968
|
+
return p;
|
|
1969
|
+
}
|
|
1970
|
+
let r, g, b;
|
|
1971
|
+
if (s === 0) {
|
|
1972
|
+
r = g = b = l;
|
|
2150
1973
|
} else {
|
|
2151
|
-
|
|
1974
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
1975
|
+
const p = 2 * l - q;
|
|
1976
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
1977
|
+
g = hue2rgb(p, q, h);
|
|
1978
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
2152
1979
|
}
|
|
1980
|
+
return `rgba(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)},${a})`;
|
|
2153
1981
|
},
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
*
|
|
2157
|
-
* @param el HTML 或 SVG 元素
|
|
2158
|
-
* @param name 要设置的类名,多个类名之间用空格分隔
|
|
2159
|
-
*/
|
|
2160
|
-
setClass(el, name) {
|
|
2161
|
-
if ("classList" in el) {
|
|
2162
|
-
el.classList.value = "";
|
|
2163
|
-
name.split(" ").forEach((className) => el.classList.add(className));
|
|
2164
|
-
}
|
|
1982
|
+
isHex(a) {
|
|
1983
|
+
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(a);
|
|
2165
1984
|
},
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
1985
|
+
isRgb(a) {
|
|
1986
|
+
return /^rgb/.test(a);
|
|
1987
|
+
},
|
|
1988
|
+
isHsl(a) {
|
|
1989
|
+
return /^hsl/.test(a);
|
|
1990
|
+
},
|
|
1991
|
+
isColor(a) {
|
|
1992
|
+
return this.isHex(a) || this.isRgb(a) || this.isHsl(a);
|
|
1993
|
+
},
|
|
1994
|
+
colorToRgb(val) {
|
|
1995
|
+
if (this.isRgb(val)) return this.rgbToRgba(val);
|
|
1996
|
+
if (this.isHex(val)) return this.hexToRgba(val);
|
|
1997
|
+
if (this.isHsl(val)) return this.hslToRgba(val);
|
|
2176
1998
|
}
|
|
2177
1999
|
};
|
|
2178
2000
|
const TYPES = ["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon"];
|
|
@@ -2365,309 +2187,772 @@ const GeoJsonUtil = {
|
|
|
2365
2187
|
break;
|
|
2366
2188
|
}
|
|
2367
2189
|
}
|
|
2368
|
-
if (fType) {
|
|
2369
|
-
for (let i = 0, len = coordinates.length; i < len; i++) {
|
|
2370
|
-
features.push({
|
|
2371
|
-
type: "Feature",
|
|
2372
|
-
geometry: {
|
|
2373
|
-
type: fType,
|
|
2374
|
-
coordinates: coordinates[i]
|
|
2375
|
-
},
|
|
2376
|
-
properties
|
|
2377
|
-
});
|
|
2190
|
+
if (fType) {
|
|
2191
|
+
for (let i = 0, len = coordinates.length; i < len; i++) {
|
|
2192
|
+
features.push({
|
|
2193
|
+
type: "Feature",
|
|
2194
|
+
geometry: {
|
|
2195
|
+
type: fType,
|
|
2196
|
+
coordinates: coordinates[i]
|
|
2197
|
+
},
|
|
2198
|
+
properties
|
|
2199
|
+
});
|
|
2200
|
+
}
|
|
2201
|
+
} else {
|
|
2202
|
+
features.push(feature);
|
|
2203
|
+
}
|
|
2204
|
+
return features;
|
|
2205
|
+
},
|
|
2206
|
+
/**
|
|
2207
|
+
* 根据坐标数组生成GeoJSON要素
|
|
2208
|
+
*
|
|
2209
|
+
* @param coordinates 坐标数组
|
|
2210
|
+
* @returns GeoJSONFeature 生成的GeoJSON要素
|
|
2211
|
+
* @throws Error 如果coordinates参数格式错误
|
|
2212
|
+
*/
|
|
2213
|
+
getGeoJsonByCoordinates(coordinates) {
|
|
2214
|
+
if (!Array.isArray(coordinates)) {
|
|
2215
|
+
throw Error("coordinates 参数格式错误");
|
|
2216
|
+
}
|
|
2217
|
+
let type;
|
|
2218
|
+
if (coordinates.length === 2 && typeof coordinates[0] === "number" && typeof coordinates[1] === "number") {
|
|
2219
|
+
type = "Point";
|
|
2220
|
+
} else if (Array.isArray(coordinates[0]) && coordinates[0].length === 2) {
|
|
2221
|
+
type = "LineString";
|
|
2222
|
+
} else if (Array.isArray(coordinates[0]) && Array.isArray(coordinates[0][0])) {
|
|
2223
|
+
const outerRing = coordinates[0];
|
|
2224
|
+
const isClosed = outerRing[0].join(",") === outerRing[outerRing.length - 1].join(",");
|
|
2225
|
+
if (isClosed) {
|
|
2226
|
+
type = "Polygon";
|
|
2227
|
+
} else if (coordinates.length > 1) {
|
|
2228
|
+
type = "MultiPolygon";
|
|
2229
|
+
} else {
|
|
2230
|
+
throw Error("coordinates 参数格式错误");
|
|
2231
|
+
}
|
|
2232
|
+
} else {
|
|
2233
|
+
throw Error("coordinates 参数格式错误");
|
|
2234
|
+
}
|
|
2235
|
+
return {
|
|
2236
|
+
type: "Feature",
|
|
2237
|
+
geometry: { type, coordinates }
|
|
2238
|
+
};
|
|
2239
|
+
}
|
|
2240
|
+
};
|
|
2241
|
+
const AssertUtil = {
|
|
2242
|
+
assertEmpty(...arg) {
|
|
2243
|
+
arg.forEach((a) => {
|
|
2244
|
+
if (CommUtil.isEmpty(a)) {
|
|
2245
|
+
throw Error("变量为空:>>>" + a);
|
|
2246
|
+
}
|
|
2247
|
+
});
|
|
2248
|
+
},
|
|
2249
|
+
assertNumber(...arg) {
|
|
2250
|
+
arg.forEach((a) => {
|
|
2251
|
+
if (!CommUtil.isNumber(a)) {
|
|
2252
|
+
throw Error("不是数字:>>>" + a);
|
|
2253
|
+
}
|
|
2254
|
+
});
|
|
2255
|
+
},
|
|
2256
|
+
assertArray(...arg) {
|
|
2257
|
+
arg.forEach((a) => {
|
|
2258
|
+
if (!CommUtil.isArray(a)) {
|
|
2259
|
+
throw Error(ErrorType.PARAMETER_ERROR_ARRAY + ":>>>" + a);
|
|
2260
|
+
}
|
|
2261
|
+
});
|
|
2262
|
+
},
|
|
2263
|
+
assertFunction(...arg) {
|
|
2264
|
+
arg.forEach((a) => {
|
|
2265
|
+
if (!CommUtil.isFunction(a)) {
|
|
2266
|
+
throw Error(ErrorType.PARAMETER_ERROR_FUNCTION + ":>>>" + a);
|
|
2267
|
+
}
|
|
2268
|
+
});
|
|
2269
|
+
},
|
|
2270
|
+
assertObject(...arg) {
|
|
2271
|
+
arg.forEach((a) => {
|
|
2272
|
+
if (!CommUtil.isObject(a)) {
|
|
2273
|
+
throw Error(ErrorType.PARAMETER_ERROR_OBJECT + ":>>>" + a);
|
|
2274
|
+
}
|
|
2275
|
+
});
|
|
2276
|
+
},
|
|
2277
|
+
assertColor(...arg) {
|
|
2278
|
+
arg.forEach((a) => {
|
|
2279
|
+
if (!ColorUtil.isColor(a)) {
|
|
2280
|
+
throw Error("颜色代码不正确:>>>" + a);
|
|
2281
|
+
}
|
|
2282
|
+
});
|
|
2283
|
+
},
|
|
2284
|
+
assertLnglat(...arg) {
|
|
2285
|
+
arg.forEach((a) => {
|
|
2286
|
+
if (!GeoUtil.isLnglat(a.lng, a.lat)) {
|
|
2287
|
+
throw Error(ErrorType.COORDINATE_ERROR + ":>>>" + a);
|
|
2288
|
+
}
|
|
2289
|
+
});
|
|
2290
|
+
},
|
|
2291
|
+
assertGeoJson(...arg) {
|
|
2292
|
+
arg.forEach((a) => {
|
|
2293
|
+
if (!GeoJsonUtil.isGeoJson(a)) {
|
|
2294
|
+
throw Error("不是GeoJSON:>>>" + a);
|
|
2295
|
+
}
|
|
2296
|
+
});
|
|
2297
|
+
},
|
|
2298
|
+
assertContain(str, ...args) {
|
|
2299
|
+
let res = false;
|
|
2300
|
+
const len = args.length || 0;
|
|
2301
|
+
for (let i = 0, l = len; i < l; i++) {
|
|
2302
|
+
res = str.indexOf(args[i]) >= 0;
|
|
2303
|
+
}
|
|
2304
|
+
if (res) {
|
|
2305
|
+
throw Error(ErrorType.STRING_CHECK_LOSS + ":>>>" + str);
|
|
2306
|
+
}
|
|
2307
|
+
},
|
|
2308
|
+
/**
|
|
2309
|
+
* 判断字符串是否合法
|
|
2310
|
+
*
|
|
2311
|
+
* @param value 待判断的字符串
|
|
2312
|
+
* @param type 字符串类型
|
|
2313
|
+
* @throws 当字符串不合法时,抛出错误,错误信息为“参数错误:>>>不是{typename}”
|
|
2314
|
+
*/
|
|
2315
|
+
assertLegal(value, type) {
|
|
2316
|
+
const bool = StringUtil.checkStr(value, type);
|
|
2317
|
+
let typename = "";
|
|
2318
|
+
switch (type) {
|
|
2319
|
+
case "phone":
|
|
2320
|
+
typename = "电话";
|
|
2321
|
+
break;
|
|
2322
|
+
case "tel":
|
|
2323
|
+
typename = "座机";
|
|
2324
|
+
break;
|
|
2325
|
+
case "card":
|
|
2326
|
+
typename = "身份证";
|
|
2327
|
+
break;
|
|
2328
|
+
case "pwd":
|
|
2329
|
+
typename = "密码";
|
|
2330
|
+
break;
|
|
2331
|
+
case "postal":
|
|
2332
|
+
typename = "邮政编码";
|
|
2333
|
+
break;
|
|
2334
|
+
case "QQ":
|
|
2335
|
+
typename = "QQ";
|
|
2336
|
+
break;
|
|
2337
|
+
case "email":
|
|
2338
|
+
typename = "邮箱";
|
|
2339
|
+
break;
|
|
2340
|
+
case "money":
|
|
2341
|
+
typename = "金额";
|
|
2342
|
+
break;
|
|
2343
|
+
case "URL":
|
|
2344
|
+
typename = "网址";
|
|
2345
|
+
break;
|
|
2346
|
+
case "IP":
|
|
2347
|
+
typename = "IP";
|
|
2348
|
+
break;
|
|
2349
|
+
case "date":
|
|
2350
|
+
typename = "日期时间";
|
|
2351
|
+
break;
|
|
2352
|
+
case "number":
|
|
2353
|
+
typename = "数字";
|
|
2354
|
+
break;
|
|
2355
|
+
case "english":
|
|
2356
|
+
typename = "英文";
|
|
2357
|
+
break;
|
|
2358
|
+
case "chinese":
|
|
2359
|
+
typename = "中文";
|
|
2360
|
+
break;
|
|
2361
|
+
case "lower":
|
|
2362
|
+
typename = "小写";
|
|
2363
|
+
break;
|
|
2364
|
+
case "upper":
|
|
2365
|
+
typename = "大写";
|
|
2366
|
+
break;
|
|
2367
|
+
case "HTML":
|
|
2368
|
+
typename = "HTML标记";
|
|
2369
|
+
break;
|
|
2370
|
+
}
|
|
2371
|
+
if (!bool) {
|
|
2372
|
+
throw Error(ErrorType.PARAMETER_ERROR + ":>>>不是" + typename);
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
};
|
|
2376
|
+
const BrowserUtil = {
|
|
2377
|
+
/**
|
|
2378
|
+
* 获取浏览器类型
|
|
2379
|
+
*
|
|
2380
|
+
* @returns 返回浏览器类型字符串,可能的值为 'IE'、'Firefox'、'Chrome'、'Opera'、'Safari' 或 'Unknown'
|
|
2381
|
+
*/
|
|
2382
|
+
getExplorer() {
|
|
2383
|
+
var explorer = window.navigator.userAgent;
|
|
2384
|
+
if (explorer.indexOf("MSIE") >= 0 || /Trident\//.test(explorer)) {
|
|
2385
|
+
return "IE";
|
|
2386
|
+
} else if (explorer.indexOf("Firefox") >= 0) {
|
|
2387
|
+
return "Firefox";
|
|
2388
|
+
} else if (explorer.indexOf("Chrome") >= 0) {
|
|
2389
|
+
return "Chrome";
|
|
2390
|
+
} else if (explorer.indexOf("Opera") >= 0) {
|
|
2391
|
+
return "Opera";
|
|
2392
|
+
} else if (explorer.indexOf("Safari") >= 0 && explorer.indexOf("Chrome") === -1) {
|
|
2393
|
+
return "Safari";
|
|
2394
|
+
}
|
|
2395
|
+
return "Unknown";
|
|
2396
|
+
},
|
|
2397
|
+
/**
|
|
2398
|
+
* 检测操作系统类型
|
|
2399
|
+
*
|
|
2400
|
+
* @returns 返回操作系统类型字符串,可能的值有:'MS Windows'、'Apple mac'、'Linux'、'Unix'
|
|
2401
|
+
*/
|
|
2402
|
+
detectOS() {
|
|
2403
|
+
let os_type = "";
|
|
2404
|
+
const windows = navigator.userAgent.indexOf("Windows", 0) != -1 ? 1 : 0;
|
|
2405
|
+
const mac = navigator.userAgent.indexOf("mac", 0) != -1 ? 1 : 0;
|
|
2406
|
+
const linux = navigator.userAgent.indexOf("Linux", 0) != -1 ? 1 : 0;
|
|
2407
|
+
const unix = navigator.userAgent.indexOf("X11", 0) != -1 ? 1 : 0;
|
|
2408
|
+
if (windows) os_type = "MS Windows";
|
|
2409
|
+
else if (mac) os_type = "Apple mac";
|
|
2410
|
+
else if (linux) os_type = "Linux";
|
|
2411
|
+
else if (unix) os_type = "Unix";
|
|
2412
|
+
return os_type;
|
|
2413
|
+
},
|
|
2414
|
+
/**
|
|
2415
|
+
* 切换全屏状态
|
|
2416
|
+
*
|
|
2417
|
+
* @param status 是否全屏
|
|
2418
|
+
*/
|
|
2419
|
+
switchFullScreen(status) {
|
|
2420
|
+
if (status) {
|
|
2421
|
+
const element = document.documentElement;
|
|
2422
|
+
if (element.requestFullscreen) {
|
|
2423
|
+
element.requestFullscreen();
|
|
2424
|
+
} else if ("msRequestFullscreen" in element) {
|
|
2425
|
+
element.msRequestFullscreen();
|
|
2426
|
+
} else if ("mozRequestFullScreen" in element) {
|
|
2427
|
+
element.mozRequestFullScreen();
|
|
2428
|
+
} else if ("webkitRequestFullscreen" in element) {
|
|
2429
|
+
element.webkitRequestFullscreen();
|
|
2430
|
+
}
|
|
2431
|
+
} else {
|
|
2432
|
+
if (document.exitFullscreen) {
|
|
2433
|
+
document.exitFullscreen();
|
|
2434
|
+
} else if ("msExitFullscreen" in document) {
|
|
2435
|
+
document.msExitFullscreen();
|
|
2436
|
+
} else if ("mozCancelFullScreen" in document) {
|
|
2437
|
+
document.mozCancelFullScreen();
|
|
2438
|
+
} else if ("webkitExitFullscreen" in document) {
|
|
2439
|
+
document.webkitExitFullscreen();
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
},
|
|
2443
|
+
/**
|
|
2444
|
+
* 刷新缩放比例
|
|
2445
|
+
*
|
|
2446
|
+
* @returns 无返回值
|
|
2447
|
+
*/
|
|
2448
|
+
refreshScale() {
|
|
2449
|
+
const baseWidth = document.documentElement.clientWidth || 0;
|
|
2450
|
+
const baseHeight = document.documentElement.clientHeight || 0;
|
|
2451
|
+
const appElement = document.getElementById("app");
|
|
2452
|
+
if (!appElement) return;
|
|
2453
|
+
const appStyle = appElement.style;
|
|
2454
|
+
const realRatio = baseWidth / baseHeight;
|
|
2455
|
+
const designRatio = 16 / 9;
|
|
2456
|
+
let scaleRate = baseWidth / 1920;
|
|
2457
|
+
if (realRatio > designRatio) {
|
|
2458
|
+
scaleRate = baseHeight / 1080;
|
|
2459
|
+
}
|
|
2460
|
+
appStyle.transformOrigin = "left top";
|
|
2461
|
+
appStyle.transform = `scale(${scaleRate}) translateX(-49.99%)`;
|
|
2462
|
+
appStyle.width = `${baseWidth / scaleRate}px`;
|
|
2463
|
+
},
|
|
2464
|
+
/**
|
|
2465
|
+
* 获取HTML字体大小
|
|
2466
|
+
*
|
|
2467
|
+
* @returns 无返回值,该函数会直接修改HTML元素的字体大小
|
|
2468
|
+
*/
|
|
2469
|
+
getHtmlFontSize() {
|
|
2470
|
+
const htmlwidth = document.documentElement.clientWidth || document.body.clientWidth;
|
|
2471
|
+
const htmlDom = document.querySelector("html");
|
|
2472
|
+
if (htmlDom) {
|
|
2473
|
+
htmlDom.style.fontSize = htmlwidth / 192 + "px";
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
};
|
|
2477
|
+
const CoordsUtil = {
|
|
2478
|
+
PI: 3.141592653589793,
|
|
2479
|
+
XPI: 3.141592653589793 * 3e3 / 180,
|
|
2480
|
+
delta(lat, lng) {
|
|
2481
|
+
const a = 6378245;
|
|
2482
|
+
const ee = 0.006693421622965943;
|
|
2483
|
+
let dLat = this.transformLat(lng - 105, lat - 35);
|
|
2484
|
+
let dLon = this.transformLon(lng - 105, lat - 35);
|
|
2485
|
+
const radLat = lat / 180 * this.PI;
|
|
2486
|
+
let magic = Math.sin(radLat);
|
|
2487
|
+
magic = 1 - ee * magic * magic;
|
|
2488
|
+
const sqrtMagic = Math.sqrt(magic);
|
|
2489
|
+
dLat = dLat * 180 / (a * (1 - ee) / (magic * sqrtMagic) * this.PI);
|
|
2490
|
+
dLon = dLon * 180 / (a / sqrtMagic * Math.cos(radLat) * this.PI);
|
|
2491
|
+
return { lat: dLat, lng: dLon };
|
|
2492
|
+
},
|
|
2493
|
+
/**
|
|
2494
|
+
* 判断经纬度是否不在中国境内
|
|
2495
|
+
*
|
|
2496
|
+
* @param lng 经度
|
|
2497
|
+
* @param lat 纬度
|
|
2498
|
+
* @returns 如果经纬度不在中国境内则返回true,否则返回false
|
|
2499
|
+
*/
|
|
2500
|
+
outOfChina(lng, lat) {
|
|
2501
|
+
if (lng < 72.004 || lng > 137.8347) {
|
|
2502
|
+
return true;
|
|
2503
|
+
}
|
|
2504
|
+
if (lat < 0.8293 || lat > 55.8271) {
|
|
2505
|
+
return true;
|
|
2506
|
+
}
|
|
2507
|
+
return false;
|
|
2508
|
+
},
|
|
2509
|
+
// WGS-84 to GCJ-02
|
|
2510
|
+
gcjEncrypt(wgsLat, wgsLon) {
|
|
2511
|
+
if (this.outOfChina(wgsLat, wgsLon)) {
|
|
2512
|
+
return { lat: wgsLat, lng: wgsLon };
|
|
2513
|
+
}
|
|
2514
|
+
const d = this.delta(wgsLat, wgsLon);
|
|
2515
|
+
return { lat: wgsLat + d.lat, lng: wgsLon + d.lng };
|
|
2516
|
+
},
|
|
2517
|
+
// GCJ-02 to WGS-84
|
|
2518
|
+
gcjDecrypt(gcjLat, gcjLon) {
|
|
2519
|
+
if (this.outOfChina(gcjLat, gcjLon)) {
|
|
2520
|
+
return { lat: gcjLat, lng: gcjLon };
|
|
2521
|
+
}
|
|
2522
|
+
const d = this.delta(gcjLat, gcjLon);
|
|
2523
|
+
return { lat: gcjLat - d.lat, lng: gcjLon - d.lng };
|
|
2524
|
+
},
|
|
2525
|
+
// GCJ-02 to WGS-84 exactly
|
|
2526
|
+
gcjDecryptExact(gcjLat, gcjLon) {
|
|
2527
|
+
const initDelta = 0.01;
|
|
2528
|
+
const threshold = 1e-9;
|
|
2529
|
+
let dLat = initDelta;
|
|
2530
|
+
let dLon = initDelta;
|
|
2531
|
+
let mLat = gcjLat - dLat;
|
|
2532
|
+
let mLon = gcjLon - dLon;
|
|
2533
|
+
let pLat = gcjLat + dLat;
|
|
2534
|
+
let pLon = gcjLon + dLon;
|
|
2535
|
+
let wgsLat = 0;
|
|
2536
|
+
let wgsLon = 0;
|
|
2537
|
+
let i = 0;
|
|
2538
|
+
while (1) {
|
|
2539
|
+
wgsLat = (mLat + pLat) / 2;
|
|
2540
|
+
wgsLon = (mLon + pLon) / 2;
|
|
2541
|
+
const tmp = this.gcjEncrypt(wgsLat, wgsLon);
|
|
2542
|
+
dLat = tmp.lat - gcjLat;
|
|
2543
|
+
dLon = tmp.lng - gcjLon;
|
|
2544
|
+
if (Math.abs(dLat) < threshold && Math.abs(dLon) < threshold) {
|
|
2545
|
+
break;
|
|
2378
2546
|
}
|
|
2379
|
-
|
|
2380
|
-
|
|
2547
|
+
if (dLat > 0) pLat = wgsLat;
|
|
2548
|
+
else mLat = wgsLat;
|
|
2549
|
+
if (dLon > 0) pLon = wgsLon;
|
|
2550
|
+
else mLon = wgsLon;
|
|
2551
|
+
if (++i > 1e4) break;
|
|
2381
2552
|
}
|
|
2382
|
-
return
|
|
2553
|
+
return { lat: wgsLat, lng: wgsLon };
|
|
2554
|
+
},
|
|
2555
|
+
// GCJ-02 to BD-09
|
|
2556
|
+
bdEncrypt(gcjLat, gcjLon) {
|
|
2557
|
+
const x = gcjLon;
|
|
2558
|
+
const y = gcjLat;
|
|
2559
|
+
const z = Math.sqrt(x * x + y * y) + 2e-5 * Math.sin(y * this.XPI);
|
|
2560
|
+
const theta = Math.atan2(y, x) + 3e-6 * Math.cos(x * this.XPI);
|
|
2561
|
+
const bdLon = z * Math.cos(theta) + 65e-4;
|
|
2562
|
+
const bdLat = z * Math.sin(theta) + 6e-3;
|
|
2563
|
+
return { lat: bdLat, lng: bdLon };
|
|
2564
|
+
},
|
|
2565
|
+
// BD-09 to GCJ-02
|
|
2566
|
+
bdDecrypt(bdLat, bdLon) {
|
|
2567
|
+
const x = bdLon - 65e-4;
|
|
2568
|
+
const y = bdLat - 6e-3;
|
|
2569
|
+
const z = Math.sqrt(x * x + y * y) - 2e-5 * Math.sin(y * this.XPI);
|
|
2570
|
+
const theta = Math.atan2(y, x) - 3e-6 * Math.cos(x * this.XPI);
|
|
2571
|
+
const gcjLon = z * Math.cos(theta);
|
|
2572
|
+
const gcjLat = z * Math.sin(theta);
|
|
2573
|
+
return { lat: gcjLat, lng: gcjLon };
|
|
2574
|
+
},
|
|
2575
|
+
// WGS-84 to Web mercator
|
|
2576
|
+
// mercatorLat -> y mercatorLon -> x
|
|
2577
|
+
mercatorEncrypt(wgsLat, wgsLon) {
|
|
2578
|
+
const x = wgsLon * 2003750834e-2 / 180;
|
|
2579
|
+
let y = Math.log(Math.tan((90 + wgsLat) * this.PI / 360)) / (this.PI / 180);
|
|
2580
|
+
y = y * 2003750834e-2 / 180;
|
|
2581
|
+
return { lat: y, lng: x };
|
|
2582
|
+
},
|
|
2583
|
+
// Web mercator to WGS-84
|
|
2584
|
+
// mercatorLat -> y mercatorLon -> x
|
|
2585
|
+
mercatorDecrypt(mercatorLat, mercatorLon) {
|
|
2586
|
+
const x = mercatorLon / 2003750834e-2 * 180;
|
|
2587
|
+
let y = mercatorLat / 2003750834e-2 * 180;
|
|
2588
|
+
y = 180 / this.PI * (2 * Math.atan(Math.exp(y * this.PI / 180)) - this.PI / 2);
|
|
2589
|
+
return { lat: y, lng: x };
|
|
2590
|
+
},
|
|
2591
|
+
transformLat(x, y) {
|
|
2592
|
+
let ret = -100 + 2 * x + 3 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
|
2593
|
+
ret += (20 * Math.sin(6 * x * this.PI) + 20 * Math.sin(2 * x * this.PI)) * 2 / 3;
|
|
2594
|
+
ret += (20 * Math.sin(y * this.PI) + 40 * Math.sin(y / 3 * this.PI)) * 2 / 3;
|
|
2595
|
+
ret += (160 * Math.sin(y / 12 * this.PI) + 320 * Math.sin(y * this.PI / 30)) * 2 / 3;
|
|
2596
|
+
return ret;
|
|
2597
|
+
},
|
|
2598
|
+
transformLon(x, y) {
|
|
2599
|
+
let ret = 300 + x + 2 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
|
2600
|
+
ret += (20 * Math.sin(6 * x * this.PI) + 20 * Math.sin(2 * x * this.PI)) * 2 / 3;
|
|
2601
|
+
ret += (20 * Math.sin(x * this.PI) + 40 * Math.sin(x / 3 * this.PI)) * 2 / 3;
|
|
2602
|
+
ret += (150 * Math.sin(x / 12 * this.PI) + 300 * Math.sin(x / 30 * this.PI)) * 2 / 3;
|
|
2603
|
+
return ret;
|
|
2383
2604
|
},
|
|
2384
2605
|
/**
|
|
2385
|
-
*
|
|
2606
|
+
* 生成指定范围内的随机经纬度坐标
|
|
2386
2607
|
*
|
|
2387
|
-
* @param
|
|
2388
|
-
* @
|
|
2389
|
-
* @
|
|
2608
|
+
* @param min 最小坐标,包含属性 x 和 y,分别表示最小经度和最小纬度
|
|
2609
|
+
* @param max 最大坐标,包含属性 x 和 y,分别表示最大经度和最大纬度
|
|
2610
|
+
* @returns 返回生成的随机经纬度坐标,包含属性 lat 和 lng,分别表示纬度和经度
|
|
2390
2611
|
*/
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2612
|
+
random({ x: minX, y: minY }, { x: maxX, y: maxY }) {
|
|
2613
|
+
return {
|
|
2614
|
+
lat: Math.random() * (maxY - minY) + minY,
|
|
2615
|
+
lng: Math.random() * (maxX - minX) + minX
|
|
2616
|
+
};
|
|
2617
|
+
},
|
|
2618
|
+
deCompose(arr, fn, context) {
|
|
2619
|
+
if (!Array.isArray(arr)) {
|
|
2620
|
+
return context ? fn.call(context, arr) : fn(arr);
|
|
2394
2621
|
}
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
if (
|
|
2404
|
-
|
|
2405
|
-
} else if (coordinates.length > 1) {
|
|
2406
|
-
type = "MultiPolygon";
|
|
2622
|
+
const result = [];
|
|
2623
|
+
let p, pp;
|
|
2624
|
+
for (let i = 0, len = arr.length; i < len; i++) {
|
|
2625
|
+
p = arr[i];
|
|
2626
|
+
if (CommUtil.isNil(p)) {
|
|
2627
|
+
result.push(null);
|
|
2628
|
+
continue;
|
|
2629
|
+
}
|
|
2630
|
+
if (Array.isArray(p)) {
|
|
2631
|
+
result.push(this.deCompose(p, fn, context));
|
|
2407
2632
|
} else {
|
|
2408
|
-
|
|
2633
|
+
pp = context ? fn.call(context, p) : fn(p);
|
|
2634
|
+
result.push(pp);
|
|
2409
2635
|
}
|
|
2410
|
-
} else {
|
|
2411
|
-
throw Error("coordinates 参数格式错误");
|
|
2412
2636
|
}
|
|
2413
|
-
return
|
|
2414
|
-
type: "Feature",
|
|
2415
|
-
geometry: { type, coordinates }
|
|
2416
|
-
};
|
|
2637
|
+
return result;
|
|
2417
2638
|
}
|
|
2418
2639
|
};
|
|
2419
|
-
const
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2640
|
+
const myDate = Object.create(Date);
|
|
2641
|
+
myDate.prototype.format = function(fmt = "yyyy-MM-dd hh:mm:ss") {
|
|
2642
|
+
const o = {
|
|
2643
|
+
"M+": this.getMonth() + 1,
|
|
2644
|
+
// 月份
|
|
2645
|
+
"d+": this.getDate(),
|
|
2646
|
+
// 日
|
|
2647
|
+
"h+": this.getHours() % 12,
|
|
2648
|
+
// 小时
|
|
2649
|
+
"H+": this.getHours(),
|
|
2650
|
+
// 小时 (24小时制)
|
|
2651
|
+
"m+": this.getMinutes(),
|
|
2652
|
+
// 分
|
|
2653
|
+
"s+": this.getSeconds(),
|
|
2654
|
+
// 秒
|
|
2655
|
+
"q+": Math.floor((this.getMonth() + 3) / 3),
|
|
2656
|
+
// 季度
|
|
2657
|
+
S: this.getMilliseconds()
|
|
2658
|
+
// 毫秒
|
|
2659
|
+
};
|
|
2660
|
+
if (/(y+)/.test(fmt)) {
|
|
2661
|
+
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
|
|
2662
|
+
}
|
|
2663
|
+
for (const k in o) {
|
|
2664
|
+
if (new RegExp("(" + k + ")").test(fmt)) {
|
|
2665
|
+
const len = k.length === 1 ? 1 : Number(k.slice(1));
|
|
2666
|
+
fmt = fmt.replace(RegExp.$1, ("00" + o[k]).substr(("" + o[k]).length + len - (o[k] + "").length));
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
return fmt;
|
|
2670
|
+
};
|
|
2671
|
+
myDate.prototype.addDate = function(interval, number) {
|
|
2672
|
+
const date = new Date(this);
|
|
2673
|
+
switch (interval) {
|
|
2674
|
+
case "y":
|
|
2675
|
+
date.setFullYear(this.getFullYear() + number);
|
|
2676
|
+
break;
|
|
2677
|
+
case "q":
|
|
2678
|
+
date.setMonth(this.getMonth() + number * 3);
|
|
2679
|
+
break;
|
|
2680
|
+
case "M":
|
|
2681
|
+
date.setMonth(this.getMonth() + number);
|
|
2682
|
+
break;
|
|
2683
|
+
case "w":
|
|
2684
|
+
date.setDate(this.getDate() + number * 7);
|
|
2685
|
+
break;
|
|
2686
|
+
case "d":
|
|
2687
|
+
date.setDate(this.getDate() + number);
|
|
2688
|
+
break;
|
|
2689
|
+
case "h":
|
|
2690
|
+
date.setHours(this.getHours() + number);
|
|
2691
|
+
break;
|
|
2692
|
+
case "m":
|
|
2693
|
+
date.setMinutes(this.getMinutes() + number);
|
|
2694
|
+
break;
|
|
2695
|
+
case "s":
|
|
2696
|
+
date.setSeconds(this.getSeconds() + number);
|
|
2697
|
+
break;
|
|
2698
|
+
default:
|
|
2699
|
+
date.setDate(this.getDate() + number);
|
|
2700
|
+
break;
|
|
2701
|
+
}
|
|
2702
|
+
return date;
|
|
2703
|
+
};
|
|
2704
|
+
const DateUtil = {
|
|
2705
|
+
lastMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth() - 1, 1),
|
|
2706
|
+
thisMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), 1),
|
|
2707
|
+
nextMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth() + 1, 1),
|
|
2708
|
+
lastWeekDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() + 1 - 7 - (/* @__PURE__ */ new Date()).getDay()),
|
|
2709
|
+
thisWeekDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() + 1 - (/* @__PURE__ */ new Date()).getDay()),
|
|
2710
|
+
nextWeekDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() + 1 + 7 - (/* @__PURE__ */ new Date()).getDay()),
|
|
2711
|
+
lastDayDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() - 1),
|
|
2712
|
+
thisDayDate: new Date((/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0)),
|
|
2713
|
+
nextDayDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() + 1),
|
|
2714
|
+
parseDate(str) {
|
|
2715
|
+
if (typeof str == "string") {
|
|
2716
|
+
var results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) *$/);
|
|
2717
|
+
if (results && results.length > 3) return new Date(parseInt(results[1]), parseInt(results[2]) - 1, parseInt(results[3]));
|
|
2718
|
+
results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) +(\d{1,2}):(\d{1,2}):(\d{1,2}) *$/);
|
|
2719
|
+
if (results && results.length > 6)
|
|
2720
|
+
return new Date(
|
|
2721
|
+
parseInt(results[1]),
|
|
2722
|
+
parseInt(results[2]) - 1,
|
|
2723
|
+
parseInt(results[3]),
|
|
2724
|
+
parseInt(results[4]),
|
|
2725
|
+
parseInt(results[5]),
|
|
2726
|
+
parseInt(results[6])
|
|
2727
|
+
);
|
|
2728
|
+
results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) +(\d{1,2}):(\d{1,2}):(\d{1,2})\.(\d{1,9}) *$/);
|
|
2729
|
+
if (results && results.length > 7)
|
|
2730
|
+
return new Date(
|
|
2731
|
+
parseInt(results[1]),
|
|
2732
|
+
parseInt(results[2]) - 1,
|
|
2733
|
+
parseInt(results[3]),
|
|
2734
|
+
parseInt(results[4]),
|
|
2735
|
+
parseInt(results[5]),
|
|
2736
|
+
parseInt(results[6]),
|
|
2737
|
+
parseInt(results[7])
|
|
2738
|
+
);
|
|
2739
|
+
}
|
|
2740
|
+
return null;
|
|
2431
2741
|
},
|
|
2432
2742
|
/**
|
|
2433
|
-
*
|
|
2743
|
+
* 格式化时间间隔
|
|
2434
2744
|
*
|
|
2435
|
-
* @param
|
|
2436
|
-
* @param
|
|
2437
|
-
* @returns
|
|
2745
|
+
* @param startTime 开始时间,可以是字符串、数字或日期类型
|
|
2746
|
+
* @param endTime 结束时间,可以是字符串、数字或日期类型
|
|
2747
|
+
* @returns 返回格式化后的时间间隔字符串,格式为"天数 天 小时 时 分钟 分 秒 秒"或"少于1秒"
|
|
2438
2748
|
*/
|
|
2439
|
-
|
|
2440
|
-
|
|
2749
|
+
formatDateInterval(startTime, endTime) {
|
|
2750
|
+
const dateCreateTime = new Date(startTime);
|
|
2751
|
+
const dateFinishTime = new Date(endTime);
|
|
2752
|
+
const dateInterval = dateFinishTime.getTime() - dateCreateTime.getTime();
|
|
2753
|
+
const days = Math.floor(dateInterval / (24 * 3600 * 1e3));
|
|
2754
|
+
const leave1 = dateInterval % (24 * 3600 * 1e3);
|
|
2755
|
+
const hours = Math.floor(leave1 / (3600 * 1e3));
|
|
2756
|
+
const leave2 = leave1 % (3600 * 1e3);
|
|
2757
|
+
const minutes = Math.floor(leave2 / (60 * 1e3));
|
|
2758
|
+
const leave3 = leave2 % (60 * 1e3);
|
|
2759
|
+
const seconds = Math.round(leave3 / 1e3);
|
|
2760
|
+
let intervalDes = "";
|
|
2761
|
+
if (days > 0) {
|
|
2762
|
+
intervalDes += days + "天";
|
|
2763
|
+
}
|
|
2764
|
+
if (hours > 0) {
|
|
2765
|
+
intervalDes += hours + "时";
|
|
2766
|
+
}
|
|
2767
|
+
if (minutes > 0) {
|
|
2768
|
+
intervalDes += minutes + "分";
|
|
2769
|
+
}
|
|
2770
|
+
if (seconds > 0) {
|
|
2771
|
+
intervalDes += seconds + "秒";
|
|
2772
|
+
}
|
|
2773
|
+
if (days === 0 && hours === 0 && minutes === 0 && seconds === 0) {
|
|
2774
|
+
intervalDes = "少于1秒";
|
|
2775
|
+
}
|
|
2776
|
+
return intervalDes;
|
|
2777
|
+
},
|
|
2778
|
+
formatterCounter(times) {
|
|
2779
|
+
const checked = function(j) {
|
|
2780
|
+
return (j > 10 ? "" : "0") + (j || 0);
|
|
2781
|
+
};
|
|
2782
|
+
const houres = checked(Math.floor(times / 3600));
|
|
2783
|
+
const level1 = times % 3600;
|
|
2784
|
+
const minutes = checked(Math.floor(level1 / 60));
|
|
2785
|
+
const leave2 = level1 % 60;
|
|
2786
|
+
const seconds = checked(Math.round(leave2));
|
|
2787
|
+
return `${houres}:${minutes}:${seconds}`;
|
|
2441
2788
|
},
|
|
2789
|
+
sleep(d) {
|
|
2790
|
+
}
|
|
2791
|
+
};
|
|
2792
|
+
function trim(str) {
|
|
2793
|
+
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, "");
|
|
2794
|
+
}
|
|
2795
|
+
function splitWords(str) {
|
|
2796
|
+
return trim(str).split(/\s+/);
|
|
2797
|
+
}
|
|
2798
|
+
const DomUtil = {
|
|
2442
2799
|
/**
|
|
2443
|
-
*
|
|
2800
|
+
* 获取元素的样式值
|
|
2444
2801
|
*
|
|
2445
|
-
* @param
|
|
2446
|
-
* @param
|
|
2447
|
-
* @returns
|
|
2802
|
+
* @param el 元素对象
|
|
2803
|
+
* @param style 样式属性名称
|
|
2804
|
+
* @returns 元素的样式值,如果获取不到则返回 null
|
|
2448
2805
|
*/
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
const alpha = Math.acos(s);
|
|
2459
|
-
const distance = alpha * earthR;
|
|
2460
|
-
return distance;
|
|
2806
|
+
getStyle(el, style) {
|
|
2807
|
+
var _a;
|
|
2808
|
+
let value = el.style[style];
|
|
2809
|
+
if (!value || value === "auto") {
|
|
2810
|
+
const css = (_a = document.defaultView) == null ? void 0 : _a.getComputedStyle(el, null);
|
|
2811
|
+
value = css ? css[style] : null;
|
|
2812
|
+
if (value === "auto") value = null;
|
|
2813
|
+
}
|
|
2814
|
+
return value;
|
|
2461
2815
|
},
|
|
2462
2816
|
/**
|
|
2463
|
-
*
|
|
2817
|
+
* 创建一个HTML元素
|
|
2464
2818
|
*
|
|
2465
|
-
* @param
|
|
2466
|
-
* @param
|
|
2467
|
-
* @
|
|
2819
|
+
* @param tagName 元素标签名
|
|
2820
|
+
* @param className 元素类名
|
|
2821
|
+
* @param container 父容器,若传入,则新创建的元素会被添加到该容器中
|
|
2822
|
+
* @returns 返回新创建的HTML元素
|
|
2468
2823
|
*/
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
const seconds = (valueInDegrees - degree) * 3600 - minutes * 60;
|
|
2475
|
-
return `${degree}°${minutes}′${seconds.toFixed(2)}″`;
|
|
2476
|
-
}
|
|
2477
|
-
if (this.isLnglat(lng, lat)) {
|
|
2478
|
-
res = formatDegreeToDMS(lng) + "," + formatDegreeToDMS(lat);
|
|
2479
|
-
} else if (!isNaN(lng)) {
|
|
2480
|
-
res = formatDegreeToDMS(lng);
|
|
2481
|
-
} else if (!isNaN(lat)) {
|
|
2482
|
-
res = formatDegreeToDMS(lat);
|
|
2824
|
+
create(tagName, className, container) {
|
|
2825
|
+
const el = document.createElement(tagName);
|
|
2826
|
+
el.className = className || "";
|
|
2827
|
+
if (container) {
|
|
2828
|
+
container.appendChild(el);
|
|
2483
2829
|
}
|
|
2484
|
-
return
|
|
2830
|
+
return el;
|
|
2485
2831
|
},
|
|
2486
2832
|
/**
|
|
2487
|
-
*
|
|
2833
|
+
* 从父节点中移除指定元素。
|
|
2488
2834
|
*
|
|
2489
|
-
* @param
|
|
2490
|
-
* @param lat 纬度字符串
|
|
2491
|
-
* @returns 转换后的经纬度对象
|
|
2835
|
+
* @param el 要移除的元素对象,必须包含parentNode属性。
|
|
2492
2836
|
*/
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
const numericParts = dmsString.match(/[\d.]+/g) || [];
|
|
2498
|
-
let degrees = 0;
|
|
2499
|
-
for (let i = 0; i < numericParts.length; i++) {
|
|
2500
|
-
degrees += parseFloat(numericParts[i]) / factor;
|
|
2501
|
-
factor *= 60;
|
|
2502
|
-
}
|
|
2503
|
-
return degrees;
|
|
2504
|
-
}
|
|
2505
|
-
if (lng && lat) {
|
|
2506
|
-
return {
|
|
2507
|
-
lng: dms2deg(lng),
|
|
2508
|
-
lat: dms2deg(lat)
|
|
2509
|
-
};
|
|
2837
|
+
remove(el) {
|
|
2838
|
+
const parent = el.parentNode;
|
|
2839
|
+
if (parent) {
|
|
2840
|
+
parent.removeChild(el);
|
|
2510
2841
|
}
|
|
2511
2842
|
},
|
|
2512
2843
|
/**
|
|
2513
|
-
*
|
|
2844
|
+
* 清空给定元素的子节点
|
|
2514
2845
|
*
|
|
2515
|
-
* @param
|
|
2516
|
-
* @param poly 多边形顶点数组,可以是字符串数组或对象数组
|
|
2517
|
-
* @returns 返回字符串,表示点相对于多边形的位置:'in'表示在多边形内,'out'表示在多边形外,'on'表示在多边形上
|
|
2846
|
+
* @param el 要清空子节点的元素,包含firstChild和removeChild属性
|
|
2518
2847
|
*/
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
var sx = poly[i].x, sy = poly[i].y, tx = poly[j].x, ty = poly[j].y;
|
|
2523
|
-
if (sx === px && sy === py || tx === px && ty === py) {
|
|
2524
|
-
return "on";
|
|
2525
|
-
}
|
|
2526
|
-
if (sy < py && ty >= py || sy >= py && ty < py) {
|
|
2527
|
-
var x = sx + (py - sy) * (tx - sx) / (ty - sy);
|
|
2528
|
-
if (x === px) {
|
|
2529
|
-
return "on";
|
|
2530
|
-
}
|
|
2531
|
-
if (x > px) {
|
|
2532
|
-
flag = !flag;
|
|
2533
|
-
}
|
|
2534
|
-
}
|
|
2848
|
+
empty(el) {
|
|
2849
|
+
while (el.firstChild) {
|
|
2850
|
+
el.removeChild(el.firstChild);
|
|
2535
2851
|
}
|
|
2536
|
-
return flag ? "in" : "out";
|
|
2537
2852
|
},
|
|
2538
2853
|
/**
|
|
2539
|
-
*
|
|
2854
|
+
* 将元素移到父节点的最前面
|
|
2540
2855
|
*
|
|
2541
|
-
* @param
|
|
2542
|
-
* @param p2 旋转中心坐标
|
|
2543
|
-
* @param θ 旋转角度(顺时针旋转为正)
|
|
2544
|
-
* @returns 旋转后点坐标
|
|
2856
|
+
* @param el 要移动的元素,需要包含 parentNode 属性
|
|
2545
2857
|
*/
|
|
2546
|
-
|
|
2547
|
-
const
|
|
2548
|
-
|
|
2549
|
-
|
|
2858
|
+
toFront(el) {
|
|
2859
|
+
const parent = el.parentNode;
|
|
2860
|
+
if (parent && parent.lastChild !== el) {
|
|
2861
|
+
parent.appendChild(el);
|
|
2862
|
+
}
|
|
2550
2863
|
},
|
|
2551
2864
|
/**
|
|
2552
|
-
*
|
|
2865
|
+
* 将元素移动到其父节点的最前面
|
|
2553
2866
|
*
|
|
2554
|
-
* @param
|
|
2555
|
-
* @param p2 第二个点的坐标对象
|
|
2556
|
-
* @returns 返回一个对象,包含angle和distance属性,分别表示两点之间的角度(以度为单位,取值范围为0~359)和距离
|
|
2867
|
+
* @param el 要移动的元素,需要包含parentNode属性
|
|
2557
2868
|
*/
|
|
2558
|
-
|
|
2559
|
-
const
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
2564
|
-
const angleInRadians = Math.atan2(dy, dx);
|
|
2565
|
-
const angle = (angleInRadians * (180 / Math.PI) + 360 + 90) % 360;
|
|
2566
|
-
return { angle, distance };
|
|
2869
|
+
toBack(el) {
|
|
2870
|
+
const parent = el.parentNode;
|
|
2871
|
+
if (parent && parent.firstChild !== el) {
|
|
2872
|
+
parent.insertBefore(el, parent.firstChild);
|
|
2873
|
+
}
|
|
2567
2874
|
},
|
|
2568
2875
|
/**
|
|
2569
|
-
*
|
|
2876
|
+
* 获取元素的类名
|
|
2570
2877
|
*
|
|
2571
|
-
* @param
|
|
2572
|
-
* @param
|
|
2573
|
-
* @
|
|
2878
|
+
* @param el 包含对应元素和类名的对象
|
|
2879
|
+
* @param el.correspondingElement 对应的元素
|
|
2880
|
+
* @param el.className 类名对象
|
|
2881
|
+
* @param el.className.baseVal 类名字符串
|
|
2882
|
+
* @returns 返回元素的类名字符串
|
|
2574
2883
|
*/
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
var x = Math.cos(f1 * this.toRadian) * Math.sin(f2 * this.toRadian) - Math.sin(f1 * this.toRadian) * Math.cos(f2 * this.toRadian) * Math.cos((l2 - l1) * this.toRadian);
|
|
2579
|
-
var angle = Math.atan2(y, x) * (180 / Math.PI);
|
|
2580
|
-
var deltaF = (f2 - f1) * this.toRadian;
|
|
2581
|
-
var deltaL = (l2 - l1) * this.toRadian;
|
|
2582
|
-
var a = Math.sin(deltaF / 2) * Math.sin(deltaF / 2) + Math.cos(f1 * this.toRadian) * Math.cos(f2 * this.toRadian) * Math.sin(deltaL / 2) * Math.sin(deltaL / 2);
|
|
2583
|
-
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
2584
|
-
var distance = this.R * c;
|
|
2585
|
-
return {
|
|
2586
|
-
angle,
|
|
2587
|
-
distance
|
|
2588
|
-
};
|
|
2884
|
+
getClass(el) {
|
|
2885
|
+
const shadowElement = (el == null ? void 0 : el.host) || el;
|
|
2886
|
+
return shadowElement.className.toString();
|
|
2589
2887
|
},
|
|
2590
2888
|
/**
|
|
2591
|
-
*
|
|
2889
|
+
* 判断元素是否包含指定类名
|
|
2592
2890
|
*
|
|
2593
|
-
* @param
|
|
2594
|
-
* @param
|
|
2595
|
-
* @
|
|
2596
|
-
* @returns 点P到线段P1P2的最短距离
|
|
2891
|
+
* @param el 元素对象,包含classList属性,classList属性包含contains方法
|
|
2892
|
+
* @param name 要判断的类名
|
|
2893
|
+
* @returns 返回一个布尔值,表示元素是否包含指定类名
|
|
2597
2894
|
*/
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
|
|
2603
|
-
}
|
|
2604
|
-
const d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
|
|
2605
|
-
if (cross >= d2) {
|
|
2606
|
-
return Math.sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
|
|
2895
|
+
hasClass(el, name) {
|
|
2896
|
+
var _a;
|
|
2897
|
+
if ((_a = el.classList) == null ? void 0 : _a.contains(name)) {
|
|
2898
|
+
return true;
|
|
2607
2899
|
}
|
|
2608
|
-
const
|
|
2609
|
-
|
|
2610
|
-
const py = y1 + (y2 - y1) * r;
|
|
2611
|
-
return Math.sqrt((x - px) * (x - px) + (y - py) * (y - py));
|
|
2900
|
+
const className = this.getClass(el);
|
|
2901
|
+
return className.length > 0 && new RegExp(`(^|\\s)${name}(\\s|$)`).test(className);
|
|
2612
2902
|
},
|
|
2613
2903
|
/**
|
|
2614
|
-
*
|
|
2904
|
+
* 给指定的 HTML 元素添加类名
|
|
2615
2905
|
*
|
|
2616
|
-
* @param
|
|
2617
|
-
* @param
|
|
2618
|
-
* @param distance 距离值,单位为米,表示从当前点出发的距离
|
|
2619
|
-
* @returns 返回计算后的新经纬度点,类型为{lat: number, lng: number}
|
|
2906
|
+
* @param el 要添加类名的 HTML 元素
|
|
2907
|
+
* @param name 要添加的类名,多个类名之间用空格分隔
|
|
2620
2908
|
*/
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
};
|
|
2909
|
+
addClass(el, name) {
|
|
2910
|
+
if (el.classList !== void 0) {
|
|
2911
|
+
const classes = splitWords(name);
|
|
2912
|
+
for (let i = 0, len = classes.length; i < len; i++) {
|
|
2913
|
+
el.classList.add(classes[i]);
|
|
2914
|
+
}
|
|
2915
|
+
} else if (!this.hasClass(el, name)) {
|
|
2916
|
+
const className = this.getClass(el);
|
|
2917
|
+
this.setClass(el, (className ? className + " " : "") + name);
|
|
2918
|
+
}
|
|
2632
2919
|
},
|
|
2633
2920
|
/**
|
|
2634
|
-
*
|
|
2921
|
+
* 从元素中移除指定类名
|
|
2635
2922
|
*
|
|
2636
|
-
* @param
|
|
2637
|
-
* @param
|
|
2638
|
-
* @returns 返回包含转换后的经度lng和纬度lat的对象
|
|
2923
|
+
* @param el 要移除类名的元素
|
|
2924
|
+
* @param name 要移除的类名,多个类名用空格分隔
|
|
2639
2925
|
*/
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2926
|
+
removeClass(el, name) {
|
|
2927
|
+
if (el.classList !== void 0) {
|
|
2928
|
+
const classes = splitWords(name);
|
|
2929
|
+
classes.forEach((className) => el.classList.remove(className));
|
|
2930
|
+
} else {
|
|
2931
|
+
this.setClass(el, (" " + this.getClass(el) + " ").replace(" " + name + " ", " ").trim());
|
|
2932
|
+
}
|
|
2645
2933
|
},
|
|
2646
2934
|
/**
|
|
2647
|
-
*
|
|
2935
|
+
* 设置元素的 CSS 类名
|
|
2648
2936
|
*
|
|
2649
|
-
* @param
|
|
2650
|
-
* @param
|
|
2651
|
-
* @returns 墨卡托坐标对象,包含x和y属性
|
|
2937
|
+
* @param el HTML 或 SVG 元素
|
|
2938
|
+
* @param name 要设置的类名,多个类名之间用空格分隔
|
|
2652
2939
|
*/
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
return { x, y };
|
|
2940
|
+
setClass(el, name) {
|
|
2941
|
+
if ("classList" in el) {
|
|
2942
|
+
el.classList.value = "";
|
|
2943
|
+
name.split(" ").forEach((className) => el.classList.add(className));
|
|
2944
|
+
}
|
|
2659
2945
|
},
|
|
2660
2946
|
/**
|
|
2661
|
-
*
|
|
2947
|
+
* 从字符串中解析XML文档,并返回根节点
|
|
2662
2948
|
*
|
|
2663
|
-
* @param
|
|
2664
|
-
* @
|
|
2665
|
-
* @param percent 百分比,取值范围0-1
|
|
2666
|
-
* @returns 返回插值后的坐标
|
|
2949
|
+
* @param str 要解析的XML字符串
|
|
2950
|
+
* @returns 解析后的XML文档的根节点
|
|
2667
2951
|
*/
|
|
2668
|
-
|
|
2669
|
-
const
|
|
2670
|
-
|
|
2952
|
+
parseFromString(str) {
|
|
2953
|
+
const parser = new DOMParser();
|
|
2954
|
+
const doc = parser.parseFromString(str, "text/xml");
|
|
2955
|
+
return doc.children[0];
|
|
2671
2956
|
}
|
|
2672
2957
|
};
|
|
2673
2958
|
const FileUtil = {
|
|
@@ -2861,162 +3146,6 @@ const OptimizeUtil = {
|
|
|
2861
3146
|
};
|
|
2862
3147
|
}
|
|
2863
3148
|
};
|
|
2864
|
-
const StringUtil = {
|
|
2865
|
-
/**
|
|
2866
|
-
* 校验字符串是否符合指定类型
|
|
2867
|
-
*
|
|
2868
|
-
* @param str 待校验字符串
|
|
2869
|
-
* @param type 校验类型,可选值包括:
|
|
2870
|
-
* - 'phone': 手机号码
|
|
2871
|
-
* - 'tel': 座机
|
|
2872
|
-
* - 'card': 身份证
|
|
2873
|
-
* - 'pwd': 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线)
|
|
2874
|
-
* - 'postal': 邮政编码
|
|
2875
|
-
* - 'QQ': QQ号
|
|
2876
|
-
* - 'email': 邮箱
|
|
2877
|
-
* - 'money': 金额(小数点2位)
|
|
2878
|
-
* - 'URL': 网址
|
|
2879
|
-
* - 'IP': IP地址
|
|
2880
|
-
* - 'date': 日期时间
|
|
2881
|
-
* - 'number': 数字
|
|
2882
|
-
* - 'english': 英文
|
|
2883
|
-
* - 'chinese': 中文
|
|
2884
|
-
* - 'lower': 小写字母
|
|
2885
|
-
* - 'upper': 大写字母
|
|
2886
|
-
* - 'HTML': HTML标记
|
|
2887
|
-
* @returns 校验结果,符合返回true,否则返回false
|
|
2888
|
-
*/
|
|
2889
|
-
checkStr(str, type) {
|
|
2890
|
-
switch (type) {
|
|
2891
|
-
case "phone":
|
|
2892
|
-
return /^1[3|4|5|6|7|8|9][0-9]{9}$/.test(str);
|
|
2893
|
-
case "tel":
|
|
2894
|
-
return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);
|
|
2895
|
-
case "card":
|
|
2896
|
-
return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(str);
|
|
2897
|
-
case "pwd":
|
|
2898
|
-
return /^[a-zA-Z]\w{5,17}$/.test(str);
|
|
2899
|
-
case "postal":
|
|
2900
|
-
return /[1-9]\d{5}(?!\d)/.test(str);
|
|
2901
|
-
case "QQ":
|
|
2902
|
-
return /^[1-9][0-9]{4,9}$/.test(str);
|
|
2903
|
-
case "email":
|
|
2904
|
-
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
|
|
2905
|
-
case "money":
|
|
2906
|
-
return /^\d*(?:\.\d{0,2})?$/.test(str);
|
|
2907
|
-
case "URL":
|
|
2908
|
-
return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(str);
|
|
2909
|
-
case "IP":
|
|
2910
|
-
return /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/.test(str);
|
|
2911
|
-
case "date":
|
|
2912
|
-
return /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/.test(str) || /^(\d{4})\-(\d{2})\-(\d{2})$/.test(str);
|
|
2913
|
-
case "number":
|
|
2914
|
-
return /^[0-9]$/.test(str);
|
|
2915
|
-
case "english":
|
|
2916
|
-
return /^[a-zA-Z]+$/.test(str);
|
|
2917
|
-
case "chinese":
|
|
2918
|
-
return /^[\u4E00-\u9FA5]+$/.test(str);
|
|
2919
|
-
case "lower":
|
|
2920
|
-
return /^[a-z]+$/.test(str);
|
|
2921
|
-
case "upper":
|
|
2922
|
-
return /^[A-Z]+$/.test(str);
|
|
2923
|
-
case "HTML":
|
|
2924
|
-
return /<("[^"]*"|'[^']*'|[^'">])*>/.test(str);
|
|
2925
|
-
default:
|
|
2926
|
-
return true;
|
|
2927
|
-
}
|
|
2928
|
-
},
|
|
2929
|
-
/**
|
|
2930
|
-
* 转换字符串大小写
|
|
2931
|
-
*
|
|
2932
|
-
* @param str 待转换的字符串
|
|
2933
|
-
* @param type 转换类型,可选值为 1-5,默认为 4
|
|
2934
|
-
* 1:首字母大写,其余小写
|
|
2935
|
-
* 2:首字母小写,其余大写
|
|
2936
|
-
* 3:字母大小写反转
|
|
2937
|
-
* 4:全部大写
|
|
2938
|
-
* 5:全部小写
|
|
2939
|
-
* @returns 转换后的字符串
|
|
2940
|
-
*/
|
|
2941
|
-
changeCase(str, type) {
|
|
2942
|
-
type = type || 4;
|
|
2943
|
-
switch (type) {
|
|
2944
|
-
case 1:
|
|
2945
|
-
return str.replace(/\b\w+\b/g, function(word) {
|
|
2946
|
-
return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase();
|
|
2947
|
-
});
|
|
2948
|
-
case 2:
|
|
2949
|
-
return str.replace(/\b\w+\b/g, function(word) {
|
|
2950
|
-
return word.substring(0, 1).toLowerCase() + word.substring(1).toUpperCase();
|
|
2951
|
-
});
|
|
2952
|
-
case 3:
|
|
2953
|
-
return str.split("").map(function(word) {
|
|
2954
|
-
if (/[a-z]/.test(word)) {
|
|
2955
|
-
return word.toUpperCase();
|
|
2956
|
-
} else {
|
|
2957
|
-
return word.toLowerCase();
|
|
2958
|
-
}
|
|
2959
|
-
}).join("");
|
|
2960
|
-
case 4:
|
|
2961
|
-
return str.toUpperCase();
|
|
2962
|
-
case 5:
|
|
2963
|
-
return str.toLowerCase();
|
|
2964
|
-
default:
|
|
2965
|
-
return str;
|
|
2966
|
-
}
|
|
2967
|
-
},
|
|
2968
|
-
/**
|
|
2969
|
-
* 根据字符串数组和参数生成新的字符串
|
|
2970
|
-
*
|
|
2971
|
-
* @param strArray 字符串数组
|
|
2972
|
-
* @param args 可变参数列表,支持 Object、Array 类型和任意其他类型,若为 null 或 undefined,则按类型默认转换为 '{}'、'[]' 或 ''
|
|
2973
|
-
* @returns 返回生成的新字符串
|
|
2974
|
-
*/
|
|
2975
|
-
tag(strArray, ...args) {
|
|
2976
|
-
args = args.map((val) => {
|
|
2977
|
-
switch (CommUtils.getDataType(val)) {
|
|
2978
|
-
case "Object":
|
|
2979
|
-
return val || "{}";
|
|
2980
|
-
case "Array":
|
|
2981
|
-
return val || "[]";
|
|
2982
|
-
default:
|
|
2983
|
-
return val || "";
|
|
2984
|
-
}
|
|
2985
|
-
});
|
|
2986
|
-
return strArray.reduce((prev, next, index) => `${prev}${args[index - 1]}${next}`);
|
|
2987
|
-
},
|
|
2988
|
-
/**
|
|
2989
|
-
* 计算字符串的字节长度
|
|
2990
|
-
*
|
|
2991
|
-
* @param str 需要计算字节长度的字符串
|
|
2992
|
-
* @returns 返回字符串的字节长度
|
|
2993
|
-
*/
|
|
2994
|
-
getByteLength(str) {
|
|
2995
|
-
return str.replace(/[\u0391-\uFFE5]/g, "aa").length;
|
|
2996
|
-
},
|
|
2997
|
-
/**
|
|
2998
|
-
* 截取字符串中指定字节长度的子串
|
|
2999
|
-
*
|
|
3000
|
-
* @param str 字符串对象,包含replace、length和substring方法
|
|
3001
|
-
* @param start 截取起始位置
|
|
3002
|
-
* @param n 截取字节长度
|
|
3003
|
-
* @returns 返回截取后的子串
|
|
3004
|
-
*/
|
|
3005
|
-
subStringByte(str, start, n) {
|
|
3006
|
-
var r = /[^\x00-\xff]/g;
|
|
3007
|
-
if (str.replace(r, "mm").length <= n) {
|
|
3008
|
-
return str;
|
|
3009
|
-
}
|
|
3010
|
-
var m = Math.floor(n / 2);
|
|
3011
|
-
for (var i = m; i < str.length; i++) {
|
|
3012
|
-
let sub = str.substring(start, i);
|
|
3013
|
-
if (sub.replace(r, "mm").length >= n) {
|
|
3014
|
-
return sub;
|
|
3015
|
-
}
|
|
3016
|
-
}
|
|
3017
|
-
return str;
|
|
3018
|
-
}
|
|
3019
|
-
};
|
|
3020
3149
|
const UrlUtil = {
|
|
3021
3150
|
/**
|
|
3022
3151
|
* 将json对象转换为查询字符串
|
|
@@ -3069,6 +3198,7 @@ const UrlUtil = {
|
|
|
3069
3198
|
export {
|
|
3070
3199
|
AjaxUtil,
|
|
3071
3200
|
ArrayUtil,
|
|
3201
|
+
AssertUtil,
|
|
3072
3202
|
AudioPlayer,
|
|
3073
3203
|
BrowserUtil,
|
|
3074
3204
|
CanvasDrawer,
|
|
@@ -3097,6 +3227,6 @@ export {
|
|
|
3097
3227
|
Storage,
|
|
3098
3228
|
StringUtil,
|
|
3099
3229
|
UrlUtil,
|
|
3100
|
-
|
|
3230
|
+
CommUtil as Util,
|
|
3101
3231
|
WebSocketClient
|
|
3102
3232
|
};
|