From 73ae0e9683467443d7824546e08ca0a358e9a670 Mon Sep 17 00:00:00 2001 From: jinhee park Date: Fri, 19 Mar 2021 13:55:51 +0900 Subject: [PATCH] =?UTF-8?q?[#786][3.0]=20[3.0]=20chart=20bar=20=EA=B7=B8?= =?UTF-8?q?=EB=9D=BC=EB=8D=B0=EC=9D=B4=EC=85=98=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20##################################=20-=20b?= =?UTF-8?q?ar,=20legend,=20tooltip,=20highlight=20=EB=B6=80=EB=B6=84?= =?UTF-8?q?=EC=97=90=20=EA=B7=B8=EB=9D=BC=EB=8D=B0=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?-=20=EA=B7=B8=EB=9D=BC=EB=8D=B0=EC=9D=B4=EC=85=98=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20Sample=20Code=20=EC=9E=91=EC=84=B1=20=EB=B0=8F=20?= =?UTF-8?q?=EC=84=A4=EB=AA=85=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/views/barChart/api/barChart.md | 15 +++++- docs/views/barChart/example/Gradient.vue | 49 +++++++++++++++++++ docs/views/barChart/props.js | 7 +++ src/components/chart/element/element.bar.js | 30 +++++++++--- .../chart/helpers/helpers.canvas.js | 39 +++++++++++++++ .../chart/plugins/plugins.legend.js | 14 +++++- .../chart/plugins/plugins.tooltip.js | 13 ++++- 7 files changed, 156 insertions(+), 11 deletions(-) create mode 100644 docs/views/barChart/example/Gradient.vue diff --git a/docs/views/barChart/api/barChart.md b/docs/views/barChart/api/barChart.md index 38c68017b..a51dd30fc 100644 --- a/docs/views/barChart/api/barChart.md +++ b/docs/views/barChart/api/barChart.md @@ -23,9 +23,22 @@ |------------ |-----------|---------|-------------------------|---------------------------------------------------| | name | String | series-${index} | 특정 데이터에 대한 시리즈 옵션 | | | type | String | 'bar' | 시리즈에 해당하는 데이터 표현 방식 | 'bar', 'pie', 'line', 'scatter' | - | color | HexCode(String) | COLOR[index] | 사전에 정의된 16개 색상('#2b99f0' ~ '#df6264)을 순차적으로 적용 | | + | color | String or Object | COLOR[index] | 특정 색상을 지정하지 않으면 사전에 정의된 16개 색상('#2b99f0' ~ '#df6264)을 순차적으로 적용 | | | showValue | Object | ([상세](#showvalue)) | 막대 위에 값 표시 여부 및 속성 | | +#### color Example +``` +const chartData = { + series: { + series1: { name: 'series#1' }, // 기본 색상으로 자동 할당 + series2: { name: 'series#2', color: '#FF00FF' }, // 특정 색상 지정 + series3: { name: 'series#3', color: [[0, '#FBC2EB'], [1, '#A6C1EE']] }, // 특정 색상으로 그라데이션 + series4: { name: 'series#3', color: [[], [1, '#ED9B57']] }, // 투명하게 시작하여 특정 색상으로 그라데이션 + }, + ... 생략 +} +``` + #### showValue | 이름 | 타입 | 디폴트 | 설명 | 종류(예시) | | --- | ---- | ----- | --- | ----------| diff --git a/docs/views/barChart/example/Gradient.vue b/docs/views/barChart/example/Gradient.vue new file mode 100644 index 000000000..162d09184 --- /dev/null +++ b/docs/views/barChart/example/Gradient.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/docs/views/barChart/props.js b/docs/views/barChart/props.js index 121a65181..ac29e5ddf 100644 --- a/docs/views/barChart/props.js +++ b/docs/views/barChart/props.js @@ -12,6 +12,8 @@ import Time from './example/Time'; import TimeRaw from '!!raw-loader!./example/Time'; import Event from './example/Event'; import EventRaw from '!!raw-loader!./example/Event'; +import Gradient from './example/Gradient'; +import GradientRaw from '!!raw-loader!./example/Gradient'; export default { mdText, @@ -46,5 +48,10 @@ export default { component: Event, parsedData: parseComponent(EventRaw), }, + Gradient: { + description: '막대에 그라데이션 효과를 줄 수 있습니다.', + component: Gradient, + parsedData: parseComponent(GradientRaw), + }, }, }; diff --git a/src/components/chart/element/element.bar.js b/src/components/chart/element/element.bar.js index de8c9a11f..b0d37fe06 100644 --- a/src/components/chart/element/element.bar.js +++ b/src/components/chart/element/element.bar.js @@ -96,9 +96,6 @@ class Bar { ctx.beginPath(); - const opacity = this.state === 'downplay' ? 0.1 : 1; - ctx.fillStyle = `rgba(${Util.hexToRgb(this.color)},${opacity})` || ''; - this.data.forEach((item, index) => { if (isHorizontal) { categoryPoint = ysp - (cArea * index) - cPad; @@ -128,6 +125,19 @@ class Bar { h = Canvas.calculateY(item.y, minmaxY.graphMin, minmaxY.graphMax, yArea); } + const opacity = this.state === 'downplay' ? 0.1 : 1; + if (typeof this.color !== 'string') { + ctx.fillStyle = Canvas.createGradient( + ctx, + isHorizontal, + { x, y, w, h }, + this.color, + opacity, + ); + } else { + ctx.fillStyle = `rgba(${Util.hexToRgb(this.color)},${opacity})` || ''; + } + ctx.fillRect(x, y, w, isHorizontal ? -h : h); if (showValue.use) { @@ -159,8 +169,7 @@ class Bar { * @returns {undefined} */ itemHighlight(item, context) { - const showValue = this.showValue; - + const { showValue, isHorizontal } = this; const gdata = item.data; const ctx = context; @@ -170,11 +179,18 @@ class Bar { const h = gdata.h; ctx.save(); - ctx.fillStyle = this.color; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.shadowBlur = 4; - ctx.shadowColor = this.color; + + if (typeof this.color !== 'string') { + const grd = Canvas.createGradient(ctx, isHorizontal, { x, y, w, h }, this.color); + ctx.fillStyle = grd; + ctx.shadowColor = this.color[this.color.length - 1][1]; + } else { + ctx.fillStyle = this.color; + ctx.shadowColor = this.color; + } ctx.fillRect(x, y, w, h); diff --git a/src/components/chart/helpers/helpers.canvas.js b/src/components/chart/helpers/helpers.canvas.js index 458bde057..ef79e779b 100644 --- a/src/components/chart/helpers/helpers.canvas.js +++ b/src/components/chart/helpers/helpers.canvas.js @@ -1,3 +1,5 @@ +import Util from './helpers.util'; + export default { /** * Calculate X position @@ -234,4 +236,41 @@ export default { ctx.rect(x, y, width, height); } }, + + /** + * create Linear Gradient + * @param ctx + * @param isHorizontal + * @param positions + * @param stops + * @param opacity + * + * @returns {object} gradient + */ + createGradient(ctx, isHorizontal, positions, stops, opacity = 1) { + const { x, y, w, h } = positions; + let gradient; + + if (isHorizontal) { + gradient = ctx.createLinearGradient(x, 0, x + w, 0); + } else { + gradient = ctx.createLinearGradient(0, y, 0, y + h); + } + + for (let ix = 0; ix < stops.length; ix++) { + let opa; + let stop = stops[ix]; + + if (!stop.length) { + stop = [ix, '#FFFFFF']; + opa = 0; + } else { + opa = opacity; + } + + gradient.addColorStop(stop[0], `rgba(${Util.hexToRgb(stop[1])},${opa})`); + } + + return gradient; + }, }; diff --git a/src/components/chart/plugins/plugins.legend.js b/src/components/chart/plugins/plugins.legend.js index 2b608a4fc..e590d9e93 100644 --- a/src/components/chart/plugins/plugins.legend.js +++ b/src/components/chart/plugins/plugins.legend.js @@ -102,7 +102,12 @@ const modules = { nameDOM.style.color = opt.inactive; } else { this.seriesInfo.count++; - colorDOM.style.backgroundColor = series.color; + if (typeof series.color !== 'string') { + colorDOM.style.backgroundColor = series.color[series.color.length - 1][1]; + } else { + colorDOM.style.backgroundColor = series.color; + } + nameDOM.style.color = opt.color; } @@ -249,7 +254,12 @@ const modules = { nameDOM.series = series; - colorDOM.style.backgroundColor = series.color; + if (typeof series.color !== 'string') { + colorDOM.style.backgroundColor = series.color[series.color.length - 1][1]; + } else { + colorDOM.style.backgroundColor = series.color; + } + colorDOM.dataset.type = 'color'; nameDOM.style.color = opt.color; nameDOM.textContent = series.name; diff --git a/src/components/chart/plugins/plugins.tooltip.js b/src/components/chart/plugins/plugins.tooltip.js index 42dace39d..e2cbd2a5f 100644 --- a/src/components/chart/plugins/plugins.tooltip.js +++ b/src/components/chart/plugins/plugins.tooltip.js @@ -1,5 +1,6 @@ import { numberWithComma } from '@/common/utils'; import debounce from '@/common/utils.debounce'; +import Canvas from '../helpers/helpers.canvas'; import Util from '../helpers/helpers.util'; const modules = { @@ -256,7 +257,17 @@ const modules = { itemY += Util.aliasPixel(itemY); ctx.beginPath(); - ctx.fillStyle = color; + + if (typeof color !== 'string') { + ctx.fillStyle = Canvas.createGradient( + ctx, + isHorizontal, + { x: itemX - 4, y: itemY, w: 12, h: -12 }, + color, + ); + } else { + ctx.fillStyle = color; + } ctx.fillRect(itemX - 4, itemY - 12, 12, 12); ctx.fillStyle = '#FFFFFF';