이 글은 참고용으로 HTML5 캔버스에서 드래그 가능한 중국 지방 지도를 구현하는 방법의 예를 공유합니다.
1. 데이터 수집
지도를 그리려면 이론적으로 Baidu API를 사용하여 매번 데이터를 얻어서 그릴 수 있지만 효율성을 높이기 위해 먼저 모든 좌표를 얻어 데이터베이스에 저장합니다.
새로운 지방 데이터 배열 생성
var allZoneData = [{'name':'랴오닝성',' been': 'yes','id':'01'},{'name':'지린성','been' :'예','id':'02'},……];
배열을 폴링하고 Baidu API에 요청하여 지방 이름을 기반으로 좌표 데이터를 얻은 다음 Ajax 모드에서 데이터를 PHP로 완화합니다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | var myGeo = new BMap.Geocoder();
( function (){
for ( var i = 0;i < allZoneData.length;i++){
getAllZone(allZoneData[i].name,allZoneData[i].been,allZoneData[i].id);
}
})();
function getAllZone (name,been,id) {
var data,temp;
var bdary = new BMap.Boundary();
bdary.get(name, function (rs){
var count = rs.boundaries.length;
for ( var j = 0; j < count ; j++){
var ply = new BMap.Polygon(rs.boundaries[j], {strokeWeight: 2, strokeColor: "#ff0000" });
data = ply.getPath();
$.ajax({
url: "addData.php" ,
type: "POST" ,
data: { 'data' :data, 'name' : name, 'cir' :j, 'been' :been, 'id' :id},
success: function (txt){
console.log(txt);
},
error: function (){
alert( '添加数据出错!' );
}
});
}
});
}
|
로그인 후 복사
PHP는 데이터를 가져온 후 데이터를 구문 분석하고 사전 구축된 데이터베이스에 데이터를 저장합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <?php
header( "content-type:text/html; charset=utf-8" );
$data = $_REQUEST [ 'data' ];
$name = $_REQUEST [ 'name' ];
$cir = $_REQUEST [ 'cir' ];
$been = $_REQUEST [ 'been' ];
$id = $_REQUEST [ 'id' ];
$con = mysql_connect( "localhost" , "……" , "……" );
if (! $con ){
die ( 'Could not connect: ' . mysql_error());
}
mysql_select_db( "……" , $con );
mysql_set_charset( 'utf8' , $con );
foreach ( $data as $temp ){
$sql = "insert into place (id,name,lng,lat,cir,been) values ('" . $id . "', '" . $name . "', '" . $temp ['lng ']."' , '".$temp[' lat ']."' , '".$cir."' , '".$been."' )";
if (!mysql_query( $sql , $con )){
die ( 'Error: ' . mysql_error());
}
}
mysql_close( $con );
echo 'Success' ;
?>
|
로그인 후 복사
2. 지도 그리기(기본 지도는 mapCanvas 레이어에 그려집니다)
지방 배열을 폴링하고 Ajax를 통해 지방 경계 좌표를 요청한 후 그립니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | var drawMap = function (context,data,l,t) {
if (data.been == 'yes' ){
context.fillStyle = "green" ;
} else {
context.fillStyle = "grey" ;
}
context.globalAlpha = 0.8;
context.beginPath();
cleft = (data.coordinate[0].lng - temp_left) * bigger + l;
ctop = (temp_top - data.coordinate[0].lat) * bigger + t;
context.moveTo(cleft,ctop);
for ( var j = 1;j < data.coordinate.length;j++){
cleft = (data.coordinate[j].lng - temp_left) * bigger + l;
ctop = (temp_top - data.coordinate[j].lat) * bigger + t;
context.lineTo(cleft,ctop);
}
context.closePath();
context.stroke();
context.fill();
}
|
로그인 후 복사
3. 움직이는 연결 그리기(연결선과 이동된 지역은 moveMapCanvas 레이어에 그려집니다)
지도에서 지방을 드래그하면 이동한 지방과 원래 지방을 연결하는 여러 개의 직선이 나타납니다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | var drawLinkLine = function (data,l,t){
for ( var k = 0;k < data.coordinate.length;k++){
if (k % 60 == 0){
moveMapContext.beginPath();
lineLength = Math.sqrt(l * l + t * t) / 100;
lineLength = lineLength >= 4.5 ? 4.5 : lineLength;
moveMapContext.lineWidth = 5 - lineLength;
moveMapContext.strokeStyle = "rgba(0,120,60,0.4)" ;
cleft = (data.coordinate[k].lng - temp_left) * bigger;
ctop = (temp_top - data.coordinate[k].lat) * bigger;
moveMapContext.moveTo(cleft,ctop);
cleft = (data.coordinate[k].lng - temp_left) * bigger + l;
ctop = (temp_top - data.coordinate[k].lat) * bigger + t;
moveMapContext.lineTo(cleft,ctop);
moveMapContext.closePath();
moveMapontext.stroke();
}
}
}
|
로그인 후 복사
4. 이벤트
마우스 누르기 이벤트: 지도를 클릭할 때 클릭 위치를 결정하고, 위치 정보를 경도와 위도로 변환한 후, 바이두 API를 통해 경도와 위도를 기준으로 도명을 얻어와야 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | $( '#eventCanvas' ).mousedown( function (ev){
var mouseX, mouseY;
if (ev.layerX || ev.layerX==0){
mouseX = ev.layerX;
mouseY = ev.layerY;
} else if (ev.offsetX || ev.offsetX==0){
mouseX = ev.offsetX;
mouseY = ev.offsetY;
}
tempX = mouseX;
tempY = mouseY;
mouseX = mouseX/bigger + temp_left;
mouseY = temp_top - mouseY/bigger;
if (opts.dragAll){
draging = true;
} else {
moveMapContext.clearRect(0, 0, 1100, 630);
myGeo.getLocation( new BMap.Point(mouseX, mouseY),
function (result){
tempName = '' ;
draging = true;
name = result.addressComponents.province;
tempName = name;
pubFuns.drawMoveLayerLine(0,0);
});
}
});
|
로그인 후 복사
마우스 이동 이벤트 : 클릭한 지방명을 기준으로 데이터를 획득하고, 움직이는 레이어의 지방을 실시간으로 다시 그립니다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | $( '#eventCanvas' ).mousemove( function (ev){
var mouseX, mouseY;
if (ev.layerX || ev.layerX==0){
mouseX = ev.layerX;
mouseY = ev.layerY;
} else if (ev.offsetX || ev.offsetX==0){
mouseX = ev.offsetX;
mouseY = ev.offsetY;
}
if (draging){
if (opts.dragAll){ <span style= "font-family: Arial, Helvetica, sans-serif;" >
mapContext.clearRect(0, 0, 1100, 630);
for ( var i = 0;i < allZoneData.length;i++){
for ( var j = 0;j < allData[allZoneData[i].name].length;j++){
pubFuns.drawMap(mapContext,allData[allZoneData[i].name][j],mouseX - tempX, mouseY - tempY);
}
}
} else {
moveMapContext.clearRect(0, 0, 1100, 630);
pubFuns.drawMoveLayerLine(mouseX - tempX, mouseY - tempY);
}
}
});
|
로그인 후 복사
마우스 업 이벤트: 드래그를 false로 설정하고 움직이는 레이어를 지웁니다.
1 2 3 4 5 6 7 | $( '#eventCanvas' ).mouseup( function (e){
if (opts.dragAll){
} else {
moveMapContext.clearRect(0, 0, 1100, 630);
}
draging = false;
});
|
로그인 후 복사

요약: 기능과 원리는 매우 간단하지만 캔버스의 몇 가지 속성과 방법을 익히면 익숙해질 수 있습니다. 캔버스 레이어를 서로 겹쳐서 서로 다른 레이어에 서로 다른 콘텐츠를 그려 유지 관리를 용이하게 할 수 있습니다.
위 내용은 이 글의 전체 내용입니다. 모든 분들의 공부에 도움이 되었으면 좋겠습니다.