{"id":595,"date":"2019-02-04T12:50:00","date_gmt":"2019-02-04T18:50:00","guid":{"rendered":"https:\/\/blog.felineflock.com\/?p=595"},"modified":"2024-01-01T12:51:48","modified_gmt":"2024-01-01T18:51:48","slug":"how-to-create-charts-using-svg-and-visualforce","status":"publish","type":"post","link":"https:\/\/blog.felineflock.com\/index.php\/2019\/02\/04\/how-to-create-charts-using-svg-and-visualforce\/","title":{"rendered":"How to Create Charts using SVG and VisualForce"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"755\" height=\"598\" src=\"https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG1.png\" alt=\"\" class=\"wp-image-596\" srcset=\"https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG1.png 755w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG1-300x238.png 300w\" sizes=\"auto, (max-width: 755px) 100vw, 755px\" \/><\/figure>\n\n\n\n<p>VisualForce is used to generate HTML pages but it can also create other kinds of presentation. One common alternative is to render VisualForce as PDF.<\/p>\n\n\n\n<p>This article proposes a third type of presentation that can be generated via VisualForce:  images.<\/p>\n\n\n\n<p>Scalable Vector Graphics is a graphics format that uses a markup language to describe the images. It is text-like just like HTML. With HTML you can tell the browser to draw an input element or a paragraph and specify the border, colors, margins, and with SVG you can tell the browser to draw rectangles, circles, polygons and other shapes.<\/p>\n\n\n\n<p>In the example below, I&#8217;ve used a VisualForce page rendered as SVG to draw a donut chart:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"646\" src=\"https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG2-1024x646.png\" alt=\"\" class=\"wp-image-597\" srcset=\"https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG2-1024x646.png 1024w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG2-300x189.png 300w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG2-768x484.png 768w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG2-1536x969.png 1536w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG2.png 1582w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The donut chart is an IMAGE formula field in the Property custom object.<\/p>\n\n\n\n<p>Usually the IMAGE function is used to display static images, such as red flags, say when an approval status is rejected: IMAGE ( &#8220;\/img\/samples\/flag_red.gif&#8221;, &#8220;Red&#8221; )<\/p>\n\n\n\n<p>This pushes the envelope a little further by invoking a VisualForce page with parameters to generate a image.<\/p>\n\n\n\n<p>Here is how the formula for the donut chart is defined:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>IMAGE( &#8216;\/apex\/DonutChart?labels=Living Room,Dining Room,Master BR&#8217;<\/p>\n\n\n\n<p>  \u00a0 \u00a0 + &#8216;,Bedroom %232,Bedroom %233,Others&amp;values=&#8217;<\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0+ TEXT( Living_Room__c ) + &#8216;,&#8217; + TEXT( Dining_Room__c )<\/p>\n\n\n\n<p>  \u00a0 \u00a0 + &#8216;,&#8217; + TEXT( Master_Bedroom__c ) + &#8216;,&#8217;<\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0+ TEXT( Bedroom_2__c ) + &#8216;,&#8217; + TEXT( Bedroom_3__c ) + &#8216;,&#8217;<\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0+ TEXT( Square_Feet__c &#8211; Living_Room__c &#8211; Dining_Room__c\u00a0 \u00a0 &#8211; Master_Bedroom__c &#8211; Bedroom_2__c &#8211; Bedroom_3__c )<\/p>\n\n\n\n<p>  \u00a0 \u00a0 + &#8216;&amp;number=&#8217; + TEXT( Square_Feet__c )<\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0+ &#8216;&amp;label=Square Feet&#8217;<\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0, &#8216;chart&#8217;, 250, 250 )<\/p>\n<\/blockquote>\n\n\n\n<p>The formula is invoking the VisualForce page named &#8220;DonutChart&#8221; and passing the following parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>a comma-separated list of labels (Living Room, Dining Room, &#8230;) to be printed at the perimeter of the donut and in the legend.<\/li>\n\n\n\n<li>a comma-separated list of values (Living_Room__c, Dining_Room__c, &#8230;) in the same order as the corresponding labels. The values come from the fields of the Property__c object &#8211; the last value is a subtraction to obtain the remaining square footage.<\/li>\n\n\n\n<li>the number to be printed in the middle of the donut to indicate the total square feet of the property.<\/li>\n\n\n\n<li>the label to be printed in the middle of the donut just saying &#8220;Square Feet&#8221;.<\/li>\n\n\n\n<li>and lastly, the normal parameters of the IMAGE function to indicate default size and alternative text.<\/li>\n<\/ul>\n\n\n\n<p>This is relatively simple to use and you can add that donut chart field virtually anywhere: below is the same field in a list and in a report detail.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"585\" src=\"https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG3-1024x585.png\" alt=\"\" class=\"wp-image-598\" srcset=\"https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG3-1024x585.png 1024w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG3-300x171.png 300w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG3-768x439.png 768w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG3-1536x877.png 1536w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG3-2048x1169.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"988\" height=\"1024\" src=\"https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG4-988x1024.png\" alt=\"\" class=\"wp-image-599\" srcset=\"https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG4-988x1024.png 988w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG4-289x300.png 289w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG4-768x796.png 768w, https:\/\/blog.felineflock.com\/wp-content\/uploads\/2024\/01\/vfSVG4.png 1142w\" sizes=\"auto, (max-width: 988px) 100vw, 988px\" \/><\/figure>\n\n\n\n<p>Before going into the gobbledygook code here is a list with a few other ideas of how this mechanism could be used:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>print barcodes and QR codes<\/li>\n\n\n\n<li>expose charts to community users (as an alternative to the apex:chart tag)<\/li>\n\n\n\n<li>create custom mini-related lists to fit your page layout<\/li>\n\n\n\n<li>create custom map pins with any color or shape (otherwise you would have to create the images for each combination &#8211; maybe hundreds &#8211; of pin colors and shapes and upload them as static resource)<\/li>\n\n\n\n<li>display a mini-map of the country where each state has a different color according to the data<\/li>\n\n\n\n<li>display an organizational chart or a tree view of data<\/li>\n\n\n\n<li>create custom charts that are not available out of the box<\/li>\n\n\n\n<li>represent data in some non-conventional way using text, colors or shapes<\/li>\n<\/ul>\n\n\n\n<p>Here is a summary of how the page is structured:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&lt;apex:page sidebar=&#8221;false&#8221; showHeader=&#8221;false&#8221;<\/p>\n\n\n\n<p>    controller=&#8221;DonutChartController&#8221;<\/p>\n\n\n\n<p> \u00a0  applyHtmlTag=&#8221;false&#8221; applyBodyTag=&#8221;false&#8221;<\/p>\n\n\n\n<p>    standardStylesheets=&#8221;false&#8221;<\/p>\n\n\n\n<p> \u00a0 \u00a0ContentType=&#8221;image\/svg+xml&#8221; ><\/p>\n<\/blockquote>\n\n\n\n<p>The header above tells that the content type is in the SVG format. It tells the browser to follow the markup instructions contained in the VF page and display an image.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&lt;svg id=&#8221;layer_1&#8243;\u00a0xmlns=&#8221;http:\/\/www.w3.org\/2000\/svg&#8221;<\/p>\n\n\n\n<p> \u00a0 \u00a0 xmlns:xlink=&#8221;http:\/\/www.w3.org\/1999\/xlink&#8221;<\/p>\n\n\n\n<p>\u00a0 \u00a0 \u00a0width=&#8221;{! IF( $CurrentPage.parameters.chartWidth != null, $CurrentPage.parameters.chartWidth, &#8221; )}&#8221;<\/p>\n\n\n\n<p>\u00a0 \u00a0 height=&#8221;100%&#8221; viewBox=&#8221;-4 0 68 43&#8243; ><\/p>\n<\/blockquote>\n\n\n\n<p>The SVG tag above specifies the viewBox, which tells the coordinates of the image it should display and some other parameters such as &#8220;width&#8221; for convenience.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&lt;circle class=&#8221;donut-hole&#8221; cx=&#8221;21&#8243; cy=&#8221;21&#8243; r=&#8221;15.91549430918954&#8243;<\/p>\n\n\n\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 fill=&#8221;white&#8221; \/> <\/p>\n\n\n\n<p>    &lt;circle class=&#8221;donut-ring&#8221; cx=&#8221;21&#8243; cy=&#8221;21&#8243; r=&#8221;15.91549430918954&#8243;<\/p>\n\n\n\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 fill=&#8221;transparent&#8221; stroke=&#8221;lightgray&#8221; stroke-width=&#8221;7&#8243; \/><\/p>\n<\/blockquote>\n\n\n\n<p>The CIRCLE tags above define the center, the radius and that the inside of the donut will be white and the contour thickness will be light gray by default (other colors will be added soon below).<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&lt;apex:repeat var=&#8221;i&#8221; value=&#8221;{!indexList}&#8221;><\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 &lt;circle id=&#8221;segment{!i}&#8221; cx=&#8221;21&#8243; cy=&#8221;21&#8243; r=&#8221;15.91549430918954&#8243;<\/p>\n\n\n\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 fill=&#8221;transparent&#8221; stroke-width=&#8221;7&#8243;<\/p>\n\n\n\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 stroke=&#8221;{!colorList[ i -1 ]}&#8221;<\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  stroke-dasharray=&#8221;{!percentList[ i -1 ]} {! 100 &#8211; percentList[ i -1 ] }&#8221;<\/p>\n\n\n\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 stroke-dashoffset=&#8221;{!offsetList[ i -1 ]}&#8221;><\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 &lt;\/circle><\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 &lt;text class=&#8221;chart-legend&#8221; color=&#8221;white&#8221;<\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 x=&#8221;{!labelXList[ i -1 ]}&#8221; y=&#8221;{!labelYList[ i -1 ]}&#8221; ><\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &lt;tspan>{! IF( $CurrentPage.parameters.displayLabels != &#8216;false&#8217;, labelList[ i -1 ], &#8221; )}&lt;\/tspan><\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &lt;tspan dy=&#8221;1em&#8221;<\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0dx=&#8221;{! IF( $CurrentPage.parameters.displayLabels != &#8216;false&#8217;, &#8216;-2&#8217;, &#8216;1.5&#8217; )}em&#8221; >{! IF( $CurrentPage.parameters.displayValues != &#8216;false&#8217;, valueList[ i -1 ], &#8221; )}&lt;\/tspan><\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 &lt;\/text> <\/p>\n\n\n\n<p>&lt;\/apex:repeat><\/p>\n<\/blockquote>\n\n\n\n<p>The apex:repeat tag above will generate colored circle segments for each of the label-value pairs specified as parameters of the VF page. I&#8217;ve followed the tricks from&nbsp;<a href=\"https:\/\/medium.com\/@heyoka\/scratch-made-svg-donut-pie-charts-in-html5-2c587e935d72\" target=\"_blank\" rel=\"noreferrer noopener\">Mark Caron&#8217;s article<\/a>&nbsp;to implement the positioning of the segments according to the percentage of each value.<\/p>\n\n\n\n<p>Inside the same apex:repeat tag there is a text tag to print the labels near their respective segment (interestingly, there some trigonometry in the page controller for that).<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&lt;apex:repeat var=&#8221;i&#8221; value=&#8221;{!indexList}&#8221;><\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 \u00a0 &lt;g class=&#8221;chart-text chart-legend chart-legend-box&#8221; ><\/p>\n\n\n\n<p> \u00a0 \u00a0         &lt;rect x=&#8221;44&#8243; y=&#8221;{! i * 3 }&#8221; width=&#8221;2&#8243; height=&#8221;2&#8243;<\/p>\n\n\n\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  \u00a0 \u00a0\u00a0 \u00a0 \u00a0 stroke=&#8221;black&#8221; stroke-width=&#8221;0.125&#8243;<\/p>\n\n\n\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0  \u00a0 \u00a0\u00a0 \u00a0 \u00a0 fill=&#8221;{!colorList[ i -1 ]}&#8221; \/><\/p>\n\n\n\n<p> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0&lt;text x=&#8221;46.5&#8243; y=&#8221;{! 1.5 + i * 3 }&#8221; >{!labelList[ i -1 ]}&lt;\/text> \u00a0 \u00a0 \u00a0 \u00a0 <\/p>\n\n\n\n<p>        &lt;\/g> <\/p>\n\n\n\n<p>&lt;\/apex:repeat><\/p>\n\n\n\n<p><\/p>\n<\/blockquote>\n\n\n\n<p>This second apex:repeat tag above will cycle through the labels and create colored rectangles to display a legend.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&lt;g class=&#8221;chart-main-text&#8221;><\/p>\n\n\n\n<p> \u00a0 \u00a0 &lt;text x=&#8221;21&#8243; y=&#8221;21&#8243; class=&#8221;chart-main-number&#8221;><\/p>\n\n\n\n<p> \u00a0 \u00a0  \u00a0 \u00a0 {! $CurrentPage.parameters.number }<\/p>\n\n\n\n<p> \u00a0 \u00a0 &lt;\/text><\/p>\n\n\n\n<p> \u00a0 \u00a0 &lt;text x=&#8221;21&#8243; y=&#8221;23&#8243; class=&#8221;chart-main-label&#8221;><\/p>\n\n\n\n<p> \u00a0 \u00a0  \u00a0 \u00a0 {! $CurrentPage.parameters.label }<\/p>\n\n\n\n<p> \u00a0 \u00a0 &lt;\/text><\/p>\n\n\n\n<p>&lt;\/g><\/p>\n<\/blockquote>\n\n\n\n<p>This last tag above is grouping the text to display at the center of the donut chart.<\/p>\n\n\n\n<p>The corresponding Apex controller, briefly described:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>receives the VF page parameters and determines the colors to use for each label<\/li>\n\n\n\n<li>calculates the percentages for each label according to the values it received<\/li>\n\n\n\n<li>calculates the position of each segment and the position of the labels around the donut<\/li>\n<\/ul>\n\n\n\n<p>The rest of the code is in my GitHub repository.<\/p>\n\n\n\n<p>Check it out:&nbsp;<a href=\"https:\/\/github.com\/fmendes\/VisualForceDonutChart\/tree\/master\" target=\"_blank\" rel=\"noreferrer noopener\">VisualForceDonutChart<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>VisualForce is used to generate HTML pages but it can also create other kinds of presentation. One common alternative is to render VisualForce as PDF. This article proposes a third type of presentation that can be generated via VisualForce: images. Scalable Vector Graphics is a graphics format that uses a markup language to describe the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-595","post","type-post","status-publish","format-standard","hentry","category-blog"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/posts\/595","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/comments?post=595"}],"version-history":[{"count":1,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/posts\/595\/revisions"}],"predecessor-version":[{"id":600,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/posts\/595\/revisions\/600"}],"wp:attachment":[{"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/media?parent=595"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/categories?post=595"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/tags?post=595"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}