Skip to content

Compound.Jitter

Creates a Jitter Plot compound SVG Visual showing values as points with x-position based on value and y-position jittered around center

DaxLib.SVG.Compound.Jitter( x, y, width, height, paddingX, paddingY, axisRef, measureRef, pointColor, jitterAmount )
Parameter Type Required Description
x INT64 The x position of the compound
y INT64 The y position of the compound
width INT64 The width of the compound
height INT64 The height of the compound
paddingX DECIMAL Optional: The horizontal padding percentage (0.0-1.0, e.g., 0.1 = 10% padding). Defaults to 0
paddingY DECIMAL Optional: The vertical padding percentage (0.0-1.0, e.g., 0.1 = 10% padding). Defaults to 0
axisRef ANYREF EXPR The column that the measure will be evaluated against
measureRef NUMERIC EXPR The measure to evaluate
pointColor STRING Optional: The hex color of the points (e.g., "#01B8AA")
jitterAmount DECIMAL Optional: The amount of jitter as a percentage of height (0.0-1.0). Defaults to 0.3

STRING SVG Jitter Plot

DaxLib.SVG.SVG(
    500,
    100,
    BLANK(),
    DaxLib.SVG.Compound.Jitter(
        0,                  // x
        0,                  // y
        500,                // width
        100,                // height
        0.05,               // paddingX
        0.02,               // paddingY
        Dates[Date],        // axisRef
        [Total Cost],       // measureRef
        "#EC008C",          // pointColor
        0.5                 // jitterAmount
    ),
    BLANK()
)
function 'DaxLib.SVG.Compound.Jitter' =
        (
            x: INT64,
            y: INT64,
            width: INT64,
            height: INT64,
            paddingX: DOUBLE,
            paddingY: DOUBLE,
            axisRef: ANYREF EXPR,
            measureRef: NUMERIC EXPR,
            pointColor: STRING,
            jitterAmount: DOUBLE
        ) =>

            // Apply padding to dimensions
            VAR _X =            x + (width * (IF(ISBLANK(paddingX), 0, paddingX) / 2))
            VAR _Y =            y + (height * (IF(ISBLANK(paddingY), 0, paddingY) / 2))
            VAR _Width =        width * (1 - IF(ISBLANK(paddingX), 0, paddingX))
            VAR _Height =       height * (1 - IF(ISBLANK(paddingY), 0, paddingY))

            // Check if Axis is numeric
            VAR axisSample =    MAX( axisRef )
            VAR axisIsNumeric = ISNUMERIC( axisSample ) || ISDATETIME( axisSample )

            // For totals
            VAR _Data = 
                ADDCOLUMNS(
                    FILTER(
                        VALUES( axisRef ),
                        NOT ISBLANK( measureRef )
                    ),
                    "@AxisIndex",   
                        IF(
                            axisIsNumeric,
                            axisRef,
                            RANK( DENSE, CALCULATETABLE( VALUES( axisRef ), ALLSELECTED() ) )
                        ),
                    "@Value", measureRef
                )

            VAR _RawXMin =  MINX( _Data, [@Value] )
            VAR _XMin =     IF( _RawXMin > 0, 0, _RawXMin )
            VAR _XMax =     MAXX( _Data, [@Value] )

            // Points
            VAR _CenterY =      _Y + _Height * 0.5
            VAR _JitterRange =  _Height * IF( ISBLANK( jitterAmount ), 0.3, jitterAmount )
            VAR _CircleElements = 
                CONCATENATEX(
                    _Data,
                    IF( 
                        NOT ISBLANK( [@Value] ),
                        VAR _Seed =         ABS( [@Value] * 12345 ) + ABS( [@AxisIndex] * 67890 ) + ABS( LEN( FORMAT( [@Value], "0.000000" ) ) * 9876 )
                        VAR _PseudoRandom = MOD( _Seed, 10000 ) / 10000
                        VAR _JitterOffset = ( _PseudoRandom - 0.5 ) * _JitterRange
                        VAR _CX = DaxLib.SVG.Scale.Normalize( [@Value], _XMin, _XMax, _X, _X + _Width )
                        VAR _CY = _CenterY + _JitterOffset
                        VAR _ClampedCX = MAX( _X, MIN( _X + _Width, _CX ) )
                        VAR _ClampedCY = MAX( _Y, MIN( _Y + _Height, _CY ) )
                        RETURN
                            DaxLib.SVG.Element.Circle(
                                _ClampedCX, // cx
                                _ClampedCY,          // cy
                                2,                  // r
                                DaxLib.SVG.Attr.Shapes(
                                    pointColor,     // fill
                                    0.5,            // fillOpacity
                                    BLANK(),        // fillRule
                                    pointColor,     // stroke
                                    1,              // strokeWidth
                                    0.9,            // strokeOpacity
                                    BLANK()         // opacity
                                ),
                                BLANK()             // transforms
                            )
                    ),
                    " ",
                    [@AxisIndex],
                    ASC
                )

            RETURN

                IF( NOT ISEMPTY( _Data ), _CircleElements )