「*[JavaFX]」の検索結果を表示しています
2015-12-13 06:45

Server Event Client Sample

JavaFX Advent Calendar 2015 - Qiitaの13日目です。
昨日は@さんのJavaFX と Project Jigsaw - JavaFX in the Boxでした。
明日は@さんです。
前回Server Sent Event のサーバー処理についてちょっと実装を試したJava EEエヴァンジェリストによる!EE 8最新動向!に行ってきました! - tomoTakaの日記のですが、クライアントJavaで実装できると紹介されていたので、JavaFXサーバーから受信したレスポンスをアニメーションで表現してみるのに挑戦しました。
ですが、そもそもアニメーションがよくわかっていなくて、、、
2パターンの実装は、ここChapter 15. Server-Sent Events (SSE) Supportを参考にしました。

画面

リクエスト送信ボタンをクリックした後、指定したタスク数の「Task0〜5の結果」ラベルが左(サーバー)から右(クライアント)へタスク処理時間で指定した時間の間隔で移動します。
「リクエスト送信(非同期)」ボタンの処理は思ってようにアニメーションしますが、「リスエスト送信(同期)」ボタンの処理は、アニメーションで複数のラベルが同時になってしまいます???

f:id:tomoTaka:20151212153445p:image:w350

f:id:tomoTaka:20151212153517p:image:w370

実装

アニメーションの部分はコメントいただいて修正しています。

    @FXML
    private void requestAction2(ActionEvent event){
        listeningProperty.setValue(Boolean.TRUE);
        disableProperty.setValue(Boolean.FALSE);
        int taskCntVal = taskCnt.getValue();
        int taskIntervalVal = taskInterval.getValue();
        String url = "http://localhost:8080/event/" 
                + taskCntVal + "/" + taskIntervalVal;
        Client client = ClientBuilder.newBuilder().register(SseFeature.class).build();
        WebTarget target = client.target(url);
        eventSource = EventSource.target(target).build();
        eventSource.register(inboundEvent ->{
            String data = inboundEvent.readData(String.class);
            int id = Integer.parseInt(inboundEvent.getId());
            Label label = labels[id];
            TranslateTransition t = transitions[id]; // **サーバーより受信したIDで実行するアニメーションを設定
            Platform.runLater(()->{
                label.setText(data); // **ラベルにサーバーより受信した結果を設定
                new Timeline(new KeyFrame(Duration.millis(500), e-> t.play())).play(); / **アニメーション開始
            });
        }, "message-client");
        eventSource.open();
    }

修正後

            Platform.runLater(()->{
                 label.setText(data);
                TranslateTransition t = new TranslateTransition(Duration.millis(300), label);
                t.setFromX(0);
                t.setToX(-200);
                t.play();  // **アニメーション開始
            });
    @FXML
    private void requestAction1(ActionEvent event) {
        listeningProperty.setValue(Boolean.TRUE);
        disableProperty.setValue(Boolean.FALSE);
        Arrays.stream(labels).forEach(l -> l.setText(null));
        int taskCntVal = taskCnt.getValue();
        int taskIntervalVal = taskInterval.getValue();
        String url = "http://localhost:8080/event/" 
                + taskCntVal + "/" + taskIntervalVal;
        Client client = ClientBuilder.newBuilder().register(SseFeature.class).build();
        WebTarget target = client.target(url);
        EventInput eventInput = target.request().get(EventInput.class);
        while (!eventInput.isClosed()){
            InboundEvent inboundEvent = eventInput.read();
            if (inboundEvent == null){
                break;
            }
            int id = Integer.parseInt(inboundEvent.getId());
            Label label = labels[id];
            String data = inboundEvent.readData(String.class);
            label.setText(data);                
            TranslateTransition t = transitions[id];
            new Timeline(new KeyFrame(Duration.millis(500), e-> t.play())).play();
        }
    }

アニメーションの初期設定など

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        labels = new Label[] {label1, label2, label3, label4, label5};
        Arrays.stream(labels).forEach(l -> l.setText(null));
        transitions = new TranslateTransition[]{
            new TranslateTransition(Duration.millis(500), label1)
           ,new TranslateTransition(Duration.millis(500), label2)
           ,new TranslateTransition(Duration.millis(500), label3)
           ,new TranslateTransition(Duration.millis(500), label4)
           ,new TranslateTransition(Duration.millis(500), label5)
        };
        Arrays.stream(transitions).forEach(t -> {
            t.setFromX(0);
            t.setToX(-200);
        });
        // Buttonの使用制御
        listeningProperty = new SimpleBooleanProperty(false);
        startBtn1.disableProperty().bind(listeningProperty);
        startBtn2.disableProperty().bind(listeningProperty);
        disableProperty = new SimpleBooleanProperty(true);        
        closeBtn.disableProperty().bind(disableProperty);
    }    

実装はここGitHub - tomoTaka01/SseClientSample: Server Sent Event JavaFX Client Sampleにアップしています。
JavaFXの問題ではないのですが、非同期処理を実行するとサーバーへ何度もリクエスト送信されてしまいます?(汗)
すごく中途半端な状態で申し訳ないですが、アドバイスいただければ幸いです、、、
アニメーション難しいです、まだまだ勉強不足です、、、

2015-07-20 16:32

File Tree View with Image

Having had the message on my blog about JavaFX TreeViewSample(FYR. 2013-03-23 - tomoTakaの日記), I was so happy. So I wanted to add ImageView on this application.
It is easy thanks to JavaFX ImageView control.

You can see the Images on each Tree Cell.
f:id:tomoTaka:20150720160028p:image:w480

This code shows you how to set ImageView to TreeCell by using setGraphic method.

    @Override
    protected void updateItem(PathItem item, boolean empty) {
        super.updateItem(item, empty);
        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            final String itemString = getString();
            if (isEditing()) {
                if (textField != null) {
                    textField.setText(itemString);
                }
                setText(null);
                setGraphic(textField);
            } else {
                setText(itemString);
                if (isImage(itemString)) { // <-- see code2
                    setGraphic(getImage(itemString)); // <-- *** add ImageView here(see code3)
                } else {
                    setGraphic(null);
                }
                if (!getTreeItem().isLeaf()) {
                    setContextMenu(dirMenu);
                } else {
                    setContextMenu(fileMenu);
                }
            }
        }
    }

I found the blog about how to check if the file is image or not.(http://qiita.com/pcpDev/items/a4963bb2a7c3e5073cdb).
This helps me a lot, but it does not work for tiff file...

...
    private static List<String> imageList;
    static {
        imageList = Arrays.asList("BMP", "DIB", "RLE", "JPG", "JPEG" , "JPE", "JFIF"
        , "GIF", "EMF", "WMF", "TIF", "TIFF", "PNG", "ICO");
    }
...
    private boolean isImage(String itemPath) {
        String parentPath = getItem().getPath().getParent().toAbsolutePath().toString();
        try {
            URL url = new URL("file:" + parentPath + "/" + itemPath);
            String formatName = "";
            try (ImageInputStream iis = ImageIO.createImageInputStream(url.openStream())) {
                Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
                if (readers.hasNext()) { // <-- this does not work for tiff file???
                    ImageReader reader = readers.next();
                    formatName = reader.getFormatName();
                }
            }
            if (imageList.contains(formatName.toUpperCase())) {
                return true;
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

ImageView has very useful method like setFitWidth to resize your image.

    private Node getImage(String itemPath) {
        String parentPath = getItem().getPath().getParent().toAbsolutePath().toString();
        Image image = new Image("file:" + parentPath + "/" + itemPath);
        ImageView imageView = new ImageView();
        imageView.setImage(image);
        imageView.setFitWidth(10); // <-- set size of image
        imageView.setPreserveRatio(true);
        return imageView;
    }

The whole code is here(GitHub - tomoTaka01/FileTreeViewSample: JavaFX File Tree View Sample)

PS; When I put this blog,Mr.@ who is Java champion in Japan had suggested to use javafx.scene.image.Image instead of ImageIO. Then I amended the code about how to check if TreeCell is image or not. I feel so happy since I received message from such a nice person!

...
                setText(itemString);
                final Node image = getImage(itemString);
                if (image != null) {  // <-- not use isImage method(code2)
                    setGraphic(image); // <-- *** add image
                } else {
                    setGraphic(null);
                }
...
    private Node getImage(String itemPath) {
        String parentPath = getItem().getPath().getParent().toAbsolutePath().toString();
        Image image = new Image("file:" + parentPath + "/" + itemPath);
        if (image.isError()) {
            return null; // <-- if not image
        }
        ImageView imageView = new ImageView();
        imageView.setImage(image);
        imageView.setFitWidth(10); // <-- set size of image
        imageView.setPreserveRatio(true);
        return imageView;
    }

I tried to resolve about Tiff file, but it is very difficult for me so far. I will find the way how to deal Tiff file in Java...
Anyway coding something in Java is so fun. ;-)

2015-01-25 08:48

JavaFX connecting AWS S3 bucket simple sample

I just joined this workshop Java workshop for only women
and AWS workshop for only women last week.
It was very fun to take part in this kind of events.

At first we introduced ourselves and mentioned own today's task.
Then having fun time with teaching each other.
At last we announced today's result of each person.

My goal is implementing JavaFX sample, which connecting AWS S3. Then to show S3's buckets in JavaFX.

f:id:tomoTaka:20150125082851p:image:w680
f:id:tomoTaka:20150125082919p:image:w680

Showing the S3 bucket on JavaFX.
f:id:tomoTaka:20150125083014p:image:w330

Connecting to AWS

        AmazonS3 s3 = new AmazonS3Client();
        Region usWest2 = Region.getRegion(Regions.US_WEST_2);
        s3.setRegion(usWest2);

Getting S3 bucket, and creating Tab.

        s3.listBuckets().forEach(bucket -> {
            // creating tab for each bucket
            Tab tab = new Tab();
            String bucketNm = bucket.getName();
            tab.setText(bucketNm);
            tabPane.getTabs().add(tab);
            VBox vbox = new VBox(10);
            vbox.setPadding(new Insets(10));
            vbox.setStyle("-fx-background-color: #ffc9ae");
            // Owner
            HBox hbox1 = new HBox(10);
            Label ownerLabel = new Label("Owner:");
            String owner = bucket.getOwner().getDisplayName();
            Text ownerText = new Text(owner);
            hbox1.getChildren().addAll(ownerLabel, ownerText);
            // Create Date
            HBox hbox2 = new HBox(10);
            Label dateLabel = new Label("Create Date:");
            String createDate = bucket.getCreationDate().toString();
            Text dateText = new Text(createDate);
            hbox2.getChildren().addAll(dateLabel, dateText);
            tab.setContent(vbox);
            tab.setStyle("-fx-background-color: #ffc9ae;");
            // ListView for file path
            ObservableList<String> items = FXCollections.observableArrayList("file path");
            ListView view = new ListView(items);
            ObjectListing objList = s3.listObjects(new ListObjectsRequest()
                    .withBucketName(bucketNm)
                    .withPrefix(""))
                    ;
            objList.getObjectSummaries().forEach(obj -> {
                String filePath = obj.getKey();
                items.add(filePath);
            });
            vbox.getChildren().addAll(hbox1, hbox2, view);
        });

Whole code is here GitHub - tomoTaka01/JavaFXAWSS3Sample: AWS S3 simple sample by JavaFX

I would like to express my gratitude to staff as well as Osakan Space.
Osakan Space
just keep coding... ;-)

Java女子部勉強会に行ってきました。

1/24(土) 関西Java女子部 部活 - connpassに参加してきました。
同じ週の水曜にははじめて女子応援企画!クラウド勉強会【女子限定】 - JAWS-UG KANSAI | Doorkeeperにも参加。
関西で女子会に2回も参加できてすごく楽しかったです。

最初に自己紹介と今日の課題を各自発表、その後自習ヽ時にスイーツタイム、最後に各自が課題を発表と、あっというまに時間が経過しました!私は最近いろいろはまっているgoogle maps APIなどいろいろ教えていただいてすごく勉強なりました。
(本を読んで静かに勉強していたほかの参加者さん、うるさくしてごめんなさい、^^;)

私の課題は、AWSのS3にJavaを使ってアクセスしてその内容(Bucket)をJavaFXを使って画面に表示することに挑戦してみました。
AWSの勉強会でS3を触ってみた20150121 JAWS-UG関西女子会 第一回勉強会資料 // Speaker Deckを発表されていた(すごく楽しい発表でした)のですが、以前Javaからs3にアクセスするサンプルを実装(コピペ)してみたことを思い出したので、とりあえず勉強会では、bucketを検索して、bucketごとにJavaFXのTabを作成、各bucketのOwnerと作成日を表示するところまでで終わりました。
翌日にファイルをListViewを使って表示する機能を追加しました。
もっといろいろ(例えばファイルのアップロードとか)挑戦していきたいです!

f:id:tomoTaka:20150125082851p:image:w680
f:id:tomoTaka:20150125082919p:image:w680

上のAWSコンソールと同じbucketとファイルが表示されました。
f:id:tomoTaka:20150125083014p:image:w330

AWSのS3に接続

        AmazonS3 s3 = new AmazonS3Client();
        Region usWest2 = Region.getRegion(Regions.US_WEST_2);
        s3.setRegion(usWest2);

S3でのbucketを取得して、bucuket毎にタブを作成
作成したタブに「Owner」「作成日」とファイル一覧を表示

        s3.listBuckets().forEach(bucket -> {
            // creating tab for each bucket
            Tab tab = new Tab();
            String bucketNm = bucket.getName();
            tab.setText(bucketNm);
            tabPane.getTabs().add(tab);
            VBox vbox = new VBox(10);
            vbox.setPadding(new Insets(10));
            vbox.setStyle("-fx-background-color: #ffc9ae");
            // Owner
            HBox hbox1 = new HBox(10);
            Label ownerLabel = new Label("Owner:");
            String owner = bucket.getOwner().getDisplayName();
            Text ownerText = new Text(owner);
            hbox1.getChildren().addAll(ownerLabel, ownerText);
            // Create Date
            HBox hbox2 = new HBox(10);
            Label dateLabel = new Label("Create Date:");
            String createDate = bucket.getCreationDate().toString();
            Text dateText = new Text(createDate);
            hbox2.getChildren().addAll(dateLabel, dateText);
            tab.setContent(vbox);
            tab.setStyle("-fx-background-color: #ffc9ae;");
            // ListView for file path
            ObservableList<String> items = FXCollections.observableArrayList("file path");
            ListView view = new ListView(items);
            ObjectListing objList = s3.listObjects(new ListObjectsRequest()
                    .withBucketName(bucketNm)
                    .withPrefix(""))
                    ;
            objList.getObjectSummaries().forEach(obj -> {
                String filePath = obj.getKey();
                items.add(filePath);
            });
            vbox.getChildren().addAll(hbox1, hbox2, view);
        });

とりあえずコードはGitHub - tomoTaka01/JavaFXAWSS3Sample: AWS S3 simple sample by JavaFXにアップしました。

Java女子会、AWS女子会のスタッフの方々には、お世話になりありがとうございました!
Java女子会ではいつも会場を提供していただいている、Osakan space大阪のコワーキングスペース : Osakan Space (オオサカンスペース) : 本町駅すぐ御堂筋沿い | 御堂筋線本町駅番出口から30秒のCoworking space(コワーキングスペース)です。さんにも感謝です!

2015-01-12 15:53

JavaFX Task sample using Java8 CompletableFuture

After reading Java8 Concurrency articleJava技術最前線 - 詳解 Java SE 8 第19回 Concurrency Utilitiesのアップデート その1:ITpro by @,
I wanted to try how to use JavaFX Task with CompletableFuture.
f:id:tomoTaka:20150112094833p:image:w380
This is very easy thanks to this website. 1 Concurrency in JavaFX (Release 8)

This code shows you how to control these tasks.

public class FXMLDocumentController implements Initializable {
    @FXML
    private ProgressBar progressbarA;
    @FXML
    private ProgressBar progressbarB;
    @FXML
    private ProgressBar progressbarC;    
    @FXML
    private void startTask(ActionEvent event){
        TaskSample taskA = new TaskSample();
        this.progressbarA.progressProperty().bind(taskA.progressProperty());
        TaskSample taskB = new TaskSample();
        this.progressbarB.progressProperty().bind(taskB.progressProperty());
        TaskSample taskC = new TaskSample();
        this.progressbarC.setProgress(0);
        taskC.setOnRunning(e -> {
            this.progressbarC.progressProperty().bind(taskC.progressProperty());
        });
        // just use CompletableFuture for executing tasks
        CompletableFuture<Void> futureA = CompletableFuture.runAsync(taskA);
        CompletableFuture<Void> futureB = CompletableFuture.runAsync(taskB);
        futureA.runAfterBoth(futureB, taskC);
    }
}

You just need to extend javafx.concurrent.Task for your own tasks.

public class TaskSample extends Task<Void>{
    @Override
    protected Void call() throws Exception {
        updateProgress(0, 10);
        IntStream.rangeClosed(1, 10).forEach(i -> {
            try {
                TimeUnit.SECONDS.sleep(1); // to do something
            } catch (InterruptedException ex) {
                Logger.getLogger(TaskSample.class.getName()).log(Level.SEVERE, null, ex);
            }
            updateProgress(i, 10);
        });
        return null;
    }
}

The whole code is hereGitHub - tomoTaka01/ConcurrencyTaskSample: JavaFX Task sample using Java8 CompletableFuture
keep coding... ;-)

2014-12-31 10:51

JavaFX with google map and JSON sample

Thanks to this web site Adding HTML Content to JavaFX Applications | JavaFX 2 Tutorials and Documentation, it it easy making upcalls from JavaScript to JavaFX.
1.Adding lines to HTML's table and creating Marker on this map, by clicking on the map.
2.Saving point's information as json file.(Javascript calls JavaFX method)
3.Drawing Polyline and adding lines to HTML's table by reading json file.(JavaFX calls JavaScript method)

(The color picker on the WebView does not work? Why does Marker have black background color?)
f:id:tomoTaka:20141231101359p:image:w380

f:id:tomoTaka:20141231101418p:image:w380

f:id:tomoTaka:20141231101433p:image:w380

f:id:tomoTaka:20141231101447p:image:w380

JavaScript calls JavaFX getInfoList method(save to json button event)

        WebView webView = new WebView();
        WebEngine engine = webView.getEngine();
        URL url = getClass().getResource("sample.html");
        engine.load(url.toExternalForm());
        JSObject win = (JSObject) engine.executeScript("window");
        win.setMember("app", new JavaApp(stage)); // *** for javascript 
...
    public class JavaApp {
        private Stage stage;
        public JavaApp(Stage stage) {
            this.stage = stage;
        }
        /**
         * called from JavaScript by clicking [save to Json] button
         * @param infos 
         */
        public void getInfoList(String infos) {
            FileChooser fileChooser = new FileChooser();
            File file = fileChooser.showSaveDialog(this.stage);
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
                writer.write(infos);
            } catch (IOException ex) {
                Logger.getLogger(MapPositionSample.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
function saveJson(){
    // remove deleted info
    var newList = [];
    pointsInfo.infoList.forEach(function(info){
        if (!info.isDeleted){
            delete info.latlng;
            newList.push(info);
        }
    });
    // call java method
    var infos = JSON.stringify(newList);
    app.getInfoList(infos); // *** call Java method
}

JavaFX calls JavaScript drawPolylineFromJson method(load json to map button event)

        loadBtn.setOnAction(e -> {
            FileChooser fileChooser = new FileChooser();
            File file = fileChooser.showOpenDialog(stage);
            try (BufferedReader reader = new BufferedReader(new FileReader(file))){
                // file to json
                Object obj = JSONValue.parse(reader);
                // call JacaScript method with JSON object
                engine.executeScript("drawPolylineFromJson(" + obj + ")"); // *** call java script
            } catch (Exception ex) {
                Logger.getLogger(MapPositionSample.class.getName()).log(Level.SEVERE, null, ex);
            }
        });
function drawPolylineFromJson(pointsListJson){
    // clear map & table
    pointsInfo.pointNo = -1; // reset no
    pointsInfo.deleteAllMarkers(); // remove all markers from map
    initPolyLine.setMap(null); // remove KIX - SFO Polyline
    var tbody = $('#points');
    tbody.children().remove();
    var kixLatLng = infos[0];
    var sfoLatLng = infos[1];
    var prevPath = new google.maps.LatLng(kixLatLng.lat, kixLatLng.lng);
    pointsListJson.forEach(function(info){
        pointsInfo.addPoint(info);
        // add point to table 
        addTr(pointsInfo.getPoint());
        // create polyline
        var thisPath = new google.maps.LatLng(info.lat, info.lng);
        var polylineOpt = {
           map: map,
           path: [prevPath, thisPath],
           strokeColor: info.color
       };
       new google.maps.Polyline(polylineOpt);    
       prevPath = thisPath;
    });
    // last place - SFO
    var sfoPath = new google.maps.LatLng(sfoLatLng.lat, sfoLatLng.lng);
    var polylineOpt = {
       map: map,
       path: [prevPath, sfoPath],
       strokeColor: '#000000'
    };
    new google.maps.Polyline(polylineOpt);    
}

This is very hard for me to explain how to implement this kind of code...^^;;
The Whole code is here.GitHub - tomoTaka01/MapPositonSample: still coding...
keep coding...

JavaFX with google map and JSON sample

1.google map上でクリックしたポイントを元に、HTMLのTableに行を追加とmap上にマーカーを表示。
2.上記1の情報をJavaScriptからJavaFXのメソッドをcallしてJson形式のファイルとして保存。
3.JavaFXで上記2のjsonファイルを読み込んで、JavaScriptのメソッドをcallしてHTMLのTableに行を追加とmap上にPolylineを描画。

JavaFXでWebViewを使った時にマーカの背景が黒になる?color pickerは使えない?)
f:id:tomoTaka:20141231101359p:image:w380

f:id:tomoTaka:20141231101418p:image:w380

f:id:tomoTaka:20141231101433p:image:w380

f:id:tomoTaka:20141231101447p:image:w380

JavaScriptからJavaFXのメソッドをcall(save to json ボタン処理)

        WebView webView = new WebView();
        WebEngine engine = webView.getEngine();
        URL url = getClass().getResource("sample.html");
        engine.load(url.toExternalForm());
        JSObject win = (JSObject) engine.executeScript("window");
        win.setMember("app", new JavaApp(stage)); // *** for javascript 
...
    public class JavaApp {
        private Stage stage;
        public JavaApp(Stage stage) {
            this.stage = stage;
        }
        /**
         * called from JavaScript by clicking [save to Json] button
         * @param infos 
         */
        public void getInfoList(String infos) {
            FileChooser fileChooser = new FileChooser();
            File file = fileChooser.showSaveDialog(this.stage);
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
                writer.write(infos);
            } catch (IOException ex) {
                Logger.getLogger(MapPositionSample.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
function saveJson(){
    // remove deleted info
    var newList = [];
    pointsInfo.infoList.forEach(function(info){
        if (!info.isDeleted){
            delete info.latlng;
            newList.push(info);
        }
    });
    // call java method
    var infos = JSON.stringify(newList);
    app.getInfoList(infos); // *** call Java method
}

JavaFX からJavaScriptのメソッドをcall(load json to map ボタン処理)

        loadBtn.setOnAction(e -> {
            FileChooser fileChooser = new FileChooser();
            File file = fileChooser.showOpenDialog(stage);
            try (BufferedReader reader = new BufferedReader(new FileReader(file))){
                // file to json
                Object obj = JSONValue.parse(reader);
                // call JacaScript method with JSON object
                engine.executeScript("drawPolylineFromJson(" + obj + ")"); // *** call java script
            } catch (Exception ex) {
                Logger.getLogger(MapPositionSample.class.getName()).log(Level.SEVERE, null, ex);
            }
        });
function drawPolylineFromJson(pointsListJson){
    // clear map & table
    pointsInfo.pointNo = -1; // reset no
    pointsInfo.deleteAllMarkers(); // remove all markers from map
    initPolyLine.setMap(null); // remove KIX - SFO Polyline
    var tbody = $('#points');
    tbody.children().remove();
    var kixLatLng = infos[0];
    var sfoLatLng = infos[1];
    var prevPath = new google.maps.LatLng(kixLatLng.lat, kixLatLng.lng);
    pointsListJson.forEach(function(info){
        pointsInfo.addPoint(info);
        // add point to table 
        addTr(pointsInfo.getPoint());
        // create polyline
        var thisPath = new google.maps.LatLng(info.lat, info.lng);
        var polylineOpt = {
           map: map,
           path: [prevPath, thisPath],
           strokeColor: info.color
       };
       new google.maps.Polyline(polylineOpt);    
       prevPath = thisPath;
    });
    // last place - SFO
    var sfoPath = new google.maps.LatLng(sfoLatLng.lat, sfoLatLng.lng);
    var polylineOpt = {
       map: map,
       path: [prevPath, sfoPath],
       strokeColor: '#000000'
    };
    new google.maps.Polyline(polylineOpt);    
}

とりあえずメモとしてアップGitHub - tomoTaka01/MapPositonSample: still coding...
全然説明が書けてない、、、

tomoTaka
tomoTaka