Skip to content

Commit

Permalink
nikai
Browse files Browse the repository at this point in the history
  • Loading branch information
hinikai committed Aug 7, 2015
1 parent 9dc0498 commit 4f889f3
Show file tree
Hide file tree
Showing 6 changed files with 752 additions and 0 deletions.
82 changes: 82 additions & 0 deletions CanvasLayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* 一直覆盖在当前地图视野的Canvas对象
*
* @author nikai (@胖嘟嘟的骨头, [email protected])
*
* @param
* {
* map 地图实例对象
* }
*/

function CanvasLayer(options){
this.options = options || {};
this.paneName = this.options.paneName || 'labelPane';
this.zIndex = this.options.zIndex || 0;
this._map = options.map;
this.show();
}

CanvasLayer.prototype = new BMap.Overlay();

CanvasLayer.prototype.initialize = function(map){
this._map = map;
var canvas = this.canvas = document.createElement("canvas");
canvas.style.cssText = "position:absolute;"
+ "left:0;"
+ "top:0;"
+ "z-index:" + this.zIndex + ";";
this.adjustSize();
map.getPanes()[this.paneName].appendChild(canvas);
var that = this;
map.addEventListener('resize', function () {
that.adjustSize();
that.draw();
});
return this.canvas;
}

CanvasLayer.prototype.adjustSize = function(){
var size = this._map.getSize();
var canvas = this.canvas;
canvas.width = size.width;
canvas.height = size.height;
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
}

CanvasLayer.prototype.draw = function(){
var map = this._map;
var bounds = map.getBounds();
var sw = bounds.getSouthWest();
var ne = bounds.getNorthEast();
var pixel = map.pointToOverlayPixel(new BMap.Point(sw.lng, ne.lat));
this.canvas.style.left = pixel.x + "px";
this.canvas.style.top = pixel.y + "px";
this.dispatchEvent('draw');
this.options.update && this.options.update.call(this);
}

CanvasLayer.prototype.getContainer = function(){
return this.canvas;
}

CanvasLayer.prototype.show = function(){
if (!this.canvas) {
this._map.addOverlay(this);
}
this.canvas.style.display = "block";
}

CanvasLayer.prototype.hide = function(){
this.canvas.style.display = "none";
//this._map.removeOverlay(this);
}

CanvasLayer.prototype.setZIndex = function(zIndex){
this.canvas.style.zIndex = zIndex;
}

CanvasLayer.prototype.getZIndex = function(){
return this.zIndex;
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# 地图标签云,文本标注避让

1 change: 1 addition & 0 deletions beijing_building.js

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE HTML>
<html>
<head>
<title>地图可视化</title>
<META http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=1XjLLEhZhQNUzd93EjU5nOGQ"></script>
<script type="text/javascript" src="CanvasLayer.js"></script>
<style type="text/css">
html, body, #map{
width: 100%;
height: 100%;
overflow: hidden;
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script type="text/javascript" src="randomColor.js"></script>
<script type="text/javascript" src="beijing_building.js"></script>
<script type="text/javascript" src="index.js"></script>
</body>
</html>

248 changes: 248 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/**
* @author nikai (@胖嘟嘟的骨头, [email protected])
*/

for (var i = 0, len = building.length; i < len; i++) {
building[i].color = randomColor();
building[i].size = parseInt(Math.random() * 20) + 10;
}

building.sort(function (a, b) {
return b.size - a.size;
});

// 创建Map实例
var map = new BMap.Map("map");

var mercatorProjection = map.getMapType().getProjection();

map.centerAndZoom(new BMap.Point(116.405706, 39.927773), 12); // 初始化地图,设置中心点坐标和地图级别
map.enableScrollWheelZoom(); //启用滚轮放大缩小

map.setMapStyle({
styleJson: [{
featureType: 'water',
elementType: 'all',
stylers: {
color: '#044161'
}
}, {
featureType: 'land',
elementType: 'all',
stylers: {
color: '#091934'
}
}, {
featureType: 'boundary',
elementType: 'geometry',
stylers: {
color: '#064f85'
}
}, {
featureType: 'railway',
elementType: 'all',
stylers: {
visibility: 'off'
}
}, {
featureType: 'highway',
elementType: 'geometry',
stylers: {
color: '#004981'
}
}, {
featureType: 'highway',
elementType: 'geometry.fill',
stylers: {
color: '#005b96',
lightness: 1
}
}, {
featureType: 'highway',
elementType: 'labels',
stylers: {
visibility: 'on'
}
}, {
featureType: 'arterial',
elementType: 'geometry',
stylers: {
color: '#004981',
lightness: -39
}
}, {
featureType: 'arterial',
elementType: 'geometry.fill',
stylers: {
color: '#00508b'
}
}, {
featureType: 'poi',
elementType: 'all',
stylers: {
visibility: 'off'
}
}, {
featureType: 'green',
elementType: 'all',
stylers: {
color: '#056197',
visibility: 'off'
}
}, {
featureType: 'subway',
elementType: 'all',
stylers: {
visibility: 'off'
}
}, {
featureType: 'manmade',
elementType: 'all',
stylers: {
visibility: 'off'
}
}, {
featureType: 'local',
elementType: 'all',
stylers: {
visibility: 'off'
}
}, {
featureType: 'arterial',
elementType: 'labels',
stylers: {
visibility: 'off'
}
}, {
featureType: 'boundary',
elementType: 'geometry.fill',
stylers: {
color: '#029fd4'
}
}, {
featureType: 'building',
elementType: 'all',
stylers: {
color: '#1a5787'
}
}, {
featureType: 'label',
elementType: 'all',
stylers: {
visibility: 'off'
}
}, {
featureType: 'poi',
elementType: 'labels.text.fill',
stylers: {
color: '#ffffff'
}
}, {
featureType: 'poi',
elementType: 'labels.text.stroke',
stylers: {
color: '#1e1c1c'
}
}]
});

var canvasLayer = new CanvasLayer({
map: map,
update: update
});

var ctx = canvasLayer.canvas.getContext("2d");

function update() {
var ctx = this.canvas.getContext("2d");

var zoom = map.getZoom();
var zoomUnit = Math.pow(2, 18 - zoom);
var mcCenter = mercatorProjection.lngLatToPoint(map.getCenter());
var nwMc = new BMap.Pixel(mcCenter.x - (ctx.canvas.width / 2) * zoomUnit, mcCenter.y + (ctx.canvas.height / 2) * zoomUnit); //左上角墨卡托坐标

if (!ctx) {
return;
}

ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

var temp = {};
ctx.shadowBlur = 10;
ctx.shadowColor = "rgba(250, 250, 55, 0.7)";
ctx.beginPath();

ctx.textBaseline = "top";

for (var i = 0, len = building.length; i < len; i++) {
var x = (building[i].x - nwMc.x) / zoomUnit;
var y = (nwMc.y - building[i].y) / zoomUnit;

building[i].px = x;
building[i].py = y;
}

var rects = [];

var canvasWidth = ctx.canvas.width;
var canvasHeight = ctx.canvas.height;
var margin = 200; // canvas扩大范围绘制,使边缘展示一致
for (var i = 0, len = building.length; i < len; i++) {
var x = building[i].px;
var y = building[i].py

if (x < -margin || y < -margin || x > canvasWidth + margin || y > canvasHeight + margin) {
continue;
}

ctx.font = "bold " + building[i].size + "px Arial";
var textWidth = ctx.measureText(building[i].n).width;

// 根据文本宽度和高度调整x,y位置,使得绘制文本时候坐标点在文本中心点,这个计算出的是左上角坐标
var px = x - textWidth / 2;
var py = y - building[i].size / 2;

var rect = {
sw: {
x: px,
y: py + building[i].size
},
ne: {
x: px + textWidth,
y: py
}
}
if (!hasOverlay(rects, rect)) {
rects.push(rect);
ctx.fillStyle = building[i].color;
// ctx.fillRect(px, py, textWidth, building[i].size);
ctx.fillText(building[i].n, px, py);
}
}
}

/*
* 当前文字区域和已有的文字区域是否有重叠部分
*/
function hasOverlay(rects, overlay) {
for (var i = 0; i < rects.length; i++) {
if (isRectOverlay(rects[i], overlay)) {
return true;
}
}
return false;
}

//判断2个矩形是否有重叠部分
function isRectOverlay(rect1, rect2) {
//minx、miny 2个矩形右下角最小的x和y
//maxx、maxy 2个矩形左上角最大的x和y
var minx = Math.min(rect1.ne.x, rect2.ne.x);
var miny = Math.min(rect1.sw.y, rect2.sw.y);
var maxx = Math.max(rect1.sw.x, rect2.sw.x);
var maxy = Math.max(rect1.ne.y, rect2.ne.y);
if (minx > maxx && miny > maxy) {
return true;
}
return false;
}
Loading

0 comments on commit 4f889f3

Please sign in to comment.