diff --git a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml index 6afe27288aaf..c1233356fea2 100644 --- a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml @@ -24,7 +24,14 @@ dependencies: google_maps_flutter_android: ^2.13.0 google_maps_flutter_ios: ^2.12.0 google_maps_flutter_platform_interface: ^2.9.0 - google_maps_flutter_web: ^0.5.10 + # KNOWN ISSUE: as a result of issue https://github.com/flutter/packages/pull/3895 a fork was + # made (https://github.com/BMEC/flutter_packages) and is being used until the issue is resolved. + # Once resolved, we should revert to https://github.com/flutter/packages. + google_maps_flutter_web: # KNOWN ISSUE TODO revert to ^2.10.0 + git: + url: git@github.com:BMEC/flutter_packages.git + ref: ^1.0.0 + path: packages/google_maps_flutter/google_maps_flutter_web dev_dependencies: flutter_test: diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart index f6af32046ccd..f8bcf391f602 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart @@ -581,6 +581,81 @@ bool _isPolygonClockwise(List path) { return direction >= 0; } +/// Return the SVG [path] and total [length] generated from the [patterns]. +/// +/// Walks the [patterns] adding the appropriate SVG `instructions`. For each +/// [PatternItem] an SVG `moveto` is optionally added as follows: +/// For [PatternItem.dot] `M0 y 0 y`. +/// For [PatternItem.dash] `M0 y 0 y += length`. +/// For [PatternItem.gap] y is just incremented `y += length`. +/// +/// This draws a line in the y-direction with dots, dashes and gaps that match +/// the [pattern]. +/// +/// Reference https://www.w3.org/TR/SVG2/paths.html#PathDataGeneralInformation. +({String path, double length}) _gSymbolPathFromPatterns( + List patterns) { + // Starting SVG path string. + String path = 'M'; + + // Starting y coordinate. + double y = 0; + + // Generates the `moveto`. + String svgMoveToFromLength(double length) => '0 $y 0 ${y += length} '; + + for (final PatternItem pattern in patterns) { + // Cast to list. + final List patternJson = pattern.toJson() as List; + + // Switch on the PatternItem type. + switch (patternJson.first) { + case 'dot': + path += svgMoveToFromLength(0); + break; + case 'dash': + path += svgMoveToFromLength(patternJson.last as double); + break; + case 'gap': + y += patternJson.last as double; + break; + default: + throw UnimplementedError( + 'PatternItem ${patternJson.first} is not implemented'); + } + } + + return (path: path, length: y); +} + +/// Generates equivalent the [PolylineOptions.icons] for the [polyline.pattern]. +/// +/// See https://developers.google.com/maps/documentation/javascript/symbols#custom_paths +/// +List? _polylineOptionIconsFromPolyline(Polyline polyline) { + // Return null if there is no pattern. + if (polyline.patterns.isEmpty) { + return null; + } + + /// This scale seems to make for a good match between mobile and web. + const double scale = 0.4; + + final ({double length, String path}) gSymbolPath = + _gSymbolPathFromPatterns(polyline.patterns); + + return [ + gmaps.IconSequence() + ..repeat = '${gSymbolPath.length * scale + polyline.width}px' + ..icon = (gmaps.GSymbol() + ..strokeColor = _getCssColor(polyline.color) + ..path = gSymbolPath.path + ..scale = scale + ..strokeWeight = polyline.width + ..strokeOpacity = _getCssOpacity(polyline.color)) + ]; +} + gmaps.PolylineOptions _polylineOptionsFromPolyline( gmaps.Map googleMap, Polyline polyline) { final List paths = @@ -591,14 +666,16 @@ gmaps.PolylineOptions _polylineOptionsFromPolyline( ..strokeWeight = polyline.width ..strokeColor = _getCssColor(polyline.color) ..strokeOpacity = _getCssOpacity(polyline.color) + ..strokeOpacity = polyline.patterns.isNotEmpty + ? _getCssOpacity(Colors.transparent) + : _getCssOpacity(polyline.color) ..visible = polyline.visible ..zIndex = polyline.zIndex - ..geodesic = polyline.geodesic; + ..geodesic = polyline.geodesic + ..icons = _polylineOptionIconsFromPolyline(polyline); // this.endCap = Cap.buttCap, // this.jointType = JointType.mitered, -// this.patterns = const [], // this.startCap = Cap.buttCap, -// this.width = 10, } // Translates a [CameraUpdate] into operations on a [gmaps.Map].