tixy-ish

Inspired by tixy.land; in development; open to contributions!

ƒ

calculang ✍️ editable and dangerous! 🧙‍♂️⚠️
javascript ✨ generated from calculang ⬆️
dev tools 🧰

🎨

inputs ⚙️

eval-on-select (select formula text, then activate with F9)

compiled selection (via sourcemap)







appendix & source code of 🎨

showing selected source code of 🎨

For complete source see GitHub.

notesthis is Javascript and using tools and patterns that I repeat, but remember that calculang is unopinionated!
calculang/output is also highly portable and uniform.

visual 1 (main output, with mouse interactivity)

const spec = ({
  // vega-lite
  title: "v",
  mark: {type:'point', point: false, filled: true},
  encoding: {
    x: { field: 'x_in', type: 'quantitative', domain: _.range(0,size_in), scale: {nice:false, domain:[-1,16]} },
    y: { field: 'y_in', type: 'quantitative', domain: _.range(0,size_in), sort:'descending', scale: {nice:false, domain:[-1,16]} },
    size: { field: 'abs_v_clamped', type: 'quantitative', scale: {domain:[0,1]} },
    //color: {value: 'red'}
    color: { field: 'positive', type: 'nominal', scale: {domain:[false, true], range: ['orange','red'] }}, // todo color calcd from model?
    shape: { field: 'positive', type: 'nominal', scale: {domain:[false, true], range: ['diamond','circle'] }} // todo color calcd from model?
  },
  data: { name: "data" },
  datasets: {
    data: [],
  },
  autosize: { "type": "fit", "contains": "padding"},
  width: Math.min(400,rhs_width-30),
  height: 300,
  background:'rgba(0,0,0,0)'
})

// interactivity via vega signals and listeners
const viz = embed('#viz', spec, {patch: [{
  path: "/signals",
  op: "add",
  value: [{
    name: "mousex",
    value: 8,
    on: [
      {"events": "mousemove{30}", "update": (size_in-1)+"*x()/range('x')[1]"}
    ]
  },{
    name: "mousey",
    value: 8,
    on: [
      {"events": "mousemove{30}", "update": (size_in-1)+"*y()/range('y')[1]"}
    ]
  }]
}]})
const data_source = calcuvegadata({
  models: [model],
  spec,
  domains: {
    x_in: _.range(0,size_in),
    y_in: _.range(0,size_in)
  },
  input_cursors: [
    { t_in, mousex_in, mousey_in, random_seed_in }
  ]
})
viz.view.data("data", data_source)/*.resize()*/.run(); // turn off resize
const random_seed_in = 'x' // reactive issues if mixed in mutable updates blocks
const mousex_in = Mutable(8)
const mousey_in = Mutable(8)

viz.view.addSignalListener('mousex', a => {
  console.log('mousex', a)
  mousex_in.value = viz.view.signal('mousex')
})
viz.view.addSignalListener('mousey', a => {
  mousey_in.value = viz.view.signal('mousey')
})

visual 2

const spec2 = ({
  // vega-lite
  title: "selection",
  mark: {type:'text', point: false, filled: true},
  encoding: {
    x: { field: 'x_in', type: 'quantitative', scale: {nice:false, domain:[-1,16]} },
    y: { field: 'y_in', type: 'quantitative', sort:'descending', scale: {nice:false, domain:[-1,16]} },
    text: { field: 'selection_fn', format: ('.1f') },
    color: { field: 'selection_fn', type: 'quantitative', legend: false/*, scale: {domain:[0,1] }*/}
  },
  data: { name: "data" },
  datasets: {
    data: [],
  },
  autosize: { "type": "fit", "contains": "padding"},
  width: Math.min(500,rhs_width-30),
  height: 300,
  background:'rgba(0,0,0,0)'
})

const viz2 = embed('#viz2', spec2)
const data_source2 = calcuvegadata({
  models: [{selection_fn: (a) => selection_fn(model,a)}],
  spec: spec2,
  domains: {
    x_in: _.range(0,size_in),
    y_in: _.range(0,size_in)
  },
  input_cursors: [
    { t_in, mousex_in, mousey_in, random_seed_in }
  ]
})
viz2.view.data("data", data_source2)/*.resize()*/.run(); // turn off resize

const size_in = 16

const t_in_Input = Inputs.input(0);
const t_in = Generators.input(t_in_Input);

const rhs_width = Generators.width(document.querySelector(".rhs")); // keep as a generator for reactivity

eval-on-select

// all inputs must be maintianed here to pass to selection function

const ins = ({x_in: 8, y_in:8, t_in, random_seed_in, mousex_in, mousey_in})

todo maintain eval selection range with edits? Alt.: don't react to edits by freezing into Mutable, but this is poor. and multi-selection (concatenating useful imo)