Sfoglia il codice sorgente

[animate] cycle update, x axis

tags/1.2.0
Prateeksha Singh 7 anni fa
parent
commit
8d3bd38d6d
12 ha cambiato i file con 362 aggiunte e 232 eliminazioni
  1. +178
    -111
      dist/frappe-charts.esm.js
  2. +1
    -1
      dist/frappe-charts.min.cjs.js
  3. +1
    -1
      dist/frappe-charts.min.esm.js
  4. +1
    -1
      dist/frappe-charts.min.iife.js
  5. +1
    -1
      dist/frappe-charts.min.iife.js.map
  6. +1
    -1
      docs/assets/js/frappe-charts.min.js
  7. +1
    -1
      docs/assets/js/frappe-charts.min.js.map
  8. +60
    -32
      src/js/charts/AxisChart.js
  9. +2
    -2
      src/js/charts/BaseChart.js
  10. +34
    -34
      src/js/charts/PercentageChart.js
  11. +48
    -10
      src/js/objects/ChartComponents.js
  12. +34
    -37
      src/js/utils/draw.js

+ 178
- 111
dist/frappe-charts.esm.js Vedi File

@@ -301,7 +301,9 @@ function translate(unit, oldCoord, newCoord, duration) {
];
}


function translateVertLine(xLine, newX, oldX) {
return translate(xLine, [oldX, 0], [newX, 0], MARKER_LINE_ANIM_DUR);
}

function translateHoriLine(yLine, newY, oldY) {
return translate(yLine, [0, oldY], [0, newY], MARKER_LINE_ANIM_DUR);
@@ -551,6 +553,40 @@ function yLine(y, label, width, options={}) {
});
}

function xLine$1(x, label, height, options={}) {
if(!options.pos) options.pos = 'bottom';
if(!options.offset) options.offset = 0;
if(!options.mode) options.mode = 'span';
if(!options.stroke) options.stroke = BASE_LINE_COLOR;
if(!options.className) options.className = '';

// Draw X axis line in span/tick mode with optional label
// y2(span)
// |
// |
// x line |
// |
// |
// ---------------------+-- y2(tick)
// |
// y1

let y1 = height + AXIS_TICK_LENGTH;
let y2 = options.mode === 'span' ? -1 * AXIS_TICK_LENGTH : height;

if(options.mode === 'tick' && options.pos === 'top') {
// top axis ticks
y1 = -1 * AXIS_TICK_LENGTH;
y2 = 0;
}

return makeVertLine(x, label, y1, y2, {
stroke: options.stroke,
className: options.className,
lineType: options.lineType
});
}

class AxisChartRenderer {
constructor(state) {
this.refreshState(state);
@@ -569,43 +605,6 @@ class AxisChartRenderer {
this.zeroLine = zeroLine;
}

xLine(x, label, options={}) {
if(!options.pos) options.pos = 'bottom';
if(!options.offset) options.offset = 0;
if(!options.mode) options.mode = 'span';
if(!options.stroke) options.stroke = BASE_LINE_COLOR;
if(!options.className) options.className = '';

// Draw X axis line in span/tick mode with optional label
// y2(span)
// |
// |
// x line |
// |
// |
// ---------------------+-- y2(tick)
// |
// y1

let y1 = this.totalHeight + AXIS_TICK_LENGTH;
let y2 = options.mode === 'span' ? -1 * AXIS_TICK_LENGTH : this.totalHeight;

if(options.mode === 'tick' && options.pos === 'top') {
// top axis ticks
y1 = -1 * AXIS_TICK_LENGTH;
y2 = 0;
}

return makeVertLine(x, label, y1, y2, {
stroke: options.stroke,
className: options.className,
lineType: options.lineType
});
}




xMarker() {}
yMarker(y, label, options={}) {
let labelSvg = createSVG('text', {
@@ -1074,8 +1073,9 @@ class BaseChart {

this.calcWidth();
this.makeChartArea();
this.setupComponents();
this.initComponents();

this.setupComponents();
this.draw(true);
}

@@ -1160,7 +1160,6 @@ class BaseChart {
render(animate=true) {
this.refreshComponents();
this.elementsToAnimate = [].concat.apply([], this.components.map(c => c.update(animate)));
console.log(this.elementsToAnimate);
if(this.elementsToAnimate) {
runSMILAnimation(this.chartWrapper, this.svg, this.elementsToAnimate);
}
@@ -1282,6 +1281,7 @@ class ChartComponent$1 {
preMake,
makeElements,
postMake,
getData,
animateElements
}) {
this.parent = parent;
@@ -1292,6 +1292,7 @@ class ChartComponent$1 {
this.preMake = preMake;
this.makeElements = makeElements;
this.postMake = postMake;
this.getData = getData;

this.animateElements = animateElements;

@@ -1336,12 +1337,9 @@ class ChartComponent$1 {
}
}

function getYAxisComponent(parent, constants, initData) {
return new ChartComponent$1({
parent: parent,
let componentConfigs = {
yAxis: {
layerClass: 'y axis',
constants: constants,
data: initData,
makeElements: function(data) {
return data.positions.map((position, i) =>
yLine(position, data.labels[i], this.constants.width,
@@ -1352,7 +1350,6 @@ function getYAxisComponent(parent, constants, initData) {
animateElements: function(newData) {
let newPos = newData.positions;
let newLabels = newData.labels;

let oldPos = this.oldData.positions;
let oldLabels = this.oldData.labels;

@@ -1370,7 +1367,49 @@ function getYAxisComponent(parent, constants, initData) {
);
});
}
})
},

xAxis: {
layerClass: 'x axis',
makeElements: function(data) {
return data.positions.map((position, i) =>
xLine$1(position, data.labels[i], this.constants.height,
{mode: this.constants.mode, pos: this.constants.pos})
);
},

animateElements: function(newData) {
let newPos = newData.positions;
let newLabels = newData.labels;
let oldPos = this.oldData.positions;
let oldLabels = this.oldData.labels;

[oldPos, newPos] = equilizeNoOfElements(oldPos, newPos);
[oldLabels, newLabels] = equilizeNoOfElements(oldLabels, newLabels);

this.render({
positions: oldPos,
labels: newLabels
});

return this.store.map((line, i) => {
return translateVertLine(
line, newPos[i], oldPos[i]
);
});
}
}
};

function getComponent(name, parent, constants, initData, getData) {
let config = componentConfigs[name];
Object.assign(config, {
parent: parent,
constants: constants,
data: initData,
getData: getData
});
return new ChartComponent$1(config);
}

const MIN_BAR_PERCENT_HEIGHT$1 = 0.01;
@@ -2060,47 +2099,75 @@ class AxisChart extends BaseChart {

setupValues() {}

setupComponents() {
initComponents() {

// TODO: rebind new units
// if(this.isNavigable) {
// this.bind_units(units_array);
// }

this.yAxis = getYAxisComponent(
this.drawArea,
{
mode: this.yAxisMode,
width: this.width,
// pos: 'right'
},
{
positions: getRealIntervals(this.height, 4, 0, 0),
labels: getRealIntervals(this.height, 4, 0, 0).map(d => d + ""),
}
);
this.components = [
this.yAxis
// this.getXAxisComponents(),
// ...this.getYRegions(),
// ...this.getXRegions(),
// ...this.getYMarkerLines(),
// // ...this.getXMarkerLines(),
// ...this.getChartComponents(),
// ...this.getChartLabels(),

this.componentConfigs = [
[
'yAxis',
this.drawArea,
{
mode: this.yAxisMode,
width: this.width,
// pos: 'right'
},
{
positions: getRealIntervals(this.height, 4, 0, 0),
labels: getRealIntervals(this.height, 4, 0, 0).map(d => d + ""),
},
function() {
let s = this.state;
return {
positions: s.yAxis.positions,
labels: s.yAxis.labels,
}
}.bind(this)
],

[
'xAxis',
this.drawArea,
{
mode: this.xAxisMode,
height: this.height,
// pos: 'right'
},
{
positions: getRealIntervals(this.width, 4, 0, 1),
labels: getRealIntervals(this.width, 4, 0, 1).map(d => d + ""),
},
function() {
let s = this.state;
return {
positions: s.xAxisPositions,
labels: s.xAxisLabels,
}
}.bind(this)
]
];
}

refreshComponents() {
this.refreshYAxis();
// this.components = [
// yAxis
// // this.getXAxisComponents(),
// // ...this.getYRegions(),
// // ...this.getXRegions(),
// // ...this.getYMarkerLines(),
// // // ...this.getXMarkerLines(),
// // ...this.getChartComponents(),
// // ...this.getChartLabels(),
// ];
}
setupComponents() {
this.components = this.componentConfigs.map(args => getComponent(...args));
}

refreshYAxis() {
let s = this.state;
this.yAxis.refresh({
positions: s.yAxis.positions,
labels: s.yAxis.labels,
});
refreshComponents() {
this.components.forEach(comp => comp.refresh(comp.getData()));
}

getXAxisComponents() {
@@ -2786,40 +2853,40 @@ class PercentageChart extends BaseChart {

calc() {}

// bindTooltip() {
// this.slices.map((slice, i) => {
// slice.addEventListener('mouseenter', () => {
// let g_off = getOffset(this.chartWrapper), p_off = getOffset(slice);

// let x = p_off.left - g_off.left + slice.offsetWidth/2;
// let y = p_off.top - g_off.top - 6;
// let title = (this.formatted_labels && this.formatted_labels.length>0
// ? this.formatted_labels[i] : this.labels[i]) + ': ';
// let percent = (this.slice_totals[i]*100/this.grand_total).toFixed(1);

// this.tip.set_values(x, y, title, percent + "%");
// this.tip.show_tip();
// });
// });
// }
bindTooltip() {
this.slices.map((slice, i) => {
slice.addEventListener('mouseenter', () => {
let g_off = getOffset(this.chartWrapper), p_off = getOffset(slice);

// renderLegend() {
// let x_values = this.formatted_labels && this.formatted_labels.length > 0
// ? this.formatted_labels : this.labels;
// this.legend_totals.map((d, i) => {
// if(d) {
// let stats = $.create('div', {
// className: 'stats',
// inside: this.statsWrapper
// });
// stats.innerHTML = `<span class="indicator">
// <i style="background: ${this.colors[i]}"></i>
// <span class="text-muted">${x_values[i]}:</span>
// ${d}
// </span>`;
// }
// });
// }
let x = p_off.left - g_off.left + slice.offsetWidth/2;
let y = p_off.top - g_off.top - 6;
let title = (this.formatted_labels && this.formatted_labels.length>0
? this.formatted_labels[i] : this.labels[i]) + ': ';
let percent = (this.slice_totals[i]*100/this.grand_total).toFixed(1);

this.tip.set_values(x, y, title, percent + "%");
this.tip.show_tip();
});
});
}

renderLegend() {
let x_values = this.formatted_labels && this.formatted_labels.length > 0
? this.formatted_labels : this.labels;
this.legend_totals.map((d, i) => {
if(d) {
let stats = $$1.create('div', {
className: 'stats',
inside: this.statsWrapper
});
stats.innerHTML = `<span class="indicator">
<i style="background: ${this.colors[i]}"></i>
<span class="text-muted">${x_values[i]}:</span>
${d}
</span>`;
}
});
}
}

const ANGLE_RATIO = Math.PI / 180;


+ 1
- 1
dist/frappe-charts.min.cjs.js
File diff soppresso perché troppo grande
Vedi File


+ 1
- 1
dist/frappe-charts.min.esm.js
File diff soppresso perché troppo grande
Vedi File


+ 1
- 1
dist/frappe-charts.min.iife.js
File diff soppresso perché troppo grande
Vedi File


+ 1
- 1
dist/frappe-charts.min.iife.js.map
File diff soppresso perché troppo grande
Vedi File


+ 1
- 1
docs/assets/js/frappe-charts.min.js
File diff soppresso perché troppo grande
Vedi File


+ 1
- 1
docs/assets/js/frappe-charts.min.js.map
File diff soppresso perché troppo grande
Vedi File


+ 60
- 32
src/js/charts/AxisChart.js Vedi File

@@ -1,6 +1,6 @@
import BaseChart from './BaseChart';
import { Y_AXIS_MARGIN } from '../utils/margins';
import { getYAxisComponent } from '../objects/ChartComponents';
import { getComponent } from '../objects/ChartComponents';
import { BarChartController, LineChartController, getPaths } from '../objects/AxisChartControllers';
import { AxisChartRenderer } from '../utils/draw';
import { getOffset, fire } from '../utils/dom';
@@ -252,47 +252,75 @@ export default class AxisChart extends BaseChart {

setupValues() {}

setupComponents() {
initComponents() {

// TODO: rebind new units
// if(this.isNavigable) {
// this.bind_units(units_array);
// }

this.yAxis = getYAxisComponent(
this.drawArea,
{
mode: this.yAxisMode,
width: this.width,
// pos: 'right'
},
{
positions: getRealIntervals(this.height, 4, 0, 0),
labels: getRealIntervals(this.height, 4, 0, 0).map(d => d + ""),
}
)
this.components = [
this.yAxis
// this.getXAxisComponents(),
// ...this.getYRegions(),
// ...this.getXRegions(),
// ...this.getYMarkerLines(),
// // ...this.getXMarkerLines(),
// ...this.getChartComponents(),
// ...this.getChartLabels(),

this.componentConfigs = [
[
'yAxis',
this.drawArea,
{
mode: this.yAxisMode,
width: this.width,
// pos: 'right'
},
{
positions: getRealIntervals(this.height, 4, 0, 0),
labels: getRealIntervals(this.height, 4, 0, 0).map(d => d + ""),
},
function() {
let s = this.state;
return {
positions: s.yAxis.positions,
labels: s.yAxis.labels,
}
}.bind(this)
],

[
'xAxis',
this.drawArea,
{
mode: this.xAxisMode,
height: this.height,
// pos: 'right'
},
{
positions: getRealIntervals(this.width, 4, 0, 1),
labels: getRealIntervals(this.width, 4, 0, 1).map(d => d + ""),
},
function() {
let s = this.state;
return {
positions: s.xAxisPositions,
labels: s.xAxisLabels,
}
}.bind(this)
]
];
}

refreshComponents() {
this.refreshYAxis();
// this.components = [
// yAxis
// // this.getXAxisComponents(),
// // ...this.getYRegions(),
// // ...this.getXRegions(),
// // ...this.getYMarkerLines(),
// // // ...this.getXMarkerLines(),
// // ...this.getChartComponents(),
// // ...this.getChartLabels(),
// ];
}
setupComponents() {
this.components = this.componentConfigs.map(args => getComponent(...args));
}

refreshYAxis() {
let s = this.state;
this.yAxis.refresh({
positions: s.yAxis.positions,
labels: s.yAxis.labels,
});
refreshComponents() {
this.components.forEach(comp => comp.refresh(comp.getData()));
}

getXAxisComponents() {


+ 2
- 2
src/js/charts/BaseChart.js Vedi File

@@ -135,8 +135,9 @@ export default class BaseChart {

this.calcWidth();
this.makeChartArea();
this.setupComponents();
this.initComponents();

this.setupComponents();
this.draw(true);
}

@@ -221,7 +222,6 @@ export default class BaseChart {
render(animate=true) {
this.refreshComponents();
this.elementsToAnimate = [].concat.apply([], this.components.map(c => c.update(animate)));
console.log(this.elementsToAnimate);
if(this.elementsToAnimate) {
runSMILAnimation(this.chartWrapper, this.svg, this.elementsToAnimate);
}


+ 34
- 34
src/js/charts/PercentageChart.js Vedi File

@@ -91,38 +91,38 @@ export default class PercentageChart extends BaseChart {

calc() {}

// bindTooltip() {
// this.slices.map((slice, i) => {
// slice.addEventListener('mouseenter', () => {
// let g_off = getOffset(this.chartWrapper), p_off = getOffset(slice);
// let x = p_off.left - g_off.left + slice.offsetWidth/2;
// let y = p_off.top - g_off.top - 6;
// let title = (this.formatted_labels && this.formatted_labels.length>0
// ? this.formatted_labels[i] : this.labels[i]) + ': ';
// let percent = (this.slice_totals[i]*100/this.grand_total).toFixed(1);
// this.tip.set_values(x, y, title, percent + "%");
// this.tip.show_tip();
// });
// });
// }
// renderLegend() {
// let x_values = this.formatted_labels && this.formatted_labels.length > 0
// ? this.formatted_labels : this.labels;
// this.legend_totals.map((d, i) => {
// if(d) {
// let stats = $.create('div', {
// className: 'stats',
// inside: this.statsWrapper
// });
// stats.innerHTML = `<span class="indicator">
// <i style="background: ${this.colors[i]}"></i>
// <span class="text-muted">${x_values[i]}:</span>
// ${d}
// </span>`;
// }
// });
// }
bindTooltip() {
this.slices.map((slice, i) => {
slice.addEventListener('mouseenter', () => {
let g_off = getOffset(this.chartWrapper), p_off = getOffset(slice);
let x = p_off.left - g_off.left + slice.offsetWidth/2;
let y = p_off.top - g_off.top - 6;
let title = (this.formatted_labels && this.formatted_labels.length>0
? this.formatted_labels[i] : this.labels[i]) + ': ';
let percent = (this.slice_totals[i]*100/this.grand_total).toFixed(1);
this.tip.set_values(x, y, title, percent + "%");
this.tip.show_tip();
});
});
}
renderLegend() {
let x_values = this.formatted_labels && this.formatted_labels.length > 0
? this.formatted_labels : this.labels;
this.legend_totals.map((d, i) => {
if(d) {
let stats = $.create('div', {
className: 'stats',
inside: this.statsWrapper
});
stats.innerHTML = `<span class="indicator">
<i style="background: ${this.colors[i]}"></i>
<span class="text-muted">${x_values[i]}:</span>
${d}
</span>`;
}
});
}
}

+ 48
- 10
src/js/objects/ChartComponents.js Vedi File

@@ -1,7 +1,7 @@
import { makeSVGGroup } from '../utils/draw';
import { yLine } from '../utils/draw';
import { xLine, yLine } from '../utils/draw';
import { equilizeNoOfElements } from '../utils/draw-utils';
import { Animator, translateHoriLine } from '../utils/animate';
import { Animator, translateHoriLine, translateVertLine } from '../utils/animate';

class ChartComponent {
constructor({
@@ -15,6 +15,7 @@ class ChartComponent {
preMake,
makeElements,
postMake,
getData,
animateElements
}) {
this.parent = parent;
@@ -25,6 +26,7 @@ class ChartComponent {
this.preMake = preMake;
this.makeElements = makeElements;
this.postMake = postMake;
this.getData = getData;

this.animateElements = animateElements;

@@ -69,12 +71,9 @@ class ChartComponent {
}
}

export function getYAxisComponent(parent, constants, initData) {
return new ChartComponent({
parent: parent,
let componentConfigs = {
yAxis: {
layerClass: 'y axis',
constants: constants,
data: initData,
makeElements: function(data) {
return data.positions.map((position, i) =>
yLine(position, data.labels[i], this.constants.width,
@@ -85,12 +84,9 @@ export function getYAxisComponent(parent, constants, initData) {
animateElements: function(newData) {
let newPos = newData.positions;
let newLabels = newData.labels;

let oldPos = this.oldData.positions;
let oldLabels = this.oldData.labels;

let extra = newPos.length - oldPos.length;

[oldPos, newPos] = equilizeNoOfElements(oldPos, newPos);
[oldLabels, newLabels] = equilizeNoOfElements(oldLabels, newLabels);

@@ -105,5 +101,47 @@ export function getYAxisComponent(parent, constants, initData) {
);
});
}
},

xAxis: {
layerClass: 'x axis',
makeElements: function(data) {
return data.positions.map((position, i) =>
xLine(position, data.labels[i], this.constants.height,
{mode: this.constants.mode, pos: this.constants.pos})
);
},

animateElements: function(newData) {
let newPos = newData.positions;
let newLabels = newData.labels;
let oldPos = this.oldData.positions;
let oldLabels = this.oldData.labels;

[oldPos, newPos] = equilizeNoOfElements(oldPos, newPos);
[oldLabels, newLabels] = equilizeNoOfElements(oldLabels, newLabels);

this.render({
positions: oldPos,
labels: newLabels
});

return this.store.map((line, i) => {
return translateVertLine(
line, newPos[i], oldPos[i]
);
});
}
}
}

export function getComponent(name, parent, constants, initData, getData) {
let config = componentConfigs[name];
Object.assign(config, {
parent: parent,
constants: constants,
data: initData,
getData: getData
})
return new ChartComponent(config);
}

+ 34
- 37
src/js/utils/draw.js Vedi File

@@ -266,6 +266,40 @@ export function yLine(y, label, width, options={}) {
});
}

export function xLine(x, label, height, options={}) {
if(!options.pos) options.pos = 'bottom';
if(!options.offset) options.offset = 0;
if(!options.mode) options.mode = 'span';
if(!options.stroke) options.stroke = BASE_LINE_COLOR;
if(!options.className) options.className = '';

// Draw X axis line in span/tick mode with optional label
// y2(span)
// |
// |
// x line |
// |
// |
// ---------------------+-- y2(tick)
// |
// y1

let y1 = height + AXIS_TICK_LENGTH;
let y2 = options.mode === 'span' ? -1 * AXIS_TICK_LENGTH : height;

if(options.mode === 'tick' && options.pos === 'top') {
// top axis ticks
y1 = -1 * AXIS_TICK_LENGTH;
y2 = 0;
}

return makeVertLine(x, label, y1, y2, {
stroke: options.stroke,
className: options.className,
lineType: options.lineType
});
}

export class AxisChartRenderer {
constructor(state) {
this.refreshState(state);
@@ -284,43 +318,6 @@ export class AxisChartRenderer {
this.zeroLine = zeroLine;
}

xLine(x, label, options={}) {
if(!options.pos) options.pos = 'bottom';
if(!options.offset) options.offset = 0;
if(!options.mode) options.mode = 'span';
if(!options.stroke) options.stroke = BASE_LINE_COLOR;
if(!options.className) options.className = '';

// Draw X axis line in span/tick mode with optional label
// y2(span)
// |
// |
// x line |
// |
// |
// ---------------------+-- y2(tick)
// |
// y1

let y1 = this.totalHeight + AXIS_TICK_LENGTH;
let y2 = options.mode === 'span' ? -1 * AXIS_TICK_LENGTH : this.totalHeight;

if(options.mode === 'tick' && options.pos === 'top') {
// top axis ticks
y1 = -1 * AXIS_TICK_LENGTH;
y2 = 0;
}

return makeVertLine(x, label, y1, y2, {
stroke: options.stroke,
className: options.className,
lineType: options.lineType
});
}




xMarker() {}
yMarker(y, label, options={}) {
let labelSvg = createSVG('text', {


Caricamento…
Annulla
Salva