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