桥(PATH/index.js)
let module;
const modules=import.meta.glob('./vendors/*.js'),
init=async ()=>{
if(!module){
const res=await request_LBS_config();
module=await modules['./vendors/'+res.vendor+'.js']();
await module.init(res.config);
}
return module;
};
export async function initMap(dom,center=null){
if(!center){
const location=await getLocation();
center={
longitude:location.latitude,
longitude:location.longitude
};
}
const {MapComponent}=await init();
await MapComponent.init();
const map=new MapComponent(dom,center);
return map;
};
export class MapLabel {
id;
style;
position;
rank;
text;
constructor(id,style,position,text,{rank=0}={}){
Object.assign(this,{id,style,position,text,rank});
}
};
export class MapMarker {
id;
style;
position;
rank;
text;
constructor(id,style,position,text,{rank=0}={}){
Object.assign(this,{id,style,position,text,rank});
}
};
export class MapComponent {
setCenter(position){ throw new Error('setCenter 方法未实现'); }
addLabelStyle(id,offset,font,extra={}){ throw new Error('addLabelStyle 方法未实现'); }
addLabels(labels){ throw new Error('addLabels 方法未实现'); }
addMarkerStyle(id,icon,label={}){ throw new Error('addMarkerStyle 方法未实现'); }
addMarkers(markers){ throw new Error('addMarkers 方法未实现'); }
clear(){ throw new Error('clear 方法未实现'); }
static async init(){ throw new Error('init 方法未实现'); }
};
export async function chooseLocationByIFrame(iframe,callback,options={}){
const {initLocationChooser}=await init(),
listener=initLocationChooser(iframe,callback,options);
window.addEventListener('message',listener);
return ()=>{
window.removeEventListener('message',listener);
};
};
腾讯LBS(PATH/vendors/Tencent.js)
let config;
export function init(cfg){
config=cfg;
}
import {MapComponent as MapInterface} from '../index';
export class MapComponent extends MapInterface {
#map;
constructor(dom,center){
super();
this.#map=new window.TMap.Map(dom,{
center:new window.TMap.LatLng(center.latitude,center.longitude),
zoom:20,
viewMode:'2D'
});
}
setCenter(position){
this.#map.setCenter(new window.TMap.LatLng(position.latitude,position.longitude));
return this;
}
#labelStyles={};
addLabelStyle(id,offset,font,{padding='',backgroundColor=null,border=null,align=null}={}){
this.#labelStyles[id]=new window.TMap.LabelStyle({
offset,
size:font.size*0.8-3,
color:font.color,
padding,
backgroundColor,
});
if(border){
Object.assign(this.#labelStyles[id],{
borderWidth:border.width,
borderColor:border.color,
});
}
if(align){
Object.assign(this.#labelStyles[id],{
verticalAlignment:align.v,
alignment:align.h,
});
}
return this;
}
#labelLayer;
#labels=new Set();
addLabels(labels){
const geometries=labels.map(l=>{
this.#labels.add(l.id);
return {
id:l.id,
styleId:l.style,
position:new window.TMap.LatLng(l.position.latitude,l.position.longitude),
rank:l.rank,
content:l.text,
};
});
if(!this.#labelLayer){
this.#labelLayer=new window.TMap.MultiLabel({
styles:this.#labelStyles,
map:this.#map,
geometries,
});
}else{
this.#labelLayer.add(geometries);
}
}
#markerStyles={};
addMarkerStyle(id,icon,label={}){
const options={
src:icon.src,
width:icon.width,
height:icon.height,
color:label.color,
padding:label.padding,
backgroundColor:label.backgroundColor,
direction:label.direction||'bottom',
fontSize:label.size||12,
};
if(icon.anchor){
options.anchor={
x:{
left:0,
center:icon.width/2,
right:icon.width,
}[icon.anchor.h],
y:{
top:0,
middle:icon.height/2,
bottom:icon.height,
}[icon.anchor.v],
};
}else{
options.anchor={
x:icon.width/2,
y:icon.height/2,
};
}
if(icon.offset){
options.anchor.x-=icon.offset.x;
options.anchor.y-=icon.offset.y;
}
if(label.border){
Object.assign(this.#labelStyles[id],{
backgroundBorderWidth:label.border.width,
backgroundBorderColor:label.border.color,
});
}
this.#markerStyles[id]=new window.TMap.MarkerStyle(options);
return this;
}
#markerLayer;
#markers=new Set();
addMarkers(markers){
const geometries=markers.map(m=>{
this.#markers.add(m.id);
return {
id:m.id,
styleId:m.style,
position:new window.TMap.LatLng(m.position.latitude,m.position.longitude),
rank:m.rank,
content:m.text,
};
});
if(!this.#markerLayer){
this.#markerLayer=new window.TMap.MultiMarker({
styles:this.#markerStyles,
map:this.#map,
geometries,
});
}else{
this.#markerLayer.add(geometries);
}
}
clear(){
this.#labelLayer.remove([...this.#labels]);
this.#labels.clear();
this.#markerLayer.remove([...this.#markers]);
this.#markers.clear();
}
static async init(){
if(!window.TMap){
await loadScript(`https://map.qq.com/api/gljs?v=1.exp&key=${config.key}&libraries=visualization`);
}
}
}
export function initLocationChooser(iframe,callback,{center={},radius=1000,zoom=18,total=50}){
let src='https://apis.map.qq.com/tools/locpicker?type=1&mapdraggable=1&search=1&key='+config.key
+'&referer='+config.app
+'&radius='+radius
+'&total='+total
+'&zoom='+zoom;
if(center.latitude&¢er.longitude){
src+=`&coord=${center.latitude},${center.longitude}`;
}
iframe.setAttribute('src',src);
return e=>{
if(e.data.module==='locationPicker'&&e.source===iframe.contentWindow){
callback({
name:e.data.poiname,
address:e.data.poiaddress,
latitude:e.data.latlng.lat,
longitude:e.data.latlng.lng,
});
}
};
}
高德开放平台(PATH/vendors/AutoNavi.js)
let config;
export function init(cfg){
config=cfg;
}
import {MapComponent as MapInterface} from '../index';
export class MapComponent extends MapInterface {
#map;
constructor(dom,center){
super();
this.#map=new window.AMap.Map(dom,{
center:[center.longitude,center.latitude],
zoom:20,
viewMode:'2D'
});
}
setCenter(position){
this.#map.setCenter([position.longitude,position.latitude]);
return this;
}
#labelStyles={};
addLabelStyle(id,offset,font,{padding=0,backgroundColor='transparent',border=null,align=null}={}){
this.#labelStyles[id]={
offset:new window.AMap.Pixel(offset.x,offset.y),
style:{
fontSize:font.size+'px',
color:font.color,
padding,
backgroundColor,
border:border?border.width+'px solid '+border.color:'none',
},
align,
};
return this;
}
#labels=new Map();
addLabels(labels){
labels.forEach(l=>{
const options={
extData:{
id:l.id,
},
position:new window.AMap.LngLat(l.position.longitude,l.position.latitude),
zIndex:l.rank,
text:l.text,
};
if(l.style){
const style=this.#labelStyles[l.style];
options.style=style.style;
options.offset=style.offset;
options.anchor=style.align?style.align.v+'-'+style.align.h:'center';
}else{
options.anchor='center';
}
const overlay=new window.AMap.Text(options);
this.#labels.get(l.id)?.remove();
this.#labels.set(l.id,overlay);
this.#map.add(overlay);
});
}
#markerStyles={};
addMarkerStyle(id,icon,label={}){
const mapIcon={
image:icon.src,
size:[icon.width,icon.height],
anchor:icon.anchor?icon.anchor.v+'-'+icon.anchor.h:'center',
},
labelStyle={
fontSize:label.size||12,
padding:label.padding||0,
backgroundColor:label.backgroundColor||'rgba(0,0,0,0)',
border:label.border?label.border.width+'px solid '+label.border.color:'none',
};
if(label.color){
labelStyle.fillColor=label.color;
}
if(icon.offset){
mapIcon.offset=new window.AMap.Pixel(icon.offset.x,icon.offset.y);
}
this.#markerStyles[id]={
icon:mapIcon,
label:{
offset:[0,-labelStyle.fontSize/2],
direction:label.direction||'bottom',
style:labelStyle,
},
};
return this;
}
#LabelsLayer;
#markers=new Map();
addMarkers(markers){
if(!this.#LabelsLayer){
this.#LabelsLayer=new window.AMap.LabelsLayer({
collision: true,
opacity: 1,
zIndex: 120,
allowCollision: true,
});
this.#map.add(this.#LabelsLayer);
}
markers.forEach(m=>{
const options={
name:m.id,
position:new window.AMap.LngLat(m.position.longitude,m.position.latitude),
zIndex:m.rank,
rank:m.rank,
};
if(m.style){
options.icon=this.#markerStyles[m.style].icon;
}
if(m.text){
options.text={content:m.text};
if(m.style){
Object.assign(
options.text,
this.#markerStyles[m.style].label
);
}
}
const overlay=new window.AMap.LabelMarker(options);
this.#markers.get(m.id)?.remove();
this.#markers.set(m.id,overlay);
this.#LabelsLayer.add(overlay);
});
}
clear(){
this.#map.remove([...this.#labels.values()]);
this.#labels.clear();
this.#LabelsLayer.remove([...this.#markers.values()]);
this.#markers.clear();
}
static async init(){
if(!window.AMapLoader){
window._AMapSecurityConfig = {
securityJsCode: config.jscode,
};
await loadScript('https://webapi.amap.com/loader.js');
await window.AMapLoader.load({
key: config.key,
version: '2.0',
});
}
}
}
export function initLocationChooser(iframe,callback,{center={},radius=1000,zoom=18,total=50}){
let src=`https://m.amap.com/picker/?key=`+config.key
+'&jscode='+config.jscode
+'&radius='+radius
+'&total='+total
+'&zoom='+zoom;
if(center.latitude&¢er.longitude){
src+=`¢er=${center.longitude},${center.latitude}`;
}
iframe.setAttribute('src',src);
iframe.onload = function(){
iframe.contentWindow.postMessage('hello','https://m.amap.com/picker/');
};
return e=>{
if(e.source===iframe.contentWindow&&e.data.location){
const [longitude,latitude]=e.data.location.split(',');
callback({
name:e.data.name,
address:e.data.address,
latitude:Number(latitude),
longitude:Number(longitude),
});
}
};
}
示例
const res=await getSignInList(),
labels=[],
markers=[];
res.list.forEach(u=>{
labels.push(new MapLabel(
u.id+'_t',
'time',
u.signIn,
this.format(u.signIn.time),
{rank:u.signIn.time}
));
if(u.student?.number){
labels.push(new MapLabel(
u.id+'_n',
'number_'+u.sex.name,
u.signIn,
u.student.number,
{rank:u.signIn.time+1}
))
}
markers.push(new MapMarker(
u.id,
'student_'+u.sex.name,
u.signIn,
u.chinese?.name||u.nickname,
{rank:u.signIn.time}
));
});
let calssRoom;
if(this.lesson.room){
calssRoom=this.lesson.room.building.position;
markers.push(new MapMarker('-1','class_room',calssRoom,'教室:'+this.lesson.room.name));
}
let center=calssRoom;
const scheet=this.lesson.sheets.length===1?this.lesson.sheets[0]:
(this.conds.sheet?this.lesson.sheets.find(s=>s.id===this.conds.sheet):null);
if(scheet){
if(scheet.room){
center=scheet.room.building.position;
markers.push(new MapMarker('0','sign_in',center,'签到地点:'+scheet.room.name));
}else if(scheet.latitude&&scheet.longitude){
center=scheet;
markers.push(new MapMarker('0','sign_in',center,'室外签到点'));
}
}
if(!signInMap){
signInMap=await initMap(this.$refs.signInMap,center);
signInMap.addLabelStyle('time',{x:0,y:-25},{size:10,color:'#999999'})
.addLabelStyle('number_unknown',{x:0,y:20},{size:13,color:'#19a97b'})
.addLabelStyle('number_boy',{x:0,y:20},{size:13,color:'#1296db'})
.addLabelStyle('number_girl',{x:0,y:20},{size:13,color:'#d4237a'})
.addMarkerStyle(
'class_room',
{
width:30,
height:30,
src:'/src/img/icons/classRoom.png',
anchor:{h:'right',v:'middle'},
},
{direction:'left'},
).addMarkerStyle(
'sign_in',
{
width:30,
height:30,
src:'/src/img/icons/signInScheet.png',
anchor:{h:'left',v:'middle'},
},
{direction:'right'},
).addMarkerStyle(
'student_unknown',
{
width:20,
height:20,
src:'/src/img/icons/student.svg',
anchor:{h:'center',v:'bottom'},
},
{color:'#19a97b',size:16},
).addMarkerStyle(
'student_boy',
{
width:20,
height:20,
src:'/src/img/icons/boy.svg',
anchor:{h:'center',v:'bottom'},
},
{color:'#1296db',size:16},
).addMarkerStyle(
'student_girl',
{
width:20,
height:20,
src:'/src/img/icons/girl.svg',
anchor:{h:'center',v:'bottom'},
},
{color:'#d4237a',size:16},
);
}else if(center) signInMap.setCenter(center);
signInMap.addLabels(labels);
signInMap.addMarkers(markers);