From 69456d0f2e20bd83a56638836a45f8ca04cd6d71 Mon Sep 17 00:00:00 2001 From: vargburz Date: Wed, 13 Jan 2021 21:41:14 +0300 Subject: [PATCH] ui update --- src/index.ts | 107 ++++++++++++++++++++++++++++++--------------------- src/utils.ts | 29 ++++++++++++++ 2 files changed, 93 insertions(+), 43 deletions(-) create mode 100644 src/utils.ts diff --git a/src/index.ts b/src/index.ts index f02e35d..2d9cc3f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,10 +2,18 @@ import { GaugeTimeSerie, GaugeOptions, Stat, Stop } from './types'; import { ChartwerkPod, VueChartwerkPodMixin, ZoomType } from '@chartwerk/core'; +import { findClosest } from './utils'; + import * as d3 from 'd3'; import * as _ from 'lodash'; +const SPACE_BETWEEN_CIRCLES = 2; +const CIRCLES_ROUNDING = 0.15; //radians +const BACKGROUND_COLOR = '#262626'; +const DEFAULT_INNER_RADIUS = 48; +const DEFAULT_OUTER_RADIUS = 72; +const DEFAULT_STOPS_CIRCLE_WIDTH = 4; const DEFAULT_GAUGE_OPTIONS: GaugeOptions = { usePanning: false, @@ -29,8 +37,8 @@ const DEFAULT_GAUGE_OPTIONS: GaugeOptions = { ], defaultColor: 'red', stat: Stat.CURRENT, - innerRadius: 48, - outerRadius: 72 + innerRadius: DEFAULT_INNER_RADIUS, + outerRadius: DEFAULT_OUTER_RADIUS }; export class ChartwerkGaugePod extends ChartwerkPod { @@ -49,70 +57,75 @@ export class ChartwerkGaugePod extends ChartwerkPod { - return 'orange'; - }) - .attr('d', arc as any) - .attr('transform', this._gaugeTransform) - + const valueArcs = pie(this._valueRange); this.chartContainer.selectAll(null) - .data(arcs) + .data(valueArcs) .enter() .append('path') .style('fill', (d: object, i: number) => { - return this._colors[i]; + return this._valueArcColors[i]; }) - .attr('d', arc2 as any) - .attr('transform', this._gaugeTransform) + .attr('d', arc as any) + .attr('transform', this._gaugeTransform); + + if(this._sortedStops.length > 0) { + const stopArcs = pie(this._stopsRange); + this.chartContainer.selectAll(null) + .data(stopArcs) + .enter() + .append('path') + .style('fill', (d: object, i: number) => { + return this._colors[i]; + }) + .attr('d', thresholdArc as any) + .attr('transform', this._gaugeTransform); + } + } - const needle = this.chartContainer.selectAll('.needle') - .data([0]) - .enter() - .append('line') - .attr('x1', 0) - .attr('x2', -80) - .attr('y1', 0) - .attr('y2', 0) - .classed('needle', true) - .style('stroke', 'black') - .attr('transform', (d: number) => { - return this._gaugeTransform + 'rotate(' + d + ')' - }); + private get _valueArcColors(): [string, string] { + return [this._mainCircleColor, BACKGROUND_COLOR]; + } - this._renderNeedle(); + private get _mainCircleColor(): string { + if(this.aggregatedValue > _.max(this._stopsValues) || this.aggregatedValue < 0 || this._sortedStops.length === 0) { + // TODO: aggregatedValue can be less than 0 + return this.options.defaultColor; + } + // TODO: refactor + const closestIdx = findClosest(this._stopsValues, this.aggregatedValue); + const closestStop = this._sortedStops[closestIdx]; + if(this.aggregatedValue > closestStop.value) { + return this._sortedStops[closestIdx + 1].color; + } else { + return closestStop.color; + } } // TODO: better name - private get _valueRange(): number[] { + private get _stopsRange(): number[] { // TODO: refactor // TODO: max value might be less than the latest stop - console.log('_sortedStops', this._sortedStops); - const stopValues = [...this._sortedStops.map(stop => stop.value), this.options.maxValue || this.maxValue]; + const stopValues = [...this._stopsValues, this._maxValue]; if(stopValues.length < 2) { return stopValues; @@ -124,10 +137,18 @@ export class ChartwerkGaugePod extends ChartwerkPod stop.value); + } + private get _colors(): string[] { // TODO: refactor return [...this._sortedStops.map(stop => stop.color), this.options.defaultColor]; diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..b6a6fe9 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,29 @@ +/** + * Finds the closest item to a given number in an array using binary search + * @argument arr: ascending sorted array + * @argument num: number to find + * @returns index of the closest item to `num` + * @returns -1 if given array is empty + */ +export function findClosest(arr: number[], num: number): number { + if(arr.length === 0) { + return -1; + } + + let lowIdx = 0; + let highIdx = arr.length - 1; + + while(highIdx - lowIdx > 1) { + const midIdx = Math.floor((lowIdx + highIdx) / 2); + if(arr[midIdx] < num) { + lowIdx = midIdx; + } else { + highIdx = midIdx; + } + } + + if(num - arr[lowIdx] <= arr[highIdx] - num) { + return lowIdx; + } + return highIdx; +}