src/layers/domOverlay.js
import Overlayer from './overlay';
import Util from '../util';
const duration = 1200;
/**
* initDomOverlayer
*/
export class DomOverlayer extends Overlayer {
constructor(opts) {
super(opts);
this.domContainer = this._init();
this.redraw = _redraw.bind(this);
this.domOpts = opts.doms; // store dom config
if (opts && opts.map) {
this.setMap(opts.map);
// bind render doms to each move..performance to be promoted.
opts.map.on("move", this.redraw);
}
this.doms = []; // store dom elements.
this.lastData = [];
this.redraw();
console.log("Dom overlayer add to Map...");
}
_init() {
let canvasContainer = this.map._canvasContainer,
mapboxCanvas = this.map._canvas,
domContainer = document.createElement("div");
domContainer.style.position = "absolute";
domContainer.className = "overlay-dom";
domContainer.style.width = mapboxCanvas.style.width;
domContainer.style.height = '0';
canvasContainer.parentElement.appendChild(domContainer);
return domContainer;
}
/**
* updateDoms and redraw..
*/
setDoms(Doms) {
if (Array.isArray(Doms)) {
this.domOpts = Doms;
this.clearDoms();
this.redraw();
}
}
findDom(domId) {
for(let i = 0;i<this.doms.length;i++) {
try {
if (this.doms[i] === domId) {
return this.doms[i];
}
} catch (error) {
}
}
}
clearDoms() {
for(let i = 0;i<this.doms.length;i++) {
this.domContainer.removeChild(this.doms[i]);
}
this.doms = [];
}
}
const lineHeight = 60, dotRadius = 4, chartHeight = 60;
/**
* domOverlay register&render above default canvas..
* keep in absolute geolocation..
*/
function _redraw() {
let doms = this.domOpts;
if (doms && Array.isArray(doms)) {
// append each of domPopups to domContainer.
for (let i=0;i<doms.length;i++) {
let domOpt = doms[i];
if (typeof domOpt == undefined) continue;
// let sanity = Util.checkSanity(this.lastDoms[i], domOpt);
let x = domOpt['lon'], y = domOpt['lat'],
pix = this.lnglat2pix(x, y);
if (pix == null) continue;
let iconName = domOpt['icon'], resources = domOpt['resources'],
domStyle = domOpt['style']? domOpt['style'] + ' animated': 'bounceIn animated',
chartData = domOpt['data'], chartType = domOpt['type'];
// data sanity should be checked, domOpts not changed then just update position!
let dom = this.doms[i*3] || document.createElement("div"),
line = this.doms[i*3+1] ||document.createElement("div"),
dot =this.doms[i*3+2] || document.createElement("div");
preStyleEles(line, dot, dom, pix, chartType||resources);
let dataClone = Util.deepClone(chartData);
// handle different typesof domOverlay.
if (resources != undefined) {
dom.title = (domOpt['content'] || ``);
if (!dom.hasChildNodes() || dom.firstChild.src !== resources[0]) {
Util.setResource(dom, resources);
}
} else if (iconName != undefined) {
dom.innerHTML = (domOpt['content'] || ``) + '</br>';
Util.setIconDiv(dom, iconName);
} else if (chartData != undefined && chartType != undefined) {
if (Util.isChanged(this.lastData[i], chartData)) {
// setChart would contaminate input Data.
Util.setChart(dom, dataClone, chartType, chartHeight*2);
this.lastData[i] = chartData;
}
} else {
dom.innerHTML = (domOpt['content']|| '') + '</br>';
}
if (chartType != undefined) styleChartContainer(dom)
line.className = "dom-ele", dot.className = "dom-ele";
line.style.left = pix[0] + "px";
line.style.top = (pix[1] - (lineHeight - 10)) + "px";
dot.style.left = pix[0] - dotRadius + "px";
dot.style.top = pix[1] - dotRadius + "px";
// add dom to container at init process.
if (this.doms[i*3] == undefined) {
dom.className = `dom-popup ${domStyle}`;
line.className = dot.className = `dom-ele ${domStyle}`
console.warn(`add ${domStyle} css to dom.`)
this.domContainer.appendChild(dom);
this.domContainer.appendChild(line);
this.domContainer.appendChild(dot);
this.doms.push(...[dom, line, dot]);
}
}
}
}
/**
* ___________
* |chart/img | main popup. /// It is key topic to place popup align.
* -----------
* | line/triangle.. (should implement by psuedoClass!)
* 。 point..
* chartWidth always 2*chartHeight if using Chart.js
*/
function preStyleEles(line, dot, dom, pix, chartType) {
const isImg = Array.isArray(chartType);
line.style.height = lineHeight - 10 + 'px';
line.style.width = '1px';
line.style.position = "absolute";
dot.style.borderRadius = '50%';
dot.style.width = dot.style.height = dotRadius * 2 + 'px';
dot.style.position = "absolute";
dom.style.position = "absolute";
if (!chartType) {
dom.style.minWidth = "100px"; // consistant with chart/image dom width/height.
}
dom.style.background = "#fff";
dom.style.textAlign = "center";
dom.style.padding = '3px';
// if has chartType, display chart above vertical line.
dom.style.left = (pix[0] - (isImg? chartHeight/2: chartHeight)) + "px";
dom.style.top = (pix[1] - lineHeight - (chartType? chartHeight : 20)) + "px";
}
function styleChartContainer(dom) {
dom.style.borderWidth = '0';
dom.style.zIndex = 9999;
dom.style.backgroundColor = 'rgba(0,0,0,0.0)';
}
function animLine (line){
line.className = "dom-line";
}
const htmlTemplate = {
}