rc-bmap
Version:
<p align="center"> <img src="https://bmap.jser-club.com/home.png" width="200px"> </p> <p align="center">基于 React 的百度地图组件</p>
316 lines (286 loc) • 7.58 kB
JavaScript
import isEqual from 'lodash.isequal';
import BMapUtil from './map';
const numberRe = /^[0-9]+.?[0-9]*/;
/**
* 是否为Point
* @param {*} point
*/
const isPoint = point => numberRe.test(point.lng) && typeof numberRe.test(point.lat);
/**
* 是否为BMap.Point
* @param {*} point
*/
const isBPoint = point => isPoint(point) && point.equals;
/**
* 是否为Size
* @param {*} point
*/
const isSize = size => numberRe.test(size.width) && typeof numberRe.test(size.height);
/**
* 是否为BMap.Size
* @param {*} size
*/
const isBSize = size => isSize(size) && size.equals;
/**
* 是否为矩形范围
* @param {*} bounds
*/
const isBounds = bounds => numberRe.test(bounds.sw) && numberRe.test(bounds.ne);
/**
* 是否为BMap.Bounds
* @param {*} bounds
*/
const isBBounds = bounds => isBounds(bounds) && bounds.equals;
/**
* 是否为空
* @param {*} obj
*/
const isNil = obj => obj === undefined || obj === null;
/**
* 是否为字符串
* @param {*} str
*/
const isString = str => typeof str === 'string';
/**
* 首字母转为大写
* @param {*} str
*/
const firstUpperCase = str => str.replace(/^\S/, s => s.toUpperCase());
/**
* 首字母转为小写
* @param {*} str
*/
const firstLowerCase = str => str.replace(/^\S/, s => s.toLowerCase());
/**
* 获取行政区包含点集合
* @param {*} name 行政区名称
*/
const getBoundary = name => new Promise((resolve, reject) => {
const boundary = new global.BMap.Boundary();
boundary.get(name, (res) => {
const count = res.boundaries.length;
if (count === 0) {
reject();
}
const area = [];
let allPoints = [];
for (let i = 0; i < count; i += 1) {
const arr = res.boundaries[i].split(';').map((item) => {
const pointArr = item.split(',');
return BMapUtil.BPoint({ lng: pointArr[0], lat: pointArr[1].trim() });
});
allPoints = allPoints.concat(arr);
area.push(arr);
}
resolve({
area,
points: allPoints,
});
});
});
/**
* 将传入值转换为 BMap.Point
* @param {*} point 点对象 { lng, lat }
* @param {*} propsName 用于错误提示
*/
const convert2BPoint = (point, propsName = 'point') => {
if (isNil(point)) {
throw Error(`Missing property \`${propsName}\``);
}
if (!isPoint(point)) {
throw Error(`The \`${propsName}\` property should be a literal value \`{ lng, lat }\``);
} else if (!isBPoint(point)) {
point = BMapUtil.BPoint({ ...point });
}
return point;
};
/**
* 将传入值转换为 BMap.Size
* @param {*} point 矩形尺寸 { width, height }
* @param {*} propsName 用于错误提示
*/
const convert2BSize = (size, propsName = 'size') => {
if (isNil(size)) {
throw Error(`Missing property \`${propsName}\``);
}
if (!isSize(size)) {
throw Error(`The \`${propsName}\` property should be a literal value \`{ width, height }\``);
}
if (!isBSize(size)) {
size = BMapUtil.BSize({ ...size });
}
return size;
};
/**
* 将值转换为 BMap.Bounds
* @param {*} point 矩形区域 { sw, ne }
* @param {*} propsName 用于错误提示
*/
const convert2BBounds = (bounds, propsName = 'bounds') => {
if (isNil(bounds)) {
throw Error(`Missing property \`${propsName}\``);
}
if (!isBounds(bounds)) {
throw Error(`The \`${propsName}\` property should be a literal value \`{ width, height }\``);
}
if (!isBBounds(bounds)) {
bounds = BMapUtil.BBounds({ ...bounds });
}
return bounds;
};
/**
* 为目标对象绑定事件
* @param {*} target 目标对象
* @param {*} events 事件集合
*/
const bindEvents = (target, events = {}) => {
Object.keys(events).forEach((eventName) => {
const eventType = typeof events[eventName];
if (eventType !== 'function') {
console.warn(`Events's props value should be a function, but got '${eventType}'`);
}
const callback = (...args) => {
if (eventType === 'function') {
events[eventName].call(null, ...args);
}
};
target.events = target.events || {};
target.addEventListener(eventName, callback);
target.events[`${eventName}`] = callback;
});
};
/**
* 将目标对象中已绑定事件移除
* @param {*} target
*/
const unbindEvents = (target) => {
const { events = {} } = target;
Object.keys(events).forEach((eventName) => {
const event = events[eventName];
target.removeEventListener(eventName, event);
});
target.events = {};
};
/**
* 处理 target.setXXX 方法
* @param {*} target 目标对象
* @param {*} options 属性集合
* @param {*} values 值集合
*/
const processSetOptions = (target, options, values) => {
options.forEach((key) => {
if (values[key] || typeof values[key] === 'boolean') {
const upKey = firstUpperCase(key);
if (target[`set${upKey}`]) {
target[`set${upKey}`](values[key]);
}
}
});
};
/**
* 处理 target.enableXXX 、 target.disableXXX 方法
* @param {*} target 目标对象
* @param {*} options 属性集合
* @param {*} values 值集合
*/
const processBooleanOptions = (target, options, values) => {
options.forEach((key) => {
if (values[key] || typeof values[key] === 'boolean') {
const upKey = firstUpperCase(key);
const prefix = values[key] ? 'enable' : 'disable';
if (target[`${prefix}${upKey}`]) {
target[`${prefix}${upKey}`]();
}
}
});
};
/**
* 比较新旧config,返回差异集合
* @param {*} oldConfig
* @param {*} newConfig
*/
const compareConfig = (oldConfig, newConfig) => {
const result = { ...oldConfig, ...newConfig };
const keys = Object.keys(result);
for (let i = 0, len = keys.length; i < len; i += 1) {
const key = keys[i];
if (!isNil(oldConfig[key]) && isEqual(oldConfig[key], result[key])) {
delete result[key];
}
}
return result;
};
/**
* 转换Control配置项
* @param {*} param0
*/
const convertControlOptions = ({ anchor, offset }) => {
const result = {};
if (anchor) {
result.anchor = !isNil(global[anchor]) ? global[anchor] : anchor;
}
if (offset) {
result.offset = convert2BSize(offset, 'offset');
}
return result;
};
/**
* 处理Control显示隐藏
* @param {*} target
* @param {*} visible
*/
const processControlVisible = (target, visible) => {
if (!isNil(target) && !isNil(visible)) {
return visible ? target.show() : target.hide();
}
return null;
};
const libScriptsMap = {};
/**
* 同步请求第三方script
* @param {*} src script链接
*
* 此处保证每个script在整个文档流中有且只有一个,不重复添加
*/
const syncScript = (src) => {
let scriptLoader = libScriptsMap[src];
if (!scriptLoader) {
// eslint-disable-next-line no-multi-assign
libScriptsMap[src] = scriptLoader = new Promise((resolved) => {
const script = document.createElement('script');
script.src = src;
// eslint-disable-next-line no-multi-assign
script.onload = script.onreadystatechange = function loaded() {
// for IE
if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
resolved();
}
};
document.head.appendChild(script);
});
}
return scriptLoader;
};
export default {
syncScript,
isPoint,
isBPoint,
isSize,
isBSize,
isBounds,
isBBounds,
isNil,
isString,
getBoundary,
convert2BPoint,
convert2BSize,
convert2BBounds,
bindEvents,
unbindEvents,
processSetOptions,
processBooleanOptions,
compareConfig,
firstLowerCase,
convertControlOptions,
processControlVisible,
};