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