
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("echarts")):"function"==typeof define&&define.amd?define(["exports","echarts"],t):t(e.bmap={},e.echarts)}(this,function(e,y){"use strict";function h(e,t){this._bmap=e,this.dimensions=["lng","lat"],this._mapOffset=[0,0],this._api=t,this._projection=new BMap.MercatorProjection}function o(a,r){return r=r||[0,0],y.util.map([0,1],function(e){var t=r[e],o=a[e]/2,n=[],i=[];return n[e]=t-o,i[e]=t+o,n[1-e]=i[1-e]=r[1-e],Math.abs(this.dataToPoint(n)[e]-this.dataToPoint(i)[e])},this)}var g;function v(e){for(var t in e)if(e.hasOwnProperty(t))return!1;return!0}h.prototype.dimensions=["lng","lat"],h.prototype.setZoom=function(e){this._zoom=e},h.prototype.setCenter=function(e){this._center=this._projection.lngLatToPoint(new BMap.Point(e[0],e[1]))},h.prototype.setMapOffset=function(e){this._mapOffset=e},h.prototype.getBMap=function(){return this._bmap},h.prototype.dataToPoint=function(e){var t=new BMap.Point(e[0],e[1]),o=this._bmap.pointToOverlayPixel(t),n=this._mapOffset;return[o.x-n[0],o.y-n[1]]},h.prototype.pointToData=function(e){var t=this._mapOffset;return[(e=this._bmap.overlayPixelToPoint({x:e[0]+t[0],y:e[1]+t[1]})).lng,e.lat]},h.prototype.getViewRect=function(){var e=this._api;return new y.graphic.BoundingRect(0,0,e.getWidth(),e.getHeight())},h.prototype.getRoamTransform=function(){return y.matrix.create()},h.prototype.prepareCustoms=function(e){var t=this.getViewRect();return{coordSys:{type:"bmap",x:t.x,y:t.y,width:t.width,height:t.height},api:{coord:y.util.bind(this.dataToPoint,this),size:y.util.bind(o,this)}}},h.dimensions=h.prototype.dimensions,h.create=function(e,l){var f,u=l.getDom();e.eachComponent("bmap",function(e){var t=l.getZr().painter,o=t.getViewportRoot();if("undefined"==typeof BMap)throw new Error("BMap api is not loaded");if(g=g||function(){function e(e){this._root=e}return(e.prototype=new BMap.Overlay).initialize=function(e){return e.getPanes().labelPane.appendChild(this._root),this._root},e.prototype.draw=function(){},e}(),f)throw new Error("Only one bmap component can exist");if(!e.__bmap){var n=u.querySelector(".ec-extension-bmap");n&&(o.style.left="0px",o.style.top="0px",u.removeChild(n)),(n=document.createElement("div")).style.cssText="width:100%;height:100%",n.classList.add("ec-extension-bmap"),u.appendChild(n);var i=e.get("mapOptions")||{};delete i.mapType;var a=e.__bmap=new BMap.Map(n,i),r=new g(o);a.addOverlay(r),t.getViewportRootOffset=function(){return{offsetLeft:0,offsetTop:0}}}a=e.__bmap;var p=e.get("center"),s=e.get("zoom");if(p&&s){var m=a.getCenter(),d=a.getZoom();if(e.centerOrZoomChanged([m.lng,m.lat],d)){var c=new BMap.Point(p[0],p[1]);a.centerAndZoom(c,s)}}(f=new h(a,l)).setMapOffset(e.__mapOffset||[0,0]),f.setZoom(s),f.setCenter(p),e.coordinateSystem=f}),e.eachSeries(function(e){"bmap"===e.get("coordinateSystem")&&(e.coordinateSystem=f)})},y.extendComponentModel({type:"bmap",getBMap:function(){return this.__bmap},setCenterAndZoom:function(e,t){this.option.center=e,this.option.zoom=t},centerOrZoomChanged:function(e,t){var o=this.option;return!(function(e,t){return e&&t&&e[0]===t[0]&&e[1]===t[1]}(e,o.center)&&t===o.zoom)},defaultOption:{center:[104.114129,37.550339],zoom:5,mapStyle:{},mapStyleV2:{},mapOptions:{},roam:!1}}),y.extendComponentView({type:"bmap",render:function(i,e,a){function t(e,t){if(!r){var o=p.parentNode.parentNode.parentNode,n=[-parseInt(o.style.left,10)||0,-parseInt(o.style.top,10)||0];p.style.left=n[0]+"px",p.style.top=n[1]+"px",s.setMapOffset(n),i.__mapOffset=n,a.dispatchAction({type:"bmapRoam"})}}var r=!0,o=i.getBMap(),p=a.getZr().painter.getViewportRoot(),s=i.coordinateSystem;function n(){r||a.dispatchAction({type:"bmapRoam"})}o.removeEventListener("moving",this._oldMoveHandler),o.removeEventListener("moveend",this._oldMoveHandler),o.removeEventListener("zoomend",this._oldZoomEndHandler),o.addEventListener("moving",t),o.addEventListener("moveend",t),o.addEventListener("zoomend",n),this._oldMoveHandler=t,this._oldZoomEndHandler=n;var m=i.get("roam");m&&"scale"!==m?o.enableDragging():o.disableDragging(),m&&"move"!==m?(o.enableScrollWheelZoom(),o.enableDoubleClickZoom(),o.enablePinchToZoom()):(o.disableScrollWheelZoom(),o.disableDoubleClickZoom(),o.disablePinchToZoom());var d=i.__mapStyle,c=i.get("mapStyle")||{},l=JSON.stringify(c);JSON.stringify(d)!==l&&(v(u)||o.setMapStyle(y.util.clone(c)),i.__mapStyle=JSON.parse(l));var f=i.__mapStyle2,u=i.get("mapStyleV2")||{},h=JSON.stringify(u);JSON.stringify(f)!==h&&(v(u)||o.setMapStyleV2(y.util.clone(u)),i.__mapStyle2=JSON.parse(h)),r=!1}}),y.registerCoordinateSystem("bmap",h),y.registerAction({type:"bmapRoam",event:"bmapRoam",update:"updateLayout"},function(e,t){t.eachComponent("bmap",function(e){var t=e.getBMap(),o=t.getCenter();e.setCenterAndZoom([o.lng,o.lat],t.getZoom())})});e.version="1.0.0"});
