{"id":4229,"date":"2022-05-10T09:00:49","date_gmt":"2022-05-10T09:00:49","guid":{"rendered":"https:\/\/ionicframework.com\/blog\/?p=4229"},"modified":"2022-10-27T19:23:17","modified_gmt":"2022-10-27T19:23:17","slug":"dev-diary-native-google-maps","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps","title":{"rendered":"Dev Diary: Native Google Maps"},"content":{"rendered":"<p>Native Google Maps has been a much-anticipated addition to Capacitor\u2019s core lineup. This new plugin comes with powerful features such as the creation and installation of multiple maps, adding one or more markers, marker clustering, map type support (including indoors and traffic layers), and an advanced scrolling experience\u2014one of the most popular features.<\/p>\n<p>The scrolling implementation of Capacitor Google Maps took a few iterations. Let\u2019s step through the process of creating this complex feature.<\/p>\n<p><!--more--><\/p>\n<h2><strong>Scrolling Complexity<\/strong><\/h2>\n<p>One of the challenges we faced while working on our version of the Google Maps Capacitor Plugin was to figure out some way to improve the \u201cscrolling\u201d experience with real-world content along with a native google map.<\/p>\n<p>Most attempts at this involve simply creating the Google Map view, and placing it on the screen <strong><em>over<\/em><\/strong> the web view that contains the running application. While this works for fullscreen map implementations, this presents several problems for other scenarios:<\/p>\n<ol>\n<li>The map will not scroll inline with, nor force content that sits inline with the map, to wrap around it.<\/li>\n<li>The map lives outside of the DOM of the web application, meaning it will not respect CSS z-indexing. This could be a problem in situations where other web elements need to appear above the map, like menus, dialogs, and other advanced design techniques.<\/li>\n<\/ol>\n<div style=\"max-width: 360px; margin: 0 auto;\"><div class=\"device-demo\">\n            <figure>\n                <figcaption>Google Maps Scrolling Issue Demo<\/figcaption>\n                <video src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/android-old-scroll-bug.mp4\" controls autoplay muted loop><\/video>\n            <\/figure>\n        <\/div><\/div>\n<h2><strong>HTML Element Approach<\/strong><\/h2>\n<p>Our first naive attempt was simple: require the API consumer to create an HTML element that will \u201ccontain\u201d the map (similar to how it works with the JS Maps API), and send a reference to that element along with the rest of their map settings through our API. We then take the bounds of the container element and use those values to position the native google map over the web view.<\/p>\n<p>From here, to implement scrolling we listen to scroll events from all parent elements of the map container and send the updated map container bounds to the native layer, which is used to update the position of the native view.<\/p>\n<p>The result is a native Google Map that appears to scroll inline with the content, with Inline content that wraps around the map thanks to the map container element. This solves problem #1, but since the map view is still over the web view, we still need a way to deal with #2.<\/p>\n<div style=\"max-width: 360px; margin: 0 auto;\"><div class=\"device-demo\">\n            <figure>\n                <figcaption>Google Maps Inline Scroll Demo<\/figcaption>\n                <video src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/android-over-top.mp4\" controls autoplay muted loop><\/video>\n            <\/figure>\n        <\/div><\/div>\n<h2><strong>Inline Native Elements<\/strong><\/h2>\n<p>Normally, there is no way to integrate native elements inline with web content. However, due to an interesting quirk of iOS WebView, there is.<\/p>\n<p>If a block-level element inside an iOS WebView is given a forced overflow scroll, that scrolling element is represented on the native side as a UIScrollView &#8211; and a child of the WKWebView control. This UIScrollView is something we can add arbitrary UIViews into, and when we inject the Google Maps native view into the scroll view, something interesting happens.<\/p>\n<p>The injected native view is inserted into the web view and rendered inline with the rest of the content as if it were any piece of HTML content. Scrolling and touch events all are handled appropriately, as well as proper z-indexing with other HTML elements on the page. This solves problem #2 in the cleanest way possible &#8211; we essentially have a native element functioning as a run-of-the-mill HTML element.<\/p>\n<div style=\"max-width: 360px; margin: 0 auto;\"><div class=\"device-demo\">\n            <figure>\n                <figcaption>Google Maps iOS Scrolling Fix Demo<\/figcaption>\n                <video src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/ios-final.mp4\" controls autoplay muted loop><\/video>\n            <\/figure>\n        <\/div><\/div>\n<p>One problem with this technique is that it is currently not possible to accomplish a similar technique on Android. So, in order to solve problem #2 on Android, we kept our initial technique, but instead of having the native Google Map view above the web view, we moved it behind the web view. This allows HTML elements (<strong><em>ALL HTML<\/em><\/strong> elements, in fact) to layer above the map. The only downside of this is that the web view (and the entire DOM stack all the way down to HTML and body) must have a transparent background for the map view to be visible through the web view control. While not the cleanest resolution, it solves the two main issues with our native maps solution.<\/p>\n<div style=\"max-width: 360px; margin: 0 auto;\"><div class=\"device-demo\">\n            <figure>\n                <figcaption>Google Maps Android Scrolling Fix Demo<\/figcaption>\n                <video src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/android-final.mp4\" controls autoplay muted loop><\/video>\n            <\/figure>\n        <\/div><\/div>\n<h2><strong>Get Started<\/strong><\/h2>\n<p>The new Capacitor Google Maps plugin brings some powerful new features to the community. We hope that this look behind the curtain was insightful and got your minds thinking about how else inline native elements could be used!<\/p>\n<p>For more information on the Google Maps plugin, <a href=\"https:\/\/ionicframework.com\/blog\/announcing-the-capacitor-google-maps-plugin\">check out our blog<\/a> or visit the <a href=\"https:\/\/capacitorjs.com\/docs\/apis\/google-maps\">Capacitor docs<\/a>. We can\u2019t wait to see what you build!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Native Google Maps has been a much-anticipated addition to Capacitor\u2019s core lineup. This new plugin comes with powerful features such as the creation and installation of multiple maps, adding one or more markers, marker clustering, map type support (including indoors and traffic layers), and an advanced scrolling experience\u2014one of the most popular features. The scrolling [&hellip;]<\/p>\n","protected":false},"author":97,"featured_media":4230,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"0","publish_post_category":"26","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"546754","discourse_permalink":"https:\/\/forum.ionicframework.com\/t\/dev-diary-native-google-maps\/223134","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[151,5],"class_list":["post-4229","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-all","tag-capacitor","tag-open-source"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Dev Diary: Native Google Maps - Ionic Blog<\/title>\n<meta name=\"description\" content=\"The Google Maps Plugin empowers developers to add native Google Maps within their Ionic and Capacitor projects with ease.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Dev Diary: Native Google Maps\" \/>\n<meta property=\"og:description\" content=\"The Google Maps Plugin empowers developers to add native Google Maps within their Ionic and Capacitor projects with ease.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-05-10T09:00:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-10-27T19:23:17+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"880\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Joseph Pender\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Joseph Pender\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps\"},\"author\":{\"name\":\"Joseph Pender\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/c5a0825125cbd820e75fa559ab6fb482\"},\"headline\":\"Dev Diary: Native Google Maps\",\"datePublished\":\"2022-05-10T09:00:49+00:00\",\"dateModified\":\"2022-10-27T19:23:17+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps\"},\"wordCount\":799,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png\",\"keywords\":[\"Capacitor\",\"Open Source\"],\"articleSection\":[\"All\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps\",\"url\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps\",\"name\":\"Dev Diary: Native Google Maps - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#primaryimage\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png\",\"datePublished\":\"2022-05-10T09:00:49+00:00\",\"dateModified\":\"2022-10-27T19:23:17+00:00\",\"description\":\"The Google Maps Plugin empowers developers to add native Google Maps within their Ionic and Capacitor projects with ease.\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#primaryimage\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png\",\"width\":1600,\"height\":880,\"caption\":\"Native Google Maps Plugin\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Dev Diary: Native Google Maps\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/c5a0825125cbd820e75fa559ab6fb482\",\"name\":\"Joseph Pender\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/joey_pender-150x150.jpeg\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/joey_pender-150x150.jpeg\",\"caption\":\"Joseph Pender\"},\"url\":\"https:\/\/ionic.io\/blog\/author\/joey\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Dev Diary: Native Google Maps - Ionic Blog","description":"The Google Maps Plugin empowers developers to add native Google Maps within their Ionic and Capacitor projects with ease.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps","og_locale":"en_US","og_type":"article","og_title":"Dev Diary: Native Google Maps","og_description":"The Google Maps Plugin empowers developers to add native Google Maps within their Ionic and Capacitor projects with ease.","og_url":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps","og_site_name":"Ionic Blog","article_published_time":"2022-05-10T09:00:49+00:00","article_modified_time":"2022-10-27T19:23:17+00:00","og_image":[{"width":1600,"height":880,"url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png","type":"image\/png"}],"author":"Joseph Pender","twitter_card":"summary_large_image","twitter_creator":"@ionicframework","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Joseph Pender","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps"},"author":{"name":"Joseph Pender","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/c5a0825125cbd820e75fa559ab6fb482"},"headline":"Dev Diary: Native Google Maps","datePublished":"2022-05-10T09:00:49+00:00","dateModified":"2022-10-27T19:23:17+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps"},"wordCount":799,"commentCount":0,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"image":{"@id":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png","keywords":["Capacitor","Open Source"],"articleSection":["All"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps","url":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps","name":"Dev Diary: Native Google Maps - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#primaryimage"},"image":{"@id":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png","datePublished":"2022-05-10T09:00:49+00:00","dateModified":"2022-10-27T19:23:17+00:00","description":"The Google Maps Plugin empowers developers to add native Google Maps within their Ionic and Capacitor projects with ease.","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/dev-diary-native-google-maps"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#primaryimage","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png","width":1600,"height":880,"caption":"Native Google Maps Plugin"},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/dev-diary-native-google-maps#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"Dev Diary: Native Google Maps"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/c5a0825125cbd820e75fa559ab6fb482","name":"Joseph Pender","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/joey_pender-150x150.jpeg","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/joey_pender-150x150.jpeg","caption":"Joseph Pender"},"url":"https:\/\/ionic.io\/blog\/author\/joey"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/05\/devdiary-feature-image.png","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/4229","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/97"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=4229"}],"version-history":[{"count":0,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/4229\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media\/4230"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=4229"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=4229"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=4229"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}