View in English

  • 打开菜单 关闭菜单
  • Apple Developer
搜索
关闭搜索
  • Apple Developer
  • 新闻
  • 探索
  • 设计
  • 开发
  • 分发
  • 支持
  • 账户
在“”范围内搜索。

快捷链接

5 快捷链接

视频

打开菜单 关闭菜单
  • 专题
  • 相关主题
  • 所有视频
  • 关于

返回 WWDC25

大多数浏览器和
Developer App 均支持流媒体播放。

  • 简介
  • 转写文稿
  • 代码
  • 深入探索 MapKit

    了解 MapKit 和 MapKit JS 的最新更新。我们将介绍一种新的路线类型——骑行路线,并向你展示如何在网页上启用 3D 环视图像。了解新的 Geocoding API 如何支持坐标与地址之间的转换,以及如何使用 Address Representations API 来获取某一区域最恰当的地址。最后,我们将介绍一种新的地点引用方式,确保你的 App 能与 App Intents 无缝协作。

    章节

    • 0:00 - 简介
    • 0:45 - 查找地点
    • 9:34 - 显示地点
    • 14:14 - 畅行四方

    资源

    • Adopting unified Maps URLs
    • Place ID Lookup
    • Searching, displaying, and navigating to places
      • 高清视频
      • 标清视频

    相关视频

    WWDC24

    • 使用 MapKit 充分优化位置相关功能

    WWDC23

    • 认识 SwiftUI 版 MapKit

    WWDC22

    • MapKit 的新功能
  • 搜索此视频…

    Hi, I’m Alex. I’m an engineer on the MapKit team.

    Apple Maps enables you to navigate and explore places around the world right from your device. There’s so much to discover from historical landmarks to cozy cafes, local shops, and great hiking routes. Today, I’ll walk through the updates to MapKit and MapKit JS that let you bring the world of maps into your apps and websites. I'll start with PlaceDescriptor, a new way to find and reference places. Then, I’ll cover geocoding and how you can use it to display information about a place. And finally, I’ll help you get people where they’re going with our directions and Look Around APIs. I’ll start with finding and referencing places.

    Last year, we introduced an identifier, which can be used to reference the places represented by map items in the MapKit framework, and by Place in MapKit JS. The references are unique and they remain valid over time. Anytime the Maps team updates the data for a place, like the website URL, an app using Place ID can display that fresh information.

    Because these identifiers are unique, the app can use them as keys in its own data structures.

    Identifiers can be persisted and shared.

    Apple keeps track of the data and you can reference it at any time. Place identifiers are still the best choice when you want to persist a reference to a specific place you found with MapKit. But there are some cases where it might not be the best fit. Sometimes you still want to be able to find MapKit’s rich data for a specific place, even when you don’t have an identifier. For example, if you have a web API or CRM that provides you with the name and address of all of your places of business. Or perhaps you have the name and coordinate for a specific place. In these cases, you know you want to find an exact and single place. So APIs like a local search that return multiple results aren't the best match.

    Other times, I want to pass place references to or from code I don't own. Perhaps I want to vend places from a framework. Or when I'm using App Intents, I might want to take a place as an intent parameter, return a place as an intent result, or include a place as a property on my app entities. In these cases, you might be interacting with other apps that don't use MapKit at all.

    I can pass a purely geographic representation like CLLocation, but there’s no good way to use that to find a rich place of interest, like I can with a MapKit identifier. To account for these cases, we’re introducing a new type: PlaceDescriptor.

    It’s in a new framework: GeoToolbox. PlaceDescriptor allows you to supply information that describes a place in a structured way.

    A PlaceDescriptor can then be used by MapKit or by other Mapping Service Providers to attempt to find rich data about that place.

    A PlaceDescriptor has three top level pieces of information: a string called commonName. When making your PlaceDescriptor, you should provide well known names like Guggenheim Museum or Sydney Opera House. This field is not intended for private data like Mom’s House, and including it doesn’t help MapKit find your place.

    PlaceDescriptor also has an array of representations. These representations are common formats that any app or framework dealing with geographic information should be able to understand.

    There are three types of PlaceRepresentations to choose from.

    The first is an address string, like you would write on an envelope. Providing the most complete version of the address possible allows for the highest chance MapKit can find your place. The next is a coordinate, for things at a fixed definite point, like a known landmark or place of business.

    And finally, a deviceLocation, which uses CLLocation.

    This is appropriate for use with received GPS data and might have additional values like accuracy, timestamp, heading, or speed.

    The representations array must contain at least one representation and is ordered in decreasing precedence. For example, if a PlaceDescriptor is coming from a contacts application, a coordinate may have been derived from the address of that place. In that case, the address would come first because it’s the original source of information and the coordinate would come second. Lastly, PlaceDescriptor has an array of supporting representations. These representations are ones that may not be usable by all applications and aren't required. The supportingRepresentations array can be empty. We’ll talk more about what can be in supportingRepresentations later. To demonstrate PlaceDescriptor and all the other new APIs that are coming up, I’m going to walk you through an example app. It’s for fountain aficionados to find fountains in far-flung locations all around the world.

    I’d like to start by collecting fountains in Dublin that would be cool to visit and put them on a map.

    Since the introduction of MapKit for SwiftUI, I've been able to make a simple marker on the map with a coordinate, but I’d like to leverage rich Apple Maps data about my fountains in conjunction with all the other MapKit APIs in my app, even though I don’t have a Place ID. A great opportunity to use PlaceDescriptor.

    Let’s make a PlaceDescriptor to reference this fountain.

    First, I’ll import GeoToolbox. I know there’s a fountain at these coordinates. So when I make my PlaceDescriptor, I’ll provide a coordinate representation with them. Finally, I know it’s called the Anna Livia Fountain, so I supply that as well. That’s all I need to do to make a valid PlaceDescriptor. Then I can import MapKit and create a map item request with my PlaceDescriptor.

    Once I have my request, I can execute it to get an MKMapItem for that place. MapItem is the core type for places in MapKit, and I can use it with all kinds of APIs.

    For example, I can then use the MapItem on a map. You’ll notice the marker displays the name, colors, and iconography Apple Maps has for this place.

    Let's add a second place to the map, this time using an address to create my descriptor instead.

    I just need to provide the most complete version of the address I have for this fountain. Then I can make a PlaceDescriptor with that, and the name of the fountain. I use MKMapItemRequest just like before and add it to the map with my other fountain. It's that easy.

    I’ve shown you the power of using PlaceDescriptor to find a place with a name, as well as coordinate and address PlaceRepresentations.

    But there is one more top-level property of PlaceDescriptor you can use. There’s a single type of supporting representation, service identifiers.

    A service identifier representation is a dictionary where the key is the bundle identifier for a given mapping service, and the value is the identifier representing your place for that mapping service.

    For example, if I know the MapKit Place Identifier for a place, I can make a dictionary where the key is com.apple.mapKit, and the value is the identifier.

    Then i create a serviceIdentifiers representation and pass it to the supportingRepresentations parameter of the PlaceDescriptor initializer.

    If I know the identifier for a place from a different mapping service provider, I can supply it here.

    MapKit doesn’t use other identifiers, but supplying them can be useful in scenarios like App Intents, where you can supply a PlaceDescriptor to another app that may not use MapKit.

    You can provide as many identifiers as you like.

    If you’re using MapKit API, we always do the right thing with service identifiers.

    If present, MKMapItemRequest will use MapKit identifiers from your PlaceDescriptor to fetch the place.

    If there's no MapKit identifier, or if using the supplied identifier fails for any reason, the other representations on PlaceDescriptor will be used to find your place instead.

    Likewise, if you make a PlaceDescriptor with a MapItem you got some other way, we’ll make sure the PlaceDescriptor is populated with all the representations you need, including identifier.

    I’ll use PlaceDescriptor and MKMapItemRequest to add the rest of the Dublin fountains I know about to my app.

    MapItems requested with a PlaceDescriptor can be used with all our MapKit APIs to show rich maps data just like those fetched by identifier, or with MKLocalSearch.

    For example, Place Cards. When you present a place card for a place requested by PlaceDescriptor, we’re able to show up-to-date rich data like operating hours, as well as a link to Apple Maps.

    I can show a place card when someone selects a fountain in my app with just one line of code.

    Place cards are an easy way to show tons of great info about a place in your app. Check out “Unlock the power of places with MapKit” from WWDC2024 to learn more.

    Speaking of place cards, this year, place cards in MapKit JS also provide a universal link to Apple Maps. On devices with the Maps app installed, links will open there.

    And for devices that don’t have a Maps app, the place card links to maps.apple.com, which we launched last summer in public beta.

    Now, when your apps and websites linked to Apple Maps, even those on non Apple platforms can use Maps on the web to explore further.

    With the rollout of iOS 18.4, we updated how Maps handles URLs, so you can make similar universal links with confidence. For example, this URL to perform a search.

    We've made parameters more consistent, simpler, and easier to read.

    We’ve also added many additional parameters to link to even more features in Maps. Make sure to check out “Adopting unified Maps URLs” linked in the materials for this video, so you can adopt universal Maps links in your app.

    All right, I've found my places. Next, I'll show you how to use geocoding and address representations to display more information about places in your app.

    If you’re not familiar, forward geocoding refers to the process of taking an address and finding the coordinate it refers to. An example of this is tapping on an address in the Contacts app, which takes you to a map.

    Reverse geocoding is the opposite. You provide a coordinate and we give you an address. An example of this is when you drop a pin in the Maps app, and we show you the address information for that location.

    In iOS 18 and before, you would use CoreLocation to perform your geocoding tasks.

    This year, we’re deprecating CLGeocoder, soft-deprecating CLPlacemark, and bringing Geocoding to MapKit.

    In my app, I also want to keep track of the fountains I found and taken fabulously framed photos for.

    These photos include a geotag, which has the coordinates where they were taken, but I don’t have any supporting information like a name. That means I can't use PlaceDescriptor to find the rich place. All I have is coordinates. So I'll use reverse geocoding in MapKit to find more context to display next to my photos.

    Let’s reverse geocode my first fountain photo.

    I’ll start with the coordinates where the photo was taken. Then I’ll make an MKReverseGeocodingRequest with that location. Unlike the MKMapItemRequest with PlaceDescriptor, which I showed you earlier, MKReverseGeocodingRequests’s initializer returns an optional. If you provide a CLLocation with invalid coordinates, MapKit won’t be able to perform a request for you.

    When the request returns, I get an array of map items. For most geocoding requests, this array should contain only one entry. So I'll pick the first one. Note that because this map item came from a geocoding API, it will not contain rich information for a place of interest. This mapItem only contains information about the address point.

    Now that I have my map item, I can display the address.

    I’ll use MKReverseGeocoding request to get an address for the rest of my photos and show them in a list.

    My app is starting to come together, but I think the full address might be too much detail for this screen. So I’ll take a look at the other options I have. MKMapItem offers two optional properties for accessing address information.

    First, MKAddress. You can instantiate your own MKAddress when you make your own MKMapItem.

    And MapKit also provides an MKAddress when returning MapItems from APIs like geocoding, local search, and PlaceDescriptor resolution.

    Second, MKAddressRepresentations, which does not have an initializer.

    Address representations are only available on map items returned from MapKit APIs.

    Let me cover MKAddress first. It has two string properties, fullAddress and shortAddress.

    FullAddress is the most complete version of a postal or administrative address that we have, while the shortAddress only provides the most crucial parts.

    In some cases, the address we provide might be very brief.

    For example, a reverse geocode for coordinates in the middle of the ocean may be just one line.

    When you instantiate a MapItem of your own, the address property is used in MapKit place cards, allowing you to show your own address information.

    While MKAddress provides simple versions of an address, MKAddressRepresentations provides many powerful ways to show address information in your app. For example, if you want to show a list of full addresses, but you know they’re all in the same country, you may want to omit the region in your app UI.

    For that, you can use full address, including region, false.

    Or perhaps you want to list the city and some additional context about where the city is.

    Sometimes you want to provide a state or province like Los Angeles, California. Other times you’ll want to include the country like Paris, France.

    MapKit makes this easy by choosing the right thing for your address, as well as locale and region info of the device requesting the map item. Now that I know more about the different address representations available for my app, I’ll choose cityWithContext to make the address info I’m showing with my photos more concise. Now I’m showing the right level of detail for my app, and it looks great.

    The API for forward geocoding is very similar to reverse geocoding. With MKGeocodingRequest, I can get back a MapItem, this time for my address. That makes it super easy to access coordinates or add it to a map. It also includes all the options we just discussed for address information, so I can get the various display representations for my address that I didn’t have before I made the geocoding request.

    Now that I’ve found my places and displayed some information about them, I’ll show you MapKit APIs to help you navigate to them.

    MapKit has a directions API that can find routes for traveling between a source and destination via multiple modes of transport, like walking and driving.

    Directions provides time and distance estimates, as well as detailed information about all the steps you need to take along the way.

    Back in my map view of Dublin, I’d like to plan directions to the fountains I’ve curated. I’ll enable selection on my map by providing a map item binding in my maps initializer. I can then compute my route when the selected item changes.

    For more information on how to handle map selection, check out “Meet MapKit for SwiftUI” from WWDC 2023.

    To get my route, first I create a directions request.

    Then I set the device’s current location as the source and the selected map item as the destination.

    Next, I create a directions object.

    And finally, I calculate my route. I’ll make sure to handle any errors, and then I’ll process the response. But what’s in the response from a directions request? We’ll return you the source and destination we matched for your route. These may be slightly different than what you provided in your request.

    For example, driving directions may take into account parking, and walking directions may take you directly to the door for a building.

    We also include an array that has one or more routes that satisfy your request.

    Routes have lots of powerful information, including a localized name you can use as a title for a route, an array of notices that are relevant to your route, like road closures, the distance required to travel on that route in meters, the amount of time it would take to travel on that route, and the geometry of the route, suitable for drawing on a map.

    I’m excited to share that this year we’ve added support for cycling directions to MapKit. For my app, cycling is the perfect way to see the fountains of Dublin. It’s as simple as modifying one property on my directions request.

    I want to display a potential cycling route for my directions, so I’ll take the first route from the response. And I’ll add it to my map with MapPolyline. It’s that easy to show directions.

    Cycling routes with MapKit are powerful. They take advantage of paths and trails unavailable when driving and omit certain roads not suitable for bikes.

    You can also get cycling directions and estimated arrival times with MapKit JS.

    Just like with Swift, all I need to do is add a single line of configuration to my existing directions request to specify cycling as a transport type.

    I’m also excited to share that for the first time, you can now get directions with MapKit on watchOS! In fact, over 20 MapKit APIs have come to Apple Watch with the latest watchOS SDK.

    Now that I have a good cycling route for my Fountain Tour, I would feel even more comfortable riding if I could scope out the route before I go.

    By enabling the Maps Look Around feature, I can get 360 degree interactive street level imagery of the city and easily preview roads, bike lanes, parking, and landmarks.

    We brought Look Around to MapKit apps in iOS 16, including APIs to check if imagery is at a given location, preview look around imagery, and present it full screen. To learn more, check out the “What’s new in MapKit session” from WWDC 2022.

    This year, we’re bringing Look Around to MapKit JS, so you can enable it in your website or web application. There are two types of Look Around Views you can add.

    The first is interactive look around, which allows you to embed a user navigable look around view inside your own UI. Second is the look around preview. This gives a static snapshot of imagery at your desired location.

    Clicking on the preview launches a full screen interactive experience.

    To add an interactive look around view to my website, first I need a place object. I can use any MapKit JS API that returns a place like place lookup, search, or geocoding.

    In this case, I have an identifier, so I’ll use placeLookup.

    Then I create a look around object passing in the containing DOM element, as well as my place object, and finally an options dictionary.

    There are three options supported by LookAroundView. The first is openDialog. When this option is true, the LookAroundView will cover the whole browser window.

    Second is showsDialogControl. When this is true, a button will appear in the LookAroundView that allows you to enter and exit the full window experience. And finally, showsCloseControl. When true, a button is included that closes the look around view.

    MapKit JS will emit various events related to the LookAroundView. You can add event listeners to respond to or override default behaviors. For example, when the user taps on the close button, a close event will be sent.

    You can use this callback to perform animations or state changes that make sense in your app.

    If you don’t cancel the default action to this event, the lookAround view will be removed from the DOM.

    Other events you may want to handle include: The Load event, which is dispatched when the view is fully loaded.

    The Error event, which is dispatched when there is a problem. For example, when the imagery is not available or when the browser isn’t capable of showing the view. MapKit JS provides an error UI, but you may want to have your own error or fallback experience. And finally, lookAround dispatches readystatechange events, which you can use to monitor the lifecycle of the view. The ready state changes when the view is loading, finishes loading, has an error, or is removed from the DOM.

    In addition to the LookAroundView, you can use the Look Around Preview API to achieve a simpler experience.

    Look Around Previews aren’t interactive. The user can’t pan the view. Clicking on the Look Around Preview launches a full window look around experience.

    I think LookAround with MapKit JS will bring your websites to the next level. And that wraps up our session. It was a fountain of knowledge. I showed you ways to find places, display place information, and navigate to places all over the world with MapKit and MapKit JS.

    Before we go, let me give you some homework.

    Use PlaceDescriptor to find places with or without an identifier and to send place references to other apps.

    Update any links to Apple Maps to use our new unified URL format.

    Move your apps from CoreLocation to MapKit APIs for geocoding and leverage our excellent address representations.

    And finally, add cycling directions and look around to your app to help people get where they're going.

    Thanks for stopping by and learning about MapKit with me today!

    • 4:49 - Putting Marker on the Map with a coordinate

      // Putting Marker on the Map with a coordinate
      
      let annaLiviaCoordinates = CLLocationCoordinate2D(
          latitude: 53.347673,
          longitude: -6.290198
      )
      var body: some View {
          Map {
             Marker(
                  "Anna Livia Fountain",
                  coordinate: annaLiviaCoordinates
              )
          }
      }
    • 5:07 - Creating and resolving a PlaceDescriptor with coordinate PlaceRepresentation

      // Creating and resolving a PlaceDescriptor with coordinate PlaceRepresentation
      
      import GeoToolbox
      import MapKit
      
      let annaLiviaCoordinates = CLLocationCoordinate2D(
          latitude: 53.347673,
          longitude: -6.290198
      )
      let annaLiviaDescriptor =  PlaceDescriptor(
          representations: [.coordinate(annaLiviaCoordinates)],
          commonName: "Anna Livia Fountain"
      )
      
      let request = MKMapItemRequest(placeDescriptor: annaLiviaDescriptor)
      do {
          annaLiviaMapItem = try await request.mapItem
      } catch {
          print("Error resolving placeDescriptor: \(error)")
      }
    • 5:56 - Creating and resolving a PlaceDescriptor with address PlaceRepresentation

      // Creating and resolving a PlaceDescriptor with address PlaceRepresentation
      
      import GeoToolbox
      import MapKit
      
      let address = "121-122 James's St, Dublin 8"
      let descriptor =  PlaceDescriptor(
          representations: [.address(address)],
          commonName: "Obelisk Fountain"
      )
      
      let request = MKMapItemRequest(placeDescriptor: descriptor)
      do {
          obeliskFountain = try await request.mapItem
      } catch {
          print("Error resolving placeDescriptor: \(error)")
      }
    • 6:45 - Creating a PlaceDescriptor with identifiers

      // Creating a PlaceDescriptor with identifiers
      
      import GeoToolbox
      
      let annaLiviaCoordinates = CLLocationCoordinate2D(
          latitude: 53.347673,
          longitude: -6.290198
      )
      let identifiers = ["com.apple.MapKit" : "ICBB5FD7684CE949"]
      let annaLiviaDescriptor =  PlaceDescriptor(
          representations: [.coordinate(annaLiviaCoordinates)],
          commonName: "Anna Livia Fountain",
          supportingRepresentations: [.serviceIdentifiers(identifiers)]
      )
    • 7:28 - Fetching a MapItem from a PlaceDescriptor

      // Fetching a MapItem from a PlaceDescriptor
      
      let request = MKMapItemRequest(placeDescriptor: descriptor)
      let mapitem = try await request.mapItem
    • 7:43 - Getting a PlaceDescriptor from a MapItem

      // Getting a PlaceDescriptor from a MapItem
      
      let descriptor = PlaceDescriptor(mapItem: mapitem)
    • 8:10 - Place Card

      // Place Card
      
      var body: some View {
          Map {
              ForEach(fountains, id:\.name) { fountain in
                  Marker(item: fountain)
                      .mapItemDetailSelectionAccessory(.callout)
              }
          }
      }
    • 10:45 - Reverse geocode with MapKit

      // Reverse geocode with MapKit
      
      import MapKit
      
      let millCreekCoordinates = CLLocation(latitude: 39.042617, longitude: -94.587526)
      if let request = MKReverseGeocodingRequest(location: millCreekCoordinates) {
          do {
              let mapItems = try await request.mapItems
              millCreekMapItem = mapItems.first
          } catch {
              print("Error reverse geocoding location: \(error)")
          }
      }
    • 13:50 - Forward geocoding with MapKit

      // Forward geocoding with MapKit
      
      var body: some View {
          Map {
              if let mapItem {
                  Marker(item: mapItem)
              }
          }
          .task {
              let request = MKGeocodingRequest(
                  addressString: "1 Ferry Building, San Francisco"
              )
              do {
                  mapItem = try await request?.mapItems.first
              } catch {
                  print("Error geocoding location: \(error)")
              }
          }
      }
    • 14:38 - Allowing Map Selection

      // Allowing Map Selection
      
      @State var selectedItem: MKMapItem?
      
      var body: some View {
          Map(selection: $selectedItem) {
             UserAnnotation()
             ForEach(fountains, id: \.self) { item in
                Marker(item: item)
             }
          }
          .onChange(of: selectedItem) {
             // Compute Route
          }
      }
    • 15:00 - Fetch a route

      // Fetch a route
      
      let request = MKDirections.Request()
      request.source = MKMapItem.forCurrentLocation()
      request.destination = selectedItem
      let directions = MKDirections(request: request)
      do {
          let response = try await directions.calculate()
          returnedRoutes = response.routes
      } catch {
          print("Error calculating directions: \(error)")
      }
    • 16:06 - Fetch a cycling route

      // Fetch a cycling route
      
      let request = MKDirections.Request()
      request.source = MKMapItem.forCurrentLocation()
      request.destination = selectedItem
      request.transportType = .cycling
      let directions = MKDirections(request: request)
      do {
          let response = try await directions.calculate()
          returnedRoutes = response.routes
      } catch {
          print("Error calculating directions: \(error)")
      }
    • 16:25 - Display a route on the Map

      // Display a route on the Map
      
      Map {
          if let mapRoute {
              UserAnnotation()
              MapPolyline(mapRoute)
                  .stroke(Color.blue, lineWidth: 5)
          }
      }
    • 16:40 - Cycling directions in MapKit JS

      // Cycling directions in MapKit JS
      
      let directions = new mapkit.Directions();
      directions.route ({
          origin: safariPlayground,
          destination: cherryHillFountain,
          transportType: mapkit.Directions.Transport.Cycling
      }, (error, { routes: [{ polyline }] }) => {
          polyline.style.lineWidth = 5;
          map.showItems([
              new mapkit.PlaceAnnotation(place),
              new mapkit.PlaceAnnotation(
                place2,
                { selected: true }
              ),
              polyline
          ]);
      });
    • 17:26 - Look Around

      // Look Around
      
      var body: some View {
          Map {
              ForEach(fountains, id:\.name) { fountain in
                  Marker(item: fountain)
             }
          }
          .overlay(alignment: .bottomLeading) {
              if (lookAroundScene != nil) {
                  LookAroundPreview(scene: $lookAroundScene)
                      .frame(width: 230, height: 140)
                      .cornerRadius(10)
                      .padding(8)
              }
          }
      }
    • 18:10 - Look Around View in MapKit JS

      // Look Around View in MapKit JS
      
      const placeLookup = new mapkit.PlaceLookup();
      const place = await new Promise(
          resolve => placeLookup.getPlace(
              "IBE1F65094A7A13B1",
              (error, result) => resolve(result)
          )
      );
      
      // Create an interactive look around view.
      const lookAround = new mapkit.LookAround(
          document.getElementById("container"),
          place,
          options
      );
    • 18:35 - Look Around Options

      // Look Around Options for MapKit JS
      
      const options = {
          // Enters a full window experience
          // immediately on load
          openDialog: true,
          
          // Provides a button to enter and
          // exit full window.
          showsDialogControl: true,
          
          // Provides a button to destroy
          // the look around view.
          showsCloseControl: true,
      };
    • 19:10 - Handle MapKit JS Look Around events

      // Handle MapKit JS Look Around events
      
      lookAround.addEventListener(
          "close",
          event => {
              app.closeView();
              event.preventDefault();
          }
      );
      
      lookAround.addEventListener(
          "load",
          event => app.fadeInView()
      );
      
      lookAround.addEventListener(
          "error",
          event => app.fadeOutView()
      );
      
      lookAround.addEventListener(
          "readystatechange",
          event => console.log(lookAround.readyState)
      );
    • 20:01 - MapKit JS Look Around Preview

      // MapKit JS Look Around Preview
      
      const lookAround = new mapkit.LookAroundPreview(
          document.getElementById("container"),
          place
      );

Developer Footer

  • 视频
  • WWDC25
  • 深入探索 MapKit
  • 打开菜单 关闭菜单
    • iOS
    • iPadOS
    • macOS
    • Apple tvOS
    • visionOS
    • watchOS
    打开菜单 关闭菜单
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    打开菜单 关闭菜单
    • 辅助功能
    • 配件
    • App 扩展
    • App Store
    • 音频与视频 (英文)
    • 增强现实
    • 设计
    • 分发
    • 教育
    • 字体 (英文)
    • 游戏
    • 健康与健身
    • App 内购买项目
    • 本地化
    • 地图与位置
    • 机器学习
    • 开源资源 (英文)
    • 安全性
    • Safari 浏览器与网页 (英文)
    打开菜单 关闭菜单
    • 完整文档 (英文)
    • 部分主题文档 (简体中文)
    • 教程
    • 下载 (英文)
    • 论坛 (英文)
    • 视频
    打开菜单 关闭菜单
    • 支持文档
    • 联系我们
    • 错误报告
    • 系统状态 (英文)
    打开菜单 关闭菜单
    • Apple 开发者
    • App Store Connect
    • 证书、标识符和描述文件 (英文)
    • 反馈助理
    打开菜单 关闭菜单
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program (英文)
    • News Partner Program (英文)
    • Video Partner Program (英文)
    • 安全赏金计划 (英文)
    • Security Research Device Program (英文)
    打开菜单 关闭菜单
    • 与 Apple 会面交流
    • Apple Developer Center
    • App Store 大奖 (英文)
    • Apple 设计大奖
    • Apple Developer Academies (英文)
    • WWDC
    获取 Apple Developer App。
    版权所有 © 2025 Apple Inc. 保留所有权利。
    使用条款 隐私政策 协议和准则