understanding_rl_vision/rl_clarity/svelte/chart.svelte (152 lines of code) (raw):

<script> export let values = null; export let colors = null; export let extra_values = null; export let disable_extra = false; export let state; export let height; export let width; export let bar_width_frac = 1; export let quantile_to_overflow = 0.9; export let max_overflow = 5; export let ticks_width_frac = 0.05; export let ticks_count = 5; export let ticks_overlapped = false; const get_reduced_values_asc = function(values, extra_values, reduce) { if (values === null) { return null; } else { let reduced_values = values.map(arr => reduce.apply(null, arr)); if (extra_values !== null) { reduced_values = reduced_values.map((value, i) => reduce(value, extra_values[i])); } reduced_values.sort((a, b) => a - b); return reduced_values; } }; $: max_values_asc = get_reduced_values_asc(values, extra_values, Math.max); $: min_values_asc = get_reduced_values_asc(values, extra_values, Math.min); const quantile = function(arr_asc, q) { let pos = (arr_asc.length - 1) * q; let base = Math.floor(pos); let rest = pos - base; if (typeof(arr_asc[base + 1]) === "undefined") { return arr_asc[base]; } else { return arr_asc[base] + rest * (arr_asc[base + 1] - arr_asc[base]); } }; $: upper_value = (function() { if (values === null) { return null; } else { return Math.max( 0, quantile(max_values_asc, quantile_to_overflow), Math.max.apply(null, max_values_asc) / max_overflow); } })(); $: lower_value = (function () { if (values === null) { return null; } else { return Math.min( 0, quantile(min_values_asc, 1 - quantile_to_overflow), Math.min.apply(null, min_values_asc) / max_overflow); } })(); $: [values_to_display, colors_to_display, outlines_to_display] = (function() { if (values === null || upper_value === lower_value) { return [null, null, null]; } else { let values_to_display = values[state.position].slice(); let colors_to_display = colors.slice(); let outlines_to_display = colors.map(() => "none"); if (extra_values !== null) { values_to_display.push(extra_values[state.position]); colors_to_display.push("white"); outlines_to_display.push("1px " + (disable_extra ? "dashed" : "solid") + " gray"); } return [values_to_display, colors_to_display, outlines_to_display]; } })(); </script> {#if values_to_display !== null} <div style="position: relative; height: {height}; width: {width}; padding: 0px 1px;"> <div style="position: absolute; top: 0%; left: 0%; height: 100%; width: {ticks_width_frac * 100}%;" > <div class="center-text" style="position: absolute; z-index: 2; top: {((upper_value / (upper_value - lower_value)) - 0.5) * 100}%; left: 0%; height: 100%; width: 50%;" >0</div> {#each Array.from(Array(ticks_count).keys()) as tick_number} <div style="position: absolute; z-index: 3; top: {(((upper_value / (upper_value - lower_value)) + (tick_number / ticks_count)) % 1) * 100}%; left: 75%; height: 1px; width: 25%; background-color: gray;" ></div> {/each} <div style="position: absolute; z-index: 3; top: 0%; left: 100%; height: 100%; width: 1px; background-color: gray;" ></div> </div> <div style="position: absolute; top: 0%; left: {(ticks_overlapped ? 0 : ticks_width_frac) * 100}%; height: 100%; width: {(ticks_overlapped ? 1 : (1 - ticks_width_frac)) * 100}%;" > {#each values_to_display as value, index} <div style="position: absolute; z-index: 2; top: {((upper_value - Math.max(value, 0)) / (upper_value - lower_value)) * 100}%; left: {((index + (1 - bar_width_frac) / 2) / values_to_display.length) * 100}%; height: {(Math.abs(value) / (upper_value - lower_value)) * 100}%; width: {(bar_width_frac / values_to_display.length) * 100}%; background-color: {colors_to_display[index]}; outline: {outlines_to_display[index]}; outline-offset: -1px;" ></div> {/each} <div style="position: absolute; z-index: 3; top: {(upper_value / (upper_value - lower_value)) * 100}%; left: {(ticks_overlapped ? ticks_width_frac : 0) * 100}%; height: 1px; width: {(ticks_overlapped ? (1 - ticks_width_frac) : 1) * 100}%; background-color: gray;" ></div> {#each Array.from(Array(ticks_count).keys()) as tick_number} {#if tick_number !== 0} <div style="position: absolute; z-index: 1; top: {(((upper_value / (upper_value - lower_value)) + (tick_number / ticks_count)) % 1) * 100}%; left: {(ticks_overlapped ? ticks_width_frac : 0) * 100}%; height: 1px; width: {(ticks_overlapped ? (1 - ticks_width_frac) : 1) * 100}%; background-color: lightgray;" ></div> {/if} {/each} </div> </div> {/if}