diff --git a/apps/demos/Demos/Charts/Stock/jQuery/data.js b/apps/demos/Demos/Charts/Stock/jQuery/data.js
index 0c54305cbfbd..d458fe0dcd5b 100644
--- a/apps/demos/Demos/Charts/Stock/jQuery/data.js
+++ b/apps/demos/Demos/Charts/Stock/jQuery/data.js
@@ -1,139 +1,31 @@
-const dataSource = [{
- date: new Date(1994, 2, 1),
- l: 24.00,
- h: 25.00,
- o: 25.00,
- c: 24.875,
-}, {
- date: new Date(1994, 2, 2),
- l: 23.625,
- h: 25.125,
- o: 24.00,
- c: 24.875,
-}, {
- date: new Date(1994, 2, 3),
- l: 26.25,
- h: 28.25,
- o: 26.75,
- c: 27.00,
-}, {
- date: new Date(1994, 2, 4),
- l: 26.50,
- h: 27.875,
- o: 26.875,
- c: 27.25,
-}, {
- date: new Date(1994, 2, 7),
- l: 26.375,
- h: 27.50,
- o: 27.375,
- c: 26.75,
-}, {
- date: new Date(1994, 2, 8),
- l: 25.75,
- h: 26.875,
- o: 26.75,
- c: 26.00,
-}, {
- date: new Date(1994, 2, 9),
- l: 25.75,
- h: 26.75,
- o: 26.125,
- c: 26.25,
-}, {
- date: new Date(1994, 2, 10),
- l: 25.75,
- h: 26.375,
- o: 26.375,
- c: 25.875,
-}, {
- date: new Date(1994, 2, 11),
- l: 24.875,
- h: 26.125,
- o: 26.00,
- c: 25.375,
-}, {
- date: new Date(1994, 2, 14),
- l: 25.125,
- h: 26.00,
- o: 25.625,
- c: 25.75,
-}, {
- date: new Date(1994, 2, 15),
- l: 25.875,
- h: 26.625,
- o: 26.125,
- c: 26.375,
-}, {
- date: new Date(1994, 2, 16),
- l: 26.25,
- h: 27.375,
- o: 26.25,
- c: 27.25,
-}, {
- date: new Date(1994, 2, 17),
- l: 26.875,
- h: 27.25,
- o: 27.125,
- c: 26.875,
-}, {
- date: new Date(1994, 2, 18),
- l: 26.375,
- h: 27.125,
- o: 27.00,
- c: 27.125,
-}, {
- date: new Date(1994, 2, 21),
- l: 26.75,
- h: 27.875,
- o: 26.875,
- c: 27.75,
-}, {
- date: new Date(1994, 2, 22),
- l: 26.75,
- h: 28.375,
- o: 27.50,
- c: 27.00,
-}, {
- date: new Date(1994, 2, 23),
- l: 26.875,
- h: 28.125,
- o: 27.00,
- c: 28.00,
-}, {
- date: new Date(1994, 2, 24),
- l: 26.25,
- h: 27.875,
- o: 27.75,
- c: 27.625,
-}, {
- date: new Date(1994, 2, 25),
- l: 27.50,
- h: 28.75,
- o: 27.75,
- c: 28.00,
-}, {
- date: new Date(1994, 2, 28),
- l: 25.75,
- h: 28.25,
- o: 28.00,
- c: 27.25,
-}, {
- date: new Date(1994, 2, 29),
- l: 26.375,
- h: 27.50,
- o: 27.50,
- c: 26.875,
-}, {
- date: new Date(1994, 2, 30),
- l: 25.75,
- h: 27.50,
- o: 26.375,
- c: 26.25,
-}, {
- date: new Date(1994, 2, 31),
- l: 24.75,
- h: 27.00,
- o: 26.50,
- c: 25.25,
-}];
+function generateStockData(startDate, days) {
+ function randomOffset(amplitude) {
+ return (Math.random() - 0.5) * amplitude;
+ }
+
+ const data = [];
+ const current = new Date(startDate);
+ let price = 25;
+
+ while (data.length < days) {
+ const day = current.getDay();
+ if (day !== 0 && day !== 6) {
+ const open = price + randomOffset(1.5);
+ const close = open + randomOffset(1.5);
+ const high = Math.max(open, close) + Math.random() * 0.8;
+ const low = Math.min(open, close) - Math.random() * 0.8;
+
+ data.push({
+ date: new Date(current),
+ o: +open.toFixed(2),
+ h: +high.toFixed(2),
+ l: +low.toFixed(2),
+ c: +close.toFixed(2),
+ });
+
+ price = close;
+ }
+ current.setDate(current.getDate() + 1);
+ }
+ return data;
+}
diff --git a/apps/demos/Demos/Charts/Stock/jQuery/index.html b/apps/demos/Demos/Charts/Stock/jQuery/index.html
index 06da1058e48a..5c2280d22490 100644
--- a/apps/demos/Demos/Charts/Stock/jQuery/index.html
+++ b/apps/demos/Demos/Charts/Stock/jQuery/index.html
@@ -14,6 +14,7 @@
diff --git a/apps/demos/Demos/Charts/Stock/jQuery/index.js b/apps/demos/Demos/Charts/Stock/jQuery/index.js
index 3ee2aaefbda1..a06a4ce5681c 100644
--- a/apps/demos/Demos/Charts/Stock/jQuery/index.js
+++ b/apps/demos/Demos/Charts/Stock/jQuery/index.js
@@ -1,55 +1,154 @@
$(() => {
- $('#chart').dxChart({
+ const dayMs = 24 * 60 * 60 * 1000;
+
+ const panStepFraction = 0.25;
+ const zoomFactor = 0.75;
+ const minVisibleSpanMs = 3 * dayMs;
+
+ const initialStart = new Date(1994, 3, 15);
+ const initialEnd = new Date(1994, 3, 29);
+
+ const data = generateStockData(new Date(1994, 3, 1), 65);
+ const dataMin = data[0].date.getTime();
+ const dataMax = data[data.length - 1].date.getTime();
+
+ const chart = $('#chart').dxChart({
title: 'Stock Price',
- dataSource,
- commonSeriesSettings: {
- argumentField: 'date',
- type: 'stock',
+ dataSource: data,
+ commonSeriesSettings: { argumentField: 'date', type: 'stock' },
+ series: [{
+ name: 'E-Mart',
+ openValueField: 'o',
+ highValueField: 'h',
+ lowValueField: 'l',
+ closeValueField: 'c',
+ reduction: { color: 'red' },
+ }],
+ zoomAndPan: {
+ argumentAxis: 'both',
+ dragToZoom: true,
+ allowMouseWheel: true,
},
- series: [
- {
- name: 'E-Mart',
- openValueField: 'o',
- highValueField: 'h',
- lowValueField: 'l',
- closeValueField: 'c',
- reduction: {
- color: 'red',
- },
- },
- ],
+ scrollBar: { visible: true, position: 'bottom' },
+ legend: { verticalAlignment: 'bottom', horizontalAlignment: 'center' },
valueAxis: {
+ position: 'right',
tickInterval: 1,
- title: {
- text: 'US dollars',
- },
- label: {
- format: {
- type: 'currency',
- precision: 0,
- },
- },
+ title: { text: 'US dollars' },
+ label: { format: { type: 'currency', precision: 0 } },
},
argumentAxis: {
- workdaysOnly: true,
+ workdaysOnly: false,
+ visualRange: { startValue: initialStart, endValue: initialEnd },
label: {
- format: 'shortDate',
+ format: 'MMM dd',
+ overlappingBehavior: 'rotate',
+ rotationAngle: 30,
},
},
- export: {
- enabled: true,
- },
+ export: { enabled: true },
tooltip: {
enabled: true,
location: 'edge',
- customizeTooltip(arg) {
+ customizeTooltip({
+ openValue, closeValue, highValue, lowValue,
+ }) {
return {
- text: `Open: $${arg.openValue}
`
- + `Close: $${arg.closeValue}
`
- + `High: $${arg.highValue}
`
- + `Low: $${arg.lowValue}
`,
+ text: [
+ `Open: $${openValue}`,
+ `Close: $${closeValue}`,
+ `High: $${highValue}`,
+ `Low: $${lowValue}`,
+ ].join('
'),
};
},
},
+ }).dxChart('instance');
+
+ function clamp(value, min, max) {
+ return Math.min(Math.max(value, min), max);
+ }
+
+ function getRange() {
+ const { startValue, endValue } = chart.getArgumentAxis().visualRange();
+ return { start: startValue.getTime(), end: endValue.getTime() };
+ }
+
+ function setRange(start, end) {
+ const span = clamp(end - start, minVisibleSpanMs, dataMax - dataMin);
+ const center = (start + end) / 2;
+ const newStart = clamp(center - span / 2, dataMin, dataMax - span);
+
+ chart.getArgumentAxis().visualRange({
+ startValue: new Date(newStart),
+ endValue: new Date(newStart + span),
+ });
+ }
+
+ function pan(direction) {
+ const { start, end } = getRange();
+ const shift = (end - start) * panStepFraction * direction;
+ setRange(start + shift, end + shift);
+ }
+
+ function zoom(factor) {
+ const { start, end } = getRange();
+ const center = (start + end) / 2;
+ const half = ((end - start) * factor) / 2;
+ setRange(center - half, center + half);
+ }
+
+ function resetZoom() {
+ setRange(initialStart.getTime(), initialEnd.getTime());
+ }
+
+ $('#toolbar').dxToolbar({
+ items: [
+ {
+ location: 'after',
+ widget: 'dxButton',
+ options: {
+ icon: 'chevronleft',
+ hint: 'Pan Left',
+ onClick: () => pan(-1),
+ },
+ },
+ {
+ location: 'after',
+ widget: 'dxButton',
+ options: {
+ icon: 'chevronright',
+ hint: 'Pan Right',
+ onClick: () => pan(1),
+ },
+ },
+ {
+ location: 'after',
+ widget: 'dxButton',
+ options: {
+ icon: 'plus',
+ hint: 'Zoom In',
+ onClick: () => zoom(zoomFactor),
+ },
+ },
+ {
+ location: 'after',
+ widget: 'dxButton',
+ options: {
+ icon: 'minus',
+ hint: 'Zoom Out',
+ onClick: () => zoom(1 / zoomFactor),
+ },
+ },
+ {
+ location: 'after',
+ widget: 'dxButton',
+ options: {
+ icon: 'refresh',
+ hint: 'Reset Zoom',
+ onClick: resetZoom,
+ },
+ },
+ ],
});
});
diff --git a/apps/demos/testing/etalons/Charts-Stock (fluent.blue.light).png b/apps/demos/testing/etalons/Charts-Stock (fluent.blue.light).png
index 3932b5bca840..82dcc4e61833 100644
Binary files a/apps/demos/testing/etalons/Charts-Stock (fluent.blue.light).png and b/apps/demos/testing/etalons/Charts-Stock (fluent.blue.light).png differ
diff --git a/apps/demos/testing/etalons/Charts-Stock (material.blue.light).png b/apps/demos/testing/etalons/Charts-Stock (material.blue.light).png
index 94c83f45d2e8..88063b161822 100644
Binary files a/apps/demos/testing/etalons/Charts-Stock (material.blue.light).png and b/apps/demos/testing/etalons/Charts-Stock (material.blue.light).png differ