Better way to draw trend across multiple vertical slider

I am trying to work out a way to visualize a look up table.

like the screenshot below, I have a couple of sliders, but I want to link the dots as a chart.
image

Currently I can achieve it by having a XY chart at the back of the sliders, so when the slides are changing, I am updating the XY chart to suit.

But is there any better way that I can just draw the chart dynamically on the view? like using CSS? I am still quick new to CSS.

How about this?

coordSliderView

The green line is generated using a label with a border width of 1 and height of 2. The main CSS trick is the transform : skewY().

{
  "borderStyle": "solid",
  "borderWidth": 1
  "borderColor": "#00aa00",
  "transform": "skewY(0.0deg)"     <-- See the binding.
}
  • I'm using a coordinate view just to make the (x, y) coordinates easy to work with.
  • I have custom properties on each slider keeping track of the slider knob x and y positions.
  • The skew is calculated using atan(dy/dx) * 180 / 3.1416 to return degrees.
  • My animation was recorded on my development machine so it should be best case regarding lagginess of the line component. It may look atrociously bad with a slow connection.

Try pasting the view into Project Browser | Perspective | Views.

coordSliderView
{
  "custom": {},
  "params": {},
  "props": {
    "defaultSize": {
      "height": 328,
      "width": 412
    }
  },
  "root": {
    "children": [
      {
        "meta": {
          "name": "lblLine01"
        },
        "position": {
          "height": 2
        },
        "propConfig": {
          "custom.skew": {
            "binding": {
              "config": {
                "expression": "atan(\r\n    ({../Slider1.custom.knobY} - {../Slider0.custom.knobY})\r\n  / ({../Slider1.custom.knobX} - {../Slider0.custom.knobX})\r\n)"
              },
              "type": "expr"
            }
          },
          "position.width": {
            "binding": {
              "config": {
                "expression": "{../Slider1.custom.knobX} - {../Slider0.custom.knobX}"
              },
              "type": "expr"
            }
          },
          "position.x": {
            "binding": {
              "config": {
                "path": "../Slider0.custom.knobX"
              },
              "type": "property"
            }
          },
          "position.y": {
            "binding": {
              "config": {
                "expression": "({../Slider0.custom.knobY} + {../Slider1.custom.knobY}) / 2\r\n"
              },
              "type": "expr"
            }
          },
          "props.style.transform": {
            "binding": {
              "config": {
                "expression": "\"skewY(\" + {this.custom.skew} * 180 / 3.1416 + \"deg)\""
              },
              "type": "expr"
            }
          }
        },
        "props": {
          "style": {
            "borderColor": "#00aa00",
            "borderStyle": "solid",
            "borderWidth": 1
          }
        },
        "type": "ia.display.label"
      },
      {
        "meta": {
          "name": "Slider0"
        },
        "position": {
          "height": 200,
          "width": 20,
          "x": 80,
          "y": 40
        },
        "propConfig": {
          "custom.knobX": {
            "binding": {
              "config": {
                "expression": "{this.position.x} + {this.position.width} / 2"
              },
              "type": "expr"
            }
          },
          "custom.knobY": {
            "binding": {
              "config": {
                "expression": "{this.position.y} + {this.position.height} \r\n- ({this.props.value} - {this.props.min})\r\n/ ({this.props.max} - {this.props.min})\r\n* {this.position.height}"
              },
              "type": "expr"
            }
          }
        },
        "props": {
          "orientation": "vertical",
          "value": 54
        },
        "type": "ia.input.slider"
      },
      {
        "meta": {
          "name": "Slider1"
        },
        "position": {
          "height": 200,
          "width": 20,
          "x": 280,
          "y": 40
        },
        "propConfig": {
          "custom.knobX": {
            "binding": {
              "config": {
                "expression": "{this.position.x} + {this.position.width} / 2"
              },
              "type": "expr"
            }
          },
          "custom.knobY": {
            "binding": {
              "config": {
                "expression": "{this.position.y} + {this.position.height} \r\n- ({this.props.value} - {this.props.min})\r\n/ ({this.props.max} - {this.props.min})\r\n* {this.position.height}"
              },
              "type": "expr"
            }
          }
        },
        "props": {
          "orientation": "vertical",
          "value": 79
        },
        "type": "ia.input.slider"
      },
      {
        "meta": {
          "name": "Label"
        },
        "position": {
          "height": 32,
          "rotate": {
            "anchor": "38% 50%"
          },
          "width": 50,
          "x": 65,
          "y": 249
        },
        "propConfig": {
          "props.text": {
            "binding": {
              "config": {
                "path": "../Slider0.props.value"
              },
              "type": "property"
            }
          }
        },
        "props": {
          "textStyle": {
            "textAlign": "center"
          }
        },
        "type": "ia.display.label"
      },
      {
        "meta": {
          "name": "Label_0"
        },
        "position": {
          "height": 32,
          "rotate": {
            "anchor": "38% 50%"
          },
          "width": 50,
          "x": 265,
          "y": 249
        },
        "propConfig": {
          "props.text": {
            "binding": {
              "config": {
                "path": "../Slider1.props.value"
              },
              "type": "property"
            }
          }
        },
        "props": {
          "textStyle": {
            "textAlign": "center"
          }
        },
        "type": "ia.display.label"
      }
    ],
    "meta": {
      "name": "root"
    },
    "type": "ia.container.coord"
  }
}
3 Likes

java_KySnpUPWVe

linearInterpolation.zip (9.3 KB)

Another way to skin this cat; programmatically build an SVG behind the sliders. By using a flex repeater to display the sliders, you can force everything to stay lined up.

The screen capture was recorded over a VPN with a ~30Mbps 200ms ping connection, but your mileage may vary.

3 Likes

Thank you both.

Excellent solutions.

1 Like