From 36dd3178182fb076f4db20e2fe76a03b987d9294 Mon Sep 17 00:00:00 2001 From: jinhee park Date: Mon, 2 May 2022 16:34:43 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[#1156]=20Chart=20>=20Axis=20>=20title=20?= =?UTF-8?q?=EC=98=B5=EC=85=98=20=EC=B6=94=EA=B0=80=20#####################?= =?UTF-8?q?##############=201.=20Chart=20>=20Axis=20>=20title=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80=202.=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=98=88=EC=A0=9C=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1=20?= =?UTF-8?q?(Line=20>=20AxisTitle.vue)=203.=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=84=A4=EB=AA=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/views/barChart/api/barChart.md | 13 ++ docs/views/heatMap/api/heatMap.md | 15 +- docs/views/lineChart/api/lineChart.md | 13 ++ docs/views/lineChart/example/AxisTitle.vue | 209 ++++++++++++++++++ docs/views/lineChart/props.js | 7 + docs/views/scatterChart/api/scatterChart.md | 13 ++ src/components/chart/chart.core.js | 22 +- .../chart/helpers/helpers.constant.js | 10 + src/components/chart/helpers/helpers.util.js | 9 +- src/components/chart/scale/scale.js | 49 ++++ src/components/chart/scale/scale.step.js | 2 + .../chart/scale/scale.time.category.js | 2 + 12 files changed, 359 insertions(+), 5 deletions(-) create mode 100644 docs/views/lineChart/example/AxisTitle.vue diff --git a/docs/views/barChart/api/barChart.md b/docs/views/barChart/api/barChart.md index b29741a2a..6a2b28c90 100644 --- a/docs/views/barChart/api/barChart.md +++ b/docs/views/barChart/api/barChart.md @@ -130,6 +130,7 @@ const chartData = { | plotLines | Array | ([상세](#plotline)) | plot line(임계선 표시 용도) 설정 | | | plotBands | Array | ([상세](#plotband)) | plot band(임계영역 표시 용도) 설정 | | | formatter | function | null | 데이터가 표시되기 전에 데이터의 형식을 지정하는 데 사용 | (value) => value + '%' | + | title | Object | ([상세](#title)) | 라벨의 폰트 스타일을 설정 | | ##### linear type - interval (Axis Label 표기를 위한 interval) @@ -171,6 +172,18 @@ const chartData = { | fitWidth | Boolean | false | Label Text Ellipsis 처리 | | | fitDir | String | 'right' | Ellipsis 방향 | ( right => 'aaa...', left => '...aaa') | +##### title +| 이름 | 타입 | 디폴트 | 설명 | 종류(예시) | +|-----|------|-------|-----|-----| +| use | Boolean | false | Chart 축(Axis) Title 표시 여부 | true / false | +| text | String | null | Title 로 표시될 text | | +| fontSize | Number | 12 | 글자 크기 | | +| fontWeight | Number | 400 | 글자 굵기 | 100, 200, 300, ... 900 | +| fontFamily | String | 'Roboto' | 폰트 | | +| fontStyle | String | 'normal' | 폰트 스타일 | 'normal', 'italic' | +| textAlign | String | 'right' | 텍스트 정렬| 'right', 'left', 'center' | +| color | Hex, RGB, RGBA Code(String) | '#25262E' | 글자 색상 | | + ##### plotLine | 이름 | 타입 | 디폴트 | 설명 | 종류(예시) | |-----|------|-------|-----|-----| diff --git a/docs/views/heatMap/api/heatMap.md b/docs/views/heatMap/api/heatMap.md index 3340bbb64..453eb00d8 100644 --- a/docs/views/heatMap/api/heatMap.md +++ b/docs/views/heatMap/api/heatMap.md @@ -93,6 +93,7 @@ const chartData = | interval | String/number | | 축에 표시되는 값의 간격 단위 ( time: string / linear: number) | [time](#time-type), [linear](#linear-type) | | labelStyle | Object | ([상세](#labelstyle)) | 라벨의 폰트 스타일을 설정 | | | formatter | function | null | 데이터가 표시되기 전에 데이터의 형식을 지정하는 데 사용 | (value) => value + '%' | + | title | Object | ([상세](#title)) | 라벨의 폰트 스타일을 설정 | | ##### time type - interval (Axis Label 표기를 위한 interval) @@ -119,10 +120,22 @@ const chartData = | fitWidth | Boolean | false | Label Text Ellipsis 처리 | | | fitDir | String | 'right' | Ellipsis 방향 | ( right => 'aaa...', left => '...aaa') | +##### title +| 이름 | 타입 | 디폴트 | 설명 | 종류(예시) | +|-----|------|-------|-----|-----| +| use | Boolean | false | Chart 축(Axis) Title 표시 여부 | true / false | +| text | String | null | Title 로 표시될 text | | +| fontSize | Number | 12 | 글자 크기 | | +| fontWeight | Number | 400 | 글자 굵기 | 100, 200, 300, ... 900 | +| fontFamily | String | 'Roboto' | 폰트 | | +| fontStyle | String | 'normal' | 폰트 스타일 | 'normal', 'italic' | +| textAlign | String | 'right' | 텍스트 정렬| 'right', 'left', 'center' | +| color | Hex, RGB, RGBA Code(String) | '#25262E' | 글자 색상 | | + #### title | 이름 | 타입 | 디폴트 | 설명 | 종류(예시) | | --- | ---- | ----- | --- | ----------| -| show | Boolean | false | 타이틀 표시 여부 | true /false | +| show | Boolean | false | 차트 타이틀 표시 여부 | true /false | | height | Number | 40 | 타이틀 영역이 높이 | | | text | String | '' | 타이틀 | | | style | Object | | 타이틀 폰트 스타일 | | diff --git a/docs/views/lineChart/api/lineChart.md b/docs/views/lineChart/api/lineChart.md index 758b12e24..671ca50d2 100644 --- a/docs/views/lineChart/api/lineChart.md +++ b/docs/views/lineChart/api/lineChart.md @@ -121,6 +121,7 @@ const chartData = | plotLines | Array | ([상세](#plotline)) | plot line(임계선 표시 용도) 설정 | | | plotBands | Array | ([상세](#plotband)) | plot band(임계영역 표시 용도) 설정 | | | formatter | function | null | 데이터가 표시되기 전에 데이터의 형식을 지정하는 데 사용 | (value) => value + '%' | + | title | Object | ([상세](#title)) | 라벨의 폰트 스타일을 설정 | | ##### time type - interval (Axis Label 표기를 위한 interval) @@ -140,6 +141,18 @@ const chartData = | fitWidth | Boolean | false | Label Text Ellipsis 처리 | | | fitDir | String | 'right' | Ellipsis 방향 | ( right => 'aaa...', left => '...aaa') | +##### title +| 이름 | 타입 | 디폴트 | 설명 | 종류(예시) | +|-----|------|-------|-----|-----| +| use | Boolean | false | Chart 축(Axis) Title 표시 여부 | true / false | +| text | String | null | Title 로 표시될 text | | +| fontSize | Number | 12 | 글자 크기 | | +| fontWeight | Number | 400 | 글자 굵기 | 100, 200, 300, ... 900 | +| fontFamily | String | 'Roboto' | 폰트 | | +| fontStyle | String | 'normal' | 폰트 스타일 | 'normal', 'italic' | +| textAlign | String | 'right' | 텍스트 정렬| 'right', 'left', 'center' | +| color | Hex, RGB, RGBA Code(String) | '#25262E' | 글자 색상 | | + ##### plotLine | 이름 | 타입 | 디폴트 | 설명 | 종류(예시) | |-----|------|-------|-----|-----| diff --git a/docs/views/lineChart/example/AxisTitle.vue b/docs/views/lineChart/example/AxisTitle.vue new file mode 100644 index 000000000..2ad22f58d --- /dev/null +++ b/docs/views/lineChart/example/AxisTitle.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/docs/views/lineChart/props.js b/docs/views/lineChart/props.js index a1610739d..994266682 100644 --- a/docs/views/lineChart/props.js +++ b/docs/views/lineChart/props.js @@ -18,6 +18,8 @@ import SelectLabel from './example/SelectLabel'; import SelectLabelRaw from '!!raw-loader!./example/SelectLabel'; import SelectSeries from './example/SelectSeries'; import SelectSeriesRaw from '!!raw-loader!./example/SelectSeries'; +import AxisTitle from './example/AxisTitle'; +import AxisTitleRaw from '!!raw-loader!./example/AxisTitle'; export default { mdText, @@ -67,5 +69,10 @@ export default { component: PlotLine, parsedData: parseComponent(PlotLineRaw), }, + AxisTitle: { + description: '차트 축에 title을 설정할 수 있습니다.', + component: AxisTitle, + parsedData: parseComponent(AxisTitleRaw), + }, }, }; diff --git a/docs/views/scatterChart/api/scatterChart.md b/docs/views/scatterChart/api/scatterChart.md index 420039f86..c16cc0221 100644 --- a/docs/views/scatterChart/api/scatterChart.md +++ b/docs/views/scatterChart/api/scatterChart.md @@ -85,6 +85,7 @@ const chartData = | plotLines | Array | ([상세](#plotline)) | plot line(임계선 표시 용도) 설정 | | | plotBands | Array | ([상세](#plotband)) | plot band(임계영역 표시 용도) 설정 | | | formatter | function | null | 데이터가 표시되기 전에 데이터의 형식을 지정하는 데 사용 | (value) => value + '%' | + | title | Object | ([상세](#title)) | 라벨의 폰트 스타일을 설정 | | ##### time type - interval (Axis Label 표기를 위한 interval) @@ -108,6 +109,18 @@ const chartData = | fitWidth | Boolean | false | Label Text Ellipsis 처리 | | | fitDir | String | 'right' | Ellipsis 방향 | ( right => 'aaa...', left => '...aaa') | +##### title +| 이름 | 타입 | 디폴트 | 설명 | 종류(예시) | +|-----|------|-------|-----|-----| +| use | Boolean | false | Chart 축(Axis) Title 표시 여부 | true / false | +| text | String | null | Title 로 표시될 text | | +| fontSize | Number | 12 | 글자 크기 | | +| fontWeight | Number | 400 | 글자 굵기 | 100, 200, 300, ... 900 | +| fontFamily | String | 'Roboto' | 폰트 | | +| fontStyle | String | 'normal' | 폰트 스타일 | 'normal', 'italic' | +| textAlign | String | 'right' | 텍스트 정렬| 'right', 'left', 'center' | +| color | Hex, RGB, RGBA Code(String) | '#25262E' | 글자 색상 | | + ##### plotLine | 이름 | 타입 | 디폴트 | 설명 | 종류(예시) | |-----|------|-------|-----|-----| diff --git a/src/components/chart/chart.core.js b/src/components/chart/chart.core.js index a9556efc9..86b96a2ba 100644 --- a/src/components/chart/chart.core.js +++ b/src/components/chart/chart.core.js @@ -443,15 +443,31 @@ class EvChart { const { width, height } = this.getChartDOMRect(); const padding = this.options.padding; + const xAxisTitleOpt = this.options.axesX[0]?.title; + const yAxisTitleOpt = this.options.axesY[0]?.title; + const titleMargin = 10; + + let xAxisTitleHeight = 0; + if (xAxisTitleOpt?.use && xAxisTitleOpt?.text) { + const fontSize = isNaN(xAxisTitleOpt?.fontSize) ? 12 : xAxisTitleOpt?.fontSize; + xAxisTitleHeight = fontSize + titleMargin; + } + + let yAxisTitleHeight = 0; + if (yAxisTitleOpt?.use && yAxisTitleOpt?.text) { + const fontSize = isNaN(yAxisTitleOpt?.fontSize) ? 12 : yAxisTitleOpt?.fontSize; + yAxisTitleHeight = fontSize + titleMargin; + } + const horizontalPadding = padding.left + padding.right; - const verticalPadding = padding.top + padding.bottom; + const verticalPadding = padding.top + padding.bottom + xAxisTitleHeight + yAxisTitleHeight; const chartWidth = width > horizontalPadding ? width - horizontalPadding : width; const chartHeight = height > verticalPadding ? height - verticalPadding : height; const x1 = padding.left; const x2 = Math.max(width - padding.right, x1 + 2); - const y1 = padding.top; - const y2 = Math.max(height - padding.bottom, y1 + 2); + const y1 = padding.top + yAxisTitleHeight; + const y2 = Math.max(height - padding.bottom - xAxisTitleHeight, y1 + 2); return { x1, diff --git a/src/components/chart/helpers/helpers.constant.js b/src/components/chart/helpers/helpers.constant.js index 9b0c4b06d..21275d260 100644 --- a/src/components/chart/helpers/helpers.constant.js +++ b/src/components/chart/helpers/helpers.constant.js @@ -102,6 +102,16 @@ export const AXIS_OPTION = { fitWidth: false, fitDir: 'right', }, + title: { + use: false, + text: null, + fontWeight: 400, + fontSize: 12, + fontFamily: 'Roboto', + textAlign: 'right', + fontStyle: 'normal', + color: '#808080', + }, }; export const PLOT_LINE_OPTION = { diff --git a/src/components/chart/helpers/helpers.util.js b/src/components/chart/helpers/helpers.util.js index e8490068e..932c27913 100644 --- a/src/components/chart/helpers/helpers.util.js +++ b/src/components/chart/helpers/helpers.util.js @@ -127,7 +127,14 @@ export default { * @returns {string} computed value */ getLabelStyle(style) { - return `normal normal ${style.fontWeight} ${style.fontSize}px ${style.fontFamily}`; + const { + fontStyle = 'normal', + fontWeight = 'norma', + fontSize = '12', + fontFamily = 'Roboto', + } = style; + + return `${fontStyle} normal ${fontWeight} ${fontSize}px ${fontFamily}`; }, /** diff --git a/src/components/chart/scale/scale.js b/src/components/chart/scale/scale.js index 3441d73d0..08f18af30 100644 --- a/src/components/chart/scale/scale.js +++ b/src/components/chart/scale/scale.js @@ -156,6 +156,53 @@ class Scale { }; } + /** + * Draw Axis Title + * + * @param {object} chartRect min/max information + * @param {object} labelOffset label offset information + * + * @returns {undefined} + */ + drawAxisTitle(chartRect, labelOffset) { + debugger; + const titleOpt = this.title; + + if (!titleOpt?.use || isNaN(titleOpt.fontSize)) { + return; + } + + const ctx = this.ctx; + ctx.save(); + ctx.font = Util.getLabelStyle(titleOpt); + ctx.fillStyle = titleOpt.color; + ctx.textAlign = titleOpt.textAlign; + + const axisLinePosition = { + xLeft: chartRect.x1 + labelOffset.left, + xRight: chartRect.x2 - labelOffset.right, + yTop: chartRect.y1, + }; + + let titleXPos; + let titleYPos; + + const margin = 10; + if (this.type === 'x') { + titleXPos = axisLinePosition.xRight; + titleYPos = chartRect.y2 + titleOpt.fontSize + margin; + } else { + titleYPos = axisLinePosition.yTop - titleOpt.fontSize - margin; + titleXPos = axisLinePosition.xLeft; + } + + if (titleXPos > 0 && titleYPos > 0) { + ctx.fillText(titleOpt.text, titleXPos, titleYPos); + } + + ctx.restore(); + } + /** * Draw axis * @param {object} chartRect min/max information @@ -186,6 +233,8 @@ class Scale { let aliasPixel; + this.drawAxisTitle(chartRect, labelOffset); + // label font 설정 ctx.font = Util.getLabelStyle(this.labelStyle); ctx.fillStyle = this.labelStyle.color; diff --git a/src/components/chart/scale/scale.step.js b/src/components/chart/scale/scale.step.js index eebeb1c72..84a04a13c 100644 --- a/src/components/chart/scale/scale.step.js +++ b/src/components/chart/scale/scale.step.js @@ -89,6 +89,8 @@ class StepScale extends Scale { const offsetCounterPoint = aPos[this.units.rectOffsetCounter(this.position)]; const maxWidth = chartRect.chartWidth / (this.labels.length + 2); + this.drawAxisTitle(chartRect, labelOffset); + if (this.labelStyle?.show) { // label font 설정 ctx.font = Util.getLabelStyle(this.labelStyle); diff --git a/src/components/chart/scale/scale.time.category.js b/src/components/chart/scale/scale.time.category.js index 6aa2bbcac..d04b1783b 100644 --- a/src/components/chart/scale/scale.time.category.js +++ b/src/components/chart/scale/scale.time.category.js @@ -132,6 +132,8 @@ class TimeCategoryScale extends Scale { const offsetPoint = aPos[this.units.rectOffset(this.position)]; const offsetCounterPoint = aPos[this.units.rectOffsetCounter(this.position)]; + this.drawAxisTitle(chartRect, labelOffset); + // label font 설정 ctx.font = Util.getLabelStyle(this.labelStyle); From 226d40454ed931ba0042722e5b8af28d065e5ccd Mon Sep 17 00:00:00 2001 From: jinhee park Date: Mon, 2 May 2022 19:38:12 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[#1156]=20Chart=20>=20Axis=20>=20title=20?= =?UTF-8?q?=EC=98=B5=EC=85=98=20=EC=B6=94=EA=B0=80=20#####################?= =?UTF-8?q?##############=201.=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/chart/scale/scale.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/chart/scale/scale.js b/src/components/chart/scale/scale.js index 08f18af30..5b021b7ac 100644 --- a/src/components/chart/scale/scale.js +++ b/src/components/chart/scale/scale.js @@ -165,7 +165,6 @@ class Scale { * @returns {undefined} */ drawAxisTitle(chartRect, labelOffset) { - debugger; const titleOpt = this.title; if (!titleOpt?.use || isNaN(titleOpt.fontSize)) { From ff9dcccca6dc3df3a88be39d5426fa0b95ff60f5 Mon Sep 17 00:00:00 2001 From: jinhee park Date: Mon, 2 May 2022 19:39:28 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[#1156]=20Chart=20>=20Axis=20>=20title=20?= =?UTF-8?q?=EC=98=B5=EC=85=98=20=EC=B6=94=EA=B0=80=20#####################?= =?UTF-8?q?##############=201.=20=EC=98=A4=ED=83=88=EC=9E=90=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/views/lineChart/example/AxisTitle.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/views/lineChart/example/AxisTitle.vue b/docs/views/lineChart/example/AxisTitle.vue index 2ad22f58d..ef96e222c 100644 --- a/docs/views/lineChart/example/AxisTitle.vue +++ b/docs/views/lineChart/example/AxisTitle.vue @@ -61,7 +61,7 @@ />
- + ", "license": "MIT",