@nativescript-community/ui-chart
Version:
A powerful chart / graph plugin, supporting line, bar, pie, radar, bubble, and candlestick charts as well as scaling, panning and animations.
204 lines • 9.98 kB
JavaScript
import { Color } from '@nativescript/core';
import { Utils } from '../utils/Utils';
import { BarLineScatterCandleBubbleRenderer } from './BarLineScatterCandleBubbleRenderer';
/**
* Bubble chart implementation: Copyright 2015 Pierre-Marc Airoldi Licensed
* under Apache License 2.0 Ported by Daniel Cohen Gindi
*/
export class BubbleChartRenderer extends BarLineScatterCandleBubbleRenderer {
constructor(chart, animator, viewPortHandler) {
super(animator, viewPortHandler);
this.mChart = chart;
}
get highlightPaint() {
if (!this.mHighlightPaint) {
this.mHighlightPaint = Utils.getTemplatePaint('black-stroke');
// set alpha after color
this.mHighlightPaint.setAlpha(120);
this.mHighlightPaint.setStrokeWidth(1.5);
}
return this.mHighlightPaint;
}
drawData(c) {
const bubbleData = this.mChart.bubbleData;
for (const set of bubbleData.dataSets) {
if (set.visible) {
this.drawDataSet(c, set);
}
}
}
getShapeSize(entrySize, maxSize, reference, normalizeSize) {
const factor = normalizeSize ? (maxSize === 0 ? 1 : Math.sqrt(entrySize / maxSize)) : entrySize;
const shapeSize = reference * factor;
return shapeSize;
}
drawDataSet(c, dataSet) {
if (dataSet.entryCount < 1)
return;
const yKey = dataSet.yProperty;
const trans = this.mChart.getTransformer(dataSet.axisDependency);
const phaseY = this.animator.phaseY;
this.mXBounds.set(this.mChart, dataSet, this.animator);
const sizeBuffer = Utils.getTempArray(4);
sizeBuffer[0] = 0;
sizeBuffer[1] = 0;
sizeBuffer[2] = 1;
sizeBuffer[3] = 0;
trans.pointValuesToPixel(sizeBuffer);
const normalizeSize = dataSet.normalizeSizeEnabled;
// calcualte the full width of 1 step on the x-axis
const maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]);
const maxBubbleHeight = Math.abs(this.mViewPortHandler.contentBottom - this.mViewPortHandler.contentTop);
const referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth);
const maxSize = dataSet.maxSize;
const customRender = this.mChart.customRenderer;
const renderPaint = this.renderPaint;
const previousShader = renderPaint.getShader();
const shader = dataSet.fillShader;
if (shader) {
renderPaint.setShader(shader);
}
const pointBuffer = Utils.getTempArray(2);
for (let j = this.mXBounds.min; j <= this.mXBounds.range + this.mXBounds.min; j++) {
const entry = dataSet.getEntryForIndex(j);
const xValue = dataSet.getEntryXValue(entry, j);
pointBuffer[0] = xValue;
pointBuffer[1] = entry[yKey] * phaseY;
trans.pointValuesToPixel(pointBuffer);
const shapeHalf = this.getShapeSize(entry[dataSet.sizeProperty], maxSize, referenceSize, normalizeSize) / 2;
if (!this.mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) || !this.mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf))
continue;
if (!this.mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf))
continue;
if (!this.mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf))
break;
const color = dataSet.getColor(xValue);
renderPaint.setColor(color);
if (customRender && customRender.drawBubble) {
customRender.drawBubble(c, entry, pointBuffer[0], pointBuffer[1], shapeHalf, renderPaint);
}
else {
c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, renderPaint);
}
}
renderPaint.setShader(previousShader);
}
drawValues(c) {
const chart = this.mChart;
const data = chart.bubbleData;
const dataSets = data.dataSets;
if (!this.isDrawingValuesAllowed(chart) || dataSets.some((d) => d.drawValuesEnabled || d.drawIconsEnabled) === false) {
return;
}
// if values are drawn
const paint = this.valuePaint;
const lineHeight = Utils.calcTextHeight(paint, '1');
const customRender = chart.customRenderer;
for (let i = 0; i < dataSets.length; i++) {
const dataSet = dataSets[i];
if (!this.shouldDrawValues(dataSet) || dataSet.entryCount < 1)
continue;
// apply the text-styling defined by the DataSet
this.applyValueTextStyle(dataSet);
const phaseX = Math.max(0, Math.min(1, this.animator.phaseX));
const phaseY = this.animator.phaseY;
this.mXBounds.set(chart, dataSet, this.animator);
const { points, count } = chart.getTransformer(dataSet.axisDependency).generateTransformedValuesBubble(dataSet, phaseY, this.mXBounds.min, this.mXBounds.max);
const alpha = phaseX === 1 ? phaseY : phaseX;
const formatter = dataSet.valueFormatter;
const iconsOffset = dataSet.iconsOffset;
const valuesOffset = dataSet.valuesOffset;
const isDrawValuesEnabled = dataSet.drawValuesEnabled;
const isDrawIconsEnabled = dataSet.drawIconsEnabled;
for (let j = 0; j < count; j += 2) {
let valueTextColor = dataSet.getValueTextColor(j / 2 + this.mXBounds.min);
if (!(valueTextColor instanceof Color)) {
valueTextColor = new Color(valueTextColor);
}
if (alpha !== 1) {
valueTextColor = new Color(Math.round(255 * alpha), valueTextColor.r, valueTextColor.g, valueTextColor.b);
}
const x = points[j];
const y = points[j + 1];
if (!this.mViewPortHandler.isInBoundsRight(x))
break;
if (!this.mViewPortHandler.isInBoundsLeft(x) || !this.mViewPortHandler.isInBoundsY(y))
continue;
const index = j / 2 + this.mXBounds.min;
const entry = dataSet.getEntryForIndex(index);
if (isDrawValuesEnabled) {
this.drawValue(c, chart, dataSet, i, entry, index, (formatter.getBubbleLabel || formatter.getFormattedValue).call(formatter, entry[dataSet.sizeProperty], entry), x + valuesOffset.x, y + valuesOffset.y + 0.5 * lineHeight, valueTextColor, paint, customRender);
}
if (isDrawIconsEnabled) {
this.drawIcon(c, chart, dataSet, i, entry, index, dataSet.getEntryIcon(entry), x + iconsOffset.x, y + iconsOffset.y, customRender);
}
}
}
}
drawExtras(c) { }
drawHighlighted(c, indices) {
const bubbleData = this.mChart.bubbleData;
const phaseY = this.animator.phaseY;
let entry, index;
const customRender = this.mChart.customRenderer;
const pointBuffer = Utils.getTempArray(2);
const sizeBuffer = Utils.getTempArray(4);
for (const high of indices) {
const set = bubbleData.getDataSetByIndex(high.dataSetIndex);
const yKey = set.yProperty;
if (!set || !set.highlightEnabled) {
continue;
}
if (high.entry) {
entry = high.entry;
index = high.entryIndex;
}
else {
const r = set.getEntryAndIndexForXValue(high.x, high.y);
entry = r.entry;
index = r.index;
}
if (entry[yKey] !== high.y)
continue;
if (!this.isInBoundsX(entry, set))
continue;
const trans = this.mChart.getTransformer(set.axisDependency);
sizeBuffer[0] = 0;
sizeBuffer[1] = 0;
sizeBuffer[2] = 1;
sizeBuffer[3] = 0;
trans.pointValuesToPixel(sizeBuffer);
const normalizeSize = set.normalizeSizeEnabled;
// calcualte the full width of 1 step on the x-axis
const maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]);
const maxBubbleHeight = Math.abs(this.mViewPortHandler.contentBottom - this.mViewPortHandler.contentTop);
const referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth);
pointBuffer[0] = set.getEntryXValue(entry, index);
pointBuffer[1] = entry[yKey] * phaseY;
trans.pointValuesToPixel(pointBuffer);
high.drawX = pointBuffer[0];
high.drawY = pointBuffer[1];
const shapeHalf = this.getShapeSize(entry[set.sizeProperty], set.maxSize, referenceSize, normalizeSize) / 2;
if (!this.mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) || !this.mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf))
continue;
if (!this.mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf))
continue;
if (!this.mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf))
break;
let originalColor = set.getColor(set.getEntryXValue(entry, index));
if (!(originalColor instanceof Color)) {
originalColor = new Color(originalColor);
}
const paint = this.highlightPaint;
paint.setColor(set.highlightColor);
paint.setStrokeWidth(set.highlightCircleWidth);
if (customRender && customRender.drawHighlight) {
customRender.drawHighlight(c, high, pointBuffer[0], pointBuffer[1], shapeHalf, paint);
}
else {
c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, paint);
}
}
}
}
//# sourceMappingURL=BubbleChartRenderer.js.map