公司突然有種特殊的需求,希望從手機上瀏覽到資料庫中客戶們的位置,目的透過手機的定位裝置,找到附近的客戶們,並加上不同的顏色區分,有此需求的朋友們,可以參考以下的作法,如果你們有更好的想好也歡迎給我些意見,互相交流技術想法~
步驟一: 先建立顯示地圖div
<div data-role="page" id="geolocation_map">//頁面
<div id="geolocation_header" data-role="header"> //表頭
<a data-role="button" data-rel="back">back</a>
<h3>google
Map</h3>
<a href="#geolocation_menus" data-position="right"
data-role="button" data-icon="grid" >選單</a>
</div>
<div id="geolocation_conent" data-role="content"> //表身
<div id="geolocation_canvas">gelocation</div> //顯示地圖
<a href="#geolocation_changeColor" data-ajax="false" id="geolocation_showDialog" data-rel="dialog" data-transition="slidedown">Open dialog</a>
<input type="hidden" id="geolocation_userID" runat="server" />
</div>
<div id="geolocation_footer" data-position="fixed" data-role="footer" data-id="gelocation_footerPage"> //表尾
<div data-role="navbar">
<ul>
<li><a href="#geolocation_map">搜尋附近牙醫</a></li>
<li><a href="#setParameter_page">參數設定</a></li>
</ul>
</div>
</div>
</div>
|
步驟二: 為了可以顯示在手機裝置上(寬度和高度 不宜超大),所以使用javasScript 自動偵測
//自動縮放畫面的size
function resize_canvas() {
var canvas = $('#geolocation_canvas').width();
if ($('#geolocation_canvas').width()
<= window.innerWidth)
{
$('#geolocation_canvas').css("width",
window.innerWidth);
}
if ($('#geolocation_canvas').height()
<= window.innerHeight) {
$('#geolocation_canvas').css("height",
window.innerHeight);
}
}
|
步驟四: 呼叫目前的位置
navigator.geolocation.getCurrentPosition( function (position)
{), geo_error);
function geo_error(err)
{
if (err.code
== 1) {
alert( "Error: Access is denied!");
} else if (err.code
== 2) {
alert( "Error: Position is
unavailable!");
}
}
目前所有瀏覽器(電腦版,僅IE9正常抓到位置),因他Chrom 、safari 等只能在行動設備開啟wifi定位偵測
|
步驟五: 初始化GoogleMap
//設定目前座落的位置,並找尋附近範圍經緯度的值
function setInitMap(lat, lng, range) {
try{
var mapOptions = {
center: new google.maps.LatLng(lat, lng),
zoom: 17, //地圖比例大小
mapTypeId:
google.maps.MapTypeId.ROADMAP
};
var map = new
google.maps.Map(document.getElementById("geolocation_canvas"),
mapOptions);
var myLatlng = new google.maps.LatLng(lat, lng); //設置中心點
setMarket("current", "", "", "green", "目前位置", "",
myLatlng, map); //繪製目前的座標位置
getNeighbor(lat, lng,
range, map); //搜尋附近鄰近的診所的座標
} catch (e) {
alert(e.message);
}
}
//算出附近四座標範圍
function getNeighbor(lat, lng, range, map) {
$.ajax({
//取回json格式,符合範圍內的經緯度的診所資料
url: "Service.svc/computeNextBy?lat=" + lat
+ "&lng=" + lng
+ "&range=" +
range,
dataType: "json",
async: true,
success: function (data) {
if (!!(data) == true) {
//取得座標值,如果已拜訪過的診所/未拜訪診所等狀況,呈現不同顏色
$.each(data, function (index, value) {
var myLatlng = new
google.maps.LatLng(value["lanLng"]["Lat"],
value["lanLng"]["Lng"]);
if (value["status"] == 0 && value["isCustomer"] == false) {
//非客戶_未拜訪
setMarket(value["clinicNo"], value["isCustomer"], value["status"], "red",
value["name"],
value["address"],
myLatlng, map);
} else if
(value["status"] == 1
&& value["isCustomer"] == false) {
//非客戶_有拜訪
setMarket(value["clinicNo"], value["isCustomer"], value["status"], "yellow",
value["name"],
value["address"],
myLatlng, map);
} else if
(value["status"] == 0
&& value["isCustomer"] == true) {
//客戶_未拜訪
setMarket(value["clinicNo"], value["isCustomer"], value["status"], "purple",
value["name"],
value["address"],
myLatlng, map);
}
else if
(value["status"] == 1
&& value["isCustomer"] == true) {
//客戶_有拜訪
setMarket(value["clinicNo"], value["isCustomer"], value["status"], "blue",
value["name"],
value["address"],
myLatlng, map);
}
});
}
},
error: function (xhr, status) {
}
});
}
//改變狀態時,將標籤的的顏色改變
function setMarket(clinicNo, isCustomer, isVisited, color,
title, addr, myLatlng, map) {
var strMakerLink = "";
switch (color) {
case "red":
strMakerLink = 'http://maps.google.com/mapfiles/ms/icons/red-dot.png';
break;
case "blue":
strMakerLink = 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png';
break;
case "yellow":
strMakerLink = 'http://maps.google.com/mapfiles/ms/icons/yellow-dot.png';
break;
case "purple":
strMakerLink = 'http://maps.google.com/mapfiles/ms/icons/purple-dot.png';
break;
case "green":
strMakerLink = 'http://maps.google.com/mapfiles/ms/icons/green-dot.png';
break;
default:
strMakerLink = 'http://maps.google.com/mapfiles/ms/icons/red-dot.png';
break;
}
//建立地圖google座標
var marker = new google.maps.Marker({
position: myLatlng,
title: title,
icon: strMakerLink,
})
//google座標放進地圖
marker.setMap(map);
google.maps.event.addListener(marker, 'click', function () {
callCustomData(clinicNo);
$("#geolocation_showDialog").click(); //點選座標後,跳出視窗
return false;
});
}
|
步驟六: 查詢範圍內的診所(WCF的函式)
/// <summary>
/// 算出附近鄰近四個經緯度
/// </summary>
public List<Clinic> computeNextBy(double doubleLat, double doubleLng, double doubleRange)
{
try
{
//先取此座標附近的範圍~ 四角形座標範圍
Dictionary<string, Marker>
dicClinicRange = getNeighborRange(doubleLat, doubleLng, doubleRange);
//取其左上和右下的兩點座標, 找出中間範圍所有診所座標
Marker markerSource= dicClinicRange["left_top"];
Marker markerTarget = dicClinicRange["right_bottom"];
double minLat, maxLat, minLng, maxLng;
//座標(經緯)並非數字大小決定位置,但sql查詢範圍條件的 between 是以小到大
if(markerSource.Lat <= markerTarget.Lat)
{
minLat=markerSource.Lat;
maxLat =
markerTarget.Lat;
}else{
minLat =
markerTarget.Lat;
maxLat =
markerSource.Lat;
}
if (markerSource.Lng <= markerTarget.Lng)
{
minLng =
markerSource.Lng;
maxLng =
markerTarget.Lng;
}
else
{
minLng =
markerTarget.Lng;
maxLng =
markerSource.Lng;
}
List<Clinic> liNeighborClinics = getNeighborLocation(minLat,minLng, maxLat,
maxLng, doubleLat, doubleLng); //從資料庫中取回落在查詢範圍內的經緯度的客戶
return liNeighborClinics;
}
catch (Exception ex) {
throw new Exception(ex.Message);
}
}
/// <summary>
/// 計算出四角形的個別座標 (就能找到自已附近範圍的客戶)
public Dictionary<string, Marker> getNeighborRange(double
doubleLat, double doubleLng, double doubleRange)
{
try
{
Dictionary<string, Marker> dicMarkers = new Dictionary<string, Marker>();
Marker leftTop = new Marker();
Marker rightTop = new Marker();
Marker leftBottom = new Marker();
Marker rightBottom = new Marker();
leftTop.Lat =
doubleLat;
leftTop.Lng =
doubleLng;
/*
台灣地區:
兩地經緯度相差 0.5度:距離相差約 50公里
兩地經緯度相差 0.1度:距離相差約 10公里
兩地經緯度相差 0.05度:距離相差約 5公里
兩地經緯度相差 0.01度:距離相差約 1公里
*/
double dLng = 0.01 * 0.001 * doubleRange;
double dLat = 0.01 * 0.001 * doubleRange;
leftTop.Lat =
doubleLat + dLat;
leftTop.Lng =
doubleLng - dLng;
dicMarkers["left_top"] = leftTop;
rightTop.Lat =
doubleLat + dLat;
rightTop.Lng =
doubleLng + dLng;
dicMarkers["right_top"] = rightTop;
leftBottom.Lat =
doubleLat - dLat;
leftBottom.Lng =
doubleLng - dLng;
dicMarkers["left_bottom"] = leftBottom;
rightBottom.Lat =
doubleLat - dLat;
rightBottom.Lng =
doubleLng + dLng;
dicMarkers["right_bottom"] = rightBottom;
return dicMarkers;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
|
呈現樣式如下
補充說明: 如何將資料庫的客戶的地址全部轉換成經緯度
//將地址轉換成google 的經緯度值
public decimal[] getLocation(string address)
{
decimal[] strLatIng = new decimal[2];
var url = String.Format("http://maps.google.com/maps/api/geocode/json?sensor=false&address={0}", address);
string result = String.Empty;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
using (var response = request.GetResponse())
{
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
GeoResponse geoResponse = JsonConvert.DeserializeObject<GeoResponse>(result);
if (geoResponse.Status == "OK")
{
int count = geoResponse.Results.Length;
if (count > 0)
{
strLatIng[0] =
geoResponse.Results[0].Geometry.Location.Lat;
strLatIng[1] =
geoResponse.Results[0].Geometry.Location.Lng;
}
}
}
}
return strLatIng;
}
public class GeoLocation
{
public decimal Lat
{
get;
set;
}
public decimal Lng
{
get;
set;
}
}
public class GeoGeometry
{
public GeoLocation
Location
{
get;
set;
}
}
public class GeoResult
{
public GeoGeometry
Geometry
{
get;
set;
}
}
public class GeoResponse
{
public string Status
{
get;
set;
}
public GeoResult[]
Results
{
get;
set;
}
}
|
步驟二: 更新資料欄位的函式
public void updateAllClinicGelocation()
{
string strConnection = ConfigurationManager.ConnectionStrings["TCS"].ConnectionString;
SqlConnection sqlCon = new SqlConnection();
sqlCon.ConnectionString = strConnection;
sqlCon.Open();
string strCommand = "SELECT 機構代號,名稱,地址
from tclinic with (nolock) where (緯度 is null or 緯度=0) and (經度 is null or 經度=0) ";
SqlCommand sqlCmd = new SqlCommand(strCommand,
sqlCon);
SqlDataReader sqlReader = sqlCmd.ExecuteReader(CommandBehavior.CloseConnection);
if (sqlReader.HasRows)
{
SqlConnection sqlCon2 = new SqlConnection();
sqlCon2.ConnectionString = strConnection;
sqlCon2.Open();
while (sqlReader.Read())
{
decimal[] deciLocation = new decimal[2];
deciLocation = getLocation(sqlReader["地址"].ToString());
if (deciLocation[0] > 0 &&
deciLocation[1] > 0)
{
SqlCommand sqlUpdateCmd = new SqlCommand("update tclinic set 緯度=@緯度, 經度=@經度
where 機構代號=@機構代號", sqlCon2);
SqlParameter spUpdateClinicNo = new SqlParameter("@機構代號", sqlReader["機構代號"].ToString());
SqlParameter spClinicLat = new SqlParameter("@緯度", deciLocation[0]);
SqlParameter spClinicIng = new SqlParameter("@經度", deciLocation[1]);
sqlUpdateCmd.Parameters.Add(spUpdateClinicNo);
sqlUpdateCmd.Parameters.Add(spClinicLat);
sqlUpdateCmd.Parameters.Add(spClinicIng);
sqlUpdateCmd.ExecuteNonQuery();
Thread.Sleep(1500); //記得加上這一行,以免伺服器過忙碌
}
}
sqlCon2.Close();
}
|
步驟三: 使用Await和Async執行非同步執行作業,同時更新畫面值
private async void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true; // 啟用Timer
timer1.Start();
timer1.Interval =
5000; // The time per tick.
timer1.Tick += new EventHandler(timer1_Tick);
WorkTemp workObj = new WorkTemp();
await workObj.DoWork();
}
private async void timer1_Tick(object sender, EventArgs e)
{
WorkTemp workObj = new WorkTemp();
await workObj.DoComplete();
progressBar1.Value =
workObj.theValue;
label1.Text = "進度:" + workObj.theValue.ToString();
}
public class WorkTemp
{
public int theValue; //傳回資料庫的完成度
public async Task DoWork()
{
await Task.Run(async () =>
{
updateAllClinicGelocation(); //更新資料庫的經緯度.
});
}
public async Task
DoComplete()
{
await Task.Run(async () =>
{
computePercent(); //計算已更新經緯度的資料庫的百分比
});
}
}
|
示範程式畫面:可以在畫面顯示完程度進度
Button1_click:啟動workObj.DoWork()
Timer: 每隔秒去觸發workObj.DoComplete()
沒有留言:
張貼留言