Skip to content

Instantly share code, notes, and snippets.

@tirnovar
Last active August 18, 2023 13:38
Show Gist options
  • Select an option

  • Save tirnovar/30a502c01235f0e6fd1a676e215393f9 to your computer and use it in GitHub Desktop.

Select an option

Save tirnovar/30a502c01235f0e6fd1a676e215393f9 to your computer and use it in GitHub Desktop.
Hills and Falls - DAX SVG Generator
/* SETUP */
VAR _initTbl =
ADDCOLUMNS(
SELECTCOLUMNS(
SUMMARIZE( <TABLE>, <X-AXIS-COLUMN> ),
"@yAxisCategory", <X-AXIS-COLUMN>
),
"@firstLine", <MEASURE-1>,
"@secondLine", <MEASURE-2>
)
VAR _squareCanvasSize = 400
VAR _paddingSpace = 15
//SERIES LABELS
VAR _firstLineText = "Exports"
VAR _secondLineText = "Imports"
/* COLORS DECLARTIONS */
VAR _firstLineColor = "#12239E"
VAR _secondLineColor = "#118DFF"
VAR _green = "#7EC8B8"
VAR _red = "#722838"
VAR _grey = "#CCCCCC"
/* SVG DECLARTIONS */
VAR _svgDeclaration = "data:image/svg+xml;utf8,"
VAR _svgHeader =
"<svg xmlns='http://www.w3.org/2000/svg' height='"
& _squareCanvasSize
& "' width='"
& _squareCanvasSize + 50
& "'>"
VAR _svgEnd = "</svg>"
/* CALCULATION */
VAR _tblPrecalculation =
ADDCOLUMNS(
_initTbl,
"@positionChanged",
VAR _rowNumber =
ROWNUMBER( _initTbl, ORDERBY( [@yAxisCategory], ASC ) )
RETURN
IF(
IF( [@firstLine] >= [@secondLine], 1, 0 )
= MINX(
OFFSET( -1, _initTbl ),
IF( [@firstLine] >= [@secondLine], 1, 0 )
)
|| _rowNumber = 1,
BLANK( ),
1
),
"@clrSetter", IF( [@firstLine] >= [@secondLine], 1, 0 ),
"@rowNum",
ROWNUMBER( _initTbl, ORDERBY( [@yAxisCategory], ASC ) )
)
VAR _precountOfSegments =
COUNTAX( _tblPrecalculation, [@positionChanged] ) + 1
VAR _generateSpaceForSegments =
GENERATESERIES( 1, _precountOfSegments, 1 )
VAR _usableCanvasSpace = _squareCanvasSize - ( _paddingSpace * 2 )
VAR _usableCanvasPoints = _usableCanvasSpace / 100
VAR _rowsCounter = COUNTROWS( _tblPrecalculation )
VAR _paddingSpaceBetweenPoitns =
_usableCanvasSpace / _rowsCounter
VAR _highestValueOfMeasures =
MAXX(
_tblPrecalculation,
MAX( [@firstLine], [@secondLine] )
)
* 1.05
VAR _lowestValueOfMeasures =
MINX(
_tblPrecalculation,
MIN( [@firstLine], [@secondLine] )
)
* 0.95
VAR _differenceBetweenPositions =
_highestValueOfMeasures - _lowestValueOfMeasures
VAR _percentModificator = 100 / _highestValueOfMeasures
VAR _tblCoordinatesPreCalculation =
ADDCOLUMNS(
_tblPrecalculation,
"@xCoordinates",
VAR _perc =
( [@firstLine] * _percentModificator ) * _usableCanvasPoints
RETURN
_paddingSpace + [@rowNum] * _paddingSpaceBetweenPoitns
- _paddingSpaceBetweenPoitns * ( 1 / 2 ),
"@yCoordinatesForFirstLine",
( 1
- DIVIDE(
[@firstLine] - _lowestValueOfMeasures,
_differenceBetweenPositions
) )
* _usableCanvasSpace,
"@yCoordinatesForSecondLine",
( 1
- DIVIDE(
[@secondLine] - _lowestValueOfMeasures,
_differenceBetweenPositions
) )
* _usableCanvasSpace
)
VAR _tblConnectionPoints =
ADDCOLUMNS(
_tblCoordinatesPreCalculation,
"@LinesConnection",
IF(
NOT ISBLANK( [@positionChanged] ),
VAR _offset = OFFSET( -1, _tblCoordinatesPreCalculation )
// X Shared Positions
VAR _x1 = [@xCoordinates]
VAR _xMoved = CALCULATE( MINX( _offset, [@xCoordinates] ) )
// FIRST LINE Y Position
VAR _y1 = [@yCoordinatesForFirstLine]
VAR _y2 =
CALCULATE( MINX( _offset, [@yCoordinatesForFirstLine] ) )
// SECOND LINE Y Position
VAR _y3 = [@yCoordinatesForSecondLine]
VAR _y4 =
CALCULATE( MINX( _offset, [@yCoordinatesForSecondLine] ) )
// NEW POSITIONS
VAR _x =
DIVIDE(
( ( _y2 - _y1 ) * ( _xMoved - _x1 ) * _x1 )
+ ( ( _xMoved - _x1 ) * ( _xMoved - _x1 ) * ( _y3 - _y1 ) )
- ( ( _y4 - _y3 ) * ( _xMoved - _x1 ) * _x1 ),
( ( _y2 - _y1 ) * ( _xMoved - _x1 ) ) - ( ( _xMoved - _x1 ) * ( _y4 - _y3 ) )
)
VAR _y =
DIVIDE(
( _x * ( _y2 - _y1 ) ) + ( _y1 * ( _xMoved - _x1 ) ) - ( _x1 * ( _y2 - _y1 ) ),
_xMoved - _x1
)
RETURN
_x & " " & _y,
BLANK( )
)
)
VAR _line =
"<g stroke-width='3' fill='none'>" & "<path stroke='"
& _firstLineColor
& "' d='"
& CONCATENATEX(
_tblCoordinatesPreCalculation,
IF( [@rowNum] = 1, "M", " L " ) & [@xCoordinates] & " "
& [@yCoordinatesForFirstLine]
)
& "' />"
& "<path stroke='"
& _secondLineColor
& "' d='"
& CONCATENATEX(
_tblCoordinatesPreCalculation,
IF( [@rowNum] = 1, "M", " L " ) & [@xCoordinates] & " "
& [@yCoordinatesForSecondLine]
)
& "' />"
& "</g>"
VAR _segmentsFirstLine =
CONCATENATEX(
_tblConnectionPoints,
" "
& IF(
ISBLANK( [@positionChanged] ),
[@xCoordinates] & " " & [@yCoordinatesForFirstLine],
[@LinesConnection] & " | " & [@LinesConnection] & " L "
& [@xCoordinates]
& " "
& [@yCoordinatesForFirstLine]
),
"",
[@yAxisCategory], ASC
)
VAR _segmentsSecondLine =
CONCATENATEX(
_tblConnectionPoints,
" "
& IF(
ISBLANK( [@positionChanged] ),
" " & [@xCoordinates] & " " & [@yCoordinatesForSecondLine],
" " & [@xCoordinates] & " " & [@yCoordinatesForSecondLine]
& " | "
),
"",
[@yAxisCategory], DESC
)
VAR _segments =
"<g stroke='none'>"
& CONCATENATEX(
_generateSpaceForSegments,
VAR _rowValue =
IF(
[Value] = 1,
SELECTCOLUMNS(
TOPN( 1, _tblConnectionPoints, [@yAxisCategory], ASC ),
"@forInternalPurpose", [@clrSetter]
),
SELECTCOLUMNS(
TOPN(
1,
TOPN(
[Value] - 1,
FILTER(
_tblConnectionPoints,
NOT ISBLANK( [@positionChanged] )
),
[@yAxisCategory], ASC
),
[@yAxisCategory], DESC
),
"@forInternalPurpose", [@clrSetter]
)
)
VAR _colorSelector = IF( _rowValue = 1, _green, _red )
RETURN
"<path fill='" & _colorSelector & "' d='M"
& PATHITEM( _segmentsFirstLine, [Value] )
& " "
& PATHITEM(
_segmentsSecondLine,
_precountOfSegments - ( [Value] - 1 )
)
& "Z"
& "' />",
"",
[Value], ASC
)
& "</g>"
VAR _supportLines =
"<g stroke='" & _grey & "' stroke-dasharray='5 5'>"
& CONCATENATEX(
_tblConnectionPoints,
"<line x1='" & [@xCoordinates] & "' x2='" & [@xCoordinates]
& "' y1='"
& _paddingSpace + 5
& "' y2='"
& _squareCanvasSize - _paddingSpace - 5
& "'/>"
)
& "</g>"
VAR _texts =
VAR _lastIndexedYAxisPoint =
INDEX(
1,
_tblConnectionPoints,
ORDERBY( [@yAxisCategory], DESC )
)
VAR _yPositionsFirstLine =
MAXX( _lastIndexedYAxisPoint, [@yCoordinatesForFirstLine] )
VAR _yPositionsSecondLine =
MAXX( _lastIndexedYAxisPoint, [@yCoordinatesForSecondLine] )
VAR _xPosition =
MAXX( _lastIndexedYAxisPoint, [@xCoordinates] )
RETURN
"<g font-size='80%' font-family='Segoe UI' dominant-baseline='middle'>
<g text-anchor='start' font-weight='bold'>"
& "<text fill='"
& _firstLineColor
& "' x='"
& _xPosition + _paddingSpace - 5
& "' y='"
& _yPositionsFirstLine
& "'>"
& _firstLineText
& "</text>"
& "<text fill='"
& _secondLineColor
& "' x='"
& _xPosition + _paddingSpace - 5
& "' y='"
& _yPositionsSecondLine
& "'>"
& _secondLineText
& "</text>"
& "</g>
<g text-anchor='middle' fill='"
& _grey
& "'>"
& CONCATENATEX(
_tblConnectionPoints,
"<text x='" & [@xCoordinates] & "' y='"
& _squareCanvasSize - _paddingSpace + 5
& "'>"
& [@yAxisCategory]
& "</text>"
)
& "</g>
</g>"
VAR _result =
_svgDeclaration & _svgHeader & _supportLines & _texts
& _segments
& _line
& _svgEnd
RETURN
_result
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment