diff --git a/__tests__/integration/api-chart-auto-fit-height.spec.ts b/__tests__/integration/api-chart-auto-fit-height.spec.ts new file mode 100644 index 0000000000..bdd512b269 --- /dev/null +++ b/__tests__/integration/api-chart-auto-fit-height.spec.ts @@ -0,0 +1,24 @@ +import { chartAutoFitHeight as render } from '../plots/api'; +import { createNodeGCanvas } from './utils/createNodeGCanvas'; +import { sleep } from './utils/sleep'; +import { kebabCase } from './utils/kebabCase'; +import './utils/useSnapshotMatchers'; + +describe('chart.options.autoFit', () => { + const dir = `${__dirname}/snapshots/api/${kebabCase(render.name)}`; + const canvas = createNodeGCanvas(800, 500); + + it('chart({ autoFit: true, height: 200 }) should fit parent container width and custom height', async () => { + const { finished } = render({ + canvas, + container: document.createElement('div'), + }); + await finished; + await sleep(20); + await expect(canvas).toMatchDOMSnapshot(dir, 'step0'); + }); + + afterAll(() => { + canvas?.destroy(); + }); +}); diff --git a/__tests__/integration/api-chart-auto-fit-width.spec.ts b/__tests__/integration/api-chart-auto-fit-width.spec.ts new file mode 100644 index 0000000000..f178fb2526 --- /dev/null +++ b/__tests__/integration/api-chart-auto-fit-width.spec.ts @@ -0,0 +1,25 @@ +import { chartAutoFitWidth as render } from '../plots/api'; +import { createNodeGCanvas } from './utils/createNodeGCanvas'; +import { sleep } from './utils/sleep'; +import { kebabCase } from './utils/kebabCase'; +import './utils/useSnapshotMatchers'; + +describe('chart.options.autoFit', () => { + const dir = `${__dirname}/snapshots/api/${kebabCase(render.name)}`; + const canvas = createNodeGCanvas(800, 500); + + it('chart({ autoFit: true, width: 200 }) should fit parent container height and custom width', async () => { + const { finished } = render({ + canvas, + container: document.createElement('div'), + }); + + await finished; + await sleep(20); + await expect(canvas).toMatchDOMSnapshot(dir, 'step0'); + }); + + afterAll(() => { + canvas?.destroy(); + }); +}); diff --git a/__tests__/integration/snapshots/api/chart-auto-fit-height/step0.svg b/__tests__/integration/snapshots/api/chart-auto-fit-height/step0.svg new file mode 100644 index 0000000000..4c998e6e87 --- /dev/null +++ b/__tests__/integration/snapshots/api/chart-auto-fit-height/step0.svg @@ -0,0 +1,1577 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sports + + + + + + + + + + + + + + + + + + + + Strategy + + + + + + + + + + + + + + + + + + + + Action + + + + + + + + + + + + + + + + + + + + Shooter + + + + + + + + + + + + + + + + + + + + Other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sports + + + + + + + Strategy + + + + + + + Action + + + + + + + Shooter + + + + + + + Other + + + + + + + + + genre + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + 50 + + + + + + + 100 + + + + + + + 150 + + + + + + + 200 + + + + + + + 250 + + + + + + + 300 + + + + + + + 350 + + + + + + + + + sold + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/__tests__/integration/snapshots/api/chart-auto-fit-width/step0.svg b/__tests__/integration/snapshots/api/chart-auto-fit-width/step0.svg new file mode 100644 index 0000000000..043f7bf86b --- /dev/null +++ b/__tests__/integration/snapshots/api/chart-auto-fit-width/step0.svg @@ -0,0 +1,1572 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sports + + + + + + + + + + + + + + + + + + + + Strategy + + + + + + + + + + + + + + + + + + + + Action + + + + + + + + + + + + + + + + + + + + Shooter + + + + + + + + + + + + + + + + + + + + Other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sports + + + + + + + Strategy + + + + + + + Action + + + + + + + Shooter + + + + + + + Other + + + + + + + + + genre + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + 50 + + + + + + + 100 + + + + + + + 150 + + + + + + + 200 + + + + + + + 250 + + + + + + + 300 + + + + + + + 350 + + + + + + + + + sold + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/__tests__/plots/api/chart-auto-fit-height.ts b/__tests__/plots/api/chart-auto-fit-height.ts new file mode 100644 index 0000000000..01a908a4a4 --- /dev/null +++ b/__tests__/plots/api/chart-auto-fit-height.ts @@ -0,0 +1,51 @@ +import { Chart } from '../../../src'; + +export function chartAutoFitHeight(context) { + const { container, canvas } = context; + + // button + const button = document.createElement('button'); + button.innerText = 'Change Wrapper Container'; + container.appendChild(button); + + // wrapperDiv + const wrapperDiv = document.createElement('div'); + wrapperDiv.style.width = '800px'; + wrapperDiv.style.height = '500px'; + container.appendChild(wrapperDiv); + + const chart = new Chart({ + container: wrapperDiv, + autoFit: true, + height: 200, + canvas, + }); + + chart.data([ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ]); + + chart + .interval() + .encode('x', 'genre') + .encode('y', 'sold') + .encode('color', 'genre') + .axis({ x: { animate: false }, y: { animate: false } }); + + const finished = chart.render(); + + let resolve; + const fitted = new Promise((r) => (resolve = r)); + + button.onclick = () => { + wrapperDiv.style.width = '400px'; + wrapperDiv.style.height = '500px'; + chart.forceFit().then(resolve); + }; + + return { chart, button, finished, fitted }; +} diff --git a/__tests__/plots/api/chart-auto-fit-width.ts b/__tests__/plots/api/chart-auto-fit-width.ts new file mode 100644 index 0000000000..21f77b7ff8 --- /dev/null +++ b/__tests__/plots/api/chart-auto-fit-width.ts @@ -0,0 +1,51 @@ +import { Chart } from '../../../src'; + +export function chartAutoFitWidth(context) { + const { container, canvas } = context; + + // button + const button = document.createElement('button'); + button.innerText = 'Change Wrapper Container'; + container.appendChild(button); + + // wrapperDiv + const wrapperDiv = document.createElement('div'); + wrapperDiv.style.width = '800px'; + wrapperDiv.style.height = '500px'; + container.appendChild(wrapperDiv); + + const chart = new Chart({ + container: wrapperDiv, + autoFit: true, + width: 200, + canvas, + }); + + chart.data([ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ]); + + chart + .interval() + .encode('x', 'genre') + .encode('y', 'sold') + .encode('color', 'genre') + .axis({ x: { animate: false }, y: { animate: false } }); + + const finished = chart.render(); + + let resolve; + const fitted = new Promise((r) => (resolve = r)); + + button.onclick = () => { + wrapperDiv.style.width = '400px'; + wrapperDiv.style.height = '500px'; + chart.forceFit().then(resolve); + }; + + return { chart, button, finished, fitted }; +} diff --git a/__tests__/plots/api/index.ts b/__tests__/plots/api/index.ts index 362aefa220..52223578ce 100644 --- a/__tests__/plots/api/index.ts +++ b/__tests__/plots/api/index.ts @@ -48,4 +48,6 @@ export { chartOptionsCallbackChildren } from './chart-options-callback-children' export { chartAutoFitSlider } from './chart-auto-fit-slider'; export { chart3d } from './chart-3d'; export { chartOnScrollbarFilter } from './chart-on-scrollbar-filter'; +export { chartAutoFitHeight } from './chart-auto-fit-height'; +export { chartAutoFitWidth } from './chart-auto-fit-width'; export { chartOnLabelClick } from './chart-on-label-click'; diff --git a/src/api/utils.ts b/src/api/utils.ts index f466625658..e243201a16 100644 --- a/src/api/utils.ts +++ b/src/api/utils.ts @@ -76,9 +76,9 @@ export function valueOf(node: Node): Record { } export function sizeOf(options, container) { - const { width = 640, height = 480, autoFit, depth = 0 } = options; - let effectiveWidth = width; - let effectiveHeight = height; + const { width, height, autoFit, depth = 0 } = options; + let effectiveWidth = 640; + let effectiveHeight = 480; if (autoFit) { const { width: containerWidth, height: containerHeight } = @@ -87,6 +87,9 @@ export function sizeOf(options, container) { effectiveHeight = containerHeight || effectiveHeight; } + effectiveWidth = width || effectiveWidth; + effectiveHeight = height || effectiveHeight; + return { width: Math.max( isNumber(effectiveWidth) ? effectiveWidth : MIN_CHART_WIDTH,