<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Custom visual barchart and negative values in Developer</title>
    <link>https://community.fabric.microsoft.com/t5/Developer/Custom-visual-barchart-and-negative-values/m-p/428552#M13028</link>
    <description>&lt;P&gt;Good Day&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Im just attempting to create a custom barchart. I have used several tutorials and they are all basically the same as the one in the documentation. However one issue I have noticed is that I am unable to plot negative values on the bar chart. If i do this, the bar just does not appear.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have been attempting to fix this by changing the domain and ranges of the yScale as well as messing about with bar height and position. The error that I keep facing however is that when I plot a bar, the bar will always stretch down to the farthest point that it can reach. This is shown below&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Graph.png" style="width: 600px;"&gt;&lt;img src="https://community.fabric.microsoft.com/t5/image/serverpage/image-id/98562i5B039ED03980E643/image-size/large?v=v2&amp;amp;px=999" role="button" title="Graph.png" alt="Graph.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;For claritys sake let me show you my data source. It is not much.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Jess: 70&lt;/P&gt;&lt;P&gt;Aimee: 32&lt;/P&gt;&lt;P&gt;Chris: 28&lt;/P&gt;&lt;P&gt;Erik: 24&lt;BR /&gt;Jehan: 3&lt;/P&gt;&lt;P&gt;Ced: -20&lt;/P&gt;&lt;P&gt;Ronan: -35&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The first 5 values should be starting at the 0 tick untill their respective values and the two last negative values should be stopping at 20 and 35 respectively.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Ill also post the code if it will help?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;module powerbi.extensibility.visual {

    interface DataPoint {
        category: string;
        value: number;
        colour: string;
        identity: powerbi.visuals.ISelectionId;
        highlighted: boolean;
    };

    interface ViewModel {
        dataPoints: DataPoint[];
        maxValue: number;
        highlights: boolean;
    };

    export class Visual implements IVisual {

        private host: IVisualHost;
        private svg: d3.Selection&amp;lt;SVGElement&amp;gt;;
        private barGroup: d3.Selection&amp;lt;SVGElement&amp;gt;;
        private xPadding: number = 0.1;
        private selectionManager: ISelectionManager;
        private xAxisGroup: d3.Selection&amp;lt;SVGElement&amp;gt;;
        private yAxisGroup: d3.Selection&amp;lt;SVGElement&amp;gt;;

        private settings = {
            axis: {
                x: {
                    padding: 50
                },
                y: {
                    padding: 50
                }
            },
            border: {
                top: 10
            }
        }

        constructor(options: VisualConstructorOptions) {
            this.host = options.host;
            this.svg = d3.select(options.element)
                .append("svg")
                .classed("my-little-bar-chart", true);
            this.barGroup = this.svg.append("g")
                .classed("bar-group", true);

            this.xAxisGroup = this.svg.append("g")
                .classed("x-axis", true);

            this.yAxisGroup = this.svg.append("g")
                .classed("y-axis", true);

            this.selectionManager = this.host.createSelectionManager();
        }

        public update(options: VisualUpdateOptions) {

            

            let viewModel = this.getViewModel(options);

            let width = options.viewport.width;
            let height = options.viewport.height;

            this.svg.attr({
                width: width,
                height: height
            });

            let yScale = d3.scale.linear()
                .domain([-60, viewModel.maxValue])
                .range([height - this.settings.axis.x.padding, 0+this.settings.border.top]);

            let yAxis = d3.svg.axis()
                .scale(yScale)
                .orient("left")
                .tickSize(1);

            this.yAxisGroup
                .call(yAxis)
                .attr({
                    transform: "translate(" + this.settings.axis.y.padding + ",0)"
                })
                .style({
                    fill: "#777777"
                })
                .selectAll("text")
                .style({
                    "text-anchor": "end",
                    "font-size": "x-small"
                });

            let xScale = d3.scale.ordinal()
                .domain(viewModel.dataPoints.map(d =&amp;gt; d.category))
                .rangeRoundBands([this.settings.axis.y.padding, width], this.xPadding);

            let xAxis = d3.svg.axis()
                .scale(xScale)
                .orient("bottom")
                .tickSize(1);

            this.xAxisGroup
                .call(xAxis)
                .attr({
                    transform: "translate(0, " + (height - this.settings.axis.x.padding) + ")"
                })
                .style({
                    fill: "#777777"
                })
                .selectAll("text")
                .attr({
                    transform: "rotate(-35)"
                })
                .style({
                    "text-anchor": "end",
                    "font-size": "x-small"
                });

            let bars = this.barGroup
                .selectAll(".bar")
                .data(viewModel.dataPoints);

            bars.enter()
                .append("rect")
                .classed("bar", true);

            bars
                .attr({
                    width: xScale.rangeBand(),
                    height: d =&amp;gt; {
                        if(d.value&amp;gt;= 0)
                        {
                            console.log("-" + yScale(1))
                            console.log("--" + yScale(2))
                            console.log("---" + yScale(32))
                            console.log(d.category +" "+(height - yScale(d.value) - this.settings.axis.x.padding- yScale(32)));
                            return height - yScale(d.value) - this.settings.axis.x.padding;
                        }
                        else{
                            console.log(d.category +d.value);
                            var _temp = Math.abs(d.value);
                            return height + yScale(_temp)- this.settings.axis.x.padding;
                        }
                        
                    },
                    y: d =&amp;gt; 
                    {   
                        if(d.value&amp;gt;= 0)
                        {
                            return yScale(d.value);
                        }
                        else{
                            return yScale(0);
                        }
                        
                    },
                    x: d =&amp;gt; xScale(d.category)
                })
                .style({
                    fill: d =&amp;gt; d.colour,
                    "fill-opacity": d =&amp;gt; viewModel.highlights ? d.highlighted ? 1.0 : 0.5 : 1.0
                })
                .on("click", (d) =&amp;gt; {
                    this.selectionManager
                        .select(d.identity, true)
                        .then(ids =&amp;gt; {
                            bars.style({
                                "fill-opacity": d =&amp;gt;
                                    ids.length &amp;gt; 0 ?
                                        ids.indexOf(d.identity) &amp;gt;= 0 ?
                                            1.0 :
                                            0.5 :
                                        1.0
                            });
                        });
                });

            bars.exit()
                .remove();
        }

        private getViewModel(options: VisualUpdateOptions): ViewModel {

            let dv = options.dataViews;

            let viewModel: ViewModel = {
                dataPoints: [],
                maxValue: 0,
                highlights: false
            };

            if (!dv
                || !dv[0]
                || !dv[0].categorical
                || !dv[0].categorical.categories
                || !dv[0].categorical.categories[0].source
                || !dv[0].categorical.values)
                return viewModel;

            let view = dv[0].categorical;
            let categories = view.categories[0];
            let values = view.values[0];
            let highlights = values.highlights;

            for (let i = 0, len = Math.max(categories.values.length, values.values.length); i &amp;lt; len; i++) {
                viewModel.dataPoints.push({
                    category: &amp;lt;string&amp;gt;categories.values[i],
                    value: &amp;lt;number&amp;gt;values.values[i],
                    colour: this.host.colorPalette.getColor(&amp;lt;string&amp;gt;categories.values[i]).value,
                    identity: this.host.createSelectionIdBuilder()
                        .withCategory(categories, i)
                        .createSelectionId(),
                    highlighted: highlights ? highlights[i] ? true : false : false
                });
            }

            viewModel.maxValue = d3.max(viewModel.dataPoints, d =&amp;gt; d.value);
            viewModel.highlights = viewModel.dataPoints.filter(d =&amp;gt; d.highlighted).length &amp;gt; 0;

            return viewModel;
        }
    }
    
    
}

&lt;/PRE&gt;&lt;P&gt;The code above is probably full of errors and mistakes, but i have only just started o be nice. &lt;span class="lia-unicode-emoji" title=":face_with_tongue:"&gt;😛&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Im sorry if this answer does lie somewhere and I have not seen it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Any help with this matter would be greatly appreciated.&lt;/P&gt;&lt;P&gt;Ronan&lt;/P&gt;</description>
    <pubDate>Wed, 30 May 2018 14:06:33 GMT</pubDate>
    <dc:creator>RonanC</dc:creator>
    <dc:date>2018-05-30T14:06:33Z</dc:date>
    <item>
      <title>Custom visual barchart and negative values</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Custom-visual-barchart-and-negative-values/m-p/428552#M13028</link>
      <description>&lt;P&gt;Good Day&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Im just attempting to create a custom barchart. I have used several tutorials and they are all basically the same as the one in the documentation. However one issue I have noticed is that I am unable to plot negative values on the bar chart. If i do this, the bar just does not appear.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have been attempting to fix this by changing the domain and ranges of the yScale as well as messing about with bar height and position. The error that I keep facing however is that when I plot a bar, the bar will always stretch down to the farthest point that it can reach. This is shown below&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Graph.png" style="width: 600px;"&gt;&lt;img src="https://community.fabric.microsoft.com/t5/image/serverpage/image-id/98562i5B039ED03980E643/image-size/large?v=v2&amp;amp;px=999" role="button" title="Graph.png" alt="Graph.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;For claritys sake let me show you my data source. It is not much.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Jess: 70&lt;/P&gt;&lt;P&gt;Aimee: 32&lt;/P&gt;&lt;P&gt;Chris: 28&lt;/P&gt;&lt;P&gt;Erik: 24&lt;BR /&gt;Jehan: 3&lt;/P&gt;&lt;P&gt;Ced: -20&lt;/P&gt;&lt;P&gt;Ronan: -35&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The first 5 values should be starting at the 0 tick untill their respective values and the two last negative values should be stopping at 20 and 35 respectively.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Ill also post the code if it will help?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;module powerbi.extensibility.visual {

    interface DataPoint {
        category: string;
        value: number;
        colour: string;
        identity: powerbi.visuals.ISelectionId;
        highlighted: boolean;
    };

    interface ViewModel {
        dataPoints: DataPoint[];
        maxValue: number;
        highlights: boolean;
    };

    export class Visual implements IVisual {

        private host: IVisualHost;
        private svg: d3.Selection&amp;lt;SVGElement&amp;gt;;
        private barGroup: d3.Selection&amp;lt;SVGElement&amp;gt;;
        private xPadding: number = 0.1;
        private selectionManager: ISelectionManager;
        private xAxisGroup: d3.Selection&amp;lt;SVGElement&amp;gt;;
        private yAxisGroup: d3.Selection&amp;lt;SVGElement&amp;gt;;

        private settings = {
            axis: {
                x: {
                    padding: 50
                },
                y: {
                    padding: 50
                }
            },
            border: {
                top: 10
            }
        }

        constructor(options: VisualConstructorOptions) {
            this.host = options.host;
            this.svg = d3.select(options.element)
                .append("svg")
                .classed("my-little-bar-chart", true);
            this.barGroup = this.svg.append("g")
                .classed("bar-group", true);

            this.xAxisGroup = this.svg.append("g")
                .classed("x-axis", true);

            this.yAxisGroup = this.svg.append("g")
                .classed("y-axis", true);

            this.selectionManager = this.host.createSelectionManager();
        }

        public update(options: VisualUpdateOptions) {

            

            let viewModel = this.getViewModel(options);

            let width = options.viewport.width;
            let height = options.viewport.height;

            this.svg.attr({
                width: width,
                height: height
            });

            let yScale = d3.scale.linear()
                .domain([-60, viewModel.maxValue])
                .range([height - this.settings.axis.x.padding, 0+this.settings.border.top]);

            let yAxis = d3.svg.axis()
                .scale(yScale)
                .orient("left")
                .tickSize(1);

            this.yAxisGroup
                .call(yAxis)
                .attr({
                    transform: "translate(" + this.settings.axis.y.padding + ",0)"
                })
                .style({
                    fill: "#777777"
                })
                .selectAll("text")
                .style({
                    "text-anchor": "end",
                    "font-size": "x-small"
                });

            let xScale = d3.scale.ordinal()
                .domain(viewModel.dataPoints.map(d =&amp;gt; d.category))
                .rangeRoundBands([this.settings.axis.y.padding, width], this.xPadding);

            let xAxis = d3.svg.axis()
                .scale(xScale)
                .orient("bottom")
                .tickSize(1);

            this.xAxisGroup
                .call(xAxis)
                .attr({
                    transform: "translate(0, " + (height - this.settings.axis.x.padding) + ")"
                })
                .style({
                    fill: "#777777"
                })
                .selectAll("text")
                .attr({
                    transform: "rotate(-35)"
                })
                .style({
                    "text-anchor": "end",
                    "font-size": "x-small"
                });

            let bars = this.barGroup
                .selectAll(".bar")
                .data(viewModel.dataPoints);

            bars.enter()
                .append("rect")
                .classed("bar", true);

            bars
                .attr({
                    width: xScale.rangeBand(),
                    height: d =&amp;gt; {
                        if(d.value&amp;gt;= 0)
                        {
                            console.log("-" + yScale(1))
                            console.log("--" + yScale(2))
                            console.log("---" + yScale(32))
                            console.log(d.category +" "+(height - yScale(d.value) - this.settings.axis.x.padding- yScale(32)));
                            return height - yScale(d.value) - this.settings.axis.x.padding;
                        }
                        else{
                            console.log(d.category +d.value);
                            var _temp = Math.abs(d.value);
                            return height + yScale(_temp)- this.settings.axis.x.padding;
                        }
                        
                    },
                    y: d =&amp;gt; 
                    {   
                        if(d.value&amp;gt;= 0)
                        {
                            return yScale(d.value);
                        }
                        else{
                            return yScale(0);
                        }
                        
                    },
                    x: d =&amp;gt; xScale(d.category)
                })
                .style({
                    fill: d =&amp;gt; d.colour,
                    "fill-opacity": d =&amp;gt; viewModel.highlights ? d.highlighted ? 1.0 : 0.5 : 1.0
                })
                .on("click", (d) =&amp;gt; {
                    this.selectionManager
                        .select(d.identity, true)
                        .then(ids =&amp;gt; {
                            bars.style({
                                "fill-opacity": d =&amp;gt;
                                    ids.length &amp;gt; 0 ?
                                        ids.indexOf(d.identity) &amp;gt;= 0 ?
                                            1.0 :
                                            0.5 :
                                        1.0
                            });
                        });
                });

            bars.exit()
                .remove();
        }

        private getViewModel(options: VisualUpdateOptions): ViewModel {

            let dv = options.dataViews;

            let viewModel: ViewModel = {
                dataPoints: [],
                maxValue: 0,
                highlights: false
            };

            if (!dv
                || !dv[0]
                || !dv[0].categorical
                || !dv[0].categorical.categories
                || !dv[0].categorical.categories[0].source
                || !dv[0].categorical.values)
                return viewModel;

            let view = dv[0].categorical;
            let categories = view.categories[0];
            let values = view.values[0];
            let highlights = values.highlights;

            for (let i = 0, len = Math.max(categories.values.length, values.values.length); i &amp;lt; len; i++) {
                viewModel.dataPoints.push({
                    category: &amp;lt;string&amp;gt;categories.values[i],
                    value: &amp;lt;number&amp;gt;values.values[i],
                    colour: this.host.colorPalette.getColor(&amp;lt;string&amp;gt;categories.values[i]).value,
                    identity: this.host.createSelectionIdBuilder()
                        .withCategory(categories, i)
                        .createSelectionId(),
                    highlighted: highlights ? highlights[i] ? true : false : false
                });
            }

            viewModel.maxValue = d3.max(viewModel.dataPoints, d =&amp;gt; d.value);
            viewModel.highlights = viewModel.dataPoints.filter(d =&amp;gt; d.highlighted).length &amp;gt; 0;

            return viewModel;
        }
    }
    
    
}

&lt;/PRE&gt;&lt;P&gt;The code above is probably full of errors and mistakes, but i have only just started o be nice. &lt;span class="lia-unicode-emoji" title=":face_with_tongue:"&gt;😛&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Im sorry if this answer does lie somewhere and I have not seen it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Any help with this matter would be greatly appreciated.&lt;/P&gt;&lt;P&gt;Ronan&lt;/P&gt;</description>
      <pubDate>Wed, 30 May 2018 14:06:33 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Custom-visual-barchart-and-negative-values/m-p/428552#M13028</guid>
      <dc:creator>RonanC</dc:creator>
      <dc:date>2018-05-30T14:06:33Z</dc:date>
    </item>
    <item>
      <title>Re: Custom visual barchart and negative values</title>
      <link>https://community.fabric.microsoft.com/t5/Developer/Custom-visual-barchart-and-negative-values/m-p/429191#M13051</link>
      <description>&lt;P&gt;It seems&amp;nbsp;&lt;STRONG&gt;yScale&lt;/STRONG&gt; is incorrect as its min value is -60 but min/max values must be taken from the data set.&lt;/P&gt;
&lt;P&gt;We'd recommend to find min value in the same way you find max value and use this min value in the domain isntead of -60.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="margin: 0in; font-family: Calibri; font-size: 11.0pt; color: #333333;"&gt;Ignat Vilesov,&lt;/P&gt;
&lt;P style="margin: 0in; font-family: Calibri; font-size: 11.0pt; color: #333333;"&gt;Software Engineer&lt;/P&gt;
&lt;P style="margin: 0in; font-family: Calibri; font-size: 11.0pt; color: #333333;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="margin: 0in; font-family: Calibri; font-size: 11.0pt; color: #333333;"&gt;Microsoft Power BI Custom Visuals&lt;/P&gt;
&lt;P style="margin: 0in; font-family: Calibri; font-size: 11.0pt;"&gt;&lt;A href="mailto:pbicvsupport@microsoft.com" target="_blank"&gt;&lt;SPAN&gt;pbicvsupport@microsoft.com&lt;/SPAN&gt;&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 31 May 2018 07:53:28 GMT</pubDate>
      <guid>https://community.fabric.microsoft.com/t5/Developer/Custom-visual-barchart-and-negative-values/m-p/429191#M13051</guid>
      <dc:creator>v-viig</dc:creator>
      <dc:date>2018-05-31T07:53:28Z</dc:date>
    </item>
  </channel>
</rss>

