cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
satishr Helper III
Helper III

Need help getting D3 charts on Leaflet map

I'm creating a custom visual which requires doughnut chart to be displayed over a map. To start with I'm trying to replicate this.

http://bl.ocks.org/d3noob/9267535

 

It has circles over a leaflet map. I got the leaflet map working but D3 part doesn't work. Please help me with this. If I get the circles on the map I can later replace them with doughnuts.

 

Visual.ts

module powerbi.extensibility.visual {
    
    
    export interface Data{
        lat: number;
        lng: number;
        latlng: {};
        status: string[];
        itemCnt: number[];
    }

    export class Visual implements IVisual {
        private target: HTMLElement;
        private divMap: HTMLElement;
        private divTable: HTMLElement;
        private map: L.Map;
        private basemap: L.TileLayer;
        private layer: L.TileLayer;

        constructor(options: VisualConstructorOptions) {
            console.log('Visual constructor', options);
            this.target = options.element;
            this.divMap = document.createElement("div");
            this.divMap.id = "map";
            this.divMap.style.height = "100%";   
            this.divMap.style.width = "100%";
            options.element.appendChild(this.divMap);

            var L = typeof L !== 'undefined' ? L : window['L'];
            
            this.map = L.map('map');
            this.map.setView([-41.28,174.77], 11); 
            var mapLink = '<a href="http://openstreetmap.org">OpenStreetMap</a>';
            this.layer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '&copy; ' + mapLink + ' Contributors', maxZoom: 18, });
            this.map.addLayer(this.layer);
        }


        public update(options: VisualUpdateOptions) {
            //update map size
            this.divMap.style.height = options.viewport.height.toString() + "px";
            this.divMap.style.width = options.viewport.width.toString() + "px";
            
            var svg = d3.select("#map").select("svg"),
            g = svg.append("g");
            
            var data: Data[] = [ 
                {lat:-41.28, lng:174.77, latlng:{}, status:['Under','Over','Normal'], itemCnt: [30,40,50]},
                {lat:-41.29, lng:174.76, latlng:{}, status:['Under','Over','Normal'], itemCnt: [30,30,60]},
                {lat:-41.23, lng:174.79, latlng:{}, status:['Under','Over','Normal'], itemCnt: [30,70,10]} 
            ];

            data.forEach(function(d) {
                d.latlng = new L.LatLng(<number>d.lat, <number>d.lng);
            })
            
            var circle= g.selectAll("circle")
                .data(data)
                .enter().append("circle")
                .style("stroke", "black")  
                .style("opacity", .6) 
                .style("fill", "red")
                .attr("r", 20)
                
            this.map.on("viewreset", update);
            update();

            function update() {
                circle.attr("transform", 
                function(d)  { 
                        return "translate("+ 
                        this.map.latLngToLayerPoint(new L.LatLng(d.lat, d.lng)).x +","+ 
                        this.map.latLngToLayerPoint(new L.LatLng(d.lat, d.lng)).y +")";
                        }
                )
            }
        }


    }
}

Visual.less

@import (less) "node_modules/leaflet/dist/leaflet.css";

Package.JSON

{
  "name": "visual",
  "version": "1.1",
  "dependencies": {
    "@types/d3": "^3.5.40",
    "d3": "^3.5.17",
    "geojson": "^0.5.0",
    "leaflet": "^1.3.1",
    "powerbi-visuals-utils-dataviewutils": "1.2.0"
  },
  "devDependencies": {
    "typescript": "^2.6.2"
  }
}

pbiviz.JSON

{
  "visual": {
    "name": "customMap",
    "displayName": "Custom Map",
    "guid": "custommap5A89ADFB5F694F71AB6D00C94383BB2B",
    "visualClassName": "Visual",
    "version": "1.0.0",
    "description": "",
    "supportUrl": "",
    "gitHubUrl": ""
  },
  "apiVersion": "1.10.0",
  "author": {
    "name": "",
    "email": ""
  },
  "assets": {
    "icon": "assets/icon.png"
  },
  "externalJS": [
    "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.js",
    "node_modules/d3/d3.min.js",
    "node_modules/leaflet/dist/leaflet.js"
  ],
  "style": "style/visual.less",
  "capabilities": "capabilities.json",
  "dependencies": "dependencies.json",
  "stringResources": []
}
2 ACCEPTED SOLUTIONS

Accepted Solutions
v-viig Community Champion
Community Champion

Re: Need help getting D3 charts on Leaflet map

We replied with the fixed version of your code.

 

Could you please post the fixed code here if you are ok with sharing?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

View solution in original post

satishr Helper III
Helper III

Re: Need help getting D3 charts on Leaflet map

Thanks, @v-viig. You fix works. Here is the fixed visual.ts.

 

module powerbi.extensibility.visual {


    export interface Data {
        lat: number;
        lng: number;
        latlng: {};
        status: string[];
        itemCnt: number[];
    }

    var L = typeof L !== 'undefined' ? L : window['L'];

    export class Visual implements IVisual {
        private target: HTMLElement;
        private divMap: HTMLElement;
        private divTable: HTMLElement;
        private map: L.Map;
        private basemap: L.TileLayer;
        private layer: L.TileLayer;

        constructor(options: VisualConstructorOptions) {
            console.log('Visual constructor', options);
            this.target = options.element;
            this.divMap = document.createElement("div");
            this.divMap.id = "map";
            this.divMap.style.height = "100%";
            this.divMap.style.width = "100%";
            options.element.appendChild(this.divMap);

            this.map = L.map('map');
            this.map.setView([-41.28, 174.77], 11);
            var mapLink = '<a href="http://openstreetmap.org">OpenStreetMap</a>';
            this.layer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '&copy; ' + mapLink + ' Contributors', maxZoom: 18, });
            this.map.addLayer(this.layer);

            L.svg().addTo(this.map);
        }


        public update(options: VisualUpdateOptions) {
            debugger;
            //update map size
            this.divMap.style.height = options.viewport.height.toString() + "px";
            this.divMap.style.width = options.viewport.width.toString() + "px";

            var svg = d3.select("#map").select("svg"),
                g = svg.append("g");

            var data: Data[] = [
                { lat: -41.28, lng: 174.77, latlng: {}, status: ['Under', 'Over', 'Normal'], itemCnt: [30, 40, 50] },
                { lat: -41.29, lng: 174.76, latlng: {}, status: ['Under', 'Over', 'Normal'], itemCnt: [30, 30, 60] },
                { lat: -41.23, lng: 174.79, latlng: {}, status: ['Under', 'Over', 'Normal'], itemCnt: [30, 70, 10] }
            ];

            data.forEach(function (d) {
                d.latlng = new L.LatLng(<number>d.lat, <number>d.lng);
            })

            var circle = g.selectAll("circle")
                .data(data)
                .enter().append("circle")
                .style("stroke", "black")
                .style("opacity", .6)
                .style("fill", "red")
                .attr("r", 20)

            const map = this.map;

            function update() {
                circle.attr("transform",
                    function (d) {
                        return "translate(" +
                            map.latLngToLayerPoint(d.latlng as any).x + "," +
                            map.latLngToLayerPoint(d.latlng as any).y + ")";
                    }
                )
            }

            this.map.on("viewreset", update);
this.map.on("zoom", update); update(); } } }

View solution in original post

17 REPLIES 17
v-viig Community Champion
Community Champion

Re: Need help getting D3 charts on Leaflet map

What exactly issue have you faced? Can you sahre source code as a zip file?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Highlighted
satishr Helper III
Helper III

Re: Need help getting D3 charts on Leaflet map

I'm trying to create D3 circles on a leaflet map for a custom visual. I'm able to get the map but the D3 circles are not working. I have sent you my code. 

v-viig Community Champion
Community Champion

Re: Need help getting D3 charts on Leaflet map

We replied with the fixed version of your code.

 

Could you please post the fixed code here if you are ok with sharing?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

View solution in original post

satishr Helper III
Helper III

Re: Need help getting D3 charts on Leaflet map

Thanks, @v-viig. You fix works. Here is the fixed visual.ts.

 

module powerbi.extensibility.visual {


    export interface Data {
        lat: number;
        lng: number;
        latlng: {};
        status: string[];
        itemCnt: number[];
    }

    var L = typeof L !== 'undefined' ? L : window['L'];

    export class Visual implements IVisual {
        private target: HTMLElement;
        private divMap: HTMLElement;
        private divTable: HTMLElement;
        private map: L.Map;
        private basemap: L.TileLayer;
        private layer: L.TileLayer;

        constructor(options: VisualConstructorOptions) {
            console.log('Visual constructor', options);
            this.target = options.element;
            this.divMap = document.createElement("div");
            this.divMap.id = "map";
            this.divMap.style.height = "100%";
            this.divMap.style.width = "100%";
            options.element.appendChild(this.divMap);

            this.map = L.map('map');
            this.map.setView([-41.28, 174.77], 11);
            var mapLink = '<a href="http://openstreetmap.org">OpenStreetMap</a>';
            this.layer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '&copy; ' + mapLink + ' Contributors', maxZoom: 18, });
            this.map.addLayer(this.layer);

            L.svg().addTo(this.map);
        }


        public update(options: VisualUpdateOptions) {
            debugger;
            //update map size
            this.divMap.style.height = options.viewport.height.toString() + "px";
            this.divMap.style.width = options.viewport.width.toString() + "px";

            var svg = d3.select("#map").select("svg"),
                g = svg.append("g");

            var data: Data[] = [
                { lat: -41.28, lng: 174.77, latlng: {}, status: ['Under', 'Over', 'Normal'], itemCnt: [30, 40, 50] },
                { lat: -41.29, lng: 174.76, latlng: {}, status: ['Under', 'Over', 'Normal'], itemCnt: [30, 30, 60] },
                { lat: -41.23, lng: 174.79, latlng: {}, status: ['Under', 'Over', 'Normal'], itemCnt: [30, 70, 10] }
            ];

            data.forEach(function (d) {
                d.latlng = new L.LatLng(<number>d.lat, <number>d.lng);
            })

            var circle = g.selectAll("circle")
                .data(data)
                .enter().append("circle")
                .style("stroke", "black")
                .style("opacity", .6)
                .style("fill", "red")
                .attr("r", 20)

            const map = this.map;

            function update() {
                circle.attr("transform",
                    function (d) {
                        return "translate(" +
                            map.latLngToLayerPoint(d.latlng as any).x + "," +
                            map.latLngToLayerPoint(d.latlng as any).y + ")";
                    }
                )
            }

            this.map.on("viewreset", update);
this.map.on("zoom", update); update(); } } }

View solution in original post

Pedzilla Post Patron
Post Patron

Re: Need help getting D3 charts on Leaflet map

@v-viig hi there, I came across this and followed the steps you guys took but I got an error Invalid API version 1.10.0 Anyway idea how to fix this please?

Thank you

Pedzilla

v-viig Community Champion
Community Champion

Re: Need help getting D3 charts on Leaflet map

What version of pbiviz do you ($ pbiviz --version)?

 

You might try updating API version by running pbiviz update 1.13.0 in the directory where you visual is locatted.

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Pedzilla Post Patron
Post Patron

Re: Need help getting D3 charts on Leaflet map

Thank you @v-viig Ive done that but got the error

TYPESCRIPT   File 'C:/viz/d3leaflet/src/Clients/Typedefs/d3/d3.d.ts' not found

 error  TYPESCRIPT   File 'C:/viz/d3leaflet/src/Clients/Typedefs/jquery-visible/
jquery-visible.d.ts' not found.
 error  TYPESCRIPT   File 'C:/viz/d3leaflet/src/Clients/Typedefs/jquery/jquery.d
.ts' not found.
 error  TYPESCRIPT   File 'C:/viz/d3leaflet/src/Clients/Typedefs/leaflet/leaflet
.d.ts' not found.
 error  TYPESCRIPT  /src/visual.ts : (18,22) Cannot find namespace 'L'.
 error  TYPESCRIPT  /src/visual.ts : (19,26) Cannot find namespace 'L'.
 error  TYPESCRIPT  /src/visual.ts : (20,24) Cannot find namespace 'L'.

 

what have i done wrong please?
Thanks so much

v-viig Community Champion
Community Champion

Re: Need help getting D3 charts on Leaflet map

Can you share the source code? Did you generate a custom visual by using pbiviz new command?

 

Ignat Vilesov,

Software Engineer

 

Microsoft Power BI Custom Visuals

pbicvsupport@microsoft.com

Pedzilla Post Patron
Post Patron

Re: Need help getting D3 charts on Leaflet map

Hey there @v-viig

Thanks for replying...

 

I used exact codes shown in this thread actually. 

I started off with pbiviz new command then I used your solution as per above.

Then run pbiviz start and got following error Invalid API version

Then tried again with pbiviz update as per your suggestion then got the final error Typescript etc...

 

Thank you so much - I feel like its not far off...

Helpful resources

Announcements
Announcing the New Spanish Forum

Announcing the New Spanish Forum

Do you need help in Spanish? Check out our new Spanish community section.

April 2020 Community Highlights

April 2020 Community Highlights

Info on our Super Users, MBAS content and badges, and updates to our support articles. - Read the full Community Highlights.

MBAS Gallery 2020

MBAS Gallery 2020

Watch Microsoft Business Applications Summit sessions on-demand.