红鱼儿

图文解说ChinaCock高德地图组件采集坐标 (二)

前文介绍了如何快速在uniGUI项目中引用ChinaCock地图组件,为应用增加地图功能。本文从实战出发,继续介绍为项目增加实战功能:让用在项目中可以采集指定实体的坐标。

假设,你已经参阅了前文图文解说ChinaCock高德地图组件CCuniGUIAMap (一),所以本文不再提及前文涉及到的细节。

0.用户需求

先来看一下用户的实际需求:

1.当前用户管理着所辖区域的企业资料,现在想在地图中显示这些企业的位置

2.用户需要为这些企业在地图中标注出来,以满足第一条的实现

3.用户在标注的时候,可以拖放标注,进行微调并重新按新指定的地址进行保存

4.用户鼠标指向一个标注的时候,能在上面显示企业的名称,离开后自动隐藏企业名称

5.用户单击一个标注的时候,能显示详细信息

6.自动隐藏企业详细信息,分两种情况:

a.上一步当显示详细信息时,用户不进入详细信息区域情况下,信息显示3秒后自动隐藏

b.上一步显示的信息,即当户鼠标进入这个详细信息区域,一直显示,当离开时,信息显示3秒后自动隐藏,在这期间,如果用户鼠标又回到详细信息区域,则保持显示,离开自动隐藏,这一过程可重复执行

7.用户在知道企业名称的情况下,能在地图上按企业名称查询并快速标注该企业

8.用户可以重新标注指定企业,即当前编辑一个企业的标注时,打开地图,显示所编辑企业旧的标注点,并允许重新标注。

9.用户标注企业时,要取得经纬度及详细地址

开发者想到的需求:

1.用户编辑一个企业位置,当用户进入这个功能界面时,在地图正中心显示该企业标注,这样方便用户查看并重新标注

2.地图要显示的简洁,当前用进入时,只显示所辖区域

3.实现结果,功能界面与地图尽量整合为一体,让用户感觉就是地图上操作,没有突兀的感觉

4.尽量与业务分开,实现一个与业务分开的功能,在类似的需求中可以直接使用(这一条跟用户需求无关了)

综上所述,需求看起来不少,我基本上把与用户的需求交流都整理出来了,但实现起来,由于ChinaCock精美的地图封装控件,实现起来,就是简单的事了。

现在开始动工,制作一个通用的窗口,四步实现即满足上面的需求,这又让我想起了宋丹丹的小品,说把大象关进冰箱分几步?

1.设计标注界面

先可设化设计一个界面,如下图: 

整个布局基本显示地图,最底部显示标注信息,详细地址、经纬度,确定及取消按钮。

用三个uniEdit对应详细地址、经度、纬度

当用户在详细地址中,可以输入企业名称并提供一个查询按钮,进行查询,查询后自动在地图上进行标注

确定按钮,返回mrOK,取消按钮,返回mrCancel。

为此,我们要新建一个uniForm,然后放置对应的控件,并调整好布局,这没有什么难度,完全的可视化操作。

运行后的效果:

2.实现方法AddMarker

先实现方法AddMarker,按指定经纬度在地图上增加标注。实际上这是在开发过程中提练出来的方法,因此多处需要调用他,在地图上显示标注点。

function TGaoDeMapForm.AddMarker(ALng, ALat: Double):TCCuniGUIAMap.TMarker;
begin
  //只显示当前企业的标注
  if CCuniGUIAMap1.Markers.Count <= 0 then
  begin
    result:=  self.CCuniGUIAMap1.Markers.Add;

    with result do
    begin
      with Options.Position do
      begin
        Lng := ALng;
        Lat := ALat;
      end;

      with Options.icon.Options do // 设置图标
      begin
        Image := '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-red.png';
        // 图标所用图片大小,根据所设置的大小拉伸或压缩图片,等同于CSS中的background-size属性。可用于实现高清屏的高清效果
        with imageSize do
        begin
          width := 25;
          height := 34;
        end;
      end;
      with Options.Offset do
      begin
        X := -13;
        Y := -30;
      end;

      // 标注里加上公司名称,当用户指向一个标注时显示此名称
      CustomParams.Values['CorpName'] := self.CorpName;
      //允许用户拖放标注
      Options.draggable := true;

      // 添加到地图
      AddToMap;
    end;
  end
  else//已经标注过,则直接修改标注位置,不增加新的标注点,保证只有一个标注
  begin
    result:= self.CCuniGUIAMap1.Markers.Items[0];
    result.SetPosition(ALng,ALat);
  end;
end;

代码中,直接考虑了用户需求:3.用户在标注的时候,可以拖放标注,进行微调并重新按新指定的地址进行保存。

从Delphi的角度说,我们只是操作地图的Markers对象,为其增加一个Marker对象并设置其位置等属性信息。ChinaCock作者为其封了一个属性CustomParams,方便你在这里存储你需要的信息,注意这个属性,我们在标注上显示企业名称时用的就是他。

3.处理用户标注动作

用户在地图上点击,代码响应在地图上显示一个标注点,地图控件的事件OnMapClick,正好处理这个:

procedure TGaoDeMapForm.CCuniGUIAMap1MapClick(const ASender: TObject; APosition: TLngLat; AParams: TUniStrings);
begin

  EditLng.Text := APosition.Lng.ToString;
  EditLat.Text := APosition.Lat.ToString;

  // 根据经纬度获取位置
  self.CCuniGUIAMap1.Geocoder.GetAddress(APosition,
    procedure(AResult: TArray<String>; AParams: TUniStrings)
    begin
      // 显示获取到的位置
      self.EditAddress.Text := AResult[0];
    end);
  //在地图上显示标注
  AddMarker(APosition.Lng, APosition.Lat);

end;

在这个事件中,我们同时做了三件事:

  1. 在界面对应的经纬度控件上显示对应信息
  2. 在详细地址控件上显示详细信息,为此调用了地图控件的方法GetAddress,注意这是异步执行的。
  3. 在地图上显示标注信息

4.处理用户拖放动作

同上一步一样,地图控件同样实现了拖放标注的事件,当用户拖放一个标注时会触发。直接上代码:

procedure TGaoDeMapForm.CCuniGUIAMap1MarkerDragEnd(const ASender: TObject;
    const AMarker: TCCuniGUIAMap.TMarker; const ALngLat: TLngLat; const
    AEventParams: TUniStrings);
begin
  //拖放一个标注到新地点,重新取地址
  EditLng.Text := ALngLat.Lng.ToString;
  EditLat.Text := ALngLat.Lat.ToString;

  // 根据经纬度获取位置
  self.CCuniGUIAMap1.Geocoder.GetAddress(ALngLat,
    procedure(AResult: TArray<String>; AParams: TUniStrings)
    begin
      // 显示获取到的位置
      self.EditAddress.Text := AResult[0];
    end);
  
  //重新显示标注的名称
  var AText := self.CCuniGUIAMap1.Texts.Items[0];

  AText.Show;
  AText.SetPosition(AMarker.Options.Position);
  AText.SetText(AMarker.CustomParams.Values['CorpName']);
end;

在这个事件中,我们也是做了三件事:

  1. 在界面对应的经纬度控件上显示对应信息
  2. 在详细地址控件上显示详细信息,为此调用了地图控件的方法GetAddress,注意这是异步执行的。
  3. 重新显示标注名称

经过上面的实现,核心的标注功能就完成了!用户可以在地图上标注出一个企业,同时支持拖放操作,重新标注企业的地址,在用户标注的过程中,我们取到了想要的经纬度及详细地址。

总结来说,我们只是使用了OnMapClick及OnMarkerDrapEnd两个地图控件的事件,并在这两个事件中操作Marker对象,就达到了目的!

更进步讲,地图控件提供了Markers对象列表来管理Marker对象,让我们可以同时在地图中标注多个特定的实体并显示他们。这在后面我还会继续分享给朋友们。

接下来,就是调用这个窗口,处理返回值了!

procedure TOrgBillForm.btnMapClick(Sender: TObject);
begin
  inherited;
  // 经度
  GaoDeMapForm.Lng := MasterDataSet.FieldByName('FJD').AsString;
  // 维度
  GaoDeMapForm.Lat := MasterDataSet.FieldByName('FWD').AsString;
  //详细地址
  GaoDeMapForm.CorpAddress := MasterDataSet.FieldByName('FADDRESSNAME').AsString;
  //公司名称
  GaoDeMapForm.CorpName := MasterDataSet.FieldByName('FName').AsString;

  GaoDeMapForm.ShowModal(
    procedure(Sender: TComponent; AResult: Integer)
    begin
      case AResult of
        mrOk:
          begin
            MasterDataSet.Edit;
            // 经度
            MasterDataSet.FieldByName('FJD').AsString := GaoDeMapForm.Lng;
            // 维度
            MasterDataSet.FieldByName('FWD').AsString := GaoDeMapForm.Lat;

            MasterDataSet.FieldByName('FADDRESSNAME').AsString := GaoDeMapForm.CorpName;

            MasterDataSet.Post;
          end;
      end
    end);
end;

 

posted on 2022-05-12 06:34  红鱼儿  阅读(415)  评论(0编辑  收藏  举报