(第20讲) 示例20—全景图完整示例
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(第20讲) 示例20—全景图完整示例相关的知识,希望对你有一定的参考价值。
分类:C#、android、百度地图应用; 日期:2016-02-04
一、简介
1、展示全景图的方式
有以下展示全景图的办法:
(1)利用地理坐标展示全景图。
(2)利用全景图ID展示全景图。
(3)利用墨卡托坐标展示全景图。
(4)利用地图POI ID展示全景图。
通过以上方式,就可以使用百度提供的全景图展示服务了。
2、坐标转换
为了更方便的获取全景图,SDK还提供了坐标转化工具,利用CoordinateConverter 工具中的方法可以很方便进行坐标转换。
3、全景图控制
用户可以利用手势或者接口对全景图实现丰富的操作。手势操作包括:双指缩放、单指拖动、点击邻接街景箭头。
接口操作包括:改变当前全景图的俯仰角,偏航角以及缩放级别,设置是否显示邻接箭头(如果有邻接街景的情况)。
4、全景图覆盖物
百度SDK支持在全景图内绘制开发者自定义的标注,同时针对所绘制的标注,还支持相应的点击事件响应。目前支持图片和文本两种覆盖物。
2.0.0版本支持设置覆盖物的高度,通过SetPitchHeight(float height)设置覆盖物距离地面的高度(单位m)。
5、内景相册
2.1.0版本将内景相册的实现封装为内景相册插件,如需植入内景,只需导入内景相册插件包(IndoorscapeAlbumPlugin.jar),并通过如下一行代码即可快速完成显示内景相册。
二、运行截图
本示例的运行截图如下:
三、设计步骤
1、添加布局文件
需要在layout文件夹下添加的布局文件有(代码太多,不再粘贴到此处):
demo20_panodemo.xml
demo20_panodemo_coordinate.xml
demo20_panodemo_list_item.xml
demo20_panodemo_main.xml
2、添加Demo20PanoActivity.cs文件
在SrcSdkDemos文件夹下添加该文件,然后将其内容改为下面的代码:
using Android.App; using Android.Content; using Android.OS; using Android.Views; using Android.Widget; namespace BdMapV371Demos.SrcSdkDemos { [Activity(Label = "@string/demo_name_panorama")] public class Demo20PanoActivity : Activity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.demo20_panodemo); ListView mListView = FindViewById<ListView>(Resource.Id.panodemo_list); mListView.Adapter = new DemoListAdapter(this); mListView.ItemClick += (s, e) => { Intent intent = new Intent(this, panoDemos[e.Position].demoClass.GetType()); intent.PutExtra("type", (int)panoDemos[e.Position].type); StartActivity(intent); }; } private static readonly DemoInfo<Activity>[] panoDemos = { new DemoInfo<Activity>(PanoDemoType.PID, Resource.String.demo_title_panorama, Resource.String.demo_desc_panorama0, new Demo20PanoMain()), new DemoInfo<Activity>(PanoDemoType.Geo, Resource.String.demo_title_panorama, Resource.String.demo_desc_panorama1, new Demo20PanoMain()), new DemoInfo<Activity>(PanoDemoType.Mercator, Resource.String.demo_title_panorama, Resource.String.demo_desc_panorama2, new Demo20PanoMain()), new DemoInfo<Activity>(PanoDemoType.UIDStreet, Resource.String.demo_title_panorama, Resource.String.demo_desc_panorama3, new Demo20PanoMain()), new DemoInfo<Activity>(PanoDemoType.UIDInterior, Resource.String.demo_title_panorama, Resource.String.demo_desc_panorama4, new Demo20PanoMain()), new DemoInfo<Activity>(PanoDemoType.Marker, Resource.String.demo_title_panorama, Resource.String.demo_desc_panorama5, new Demo20PanoMain()), new DemoInfo<Activity>(PanoDemoType.CoordinateConverter, Resource.String.demo_title_panorama, Resource.String.demo_desc_panorama6, new Demo20PanoCoordinate()), new DemoInfo<Activity>(PanoDemoType.Other, Resource.String.demo_title_panorama, Resource.String.demo_desc_panorama7, new Demo20PanoMain()) }; private class DemoListAdapter : BaseAdapter { Demo20PanoActivity demo20; public DemoListAdapter(Demo20PanoActivity demo20) : base() { this.demo20 = demo20; } public override View GetView(int index, View convertView, ViewGroup parent) { convertView = View.Inflate(demo20, Resource.Layout.demo20_panodemo_list_item, null); TextView title = convertView.FindViewById<TextView>(Resource.Id.item_title); TextView desc = convertView.FindViewById<TextView>(Resource.Id.item_desc); title.SetText(panoDemos[index].title); desc.SetText(panoDemos[index].desc); return convertView; } public override int Count { get { return panoDemos.Length; } } public override Java.Lang.Object GetItem(int index) { return panoDemos[index]; } public override long GetItemId(int id) { return id; } } private class DemoInfo<T> : Java.Lang.Object where T : Activity { public readonly int title; public readonly int desc; public readonly PanoDemoType type; public readonly T demoClass; public DemoInfo(PanoDemoType type, int title, int desc, T demoClass) { this.type = type; this.title = title; this.desc = desc; this.demoClass = demoClass; } } } public enum PanoDemoType { /// <summary>PID方式</summary> PID = 0, /// <summary>经纬度方式</summary> Geo, /// <summary>墨卡托方式</summary> Mercator, /// <summary>UID方式展示外景</summary> UIDStreet, /// <summary>UID方式展示内景</summary> UIDInterior, /// <summary>标注</summary> Marker, /// <summary>坐标转换测试</summary> CoordinateConverter, /// <summary>其他测试</summary> Other } }
3、Demo20PanoMain.cs文件
在SrcSdkDemos文件夹下添加该文件,然后将其内容改为下面的代码:
using Android.App; using Android.Content.PM; using Android.OS; using Android.Widget; using Com.Baidu.Lbsapi.Panoramaview; using Com.Baidu.Lbsapi; using Android.Views; using Android.Util; using System.Threading.Tasks; using Com.Baidu.Lbsapi.Model; using Com.Baidu.Lbsapi.Tools; using Android.Content; namespace BdMapV371Demos.SrcSdkDemos { /// <summary> /// 全景Demo主Activity /// </summary> [Activity(Label = "@string/demo_name_panorama", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, ScreenOrientation = ScreenOrientation.Sensor)] public class Demo20PanoMain : Activity, IMKGeneralListener { private BMapManager mBMapManager; private PanoramaView mPanoView; private TextView textTitle; private Button btnImageMarker, btnTextMarker;// 添加移除marker测试 private Button btnIsShowArrow, btnArrowStyle01, btnArrowStyle02;// 全景其他功能测试 private Button btnIsShowInoorAblum; private View seekPitchLayout, seekHeadingLayout, seekLevelLayout; private SeekBar seekPitch, seekHeading, seekLevel;// 俯仰角,偏航角,全景图缩放测试 private bool isAddImageMarker = false; private bool isAddTextMarker = false; private bool isShowArrow = false; private bool isShowAblum = true; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); mBMapManager = new BMapManager(ApplicationContext); mBMapManager.Init(this); RequestWindowFeature(WindowFeatures.NoTitle); SetContentView(Resource.Layout.demo20_panodemo_main); InitView(); TestPanoByType(Intent.GetIntExtra("type", -1)); } private void InitView() { textTitle = FindViewById<TextView>(Resource.Id.panodemo_main_title); mPanoView = FindViewById<PanoramaView>(Resource.Id.panorama); btnImageMarker = FindViewById<Button>(Resource.Id.panodemo_main_btn_imagemarker); btnTextMarker = FindViewById<Button>(Resource.Id.panodemo_main_btn_textmarker); btnIsShowArrow = FindViewById<Button>(Resource.Id.panodemo_main_btn_showarrow); btnArrowStyle01 = FindViewById<Button>(Resource.Id.panodemo_main_btn_arrowstyle_01); btnArrowStyle02 = FindViewById<Button>(Resource.Id.panodemo_main_btn_arrowstyle_02); btnIsShowInoorAblum = FindViewById<Button>(Resource.Id.panodemo_main_btn_indoor_album); btnImageMarker.Click += delegate { if (!isAddImageMarker) { AddImageMarker(); btnImageMarker.Text = "删除图片标注"; } else { RemoveImageMarker(); btnImageMarker.Text = "添加图片标注"; } isAddImageMarker = !isAddImageMarker; }; btnTextMarker.Click += delegate { if (!isAddTextMarker) { AddTextMarker(); btnTextMarker.Text = "删除文字标注"; } else { RemoveTextMarker(); btnTextMarker.Text = "添加文字标注"; } isAddTextMarker = !isAddTextMarker; }; seekPitchLayout = FindViewById(Resource.Id.seekpitch_ly); seekHeadingLayout = FindViewById(Resource.Id.seekheading_ly); seekLevelLayout = FindViewById(Resource.Id.seeklevel_ly); seekPitch = FindViewById<SeekBar>(Resource.Id.seekpitch); seekLevel = FindViewById<SeekBar>(Resource.Id.seeklevel); seekHeading = FindViewById<SeekBar>(Resource.Id.seekheading); //seekPitch.StopTrackingTouch += (s, e) =>{ }; //seekPitch.StartTrackingTouch += (s, e) => { }; seekPitch.ProgressChanged += (s, e) => { mPanoView.PanoramaPitch = e.Progress - 90; }; //seekHeading.StopTrackingTouch += (s, e) => { }; //seekHeading.StartTrackingTouch += (s, e) => { }; seekHeading.ProgressChanged += (s, e) => { mPanoView.PanoramaHeading = e.Progress; }; //seekLevel.StopTrackingTouch += (s, e) => { }; //seekLevel.StartTrackingTouch += (s, e) => { }; seekLevel.ProgressChanged += (s, e) => { mPanoView.SetPanoramaZoomLevel(e.Progress + 1); }; } private void TestPanoByType(int type) { mPanoView.SetShowTopoLink(true); HideMarkerButton(); HideSeekLayout(); HideOtherLayout(); HideIndoorAblumLayout(); // 测试回调函数,需要注意的是回调函数要在setPanorama()之前调用,否则回调函数可能执行异常 mPanoView.LoadPanoramaBegin += (s, e) => { Log.Debug("Demo20PanoMain", "onLoadPanoramaStart..."); }; mPanoView.LoadPanoramaEnd += (s, e) => { var json = e.P0; Log.Debug("Demo20PanoMain", "onLoadPanoramaEnd : " + json); }; mPanoView.LoadPanoramaError += (s, e) => { var error = e.P0; Log.Debug("Demo20PanoMain", "onLoadPanoramaError : " + error); }; switch (type) { case (int)PanoDemoType.PID: { textTitle.SetText(Resource.String.demo_desc_panorama0); mPanoView.SetPanoramaImageLevel(PanoramaView.ImageDefinition.ImageDefinitionHigh); string pid = "0900220000141205144547300IN"; mPanoView.SetPanorama(pid); } break; case (int)PanoDemoType.Geo: { textTitle.SetText(Resource.String.demo_desc_panorama1); double lat = 39.945; double lon = 116.404; mPanoView.SetPanorama(lon, lat); } break; case (int)PanoDemoType.Mercator: { textTitle.SetText(Resource.String.demo_desc_panorama2); mPanoView.SetPanoramaImageLevel(PanoramaView.ImageDefinition.ImageDefinitionHigh); int mcX = 12971348; int mcY = 4826239; mPanoView.SetPanorama(mcX, mcY); } break; case (int)PanoDemoType.UIDStreet: { textTitle.SetText(Resource.String.demo_desc_panorama3); mPanoView.SetPanoramaZoomLevel(5); mPanoView.SetArrowTextureByUrl("http://d.lanrentuku.com/down/png/0907/system-cd-disk/arrow-up.png"); mPanoView.SetPanoramaImageLevel(PanoramaView.ImageDefinition.ImageDefinitionMiddle); string uid = "bff8fa7deabc06b9c9213da4"; mPanoView.SetPanoramaByUid(uid, PanoramaView.PanotypeStreet); } break; case (int)PanoDemoType.UIDInterior: { textTitle.SetText(Resource.String.demo_desc_panorama4); ShowIndoorAblumLayout(); mPanoView.SetPanoramaByUid("7c5e480b109e67adacb22aae", PanoramaView.PanotypeInterior); btnIsShowInoorAblum.Click += delegate { if (!isShowAblum) { btnIsShowInoorAblum.Text = "隐藏内景相册"; mPanoView.SetIndoorAlbumVisible(); } else { btnIsShowInoorAblum.Text = "显示内景相册"; mPanoView.SetIndoorAlbumGone(); } isShowAblum = !isShowAblum; }; } break; case (int)PanoDemoType.Marker: { textTitle.SetText(Resource.String.demo_desc_panorama5); showMarkerButton(); mPanoView.SetPanorama("0900220001150514054806738T5"); mPanoView.SetShowTopoLink(false); } break; case (int)PanoDemoType.Other: { textTitle.SetText(Resource.String.demo_desc_panorama7); ShowSeekLayout(); ShowOtherLayout(); mPanoView.SetPanoramaImageLevel(PanoramaView.ImageDefinition.ImageDefinitionHigh); string pid = "0900220001150514054806738T5"; mPanoView.SetPanorama(pid); // 测试获取内景的相册描述信息和服务推荐描述信息 TestPanoramaRequest(); btnIsShowArrow.Click += delegate { if (!isShowArrow) { mPanoView.SetShowTopoLink(false); btnIsShowArrow.Text = "显示全景箭头"; } else { mPanoView.SetShowTopoLink(true); btnIsShowArrow.Text = "隐藏全景箭头"; } isShowArrow = !isShowArrow; }; btnArrowStyle01.Click += delegate { mPanoView.SetArrowTextureByUrl("http://d.lanrentuku.com/down/png/0907/system-cd-disk/arrow-up.png"); }; btnArrowStyle02.Click += delegate { Android.Graphics.Bitmap bitmap = Android.Graphics.BitmapFactory.DecodeResource(Resources, Resource.Drawable.street_arrow); mPanoView.SetArrowTextureByBitmap(bitmap); }; } break; }//end switch } private void TestPanoramaRequest() { string LTAG = "Demo20PanoMain"; Task.Run(() => { PanoramaRequest panoramaRequest = PanoramaRequest.GetInstance(this); string pid = "01002200001307201550572285B"; Log.Error(LTAG, "PanoramaRecommendInfo"); Log.Info(LTAG, panoramaRequest.GetPanoramaRecommendInfo(pid)); string iid = "978602fdf6c5856bddee8b62"; Log.Error(LTAG, "PanoramaByIIdWithJson"); Log.Info(LTAG, panoramaRequest.GetPanoramaByIIdWithJson(iid)); // 通过百度经纬度坐标获取当前位置相关全景信息,包括是否有外景,外景PID,外景名称等 double lat = 40.029233; double lon = 116.32085; BaiduPanoData mPanoDataWithLatLon = panoramaRequest.GetPanoramaInfoByLatLon(lon, lat); Log.Error(LTAG, "PanoDataWithLatLon"); Log.Info(LTAG, mPanoDataWithLatLon.Description); // 通过百度墨卡托坐标获取当前位置相关全景信息,包括是否有外景,外景PID,外景名称等 int x = 12948920; int y = 4842480; BaiduPanoData mPanoDataWithXy = panoramaRequest.GetPanoramaInfoByMercator(x, y); Log.Error(LTAG, "PanoDataWithXy"); Log.Info(LTAG, mPanoDataWithXy.Description); // 通过百度地图uid获取该poi下的全景描述信息,以此来判断此UID下是否有内景及外景 string uid = "bff8fa7deabc06b9c9213da4"; BaiduPoiPanoData poiPanoData = panoramaRequest.GetPanoramaInfoByUid(uid); Log.Error(LTAG, "poiPanoData"); Log.Info(LTAG, poiPanoData.Description); }); } // 隐藏添加删除标注按钮 private void HideMarkerButton() { btnImageMarker.Visibility = ViewStates.Gone; btnTextMarker.Visibility = ViewStates.Gone; } // 显示添加删除标注按钮 private void showMarkerButton() { btnImageMarker.Visibility = ViewStates.Visible; btnTextMarker.Visibility = ViewStates.Visible; } // 隐藏设置俯仰角偏航角SeekBar private void HideSeekLayout() { seekPitchLayout.Visibility = ViewStates.Gone; seekHeadingLayout.Visibility = ViewStates.Gone; seekLevelLayout.Visibility = ViewStates.Gone; } // 显示设置俯仰角偏航角SeekBar private void ShowSeekLayout() { seekPitchLayout.Visibility = ViewStates.Visible; seekHeadingLayout.Visibility = ViewStates.Visible; seekLevelLayout.Visibility = ViewStates.Visible; } // 隐藏其他功能测试 private void HideOtherLayout() { btnIsShowArrow.Visibility = ViewStates.Gone; btnArrowStyle01.Visibility = ViewStates.Gone; btnArrowStyle02.Visibility = ViewStates.Gone; } // 显示其他功能测试 private void ShowOtherLayout() { btnIsShowArrow.Visibility = ViewStates.Visible; btnArrowStyle01.Visibility = ViewStates.Visible; btnArrowStyle02.Visibility = ViewStates.Visible; } // 隐藏内景相册测试 private void HideIndoorAblumLayout() { btnIsShowInoorAblum.Visibility = ViewStates.Gone; } // 显示内景相册测试 private void ShowIndoorAblumLayout() { btnIsShowInoorAblum.Visibility = ViewStates.Visible; } private ImageMarker marker1; private ImageMarker marker2; /// <summary> /// 添加图片标注 /// </summary> private void AddImageMarker() { // 天安门西南方向 marker1 = new ImageMarker(); marker1.SetMarkerPosition(new Point(116.356329, 39.890534)); marker1.SetMarkerHeight(2.3f); marker1.SetMarker(Resources.GetDrawable(Resource.Drawable.icon_marka)); marker1.TabMark += (s, e) => { Toast.MakeText(this, "图片MarkerA标注已被点击", ToastLength.Short).Show(); }; // 天安门东北方向 marker2 = new ImageMarker(); marker2.SetMarkerPosition(new Point(116.427116, 39.929718)); marker2.SetMarker(Resources.GetDrawable(Resource.Drawable.icon_markb)); marker2.SetMarkerHeight(7); marker2.TabMark += (s, e) => { Toast.MakeText(this, "图片MarkerB标注已被点击", ToastLength.Short).Show(); }; mPanoView.AddMarker(marker1); mPanoView.AddMarker(marker2); } /// <summary> /// 删除图片标注 /// </summary> private void RemoveImageMarker() { mPanoView.RemoveMarker(marker1); mPanoView.RemoveMarker(marker2); } private TextMarker textMark1; private TextMarker textMark2; /// <summary> /// 添加文本标注 /// </summary> private void AddTextMarker() { // 天安门西北方向 textMark1 = new TextMarker(); textMark1.SetMarkerPosition(new Point(116.399562, 39.916789)); textMark1.SetFontColor(Android.Graphics.Color.ParseColor("#FFFF0000").ToArgb()); textMark1.SetText("百度全景百度全景\\nmap pano\\n你好marker"); textMark1.SetFontSize(12); textMark1.SetBgColor(Android.Graphics.Color.ParseColor("#FFFFFFFF").ToArgb()); textMark1.SetPadding(10, 20, 15, 25); textMark1.SetMarkerHeight(20.3f); textMark1.TabMark += (s, e) => { Toast.MakeText(this, "textMark1标注已被点击", ToastLength.Short).Show(); }; // 天安门东南方向 textMark2 = new TextMarker(); textMark2.SetMarkerPosition(new Point(116.409766, 39.911808)); textMark2.SetFontColor(Android.Graphics.Color.Red.ToArgb()); textMark2.SetText("你好marker"); textMark2.SetFontSize(12); textMark2.SetBgColor(Android.Graphics.Color.Blue.ToArgb()); textMark2.SetPadding(10, 20, 15, 25); textMark2.SetMarkerHeight(10); textMark2.TabMark += (s, e) => { Toast.MakeText(this, "textMark2标注已被点击", ToastLength.Short).Show(); }; mPanoView.AddMarker(textMark1); mPanoView.AddMarker(textMark2); } /// <summary> /// 删除文本标注 /// </summary> private void RemoveTextMarker() { mPanoView.RemoveMarker(textMark1); mPanoView.RemoveMarker(textMark2); } protected override void OnPause() { mPanoView.OnPause(); base.OnPause(); } protected override void OnResume() { mPanoView.OnResume(); base.OnResume(); } protected override void OnDestroy() { mPanoView.Destroy(); mBMapManager.Dispose(); base.OnDestroy(); } public void OnGetPermissionState(int p0) { //由于MainActivity已经验证过key,所以此处不需要添加任何代码 } } }
4、Demo20PanoCoordinate.cs文件
在SrcSdkDemos文件夹下添加该文件,然后将其内容改为下面的代码:
using Android.App; using Android.OS; using Android.Views; using Android.Widget; using Com.Baidu.Lbsapi.Tools; namespace BdMapV371Demos.SrcSdkDemos { /// <summary> /// 坐标转换 /// </summary> [Activity(Label = "@string/demo_desc_panorama6")] public class Demo20PanoCoordinate : Activity { private RadioGroup radioGroup; private Button btn, btn_ll2mc, btn_mc2ll; private TextView baiduResult, mcResult, llResult; private EditText inputLat, inputLont; // 百度经纬度坐标 Point resultPointLL = null; // 百度墨卡托坐标 Point resultPointMC = null; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); RequestWindowFeature(WindowFeatures.NoTitle); SetContentView(Resource.Layout.demo20_panodemo_coordinate); radioGroup = FindViewById<RadioGroup>(Resource.Id.panodemo_coordinate_rgroup); btn = FindViewById<Button>(Resource.Id.panodemo_coordinate_btn); btn_ll2mc = FindViewById<Button>(Resource.Id.panodemo_ll2mc_btn); btn_mc2ll = FindViewById<Button>(Resource.Id.panodemo_mc2ll_btn); baiduResult = FindViewById<TextView>(Resource.Id.panodemo_coordinate_result); mcResult = FindViewById<TextView>(Resource.Id.panodemo_ll2mc_result); llResult = FindViewById<TextView>(Resource.Id.panodemo_mc2ll_result); inputLat = FindViewById<EditText>(Resource.Id.panodemo_coordinate_input_lat); inputLont = FindViewById<EditText>(Resource.Id.panodemo_coordinate_input_lont); // 测试高德经纬度 inputLat.Text = "39.907687"; inputLont.Text = "116.397539"; // 测试腾讯经纬度 // inputLat.Text="39.907741"); // inputLont.Text="116.397577"); // 测试Google经纬度 // inputLat.Text="39.907723"); // inputLont.Text="116.397543"); // 测试原始GPS经纬度 // inputLat.Text="40.040286"); // inputLont.Text="116.30085"); btn.Click += delegate { if (string.IsNullOrEmpty(inputLat.Text) || string.IsNullOrEmpty(inputLont.Text)) { Toast.MakeText(this, "请输入经纬度", ToastLength.Short).Show(); return; } // 原始点经纬度 Point sourcePoint = new Com.Baidu.Lbsapi.Tools.Point( double.Parse(inputLont.Text), double.Parse(inputLat.Text)); switch (radioGroup.CheckedRadioButtonId) { case Resource.Id.panodemo_coordinate_rgaode: resultPointLL = CoordinateConverter.Converter(CoordinateConverter.COOR_TYPE.CoorTypeGcj02, sourcePoint); break; case Resource.Id.panodemo_coordinate_rtencent: resultPointLL = CoordinateConverter.Converter(CoordinateConverter.COOR_TYPE.CoorTypeGcj02, sourcePoint); break; case Resource.Id.panodemo_coordinate_rgoogle: resultPointLL = CoordinateConverter.Converter(CoordinateConverter.COOR_TYPE.CoorTypeGcj02, sourcePoint); break; case Resource.Id.panodemo_coordinate_rgps: resultPointLL = CoordinateConverter.Converter(CoordinateConverter.COOR_TYPE.CoorTypeWgs84, sourcePoint); break; default: break; } if (resultPointLL != null) { baiduResult.Text = "百度经纬度坐标:\\nLatitude: " + resultPointLL.Y + "\\nLongitude: " + resultPointLL.X; btn_ll2mc.Visibility = ViewStates.Visible; } }; btn_ll2mc.Click += delega
以上是关于(第20讲) 示例20—全景图完整示例的主要内容,如果未能解决你的问题,请参考以下文章