1660688940
A new Flutter plugin.
Run this command:
With Flutter:
$ flutter pub add carillon_map_box
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
carillon_map_box: ^0.0.7+9
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:carillon_map_box/carillon_map_box.dart';
example/lib/main.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:carillon_map_box/carillon_map_box.dart';
import 'package:carillon_map_box/models.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
Map<String, dynamic> options = {
"mapStyleUrl": "mapbox://styles/carillon/ckwroj8nx14d815nvidt3jwea",
// DAY -> mapbox://styles/carillon/ckwroj8nx14d815nvidt3jwea
// NIGHT -> mapbox://styles/carillon/ckwrokzci2fh214mk66vm3tai
"simulateRoute": true,
"points": [
CarillonLocation(
id: 0, address: "plaisir", latitude: 48.824810, longitude: 1.965922)
.toJson(),
CarillonLocation(
id: 1, address: "clamart", latitude: 48.8, longitude: 2.25)
.toJson()
]
};
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('CarillonMapBox Example (convenient)'),
),
body: Center(
child: CarillonMapBox(
onCarillonMapBoxCreated: _onCarillonMapBoxCreated,
options: options),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
CarillonMapBox.startNavigation(options, () {
print("Start CALLBACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}, () {
print("End CALLBACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
});
Future.delayed(const Duration(seconds: 10), () {
CarillonMapBox.sendAlert(() {
print("popup button CALLBACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
});
});
},
),
),
);
}
void _onCarillonMapBoxCreated(CarillonMapBoxController controller) {}
}
This project is a starting point for a Flutter plug-in package, a specialized package that includes platform-specific implementation code for Android and/or iOS.
For help getting started with Flutter, view our online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.
Original article source at: https://pub.dev/packages/carillon_map_box
1660656183
flutter_minemap
MineData Map Component Flutter Plugin
dependencies: flutter: sdk: flutter flutter_minemap: ^x.x.x
setting accessToken, offlineAccessToken, solution
import 'package:flutter/material.dart';
import 'package:flutter_minemap_wdr/flutter_minemap.dart';
class MapDemoPage extends StatefulWidget {
MapDemoPage({Key key}) : super(key: key);
@override
_MapDemoPageState createState() => _MapDemoPageState();
}
class _MapDemoPageState extends State<MapDemoPage> {
MineMapController _mineMapController;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('地图'),
),
body: Container(
height: double.infinity,
width: double.infinity,
alignment: Alignment.center,
child: MineMapView(
mapOptions: FMMMapOptions(
accessToken: '',
offlineAccessToken: '',
solution: '',
),
onMineMapViewCreated: (MineMapController controller) {
_mineMapController = controller;
},
),
),
);
}
}
Run this command:
With Flutter:
$ flutter pub add flutter_minemap_wdr
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
flutter_minemap_wdr: ^0.0.5
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:flutter_minemap_wdr/flutter_minemap.dart';
import 'package:flutter_minemap_wdr/mimemap_controler.dart';
import 'package:flutter_minemap_wdr/minemap_view.dart';
import 'package:flutter_minemap_wdr/models/fmm_map_models.dart';
import 'package:flutter_minemap_wdr/models/fmm_map_options.dart';
import 'package:flutter_minemap_wdr/models/fmm_types.dart';
import 'package:flutter_minemap_wdr/models/overlays/cluster_layer_model.dart';
import 'package:flutter_minemap_wdr/models/overlays/fmm_marker.dart';
import 'package:flutter_minemap_wdr/private/fmm_method_channel_handler.dart';
import 'package:flutter_minemap_wdr/private/fmm_method_id.dart';
import 'package:flutter_minemap_wdr/uint/fmm_map_conveter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_minemap_example/index_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'FlutterMinemap',
home: IndexPage(),
);
}
}
Download Details:
Author: Asscre
Source Code: https://github.com/Asscre/flutter_minemap
1660429620
tmap
is an actively maintained open-source R-library for drawing thematic maps. The API is based on A Layered Grammar of Graphics and resembles the syntax of ggplot2
, a popular R-library for drawing charts.
See below the source code for these images.
tmap
is available on . Installation is straightforward:
install.packages("tmap")
For Linux and macOS users who are new to working with spatial data in R, this may fail since additional (non-R) libraries are required (which are automatically installed for Windows users).
Windows No additional installation required.
Linux (Ubuntu) See https://geocompr.github.io/post/2020/installing-r-spatial-ubuntu/. Please address installation issues in this issue.
macOS See http://www.kyngchaos.com. Please address installation issues in this issue.
The latest development version can be installed using devtools
. In order to use the development version of tmap
, it is recommended to use the development version of tmaptools as well:
library(remotes)
install_github("r-tmap/tmaptools")
install_github("r-tmap/tmap")
See NEWS for the latest features and improvements and the issue list for discussions of enhancements and bugs.
Do you want to help with the development of the package? Please let us know! Any feedback, requests, tips, or bug reports are welcome!
library(tmap)
Tennekes, M., Nowosad, J., Elegant and informative maps with tmap. Draft version, https://r-tmap.github.io/
Tennekes, M., 2018, tmap: Thematic Maps in R, Journal of Statistical Software, 84(6), 1-39
This paper has been written for tmap
1.11-2. See the reproducible code using tmap
2.x and 3.x.
tmap: what is changed in recent versions?
There are two main places to get help with tmap
:
Author: r-tmap
Source Code: https://github.com/r-tmap/tmap
License: GPL-3.0 license
1660417980
Version: 0.3
Authors@R: "Dawei Lang chiffonlang@icloud.com [aut, cre]"
Description: Provides an R interface to the JavaScript library ECharts for interactive map data visualization.
Depends: R (>= 3.1.2)
library(devtools)
install_github('lchiffon/REmap')
options(remap.js.web = T)
来切换保存到工作目录的模式get_geo_postion
把原始的机场经纬度chche改为城市经纬度options(remap.js.web = T)
to set options for saving pictures into working directoryget_geo_position
functionAuthor: Lchiffon
Source Code: https://github.com/Lchiffon/REmap
License: MIT + file LICENS
1660414080
ggmap
ggmap is an R package that makes it easy to retrieve raster map tiles from popular online mapping services like Google Maps and Stamen Maps and plot them using the ggplot2 framework:
library("ggmap")
# Loading required package: ggplot2
# Registered S3 methods overwritten by 'ggplot2':
# method from
# [.quosures rlang
# c.quosures rlang
# print.quosures rlang
# Google's Terms of Service: https://cloud.google.com/maps-platform/terms/.
# Please cite ggmap if you use it! See citation("ggmap") for details.
us <- c(left = -125, bottom = 25.75, right = -67, top = 49)
get_stamenmap(us, zoom = 5, maptype = "toner-lite") %>% ggmap()
# Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Use qmplot()
in the same way you’d use qplot()
, but with a map automatically added in the background:
library("dplyr")
#
# Attaching package: 'dplyr'
# The following objects are masked from 'package:stats':
#
# filter, lag
# The following objects are masked from 'package:base':
#
# intersect, setdiff, setequal, union
library("forcats")
# define helper
`%notin%` <- function(lhs, rhs) !(lhs %in% rhs)
# reduce crime to violent crimes in downtown houston
violent_crimes <- crime %>%
filter(
offense %notin% c("auto theft", "theft", "burglary"),
-95.39681 <= lon & lon <= -95.34188,
29.73631 <= lat & lat <= 29.78400
) %>%
mutate(
offense = fct_drop(offense),
offense = fct_relevel(offense, c("robbery", "aggravated assault", "rape", "murder"))
)
# use qmplot to make a scatterplot on a map
qmplot(lon, lat, data = violent_crimes, maptype = "toner-lite", color = I("red"))
# Using zoom = 14...
# Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
All the ggplot2 geom’s are available. For example, you can make a contour plot with geom = "density2d"
:
qmplot(lon, lat, data = violent_crimes, maptype = "toner-lite", geom = "density2d", color = I("red"))
In fact, since ggmap’s built on top of ggplot2, all your usual ggplot2 stuff (geoms, polishing, etc.) will work, and there are some unique graphing perks ggmap brings to the table, too.
robberies <- violent_crimes %>% filter(offense == "robbery")
qmplot(lon, lat, data = violent_crimes, geom = "blank",
zoom = 14, maptype = "toner-background", darken = .7, legend = "topleft"
) +
stat_density_2d(aes(fill = ..level..), geom = "polygon", alpha = .3, color = NA) +
scale_fill_gradient2("Robbery\nPropensity", low = "white", mid = "yellow", high = "red", midpoint = 650)
# Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Faceting works, too:
qmplot(lon, lat, data = violent_crimes, maptype = "toner-background", color = offense) +
facet_wrap(~ offense)
# Using zoom = 14...
# Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.
Google Maps can be used just as easily. However, since Google Maps use a center/zoom specification, their input is a bit different:
get_googlemap("waco texas", zoom = 12) %>% ggmap()
# Source : https://maps.googleapis.com/maps/api/staticmap?center=waco%20texas&zoom=12&size=640x640&scale=2&maptype=terrain&key=xxx
# Source : https://maps.googleapis.com/maps/api/geocode/json?address=waco+texas&key=xxx
Moreover, you can get various different styles of Google Maps with ggmap (just like Stamen Maps):
get_googlemap("waco texas", zoom = 12, maptype = "satellite") %>% ggmap()
get_googlemap("waco texas", zoom = 12, maptype = "hybrid") %>% ggmap()
get_googlemap("waco texas", zoom = 12, maptype = "roadmap") %>% ggmap()
Google’s geocoding and reverse geocoding API’s are available through geocode()
and revgeocode()
, respectively:
geocode("1301 S University Parks Dr, Waco, TX 76798")
# Source : https://maps.googleapis.com/maps/api/geocode/json?address=1301+S+University+Parks+Dr,+Waco,+TX+76798&key=xxx
# # A tibble: 1 x 2
# lon lat
# <dbl> <dbl>
# 1 -97.1 31.6
revgeocode(c(lon = -97.1161, lat = 31.55098))
# Source : https://maps.googleapis.com/maps/api/geocode/json?latlng=31.55098,-97.1161&key=xxx
# Multiple addresses found, the first will be returned:
# 1301 S University Parks Dr, Waco, TX 76706, USA
# 55 Baylor Ave, Waco, TX 76706, USA
# 1437 FM434, Waco, TX 76706, USA
# Bear Trail, Waco, TX 76706, USA
# Robinson, TX 76706, USA
# Waco, TX, USA
# McLennan County, TX, USA
# Texas, USA
# United States
# [1] "1301 S University Parks Dr, Waco, TX 76706, USA"
There is also a mutate_geocode()
that works similarly to dplyr’s mutate()
function:
tibble(address = c("white house", "", "waco texas")) %>%
mutate_geocode(address)
# Source : https://maps.googleapis.com/maps/api/geocode/json?address=white+house&key=xxx
# "white house" not uniquely geocoded, using "1600 pennsylvania ave nw, washington, dc 20500, usa"
# Source : https://maps.googleapis.com/maps/api/geocode/json?address=waco+texas&key=xxx
# # A tibble: 3 x 3
# address lon lat
# <chr> <dbl> <dbl>
# 1 white house -77.0 38.9
# 2 "" NA NA
# 3 waco texas -97.1 31.5
Treks use Google’s routing API to give you routes (route()
and trek()
give slightly different results; the latter hugs roads):
trek_df <- trek("houson, texas", "waco, texas", structure = "route")
# Source : https://maps.googleapis.com/maps/api/directions/json?origin=houson,+texas&destination=waco,+texas&key=xxx&mode=driving&alternatives=false&units=metric
qmap("college station, texas", zoom = 8) +
geom_path(
aes(x = lon, y = lat), colour = "blue",
size = 1.5, alpha = .5,
data = trek_df, lineend = "round"
)
# Source : https://maps.googleapis.com/maps/api/staticmap?center=college%20station,%20texas&zoom=8&size=640x640&scale=2&maptype=terrain&language=en-EN&key=xxx
# Source : https://maps.googleapis.com/maps/api/geocode/json?address=college+station,+texas&key=xxx
(They also provide information on how long it takes to get from point A to point B.)
Map distances, in both length and anticipated time, can be computed with mapdist()
). Moreover the function is vectorized:
mapdist(c("houston, texas", "dallas"), "waco, texas")
# Source : https://maps.googleapis.com/maps/api/distancematrix/json?origins=dallas&destinations=waco,+texas&key=xxx&mode=driving
# Source : https://maps.googleapis.com/maps/api/distancematrix/json?origins=houston,+texas&destinations=waco,+texas&key=xxx&mode=driving
# # A tibble: 2 x 9
# from to m km miles seconds minutes hours mode
# <chr> <chr> <int> <dbl> <dbl> <int> <dbl> <dbl> <chr>
# 1 houston, tex… waco, texas 298227 298. 185. 10257 171. 2.85 drivi…
# 2 dallas waco, texas 152480 152. 94.8 5356 89.3 1.49 drivi…
From CRAN: install.packages("ggmap")
From Github:
if (!requireNamespace("devtools")) install.packages("devtools")
devtools::install_github("dkahle/ggmap")
Google has recently changed its API requirements, and ggmap users are now required to register with Google. From a user’s perspective, there are essentially three ramifications of this:
Users must register with Google. You can do this at https://cloud.google.com/maps-platform/. While it will require a valid credit card (sorry!), there seems to be a fair bit of free use before you incur charges, and even then the charges are modest for light use.
Users must enable the APIs they intend to use. What may appear to ggmap users as one overarching “Google Maps” product, Google in fact has several services that it provides as geo-related solutions. For example, the Maps Static API provides map images, while the Geocoding API provides geocoding and reverse geocoding services. Apart from the relevant Terms of Service, generally ggmap users don’t need to think about the different services. For example, you just need to remember that get_googlemap()
gets maps, geocode()
geocodes (with Google, DSK is done), etc., and ggmap handles the queries for you. However, you do need to enable the APIs before you use them. You’ll only need to do that once, and then they’ll be ready for you to use. Enabling the APIs just means clicking a few radio buttons on the Google Maps Platform web interface listed above, so it’s easy.
Inside R, after loading the new version of ggmap, you’ll need provide ggmap with your API key, a hash value (think string of jibberish) that authenticates you to Google’s servers. This can be done on a temporary basis with register_google(key = "[your key]")
or permanently using register_google(key = "[your key]", write = TRUE)
(note: this will overwrite your ~/.Renviron
file by replacing/adding the relevant line). If you use the former, know that you’ll need to re-do it every time you reset R.
Your API key is private and unique to you, so be careful not to share it online, for example in a GitHub issue or saving it in a shared R script file. If you share it inadvertantly, just get on Google’s website and regenerate your key - this will retire the old one. Keeping your key private is made a bit easier by ggmap scrubbing the key out of queries by default, so when URLs are shown in your console, they’ll look something like key=xxx
. (Read the details section of the register_google()
documentation for a bit more info on this point.)
The new version of ggmap is now on CRAN soon, but you can install the latest version, including an important bug fix in mapdist()
, here with:
if(!requireNamespace("devtools")) install.packages("devtools")
devtools::install_github("dkahle/ggmap")
Author: Dkahle
Source Code: https://github.com/dkahle/ggmap
1660384118
GoogleMap Map Component Flutter Plugin
dependencies:
flutter:
sdk: flutter
google_map_fluttify: ^x.x.x
AndroidManifest.xml
中配置key:<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxh4"/>
<key>io.flutter.embedded_views_preview</key>
<string>YES</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要定位权限</string>
import 'package:google_map_fluttify/google_map_fluttify.dart';
参考wiki.
Run this command:
With Flutter:
$ flutter pub add google_map_fluttify
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
google_map_fluttify: ^0.1.1
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:google_map_fluttify/google_map_fluttify.dart';
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:google_map_fluttify/google_map_fluttify.dart';
import 'package:oktoast/oktoast.dart';
import 'map/map.screen.dart';
Future<void> main() async {
runApp(MyApp());
// await enableFluttifyLog(false);
await GoogleMapService.instance.init(
iosKey: 'AIzaSyDCtRumqqf5IP3nrw1H9a3KNxhMfcEs8MU',
);
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return OKToast(
child: MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('AMaps examples')),
backgroundColor: Colors.grey.shade200,
body: MapDemo(),
),
),
);
}
}
Download Details:
Author:
Source Code: https://pub.dev/packages/google_map_fluttify
1660029120
Leaflet is an open-source JavaScript library for interactive maps. This R package makes it easy to create Leaflet maps from R.
library(leaflet)
m = leaflet() %>% addTiles()
m # a map with the default OSM tile layer
m = m %>% setView(-93.65, 42.0285, zoom = 17)
m
m %>% addPopups(-93.65, 42.0285, 'Here is the <b>Department of Statistics</b>, ISU')
You can install this package from CRAN, or the development version from GitHub:
# CRAN version
install.packages('leaflet')
# Or Github version
if (!require('devtools')) install.packages('devtools')
devtools::install_github('rstudio/leaflet')
In addition to the usual R package documentation, we also have extensive docs and examples at: https://rstudio.github.io/leaflet/
leaflet
's JavaScript build tools use Node.js, along with yarn to manage the JavaScript packages.
Install yarn
using the official instructions.
You can test that Node.js and yarn are installed properly by running the following commands:
node --version
yarn --version
To make additions or modifications to the JavaScript htmlwidgets
binding layer, you must have all Node.js dependencies installed. Now you can build/minify/lint/test using yarn build
, or run in "watch" mode by just running yarn watch
. JS sources go into javascript/src
and tests go into javascript/tests
.
# install dependencies
yarn
# compile
yarn build
# watch
yarn watch
Author: rstudio
Source Code: https://github.com/rstudio/leaflet
License: View license
1660002900
This is an R package that implements a heatmap htmlwidget. It has the following features:
base::heatmap
To install:
if (!require("devtools")) install.packages("devtools")
devtools::install_github("talgalili/d3heatmap")
Like any htmlwidget, you can visualize a d3 heatmap directly from the R console:
library(d3heatmap)
d3heatmap(mtcars, scale = "column", colors = "Spectral")
You can also include them in R Markdown chunks, or use them in Shiny applications with the d3heatmapOutput
and renderD3heatmap
functions.
See ?d3heatmap
for options.
Inspired by dygraphs and able to leverage magrittr, the new API provides a second method for invoking d3heatmap and integrating with Shiny apps, modules, and gadgets! Examples:
library(d3heatmap)
library(magrittr)
d3heatmap(mtcars, dendrogram = 'none', key = TRUE, col = 'RdYlGn',
scale = 'column', key.title = "Legend", print.values = T,
notecol = 'white') %>%
hmAxis("x", title = "test", location = 'bottom') %>%
hmAxis("y", title = "test", location = 'left') %>%
hmCells(font.size = 8, color = 'blue') %>%
hmLegend(show = T, title = "Title", location = "tl")
library(d3heatmap)
library(magrittr)
rsc<-matrix(rep_len(c('good', 'bad', 'ugly'), length.out = 64), ncol = 2)
rsccols<-c('red', 'white', 'blue')
rscnames <- c('Row 1', 'Row 2')
csc<-matrix(rep_len(c('first', 'second', 'third', 'fourth', 'fifth'), length.out = 33), nrow = 3)
csccols<-c('orange', 'blue', 'grey', 'green', 'red')
cscnames <- c('Column 1', 'Column 2', 'Column 3')
library(d3heatmap)
d3heatmap(mtcars,
key = TRUE, scale = 'column',
key.title = "Legend",
col = 'RdYlGn',
srtCol = 30,
breaks = 8,
xlab = 'test',
ylab = 'TEST',
print.values = T,
density.info = 'histogram',
denscol = 'grey',
sideCol = 3,
sideRow = 4,
RowSideColors = rsc,
ColSideColors = csc,
RowColorsPalette = rsccols,
ColColorsPalette = csccols,
RowColorsNames = rscnames,
ColColorsNames = cscnames)
## using the modern API:
d3heatmap(mtcars, key = TRUE, scale = 'none') %>%
hmSideColors(axis = 'column', side.colors = csc,
palette = csccols, names = cscnames) %>%
hmSideColors(axis = 'y', side.colors = rsc,
palette = rsccols, names = rscnames)
NEWS from recent PR
An shiny gadget coupled with an S4
class that provides print()
and save()
methods. Gadget takes normal d3heatmap
inputs and allows for interactive adjustment of the heatmap. Gadget allows for filtering rows and columns, and also a dynamic filter to interatively subset the entire underlying data set. Saving the gadget to an object generates the S4
class that contains the heatmap, data, filter, and settings. Passing the gadget back into the function d3heatmapGadget(gadget)
starts the user at the last state of the gadget.
gadget <- d3heatmapGadget(mtcars, col = 'blues')
print(gadget)
save(gadget, file = "heatmap.html")
gadget <- d3heatmapGadget(gadget)
Based on example contributions and forks from several people, the side colors components of heatmap.2 and heatmap.3 have been added! Functionality includes color labels, axis labels for the color sections, and hover info. Further alignment of the old API parameters to heatmap.2 and heatmap.3, plus heatmap.2/3 and the modern API were implemented for side colors. the Readme, package news and examples were also updated.
The master branch now includes a newer, modern API, motivated by the main d3heatmap fork's desire for a new API and inspired by the API of the dygraphs package produced by RStudio. The new API takes advantage of magrittr piping and offers smaller functions to modify selected portions of the heatmap. I have conducted good, but by no means exhaustive, testing... so feel free to poke around, find bugs, and open up issues or PRs for them.
d3heatmap is not actively developed, but I will accept PR. You might consider using heatmaply, which is based on plotly (it comes with more features, but is not based on d3)
Author: Talgalili
Source Code: https://github.com/talgalili/d3heatmap
License: View license
1659500040
Need diffs in your ruby app? Diffy has you covered. It provides a convenient way to generate a diff from two strings or files. Instead of reimplementing the LCS diff algorithm Diffy uses battle tested Unix diff to generate diffs, and focuses on providing a convenient interface, and getting out of your way.
It provides several built in format options which can be passed to Diffy::Diff#to_s
.
:text
- Plain text output:color
- ANSI colorized text suitable for use in a terminal:html
- HTML output. Since version 2.0 this format does inline highlighting of the character changes between lines.:html_simple
- HTML output without inline highlighting. This may be useful in situations where high performance is required or simpler output is desired.A default format can be set like so:
Diffy::Diff.default_format = :html
gem install diffy
Ensure that you have a working diff
on your machine and in your search path.
There are several options:
Install Diff::LCS, which includes ldiff
. RSpec depends on Diff::LCS so you may already have it installed.
If you're using RubyInstaller, install the devkit.
Install unxutils http://sourceforge.net/projects/unxutils
note that these tools contain diff 2.7 which has a different handling of whitespace in the diff results. This makes Diffy spec tests yielding one fail on Windows.
Install these two individually from the gnuwin32 project http://gnuwin32.sourceforge.net/
note that this delivers diff 2.8 which makes Diffy spec pass even on Windows.
Install the gem by
gem install diffy
Here's an example of using Diffy to diff two strings
$ irb
>> string1 = <<-TXT
>" Hello how are you
>" I'm fine
>" That's great
>" TXT
=> "Hello how are you\nI'm fine\nThat's great\n"
>> string2 = <<-TXT
>" Hello how are you?
>" I'm fine
>" That's swell
>" TXT
=> "Hello how are you?\nI'm fine\nThat's swell\n"
>> puts Diffy::Diff.new(string1, string2)
-Hello how are you
+Hello how are you?
I'm fine
-That's great
+That's swell
Outputing the diff as html is easy too. Here's an example using the :html_simple
formatter.
>> puts Diffy::Diff.new(string1, string2).to_s(:html_simple)
<div class="diff">
<ul>
<li class="del"><del>Hello how are you</del></li>
<li class="ins"><ins>Hello how are you?</ins></li>
<li class="unchanged"><span>I'm fine</span></li>
<li class="del"><del>That's great</del></li>
<li class="ins"><ins>That's swell</ins></li>
</ul>
</div>
The :html
formatter will give you inline highlighting a la github.
>> puts Diffy::Diff.new("foo\n", "Foo\n").to_s(:html)
<div class="diff">
<ul>
<li class="del"><del><strong>f</strong>oo</del></li>
<li class="ins"><ins><strong>F</strong>oo</ins></li>
</ul>
</div>
There's some pretty nice css provided in Diffy::CSS
.
>> puts Diffy::CSS
.diff{overflow:auto;}
.diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;}
.diff del, .diff ins{display:block;text-decoration:none;}
.diff li{padding:0; display:table-row;margin: 0;height:1em;}
.diff li.ins{background:#dfd; color:#080}
.diff li.del{background:#fee; color:#b00}
.diff li:hover{background:#ffc}
/* try 'whitespace:pre;' if you don't want lines to wrap */
.diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;}
.diff del strong{font-weight:normal;background:#fcc;}
.diff ins strong{font-weight:normal;background:#9f9;}
.diff li.diff-comment { display: none; }
.diff li.diff-block-info { background: none repeat scroll 0 0 gray; }
There's also a colorblind-safe version of the pallete provided in Diffy::CSS_COLORBLIND_1
.
Side-by-side comparisons, or split views as called by some, are supported by using the Diffy::SplitDiff
class. This class takes a diff returned from Diffy::Diff
and splits it in two parts (or two sides): left and right. The left side represents deletions while the right side represents insertions.
The class is used as follows:
Diffy::SplitDiff.new(string1, string2, options = {})
The optional options hash is passed along to the main Diff::Diff
class, so all default options such as full diff output are supported. The output format may be changed by passing the format with the options hash (see below), and all default formats are supported.
Unlike Diffy::Diff
, Diffy::SplitDiff
does not use #to_s
to output the resulting diff. Instead, two self-explanatory methods are used to output the diff: #left
and #right
. Using the earlier example, this is what they look like in action:
>> puts Diffy::SplitDiff.new(string1, string2).left
-Hello how are you
I'm fine
-That's great
>> puts Diffy::SplitDiff.new(string1, string2).right
+Hello how are you?
I'm fine
+That's swell
The output format may be changed by passing the format with the options hash:
Diffy::SplitDiff.new(string1, string2, :format => :html)
This will result in the following:
>> puts Diffy::SplitDiff.new(string1, string2, :format => :html).left
<div class="diff">
<ul>
<li class="del"><del>Hello how are you</del></li>
<li class="unchanged"><span>I'm fine</span></li>
<li class="del"><del>That's <strong>great</strong></del></li>
</ul>
</div>
>> puts Diffy::SplitDiff.new(string1, string2, :format => :html).right
<div class="diff">
<ul>
<li class="ins"><ins>Hello how are you<strong>?</strong></ins></li>
<li class="unchanged"><span>I'm fine</span></li>
<li class="ins"><ins>That's <strong>swell</strong></ins></li>
</ul>
</div>
You can diff files instead of strings by using the :source
option.
>> puts Diffy::Diff.new('/tmp/foo', '/tmp/bar', :source => 'files')
By default Diffy removes the superfluous diff output. This is because its default is to show the complete diff'ed file (diff -U10000
is the default).
Diffy does support full output, just use the :include_diff_info => true
option when initializing:
>> Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n", :include_diff_info => true).to_s(:text)
=>--- /Users/chaffeqa/Projects/stiwiki/tmp/diffy20111116-82153-ie27ex 2011-11-16 20:16:41.000000000 -0500
+++ /Users/chaffeqa/Projects/stiwiki/tmp/diffy20111116-82153-wzrhw5 2011-11-16 20:16:41.000000000 -0500
@@ -1,2 +1,3 @@
foo
bar
+baz
And even deals a bit with the formatting!
By default Diffy will return empty string if there are no differences in inputs. In previous versions the full text of its first input was returned in this case. To restore this behaviour simply use the :allow_empty_diff => false
option when initializing.
By default Diffy doesn't include the +
, -
, and at the beginning of line for HTML output.
You can use the :include_plus_and_minus_in_html
option to include those symbols in the output.
>> puts Diffy::Diff.new(string1, string2, :include_plus_and_minus_in_html => true).to_s(:html_simple)
<div class="diff">
<ul>
<li class="del"><del><span class="symbol">-</span>Hello how are you</del></li>
<li class="ins"><ins><span class="symbol">+</span>Hello how are you?</ins></li>
<li class="unchanged"><span class="symbol"> </span><span>I'm fine</span></li>
<li class="del"><del><span class="symbol">-</span>That's great</del></li>
<li class="ins"><ins><span class="symbol">+</span>That's swell</ins></li>
</ul>
</div>
You can use the :context
option to override the number of lines of context that are shown around each change (this defaults to 10000 to show the full file).
>> puts Diffy::Diff.new("foo\nfoo\nBAR\nbang\nbaz", "foo\nfoo\nbar\nbang\nbaz", :context => 1)
foo
-BAR
+bar
bang
You can use the :diff
option to override the command line options that are passed to unix diff. They default to -U10000
. This option will noop if combined with the :context
option.
>> puts Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :diff => "-w")
foo
bar
:ignore_crlf
when doing HTML comparesYou can make the HTML output ignore the CRLF by passing the :ignore_crlf
option a truthy value.
>> puts Diffy::Diff.new(" foo\nbar\n", "foo\r\nbar\r\n", ignore_crlf: true).to_s(:html)
"<div class=\"diff\"></div>"
You can set the default options for new Diffy::Diff
s using the Diffy::Diff.default_options
and Diffy::Diff.default_options=
methods. Options passed to Diffy::Diff.new
will be merged into the default options.
>> Diffy::Diff.default_options
=> {:diff=>"-U10000", :source=>"strings", :include_diff_info=>false, :include_plus_and_minus_in_html=>false}
>> Diffy::Diff.default_options.merge!(:source => 'files')
=> {:diff=>"-U10000", :source=>"files", :include_diff_info=>false, :include_plus_and_minus_in_html=>false}
Diffy tries to make generating your own custom formatted output easy. Diffy::Diff
provides an enumerable interface which lets you iterate over lines in the diff.
>> Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").each do |line|
>* case line
>> when /^\+/ then puts "line #{line.chomp} added"
>> when /^-/ then puts "line #{line.chomp} removed"
>> end
>> end
line +baz added
=> [" foo\n", " bar\n", "+baz\n"]
You can also use Diffy::Diff#each_chunk
to iterate each grouping of additions, deletions, and unchanged in a diff.
>> Diffy::Diff.new("foo\nbar\nbang\nbaz\n", "foo\nbar\nbing\nbong\n").each_chunk.to_a
=> [" foo\n bar\n", "-bang\n-baz\n", "+bing\n+bong\n"]
Use #map
, #inject
, or any of Enumerable's methods. Go crazy.
Diffy includes a full set of rspec tests. When contributing please include tests for your changes.
Report bugs or request features at http://github.com/samg/diffy/issues
Author: samg
Source code: https://github.com/samg/diffy
License: MIT license
1659405120
A Julia package targeting the MapLight API (v1)
julia> Pkg.add("MapLight")
julia> using MapLight
julia> my_auth = MapLight.authenticate("your_auth_key")
MapLight API Key (*****************************193)
julia> bill_search(my_auth, "us", "Electronic Communications Privacy Act Amendments Act of 2012")
["bills"=>{["session"=>"112","number"=>"2471","measure"=>" H.R. 2471 (112<sup>th</sup>)\n","topic"=>"Electronic Communications Privacy Act Amendments Act of 2012","url"=>"http://maplight.org/us-congress/bill/112-hr-2471/1024048","prefix"=>"H","jurisdiction"=>"us"]}]
julia> bill_positions(my_auth, "us", 112, "H", 2471)
["bill"=>["url"=>"http://maplight.org/us-congress/bill/112-hr-2471/1024048","last_update"=>"2012-12-21T15:36:25Z","organizations"=>{["organization_id"=>"22489","name"=>"Center for Democracy & Technology","disposition"=>"support","citation"=>"Kravets, David (2011, September 23). Federal Law Blocks Netflix, Facebook Integration — But Should It?. <cite>Wired.com</cite>. Retrieved December 5, 2011, from <a href=\"http://www.wired.com/threatlevel/2011/09/netflix-video-privacy/\">http://www.wired.com/threatlevel/2011/09/netflix-video-privacy/</a>.","catcode"=>"J3000"],["organization_id"=>"25404","name"=>"Digital Media Association","disposition"=>"support","citation"=>"Gregory Alan Barnes, Director of Government Affairs, Digital Media Association (2011, October 13). <a href=\"http://www.digmedia.org/component/content/article/40/300-dima-applauds-members-of-the-house-judiciary-committee-for-streamlining-consent-requirements-under-the-video-privacy-protection-act\"><cite>DiMA Applauds Members of the House Judiciary Committee for Streamlining Consent Requirements under the Video Privacy Protection Act</cite></a>. Retrieved December 5, 2011, from Press Releases.","catcode"=>"C5140"],["organization_id"=>"22466","name"=>"Electronic Privacy Information Center","disposition"=>"oppose","citation"=>"Kravets, David (2011, September 23). Federal Law Blocks Netflix, Facebook Integration — But Should It?. <cite>Wired.com</cite>. Retrieved December 5, 2011, from <a href=\"http://www.wired.com/threatlevel/2011/09/netflix-video-privacy/\">http://www.wired.com/threatlevel/2011/09/netflix-video-privacy/</a>.","catcode"=>"J3000"],["organization_id"=>"27350","name"=>"Netflix","disposition"=>"support","citation"=>"Michael Drobac, director of Government Relations, Netflix (2011, September 22). <a href=\"http://blog.netflix.com/2011/09/help-us-bring-facebook-sharing-to.html\"><cite>Help us Bring Facebook Sharing to Netflix USA</cite></a>. Retrieved December 5, 2011, from The Netflix Blog.","catcode"=>"C5140"],["organization_id"=>"22694","name"=>"Facebook","disposition"=>"support","citation"=>"Carr, Austin (2011, August 22). Facebook, Netflix Push Congress on Social Integration, Video Privacy. <cite>Fast Company</cite>. Retrieved December 7, 2011, from <a href=\"http://www.fastcompany.com/1782164/facebook-netflix-push-congress-on-social-integration-video-privacy\">http://www.fastcompany.com/1782164/facebook-netflix-push-congress-on-social-integration-video-privacy</a>.","catcode"=>"C5140"],["organization_id"=>"22035","name"=>"American Civil Liberties Union","disposition"=>"oppose","citation"=>"Murphy, Laura W. (2012, January 31). <a href=\"http://www.aclu.org/files/assets/fnal_statement_hr_2471_013112_4.pdf\"><cite>Re: ACLU Opposes Expanded Unwarranted Law Enforcement Access to Private Rental Records and Broader Privacy Implications in HR 2471</cite></a>. Retrieved November 28, 2012, from ACLU.","catcode"=>"J7000"]}]]
julia> organization_search(my_auth, "Digital Media Association")
["organizations"=>{["organization_id"=>"25404","name"=>"Digital Media Association"]}]
julia> organization_positions(my_auth, "us", 25404)
["positions"=>{["number"=>"275","measure"=>"H.R. 275 (110<sup>th</sup>)","topic"=>"Global Online Freedom Act of 2007","last_update"=>"2011-08-29T20:44:13Z","disposition"=>"oppose","catcode"=>"C5140","prefix"=>"H","citation"=>" (n.d.). <a href=\"\"><cite>RE: H.R. 275, the “Global Online Freedom Act of 2007”</cite></a>. Retrieved n.d., from .","url"=>"http://maplight.org/us-congress/bill/110-hr-275/236522","session"=>"110","jurisdiction"=>"US"],["number"=>"2060","measure"=>"H.R. 2060 (110<sup>th</sup>)","topic"=>"Internet Radio Equality Act","last_update"=>"2011-08-29T20:28:47Z","disposition"=>"support","catcode"=>"C5140","prefix"=>"H","citation"=>" (n.d.). <a href=\"\"><cite>Congressmen Introduce Bill to Save Internet Radio</cite></a>. Retrieved n.d., from .","url"=>"http://maplight.org/us-congress/bill/110-hr-2060/291155","session"=>"110","jurisdiction"=>"US"],["number"=>"4279","measure"=>"H.R. 4279 (110<sup>th</sup>)","topic"=>"Prioritizing Resources and Organization for Intellectual Property Act of 2008","last_update"=>"2011-08-29T16:14:29Z","disposition"=>"support","catcode"=>"C5140","prefix"=>"H","citation"=>" (n.d.). <a href=\"\"><cite>Statement of Conyers</cite></a>. Retrieved n.d., from .","url"=>"http://maplight.org/us-congress/bill/110-hr-4279/377624","session"=>"110","jurisdiction"=>"US"],["number"=>"575","measure"=>"S. 575 (112<sup>th</sup>)","topic"=>"Debit Interchange Fee Study Act of 2011","last_update"=>"2012-12-20T21:51:15Z","disposition"=>"oppose","catcode"=>"C5140","prefix"=>"S","citation"=>"Undersigned Organizations (2011, June 6). <a href=\"https://www.wewear.org/assets/1/7/060611swipefee.pdf\"><cite>Dear Senator:</cite></a>. Retrieved August 6, 2012, from American Apparel and Footwear Association.","url"=>"http://maplight.org/us-congress/bill/112-s-575/900958","session"=>"112","jurisdiction"=>"US"],["number"=>"2471","measure"=>"H.R. 2471 (112<sup>th</sup>)","topic"=>"Electronic Communications Privacy Act Amendments Act of 2012","last_update"=>"2012-12-21T15:36:25Z","disposition"=>"support","catcode"=>"C5140","prefix"=>"H","citation"=>"Gregory Alan Barnes, Director of Government Affairs, Digital Media Association (2011, October 13). <a href=\"http://www.digmedia.org/component/content/article/40/300-dima-applauds-members-of-the-house-judiciary-committee-for-streamlining-consent-requirements-under-the-video-privacy-protection-act\"><cite>DiMA Applauds Members of the House Judiciary Committee for Streamlining Consent Requirements under the Video Privacy Protection Act</cite></a>. Retrieved December 5, 2011, from Press Releases.","url"=>"http://maplight.org/us-congress/bill/112-hr-2471/1024048","session"=>"112","jurisdiction"=>"US"],["number"=>"6480","measure"=>"H.R. 6480 (112<sup>th</sup>)","topic"=>"Internet Radio Fairness Act of 2012","last_update"=>"2012-12-21T01:16:16Z","disposition"=>"support","catcode"=>"C5140","prefix"=>"H","citation"=>"IRFC (n.d.). <a href=\"http://internetradiofairness.com/legislation/\"><cite>The IRFA: Good for Consumers, Artists and the Recording Industry</cite></a>. Retrieved November 20, 2012, from IRFC.","url"=>"http://maplight.org/us-congress/bill/112-hr-6480/1102695","session"=>"112","jurisdiction"=>"US"],["number"=>"3609","measure"=>"S. 3609 (112<sup>th</sup>)","topic"=>"Internet Radio Fairness Act of 2012","last_update"=>"2012-12-21T01:18:07Z","disposition"=>"support","catcode"=>"C5140","prefix"=>"S","citation"=>"IRFC (2012, October 25). Internet Radio Fairness Coalition Launches to Help Accelerate Growth and Innovation in Internet Radio To Benefit Artists, Consumers and the Recording Industry. <cite>MarketWatch: The Wall Street Journal</cite>. Retrieved November 1, 2012, from <a href=\"http://www.marketwatch.com/story/internet-radio-fairness-coalition-launches-to-help-accelerate-growth-and-innovation-in-internet-radio-to-benefit-artists-consumers-and-the-recording-industry-2012-10-25\">http://www.marketwatch.com/story/internet-radio-fairness-coalition-launches-to-help-accelerate-growth-and-innovation-in-internet-radio-to-benefit-artists-consumers-and-the-recording-industry-2012-10-25</a>.","url"=>"http://maplight.org/us-congress/bill/112-s-3609/1102959","session"=>"112","jurisdiction"=>"US"],["number"=>"3309","measure"=>"H.R. 3309 (113<sup>th</sup>)","topic"=>"Innovation Act","last_update"=>"2014-01-25T20:41:07Z","disposition"=>"support","catcode"=>"C5140","prefix"=>"H","citation"=>"undersigned organizations (n.d.). <a href=\"http://judiciary.house.gov/news/2013/12032013_PATENT/FINAL%20Growing%20Support%20for%20HR%20%203309.pdf\"><cite>Growing Support for H.R. 3309, "The Innovation Act"</cite></a>. Retrieved December 13, 2013, from House Committee on the Judiciary.","url"=>"http://maplight.org/us-congress/bill/113-hr-3309/2602316","session"=>"113","jurisdiction"=>"US"]}]
API
Returns an array of bills that match a particular string.
bill_search(auth::Auth, jurisdiction, search_str)
bill_search(auth::String, jurisdiction, search_str)
bill_search(jurisdiction, search_str; auth = authenticate())
auth
: An instance of Auth
or an api key in the form of a stringjurisdiction
: Either "us"
for federal or "ca"
for californiasearch_str
: The string to search for (the full or partial name of a bill, for instance)Returns an array of organization’s positions on a single bill.
bill_positions(auth::Auth, jurisdiction, session, prefix, number)
bill_positions(auth::String, jurisdiction, session, prefix, number)
bill_positions(jurisdiction, session, prefix, number; auth = authenticate())
auth
: An instance of Auth
or an api key in the form of a stringjurisdiction
: Either "us"
for federal or "ca"
for Californiasession
: An integer109
: The 109th session of the United States Congress (2005-2006).110
: The 110th session of the United States Congress (2007-2008).111
: The 111th session of the United States Congress (2009-2010).112
: The 112th session of the United States Congress (2011-2012).2009
: The 2009-2010 session of the California Assembly.2011
: The 2011-2012 session of the California Assembly.prefix
: A string"h"
: House Bill (i.e. H.R.)"hr"
: House Resolution (i.e. H.Res.)"hj"
: House Joint Resolution (i.e. H.J.Res.)"hc"
: House Concurrent Resolution (i.e. H.Con.Res.)"s"
: Senate Bill (i.e. S.)"sr"
: Senate Resolution (i.e. S.Res.)"sj"
: Senate Joint Resolution (i.e. S.J.Res.)"sc"
: Senate Concurrent Resolution (i.e. S.Con.Res.)number
: The bill number (without the prefix)Returns an array of organizations’ positions on all bills in a session. This response is cached and updated nightly.
bill_list(auth::Auth, jurisdiction, session; include_organizations = true, has_organizations = true)
bill_list(auth::String, jurisdiction, session; include_organizations = true, has_organizations = true)
bill_list(jurisdiction, session; auth = authenticate(), include_organizations = true, has_organizations = true)
auth
: An instance of Auth
or an api key in the form of a stringjurisdiction
: Either "us"
for federal or "ca"
for Californiasession
: An integer109
: The 109th session of the United States Congress (2005-2006).110
: The 110th session of the United States Congress (2007-2008).111
: The 111th session of the United States Congress (2009-2010).112
: The 112th session of the United States Congress (2011-2012).2009
: The 2009-2010 session of the California Assembly.2011
: The 2011-2012 session of the California Assembly.include_organizations
: true
or false
- whether to include the positions of organizations that took a stancehas_organizations
: true
or false
- whether to include in the response bills for which support and opposition are unknownReturns an array of organization IDs that match a particular string.
organization_search(auth::Auth, search_str, exact = false)
organization_search(auth::String, search_str, exact = false)
organization_search(search_str, exact = false; auth = authenticate())
auth
: An instance of Auth
or an api key in the form of a stringsearch_str
: The string to search for (the full or partial name of an organization, for instance)exact
: true
or false
- whether to search for an exact or partial string matchReturns an array an organization’s positions on bills.
organization_positions(auth::Auth, jurisdiction, org_id)
organization_positions(auth::String, jurisdiction, org_id)
organization_positions(jurisdiction, org_id; auth = authenticate())
auth
: An instance of Auth
or an api key in the form of a stringjurisdiction
: Either "us"
for federal or "ca"
for californiaorg_id
: MAPLight.org’s internal identifier for organizations (output from the organization_search method)Author: WestleyArgentum
Source Code: https://github.com/WestleyArgentum/MapLight.jl
License: MIT license
1659325740
Ruby in your shell!
Ru brings Ruby's expressiveness, cleanliness, and readability to the command line.
It lets you avoid looking up pesky options in man pages and Googling how to write a transformation in bash that would take you approximately 1s to write in Ruby.
For example, to center a file's lines, use String#center:
ru 'map(:center, 80)' myfile
Using traditional tools, this isn't as easy or readable:
awk 'printf "%" int(40+length($0)/2) "s\n", $0' myfile
For another example, let's compare summing the lines of a list of integers using Ru vs. a traditional approach:
ru 'map(:to_i).sum' myfile
awk '{s+=$1} END {print s}' myfile
Any method from Ruby Core and Active Support can be used. Ru also provides new methods (and modifies #map) to make transformations easier. Here are some variations on the above example:
ru 'map(:to_i, 10).sum' myfile
ru 'map(:to_i).reduce(&:+)' myfile
ru 'each_line.to_i.to_a.sum' myfile
ru 'grep(/^\d+$/).map(:to_i).sum' myfile
ru 'map { |n| n.to_i }.reduce(&:+)' myfile
ru 'reduce(0) { |sum, n| sum + n.to_i }' myfile
ru 'each_line.match(/(\d+)/)[1].to_i.to_a.sum' myfile
ru 'map { |n| n.to_i }.reduce(0) { |sum, n| sum + n }' myfile
See Examples and Methods for more.
gem install ru
You can now use Ruby in your shell!
For example, to sum a list of integers:
$ printf "2\n3" | ru 'map(:to_i).sum'
5
See Examples below, too!
Ru reads from stdin:
$ printf "2\n3" | ru 'map(:to_i).sum'
5
$ cat myfile | ru 'map(:to_i).sum'
5
Or from file(s):
$ ru 'map(:to_i).sum' myfile
5
$ ru 'map(:to_i).sum' myfile myfile
10
You can also run Ruby code without any input by prepending a !
:
$ ru '! 2 + 3'
5
The code argument is run as if it has $stdin.each_line.map(&:chomp).
prepended to it. The result is converted to a string and printed. So, if you run ru 'map(&:to_i).sum'
, you can think of it as running puts $stdin.each_line.map(&:chomp).map(&:to_i).sum
.
In addition to the methods provided by Ruby Core and Active Support, Ru provides other methods for performing transformations, like each_line
, files
, and grep
, and it improves map
. See Methods for more.
Let's compare the readability and conciseness of Ru relative to existing tools:
ru
ru 'map(:center, 80)' myfile
awk
awk 'printf "%" int(40+length($0)/2) "s\n", $0' myfile
sed
ru
ru 'map(:to_i).sum' myfile
awk
awk '{s+=$1} END {print s}' myfile
paste
paste -s -d+ myfile | bc
ru
ru '[4]' myfile
sed
sed '5q;d' myfile
ru
ru '[1..-2]' myfile
sed
sed '1d;$d' myfile
ru
ru 'map { |line| [line[/(\d+)( ".+"){2}$/, 1].to_i, line] }.sort.reverse.map(:join, " ")' access.log
awk
awk --re-interval '{ match($0, /(([^[:space:]]+|\[[^\]]+\]|"[^"]+")[[:space:]]+){7}/, m); print m[2], $0 }' access.log | sort -nk 1
In addition to the methods provided by Ruby Core and Active Support, Ru provides other methods for performing transformations.
Provides a shorthand for calling methods on each iteration of the input. Best explained by example:
ru 'each_line.strip.center(80)' myfile
If you'd like to transform it back into a list, call to_a
:
ru 'each_line.strip.to_a.map(:center, 80)' myfile
Converts the lines to Ru::File
objects (see Ru::File below).
$ printf "foo.txt" | ru 'files.map(:updated_at).map(:strftime, ""%Y-%m-%d")'
2014-11-08
Formats a list of Ru::File
s. You'll typically call this after calling files
to transform them into strings:
$ ru 'files.format'
644 tom staff 3 2014-10-26 09:06 bar.txt
644 tom staff 11 2014-11-04 08:29 foo.txt
The default format, 'l'
, is shown above. It prints [omode, owner, group, size, date, name]
.
Selects lines which match the given regex.
$ printf "john\npaul\ngeorge" | ru 'grep(/o[h|r]/)'
john
george
This is the same as Array#map, but it adds a new syntax that allows you to easily pass arguments to a method. For example:
$ printf "john\npaul" | ru 'map(:[], 0)'
j
p
$ printf "john\npaul" | ru 'map(:center, 8, ".")'
..john..
..paul..
Note that the examples above can also be performed with each_line
:
$ printf "john\npaul" | ru 'each_line[0]'
$ printf "john\npaul" | ru 'each_line.center(8, ".")'
The files
method returns an enumerable of Ru::File
s, which are similar to Ruby Core's File
. Each one has the following methods:
basename
created_at
(alias for ctime)ctime
extname
format
(see the format
method above)ftype
gid
group
mode
mtime
name
(alias for basename)omode
owner
size
to_s
(alias for name)uid
updated_at
(alias for mtime)world_readable?
Ru lets you save commands by name, so that you can easily use them later.
Save a command for future use:
$ ru save sum 'map(:to_i).sum'
Saved command: sum is 'map(:to_i).sum'
Run a saved command:
$ printf "2\n3" | ru run sum
5
$ ru run sum myfile
5
List all of your saved commands:
$ ru list
Saved commands:
sum map(:to_i).sum
Print a help page.
Print the installed version of Ru.
Ru is tested against Active Support 3 and 4. If you'd like to submit a PR, please be sure to use Appraisal to test your changes in both contexts:
appraisal rspec
Ru is released under the MIT License. Please see the MIT-LICENSE file for details.
Author: tombenner
Source code: https://github.com/tombenner/ru
License: MIT license
1659284806
flutter_naver_map
It is a plug-in that can launch Naver Maps in Flutter.
Plug-in which shows naver map on flutter project support Android and iOS.
This plug-in is a library with the permission of the original author, LBSTECH , and supplemented various parts based on the library.
This plug-in is a plug-in that shows the Map SDK service provided by Naver Cloud PlatForm - Map in Android and iOS environments.
pubspec.yaml
write in dependencies
dependencies:
flutter_naver_map: [최신버전]
[프로젝트 폴더]/android/app/src/AndroidManifest.xml
to
Declare the permission as follows (optional) and enter the Client ID of NAVER Map SDK .
The declaration of permission declares two corresponding permissions only when using the current location search function on NAVER Map.
<manifest>
<!-- 네이버 맵에서 현 위치 탐색 기능을 사용할 때만, 해당 권한 2개를 선언합니다 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application>
<activity> <!-- something --> </activity>
<!-- 플러터 자동 생성. 지우시면 안 됩니다. -->
<meta-data
android:name="flutterEmbedding"
android:value="2"/>
<!-- 네이버 맵 SDK의 Client ID를 넣는 곳입니다. 필수로 넣어야, 지도가 동작합니다. -->
<meta-data
android:name="com.naver.maps.map.CLIENT_ID"
android:value="여기에 Map Sdk의 Client ID를 넣습니다" />
</application>
</manifest>
In the case of NAVER Map SDK, GLSurfaceView is used by default to display a map on Android. However, when using the Hot Reload function in flutter, a crash occurs in the binary of NAVER Map SDK for an incorrect reason.
So, the default option is to use a TextureView. In order to use GLSurfaceView with good performance, it is recommended to use it only in the Release version that does not use the Hot Reload function as shown in the example below .
NaverMap(
useSurface: kReleaseMode, //해당 옵션은 Android에서만 적용됩니다.
/* many other options */
)
However, please use it only when the TextField widget is not used on the map.
While the map is being rendered using [GLSurfaceView], if the focus is moved to the [TextField], the app crashes. When updating the change of [TextField] in Flutter Engine, [GLThread] is used, and [DeadObjectException] occurs in this process.
Requires git-lfs installation to receive large files . Open a terminal and run the following command.
$ brew install git-lfs
And run the following command to use git-lfs.
If lfs is not enabled, the dependency through Pod is not downloaded.
$ git lfs install
[프로젝트 폴더]/ios/Runner/Info.plist
to
Enter the Client ID of NAVER Map SDK as follows .
<dict>
<key>NMFClientId</key>
<string>여기에 Map Sdk의 Client ID를 넣습니다</string>
</dict>
Declare permission only when using the current location search function on NAVER Map .
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>여기에 위치 사용 목적을 적으시면 됩니다.</string>
</dict>
Issues and PR are always welcome!!
Run this command:
With Flutter:
$ flutter pub add flutter_naver_map
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
flutter_naver_map: ^0.10.5
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:flutter_naver_map/flutter_naver_map.dart';
import 'package:flutter/material.dart';
import 'package:flutter_naver_map_example/padding_test.dart';
import 'package:flutter_naver_map_example/path_map.dart';
import 'package:flutter_naver_map_example/polygon_map.dart';
import 'package:flutter_naver_map_example/text_field_page.dart';
import 'base_map.dart';
import 'circle_map.dart';
import 'marker_map_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MainPage(),
);
}
}
class MainPage extends StatefulWidget {
@override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
List<String> menuText = [
'기본 지도 예제',
'마커 예제',
'패스 예제',
'원형 오버레이 예제',
'컨트롤러 테스트',
'폴리곤 예제',
'GLSurface Thread collision test',
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: menuText
.map((text) => GestureDetector(
onTap: () => _onTapMenuItem(text),
child: Container(
margin: EdgeInsets.symmetric(vertical: 8),
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
border: Border.all(color: Colors.indigo),
),
child: Text(
text,
style: TextStyle(
color: Colors.indigo,
fontSize: 12,
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.center,
),
),
))
.toList(),
),
),
);
}
_onTapMenuItem(String text) {
final index = menuText.indexOf(text);
switch (index) {
case 0:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BaseMapPage(),
));
break;
case 1:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MarkerMapPage(),
));
break;
case 2:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PathMapPage(),
));
break;
case 3:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CircleMapPage(),
));
break;
case 4:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PaddingTest(),
));
break;
case 5:
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => PolygonMap(),
));
break;
case 6:
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => TextFieldPage(),
));
}
}
}
Download Details:
Author: note11g
Source Code: https://github.com/note11g/flutter_naver_map
1659226440
Efficient, immutable, and thread-safe collection classes for Ruby.
Hamster provides 6 Persistent Data Structures: Hash
, Vector
, Set
, SortedSet
, List
, and Deque
(which works as an immutable queue or stack).
Hamster collections are immutable. Whenever you modify a Hamster collection, the original is preserved and a modified copy is returned. This makes them inherently thread-safe and shareable. At the same time, they remain CPU and memory-efficient by sharing between copies.
While Hamster collections are immutable, you can still mutate objects stored in them. We recommend that you don't do this, unless you are sure you know what you are doing. Hamster collections are thread-safe and can be freely shared between threads, but you are responsible for making sure that the objects stored in them are used in a thread-safe manner.
Hamster collections are almost always closed under a given operation. That is, whereas Ruby's collection methods always return arrays, Hamster collections will return an instance of the same class wherever possible.
Where possible, Hamster collections offer an interface compatible with Ruby's built-in Hash
, Array
, and Enumerable
, to ease code migration. Also, Hamster methods accept regular Ruby collections as arguments, so code which uses Hamster
can easily interoperate with your other Ruby code.
And lastly, Hamster lists are lazy, making it possible to (among other things) process "infinitely large" lists.
Using
To make the collection classes available in your code:
require "hamster"
Or if you prefer to only pull in certain collection types:
require "hamster/hash"
require "hamster/vector"
require "hamster/set"
require "hamster/sorted_set"
require "hamster/list"
require "hamster/deque"
Constructing a Hamster Hash
is almost as simple as a regular one:
person = Hamster::Hash[name: "Simon", gender: :male]
# => Hamster::Hash[:name => "Simon", :gender => :male]
Accessing the contents will be familiar to you:
person[:name] # => "Simon"
person.get(:gender) # => :male
Updating the contents is a little different than you are used to:
friend = person.put(:name, "James") # => Hamster::Hash[:name => "James", :gender => :male]
person # => Hamster::Hash[:name => "Simon", :gender => :male]
friend[:name] # => "James"
person[:name] # => "Simon"
As you can see, updating the hash returned a copy leaving the original intact. Similarly, deleting a key returns yet another copy:
male = person.delete(:name) # => Hamster::Hash[:gender => :male]
person # => Hamster::Hash[:name => "Simon", :gender => :male]
male.key?(:name) # => false
person.key?(:name) # => true
Since it is immutable, Hamster's Hash
doesn't provide an assignment (Hash#[]=
) method. However, Hash#put
can accept a block which transforms the value associated with a given key:
counters = Hamster::Hash[evens: 0, odds: 0] # => Hamster::Hash[:evens => 0, :odds => 0]
counters.put(:odds) { |value| value + 1 } # => Hamster::Hash[:odds => 1, :evens => 0]
Or more succinctly:
counters.put(:odds, &:next) # => {:odds => 1, :evens => 0}
This is just the beginning; see the API documentation for details on all Hash
methods.
A Vector
is an integer-indexed collection much like an immutable Array
. Examples:
vector = Hamster::Vector[1, 2, 3, 4] # => Hamster::Vector[1, 2, 3, 4]
vector[0] # => 1
vector[-1] # => 4
vector.put(1, :a) # => Hamster::Vector[1, :a, 3, 4]
vector.add(:b) # => Hamster::Vector[1, 2, 3, 4, :b]
vector.insert(2, :a, :b) # => Hamster::Vector[1, 2, :a, :b, 3, 4]
vector.delete_at(0) # => Hamster::Vector[2, 3, 4]
Other Array
-like methods like #select
, #map
, #shuffle
, #uniq
, #reverse
, #rotate
, #flatten
, #sort
, #sort_by
, #take
, #drop
, #take_while
, #drop_while
, #fill
, #product
, and #transpose
are also supported. See the API documentation for details on all Vector
methods.
A Set
is an unordered collection of values with no duplicates. It is much like the Ruby standard library's Set
, but immutable. Examples:
set = Hamster::Set[:red, :blue, :yellow] # => Hamster::Set[:red, :blue, :yellow]
set.include? :red # => true
set.add :green # => Hamster::Set[:red, :blue, :yellow, :green]
set.delete :blue # => Hamster::Set[:red, :yellow]
set.superset? Hamster::Set[:red, :blue] # => true
set.union([:red, :blue, :pink]) # => Hamster::Set[:red, :blue, :yellow, :pink]
set.intersection([:red, :blue, :pink]) # => Hamster::Set[:red, :blue]
Like most Hamster methods, the set-theoretic methods #union
, #intersection
, #difference
, and #exclusion
(aliased as #|
, #&
, #-
, and #^
) all work with regular Ruby collections, or indeed any Enumerable
object. So just like all the other Hamster collections, Hamster::Set
can easily be used in combination with "ordinary" Ruby code.
See the API documentation for details on all Set
methods.
A SortedSet
is like a Set
, but ordered. You can do everything with it that you can do with a Set
. Additionally, you can get the #first
and #last
item, or retrieve an item using an integral index:
set = Hamster::SortedSet['toast', 'jam', 'bacon'] # => Hamster::SortedSet["bacon", "jam", "toast"]
set.first # => "bacon"
set.last # => "toast"
set[1] # => "jam"
You can also specify the sort order using a block:
Hamster::SortedSet.new(['toast', 'jam', 'bacon']) { |a,b| b <=> a } Hamster::SortedSet.new(['toast', 'jam', 'bacon']) { |str| str.chars.last }
See the API documentation for details on all SortedSet
methods.
Hamster List
s have a head (the value at the front of the list), and a tail (a list of the remaining items):
list = Hamster::List[1, 2, 3]
list.head # => 1
list.tail # => Hamster::List[2, 3]
Add to a list with List#add
:
original = Hamster::List[1, 2, 3]
copy = original.add(0) # => Hamster::List[0, 1, 2, 3]
Notice how modifying a list actually returns a new list. That's because Hamster List
s are immutable.
List
is lazy where possible. It tries to defer processing items until absolutely necessary. For example, the following code will only call Prime.prime?
as many times as necessary to generate the first 3 prime numbers between 10,000 and 1,000,000:
require 'prime'
Hamster.interval(10_000, 1_000_000).select do |number|
Prime.prime?(number)
end.take(3)
# => 0.0009s
Compare that to the conventional equivalent which needs to calculate all possible values in the range before taking the first three:
(10000..1000000).select do |number|
Prime.prime?(number)
end.take(3)
# => 10s
Besides Hamster::List[]
there are other ways to construct lists:
Hamster.interval(from, to)
creates a lazy list equivalent to a list containing all the values between from
and to
without actually creating a list that big.
Hamster.stream { ... }
allows you to creates infinite lists. Each time a new value is required, the supplied block is called. To generate a list of integers you could do:
count = 0
Hamster.stream { count += 1 }
Hamster.repeat(x)
creates an infinite list with x
the value for every element.
Hamster.replicate(n, x)
creates a list of size n
with x
the value for every element.
Hamster.iterate(x) { |x| ... }
creates an infinite list where the first item is calculated by applying the block on the initial argument, the second item by applying the function on the previous result and so on. For example, a simpler way to generate a list of integers would be:
Hamster.iterate(1) { |i| i + 1 }
or even more succinctly:
Hamster.iterate(1, &:next)
Hamster::List.empty
returns an empty list, which you can build up using repeated calls to #add
or other List
methods.
Enumerable#to_list
will convert any existing Enumerable
to a list, so you can slowly transition from built-in collection classes to Hamster.
IO#to_list
enables lazy processing of huge files. For example, imagine the following code to process a 100MB file:
require 'hamster/core_ext'
File.open("my_100_mb_file.txt") do |file|
lines = []
file.each_line do |line|
break if lines.size == 10
lines << line.chomp.downcase.reverse
end
end
Compare to the following more functional version:
File.open("my_100_mb_file.txt") do |file|
file.map(&:chomp).map(&:downcase).map(&:reverse).take(10)
end
Unfortunately, though the second example reads nicely it takes many seconds to run (compared with milliseconds for the first) even though we're only interested in the first ten lines. Using #to_list
we can get the running time back comparable to the imperative version.
File.open("my_100_mb_file.txt") do |file|
file.to_list.map(&:chomp).map(&:downcase).map(&:reverse).take(10)
end
This is possible because IO#to_list
creates a lazy list whereby each line is only ever read and processed as needed, in effect converting it to the first example.
See the API documentation for details on all List
methods.
A Deque
(or "double-ended queue") is an ordered collection, which allows you to push and pop items from both front and back. This makes it perfect as an immutable stack or queue. Examples:
deque = Hamster::Deque[1, 2, 3] # => Hamster::Deque[1, 2, 3]
deque.first # 1
deque.last # 3
deque.pop # => Hamster::Deque[1, 2]
deque.push(:a) # => Hamster::Deque[1, 2, 3, :a]
deque.shift # => Hamster::Deque[2, 3]
deque.unshift(:a) # => Hamster::Deque[:a, 1, 2, 3]
Of course, you can do the same thing with a Vector
, but a Deque
is more efficient. See the API documentation for details on all Deque
methods.
Hamster arrays, hashes, and nested structures of arrays and hashes may be transformed with the update_in
method.
c = Hamster.from({
people: [{name: 'Chris', city: 'Lagos'}, {name: 'Pat', city: 'Madrid'}],
places: [{name: 'Lagos', population: 1}, {name: 'Madrid', population: 1}]})
c2 = c.update_in(:people, 1, :city) { |old_city| 'Lagos' }
c3 = c2.update_in(:places, 1, :population) { |old_population| old_population - 1 }
c4 = c3.update_in(:places, 0, :population) { |old_population| old_population + 1 }
Hamster.to_ruby(c4)
# => {:places=>[{:population=>2, :name=>"Lagos"}, {:population=>0, :name=>"Madrid"}], :people=>[{:name=>"Chris", :city=>"Lagos"}, {:name=>"Pat", :city=>"Lagos"}]}
Naturally, update_in
never mutates your collections.
See Hamster::Hash#update_in
, Hamster::Vector#update_in
, and Hamster::Associable#update_in
for details.
Installing
Add this line to your application's Gemfile:
gem "hamster"
And then execute:
$ bundle
Or install it yourself as:
$ gem install hamster
Contributing
git checkout -b my-new-feature
)git commit -am "Add some feature"
)git push origin my-new-feature
)Other Reading
Hash
and Set
: Hash Array Mapped TriesLicensing
Copyright (c) 2009-2015 Simon Harris
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Author: hamstergem
Source code: https://github.com/hamstergem/hamster
License: View license
1659110294
Flutter Map Floating Map Marker Titles
Floating Map Marker Titles for flutter_map, using the core library of the Flutter Floating Map Marker Titles project.
FlutterMapWithFMTO(
floatingTitles,
fmtoOptions: fmtoOptions,
// ... other than the 2 above option, this widget takes
// exactly the same props as the FlutterMap widget.
options: MapOptions(
center: LatLng(0, 0),
zoom: 13,
),
layers: [
TileLayerOptions(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
),
],
),
See the how-to section of the main project for more details.
Run this command:
With Flutter:
$ flutter pub add flutter_map_floating_marker_titles
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
flutter_map_floating_marker_titles: ^0.0.6
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:flutter_map_floating_marker_titles/flutter_map_floating_marker_titles.dart';
Download Details:
Author: androidseb
Source Code: https://github.com/androidseb/flutter_map_floating_marker_titles
1659108084
yandex_mapkit
A flutter plugin for displaying yandex maps on iOS and Android.
Android | iOS | |
---|---|---|
Support | SDK 21+ | iOS 12+ |
Disclaimer: This project uses Yandex Mapkit which belongs to Yandex
When using Mapkit refer to these terms of use
MapKit mobile SDK
keyimport YandexMapsMobile
to ios/Runner/AppDelegate.swift
YMKMapKit.setApiKey("YOUR_API_KEY")
inside func application
in ios/Runner/AppDelegate.swift
ios/Runner/AppDelegate.swift
platform :ios, '9.0'
in ios/Podfile
and change to platform :ios, '12.0'
ios/Runner/AppDelegate.swift
:
import UIKit
import Flutter
import YandexMapsMobile
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
YMKMapKit.setLocale("YOUR_LOCALE") // Your preferred language. Not required, defaults to system language
YMKMapKit.setApiKey("YOUR_API_KEY") // Your generated API key
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
implementation 'com.yandex.android:maps.mobile:4.1.0-full'
to android/app/build.gradle
<uses-permission android:name="android.permission.INTERNET"/>
and <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
to android/app/src/main/AndroidManifest.xml
import com.yandex.mapkit.MapKitFactory;
to android/app/src/main/.../MainActivity.java
/android/app/src/main/.../MainActivity.kt
MapKitFactory.setApiKey("YOUR_API_KEY");
inside method onCreate
in android/app/src/main/.../MainActivity.java
/android/app/src/main/.../MainActivity.kt
android/app/src/main/.../MainActivity.java
/android/app/src/main/.../MainActivity.kt
android/app/build.gradle
:
dependencies {
implementation 'com.yandex.android:maps.mobile:4.1.0-full'
}
android/app/src/main/.../MainActivity.java
:
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;
import com.yandex.mapkit.MapKitFactory;
public class MainActivity extends FlutterActivity {
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
MapKitFactory.setLocale("YOUR_LOCALE"); // Your preferred language. Not required, defaults to system language
MapKitFactory.setApiKey("YOUR_API_KEY"); // Your generated API key
super.configureFlutterEngine(flutterEngine);
}
}
android/app/src/main/.../MainActivity.kt
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
import com.yandex.mapkit.MapKitFactory
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
MapKitFactory.setLocale("YOUR_LOCALE") // Your preferred language. Not required, defaults to system language
MapKitFactory.setApiKey("YOUR_API_KEY") // Your generated API key
super.configureFlutterEngine(flutterEngine)
}
}
For usage examples refer to example app
YandexMapkit always works with one language only.
Due to native constraints after the application is launched it can't be changed.
Hybrid Composition
By default android views are rendered using Hybrid Composition. To render the YandexMap
widget on Android using Virtual Display(old composition), set AndroidYandexMap.useAndroidViewSurface to false. Place this anywhere in your code, before using YandexMap
widget.
AndroidYandexMap.useAndroidViewSurface = false;
Run this command:
With Flutter:
$ flutter pub add yandex_mapkit
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
yandex_mapkit: ^3.0.3
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:yandex_mapkit/yandex_mapkit.dart';
import 'package:flutter/material.dart';
import 'package:yandex_mapkit/yandex_mapkit.dart';
import 'package:yandex_mapkit_example/examples/widgets/map_page.dart';
import 'package:yandex_mapkit_example/examples/circle_map_object_page.dart';
import 'package:yandex_mapkit_example/examples/clusterized_placemark_collection_page.dart';
import 'package:yandex_mapkit_example/examples/bicycle_page.dart';
import 'package:yandex_mapkit_example/examples/driving_page.dart';
import 'package:yandex_mapkit_example/examples/map_controls_page.dart';
import 'package:yandex_mapkit_example/examples/map_object_collection_page.dart';
import 'package:yandex_mapkit_example/examples/placemark_map_object_page.dart';
import 'package:yandex_mapkit_example/examples/polyline_map_object_page.dart';
import 'package:yandex_mapkit_example/examples/polygon_map_object_page.dart';
import 'package:yandex_mapkit_example/examples/reverse_search_page.dart';
import 'package:yandex_mapkit_example/examples/search_page.dart';
import 'package:yandex_mapkit_example/examples/suggest_page.dart';
import 'package:yandex_mapkit_example/examples/user_layer_page.dart';
void main() {
runApp(MaterialApp(home: MainPage()));
}
const List<MapPage> _allPages = <MapPage>[
MapControlsPage(),
ClusterizedPlacemarkCollectionPage(),
MapObjectCollectionPage(),
PlacemarkMapObjectPage(),
PolylineMapObjectPage(),
PolygonMapObjectPage(),
CircleMapObjectPage(),
UserLayerPage(),
SuggestionsPage(),
SearchPage(),
ReverseSearchPage(),
BicyclePage(),
DrivingPage(),
];
class MainPage extends StatelessWidget {
void _pushPage(BuildContext context, MapPage page) {
Navigator.push(
context,
MaterialPageRoute<void>(builder: (_) =>
Scaffold(
appBar: AppBar(title: Text(page.title)),
body: Container(
padding: const EdgeInsets.all(8),
child: page
)
)
)
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('YandexMap examples')),
body: Column(
children: <Widget>[
Expanded(
child: Container(
padding: const EdgeInsets.all(8),
child: const YandexMap()
)
),
Expanded(
child: ListView.builder(
itemCount: _allPages.length,
itemBuilder: (_, int index) => ListTile(
title: Text(_allPages[index].title),
onTap: () => _pushPage(context, _allPages[index]),
),
)
)
]
)
);
}
}
Download Details:
Author: Unact
Source Code: https://github.com/Unact/yandex_mapkit