Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Earn the coveted Fabric Analytics Engineer certification. 100% off your exam for a limited time only!

Reply
dbardele
Frequent Visitor

Custom Visual cut off after resizing in Power BI Service

Hello, I'm new to developing custom visuals but I have something (sort of) working after following tutorials and watching YouTube videos. However, I cannot get mine to resize bigger than a postage stamp, nor to do so in real time as I change the viewport. This also was a problem when I was resizing the tutorial "Update Counter"...my counter didn't count up at all even though I was following the tutorial exactly. I'm wondering if it's because I'm using a different version of pbiviz (3.1.1) than the tutorial was written in.

 

Here is the code that I think defines sizing (unfortunately I cannot attach screengrabs of the visual). However, I may be missing something in one of the other files. Any advice will be greatly appreciated. Thanks!

 

Dom

 

import "./../style/visual.less";

import powerbi from "powerbi-visuals-api";
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;

import * as d3 from "d3";

export class Visual implements IVisual {

private svgRoot: d3.Selection<SVGElement, {}, HTMLElement, any>;
private xAxis: d3.Selection<SVGElement, {}, HTMLElement, any>;
private yAxis: d3.Selection<SVGElement, {}, HTMLElement, any>;
private line: d3.Selection<SVGElement, {}, HTMLElement, any>;
private circle: d3.Selection<SVGElement, {}, HTMLElement, any>;
private padding: number = 20;

constructor(options: VisualConstructorOptions) {
console.log('Visual constructor', options);

this.svgRoot = d3.select(options.element)
.append("svg")
.append("g");

this.xAxis = this.svgRoot
.append("g")
.attr("class", "x axis")
.style("stroke", "black")
.style("stroke-width", "1");

this.yAxis = this.svgRoot
.append("g")
.attr("class", "y axis")
.style("stroke", "black")
.style("stroke-width", "1");

/*
this.line = this.svgRoot
.append("g")
.style("stroke", "black");
*/

this.RenderVisual(options.element.clientWidth, options.element.clientHeight);

}

public update(options: VisualUpdateOptions) {

console.log('Visual update', options);

// let dataView: DataView = options.dataViews[0]

this.RenderVisual(options.viewport.width + 20, options.viewport.height + 20);

}

private RenderVisual(clientWidth: number, clientHeight: number) {

this.svgRoot
.attr("width", clientWidth)
.attr("height", clientHeight);

var plot = {
xOffset: 0, // this.padding,
yOffset: 0, // this.padding,
width: clientWidth - (this.padding * 2),
height: clientHeight - (this.padding * 2),
};
1 ACCEPTED SOLUTION
dm-p
Super User
Super User

Hi there,

Once thing I'd suggest is that this part of your code needs tweaking to make the visual keep track with the viewport:

this.svgRoot = d3.select(options.element)
    .append("svg")
    .append("g");

This is assigning the variable to the <g> (group) element that you append to the <svg> element, rather than the <svg> element itself.

When you call renderVisual, it's resizing the <g> element, and not the parent <svg>, e.g.:

zbcvR2bThe parent <svg> (as it has no explicit width & height attributes) will get rendered using the browser default (in my case it's 300 x 150 pixels.

Because the <g> element sits inside it, the parent will never grow to fit it.

It might be better to, set your svgRoot to the actual <svg> element, i.e.:

this.svgRoot = d3.select(options.element)
    .append("svg");

This way, renderVisual will resize the container element, e.g.:

w2sqiDb

Note that if you still want to group your axis elements, then you'll need to add in the parent <g> to group them somewehre else, as we removed it from the code, but this should allow you to size your SVG canvas with the viewport accordingly.

Good luck!

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!


My course: Introduction to Developing Power BI Visuals


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




View solution in original post

3 REPLIES 3
dm-p
Super User
Super User

Hi there,

Once thing I'd suggest is that this part of your code needs tweaking to make the visual keep track with the viewport:

this.svgRoot = d3.select(options.element)
    .append("svg")
    .append("g");

This is assigning the variable to the <g> (group) element that you append to the <svg> element, rather than the <svg> element itself.

When you call renderVisual, it's resizing the <g> element, and not the parent <svg>, e.g.:

zbcvR2bThe parent <svg> (as it has no explicit width & height attributes) will get rendered using the browser default (in my case it's 300 x 150 pixels.

Because the <g> element sits inside it, the parent will never grow to fit it.

It might be better to, set your svgRoot to the actual <svg> element, i.e.:

this.svgRoot = d3.select(options.element)
    .append("svg");

This way, renderVisual will resize the container element, e.g.:

w2sqiDb

Note that if you still want to group your axis elements, then you'll need to add in the parent <g> to group them somewehre else, as we removed it from the code, but this should allow you to size your SVG canvas with the viewport accordingly.

Good luck!

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!


My course: Introduction to Developing Power BI Visuals


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




dbardele
Frequent Visitor

Oh my goodness THANK YOU! That fixed it. It's still not resizing automatically when I drag the window size around like in the tutorial, but I can live with that. As soon as I click refresh, it resizes to the viewport window.

 

Thanks again! On to find the next thing that will confound me...

 

Dom

No probs! Glad you're sorted. There will be many confounding things to work on ;), but chip away at them...

FYI if you need to refresh the visual to fix your issue, that suggests something to do with code in the constructor method (which runs on instantiation) is working vs. the update method (which runs for every change afterwards).

I notice that you have a renderVisual call in both of these methods. It will be better to try and manage it in the update method rather than the constructor (use the contructor to create the element placeholders, but handle sizing and drawing that depends on changes to the visual in update).

Here's a simple custom visual I did for a presentation recently - it's a knock-off of the circle-card visual and is done on the older tooling, but if you look at the function code, the approach is similar. It might help you with obtaining some code to handle resizing and where to do it in the workflow.

 





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!


My course: Introduction to Developing Power BI Visuals


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




Helpful resources

Announcements
April AMA free

Microsoft Fabric AMA Livestream

Join us Tuesday, April 09, 9:00 – 10:00 AM PST for a live, expert-led Q&A session on all things Microsoft Fabric!

March Fabric Community Update

Fabric Community Update - March 2024

Find out what's new and trending in the Fabric Community.

Top Solution Authors
Top Kudoed Authors