Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#1111] scatter chart > selectItem 옵션 추가 및 tooltip 개선 #1113

Merged
merged 3 commits into from
Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions docs/views/scatterChart/api/scatterChart.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,19 @@
```

>## Props
### 1. data
### 1. v-model:selectedItem
- option에서 [selectItem](#selectitem) 옵션을 사용할 경우 유효한 바인딩
- 현재 선택된 Item에 대한 정보 (seriesID, dataIndex)
#### Example
```
const selectedItem = ref({
seriesID: 'series1', // Series ID (key)
dataIndex: 0, // 몇번째 데이터인지
});
```


### 2. data
| 이름 | 타입 | 디폴트 | 설명 | 종류 |
|------------ |-----------|---------|-------------------------|---------------------------------------------------|
| series | Object | {} | 특정 데이터에 대한 시리즈 옵션 | |
Expand Down Expand Up @@ -42,7 +54,7 @@ const chartData =
};
```

### 2. options
### 3. options
| 이름 | 타입 | 디폴트 | 설명 | 종류(예시) |
|------------ |-----------|---------|-------------------------|---------------------------------------------------|
| type | String | '' | series 별로 type값을 지정하지 않을 경우 일괄 적용될 차트의 타입 | 'bar', 'pie', 'line', 'scatter' |
Expand All @@ -55,6 +67,7 @@ const chartData =
| dragSelection | Object | ([상세](#dragselection)) | drag-select의 사용 여부 | |
| padding | Object | { top: 20, right: 2, left: 2, bottom: 4 } | 차트 내부 padding 값 |
| tooltip | Object | ([상세](#tooltip)) | 차트에 마우스를 올릴 경우 툴팁 표시 여부 및 속성 | |
| selectItem | Object | ([상세](#selectitem)) | 차트 아이템 선택 기능 활성화 여부 및 속성 | |

#### axesX axesY
##### type 공통
Expand Down Expand Up @@ -176,14 +189,27 @@ const chartData =
| showAllValueInRange | Boolean | false | 동일한 axes값을 가진 전체 series를 Tooltip에 표시 |
| formatter | function | null | 데이터가 표시되기 전에 데이터의 형식을 지정하는 데 사용 | ({x, y, name}) => y + '%' |

#### selectItem
| 이름 | 타입 | 디폴트 | 설명 | 종류(예시) |
| --- | ---- | ----- | --- | ----------|
| use | Boolean | false | 차트 아이템 선택 기능 | |
| showTextTip | Boolean | false | 선택한 위치의 TextTip(text 포함 화살표, 흡사 말풍선) 생성 여부 | |
| tipText | String | 'value' | 선택한 위치에 TextTip을 생성한다면 어떤 값 | 'value', 'label |
| showTip | Boolean | false | 선택한 위치의 Tip(화살표) 생성 여부 | |
| showIndicator | Boolean | false | 선택한 label의 indicator 표시 | |
| fixedPosTop | Boolean | false | indicator 및 tip의 위치를 최대값으로 고정 | |
| useApproximateValue | Boolean | false | 가까운 label을 선택 | |
| indicatorColor | Hex, RGB, RGBA Code(String) | '#000000' | indicator 색상 | |
| tipBackground | Hex, RGB, RGBA Code(String) | '#000000' | tip 배경색상 | |
| tipTextColor | Hex, RGB, RGBA Code(String) | '#FFFFFF' | tip 글자 색상 | |
| useSeriesOpacity | Boolean | false | 선택한 항목을 제외한 나머지 항목들에 반투명 효과 적용 여부 | |

### 3. resize-timeout
### 4. resize-timeout
- Default : 0
- debounce 사용. 연속으로 이벤트가 발생한 경우, 마지막 이벤트가 끝난 시점을 기준으로 `주어진 시간 (resize-timeout)` 이후 콜백 실행


>### Event

### 5. Event
| 이름 | 파라미터 | 설명 |
|------|----------|------|
| drag-select | data, range | 그래프에서 드래그를 해서 선택영역 안의 데이터와 선택영역에 대한 범위 값을 얻을 수 있다. <br><br> ex) data : [{ seriesName, seriesId, items: [] }, {...}, {...}] <br> ex) range : { xMin, xMax, yMin, yMax } <br><br> data의 요소 propery중 items 는 해당 Series의 데이터 들이 있으며 x, y값은 데이터 기반 <xp, yp 는 Canvas기반의 좌표 값 |
Expand Down
4 changes: 0 additions & 4 deletions docs/views/scatterChart/example/Default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@
setup() {
const pointSize = ref(3);
const pointStyle = ref('circle');
const seriesCount = ref(3);
const xAxisDataCount = ref(10);

const pointStyleList = [{
name: 'Circle (Default)',
Expand Down Expand Up @@ -183,8 +181,6 @@
pointStyleList,
chartData,
chartOptions,
seriesCount,
xAxisDataCount,
};
},
};
Expand Down
154 changes: 154 additions & 0 deletions docs/views/scatterChart/example/SelectItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<template>
<div class="case">
<ev-chart
v-model:selectedItem="defaultSelectItem"
:data="chartData"
:options="chartOptions"
@click="onClick"
/>
<div class="description">
<div class="row">
<div class="row-item">
<label class="item-title"> showTextTip </label>
<ev-toggle v-model="showTextTip"/>
</div>
<div class="row-item">
<label class="item-title"> showTip </label>
<ev-toggle v-model="showTip"/>
</div>
<div class="row-item">
<label class="item-title"> showIndicator </label>
<ev-toggle v-model="showIndicator"/>
</div>
<div class="row-item">
<label class="item-title"> useSeriesOpacity </label>
<ev-toggle v-model="useSeriesOpacity"/>
</div>
</div>
<div class="row">
<div class="badge yellow"> 기본 선택값 v-model </div>
{{ defaultSelectItem }}
</div>
<div class="row">
<div class="badge yellow"> 클릭된 Item 정보 </div>
{{ clickedInfo }}
</div>
</div>
</div>
</template>

<script>
import { ref, reactive } from 'vue';

export default {
setup() {
const chartData = reactive({
series: {
series1: { name: 'series#1' },
series2: { name: 'series#2' },
},
data: {
series1: [
{ x: 134, y: 51 }, { x: 67, y: 59 }, { x: 19, y: 49 },
{ x: 15, y: 63 }, { x: 55, y: 53 }, { x: 161, y: 51 },
{ x: 167, y: 59 }, { x: 159, y: 49 }, { x: 157, y: 63 },
{ x: 155, y: 53 }, { x: 170, y: 59 }, { x: 159, y: 47 },
{ x: 166, y: 69 }, { x: 176, y: 66 }, { x: 160, y: 75 },
{ x: 172, y: 55 }, { x: 170, y: 54 }, { x: 172, y: 62 },
{ x: 153, y: 42 }, { x: 160, y: 50 }, { x: 147, y: 49 },
{ x: 168, y: 49 }, { x: 175, y: 73 }, { x: 157, y: 47 },
{ x: 167, y: 68 }, { x: 159, y: 50 }, { x: 175, y: 82 },
{ x: 166, y: 57 }, { x: 176, y: 87 }, { x: 170, y: 72 },
],
series2: [
{ x: 9, y: 51 }, { x: 72, y: 59 }, { x: 0, y: 49 },
{ x: 57, y: 63 }, { x: 15, y: 53 }, { x: 174, y: 65 },
{ x: 175, y: 71 }, { x: 200, y: 80 }, { x: 186, y: 72 },
{ x: 187, y: 78 }, { x: 181, y: 74 }, { x: 184, y: 86 },
{ x: 184, y: 78 }, { x: 175, y: 62 }, { x: 184, y: 81 },
{ x: 180, y: 76 }, { x: 177, y: 83 }, { x: 192, y: 90 },
{ x: 176, y: 74 }, { x: 174, y: 71 }, { x: 184, y: 79 },
{ x: 192, y: 93 }, { x: 171, y: 70 }, { x: 173, y: 72 },
{ x: 176, y: 85 }, { x: 176, y: 78 }, { x: 180, y: 77 },
{ x: 172, y: 66 }, { x: 176, y: 86 }, { x: 173, y: 81 },
],
},
});

const showTextTip = ref(false);
const showTip = ref(false);
const showIndicator = ref(false);
const useSeriesOpacity = ref(false);
const fixedPosTop = ref(false);

const chartOptions = reactive({
type: 'scatter',
axesX: [{
type: 'linear',
}],
axesY: [{
type: 'linear',
}],
tooltip: {
use: true,
},
selectItem: {
use: true,
showTip,
showTextTip,
fixedPosTop,
showIndicator,
useSeriesOpacity,
},
});

const defaultSelectItem = ref({
seriesID: 'series1',
dataIndex: 1,
});

const clickedInfo = ref("''");
const onClick = (target) => {
clickedInfo.value = target;
};

return {
chartData,
chartOptions,
defaultSelectItem,
showTip,
fixedPosTop,
showTextTip,
showIndicator,
useSeriesOpacity,
clickedInfo,
onClick,
};
},
};
</script>

<style lang="scss" scoped>
.description-label {
vertical-align: top;
margin-right: 3px;
}

.row {
display: flex;
margin-bottom: 15px;
justify-content: space-between;

.row-item {
flex: 1;
display: flex;
align-items: center;

.item-title {
line-height: 33px;
margin-right: 3px;
min-width: 80px;
}
}
}
</style>
7 changes: 7 additions & 0 deletions docs/views/scatterChart/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Default from './example/Default';
import DefaultRaw from '!!raw-loader!./example/Default';
import Event from './example/Event';
import EventRaw from '!!raw-loader!./example/Event';
import SelectItem from './example/SelectItem';
import SelectItemRaw from '!!raw-loader!./example/SelectItem';
import PlotLine from './example/PlotLine';
import PlotLineRaw from '!!raw-loader!./example/PlotLine';

Expand All @@ -15,6 +17,11 @@ export default {
component: Default,
parsedData: parseComponent(DefaultRaw),
},
SelectItem: {
description: 'Point를 선택 표시할 수 있습니다.',
component: SelectItem,
parsedData: parseComponent(SelectItemRaw),
},
Event: {
description: 'Drag Select, Click, Double Click 이벤트 등록이 가능 합니다',
component: Event,
Expand Down
85 changes: 62 additions & 23 deletions src/components/chart/chart.core.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class EvChart {
* @returns {undefined}
*/
drawSeries(hitInfo) {
const { maxTip, selectLabel } = this.options;
const { maxTip, selectLabel, selectItem } = this.options;

const opt = {
ctx: this.bufferCtx,
Expand Down Expand Up @@ -181,30 +181,69 @@ class EvChart {
for (let jx = 0; jx < chartTypeSet.length; jx++) {
const series = this.seriesList[chartTypeSet[jx]];

if (chartType === 'line' || chartType === 'scatter' || chartType === 'heatMap') {
series.draw(opt);
} else if (chartType === 'bar') {
const { thickness, borderRadius } = this.options;
series.draw({ thickness, borderRadius, showSeriesCount, showIndex, ...opt });

if (series.show) {
showIndex++;
switch (chartType) {
case 'line':
case 'heatMap': {
series.draw(opt);
break;
}
} else {
const selectInfo = hitInfo
?? this.lastHitInfo
?? { sId: this.defaultSelectItemInfo?.seriesID };

if (this.options.sunburst) {
this.drawSunburst(selectInfo);
} else {
this.drawPie(selectInfo);
case 'bar': {
const { thickness, borderRadius } = this.options;
series.draw({ thickness, borderRadius, showSeriesCount, showIndex, ...opt });
if (series.show) {
showIndex++;
}
break;
}

if (this.options.doughnutHoleSize > 0) {
this.drawDoughnutHole();
case 'pie': {
const selectInfo = hitInfo
?? this.lastHitInfo
?? { sId: this.defaultSelectItemInfo?.seriesID };

if (this.options.sunburst) {
this.drawSunburst(selectInfo);
} else {
this.drawPie(selectInfo);
}

if (this.options.doughnutHoleSize > 0) {
this.drawDoughnutHole();
}
break;
}
case 'scatter': {
if (selectItem.use && selectItem.useSeriesOpacity) {
if (hitInfo) {
if (hitInfo?.maxIndex || hitInfo?.maxIndex === 0) {
opt.selectInfo = {
seriesID: hitInfo.sId,
dataIndex: hitInfo.maxIndex,
};
} else {
opt.selectInfo = null;
}
} else if (this.lastHitInfo?.maxIndex || this.lastHitInfo?.maxIndex === 0) {
opt.selectInfo = {
seriesID: this.lastHitInfo.sId,
dataIndex: this.lastHitInfo.maxIndex,
};
} else if (this.defaultSelectItemInfo?.dataIndex
|| this.defaultSelectItemInfo?.dataIndex === 0) {
opt.selectInfo = {
seriesID: this.defaultSelectItemInfo.seriesID,
dataIndex: this.defaultSelectItemInfo.dataIndex,
};
} else {
opt.selectInfo = null;
}
}

series.draw(opt);
break;
}
default: {
break;
}
break;
}
}
}
Expand Down Expand Up @@ -621,7 +660,7 @@ class EvChart {
this.labelOffset = this.getLabelOffset();
this.initSelectedLabelInfo();

this.render();
this.render(updateInfo?.hitInfo);

const isDragMove = this.dragInfo && this.drawSelectionArea;
if (isDragMove) {
Expand Down
Loading