Skip to content

Commit

Permalink
[#1268] Chart > Brush 기능
Browse files Browse the repository at this point in the history
######################################
 - zoom 영역을 고정하여 움직이는 기능
  • Loading branch information
Mun94 committed Sep 14, 2022
1 parent 4d3be27 commit c39fd06
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 33 deletions.
3 changes: 0 additions & 3 deletions docs/views/zoomChart/example/ChartBrush.vue
Original file line number Diff line number Diff line change
Expand Up @@ -196,15 +196,12 @@ export default {
show: true,
chartIdx: 0,
height: 100,
buttonColor: '#FF0000',
});
const brushOptions2 = reactive({
show: true,
chartIdx: 1,
height: 100,
buttonColor: '#FF0000',
});
const addRandomChartData = () => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/chart/chartZoom.core.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ export default class EvChartZoom {
);
}

if (!this.brushIdx.isExecutedByBrush) {
if (!this.brushIdx.isExecutedByButton && !this.brushIdx.isExecutedByWheel) {
this.brushIdx.start = zoomStartIdx;
this.brushIdx.end = zoomEndIdx;
}
Expand Down
44 changes: 42 additions & 2 deletions src/components/chart/plugins/plugins.interaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ const modules = {
}
} else {
const isCurMouseXInsideBrushBtn = xPos =>
e.offsetX + this.evBrushChartPos.width >= this.evBrushChartPos[xPos]
&& e.offsetX - this.evBrushChartPos.width <= this.evBrushChartPos[xPos];
e.offsetX + this.evBrushChartPos.buttonWidth >= this.evBrushChartPos[xPos]
&& e.offsetX - this.evBrushChartPos.buttonWidth <= this.evBrushChartPos[xPos];

if (isCurMouseXInsideBrushBtn('leftX')) {
this.overlayCanvas.style['z-index'] = 1;
Expand Down Expand Up @@ -85,7 +85,47 @@ const modules = {
*
* @returns {undefined}
*/

const onBrushMoveWheel = (e) => {
if (this.isUseZoomMode.value) {
e.preventDefault();
this.brushIdx.isExecutedByWheel = true;
if (this.brushIdx.start === this.brushIdx.end) {
return;
}

if (e.deltaY > 0) {
if (!this.brushIdx.start) {
return;
}

this.brushIdx.start -= 1;
this.brushIdx.end -= 1;
} else {
if (this.brushIdx.end === this.data.labels.length - 1) {
return;
}

this.brushIdx.start += 1;
this.brushIdx.end += 1;
}
}
};

const onMouseOver = () => {
this.overlayCanvas.addEventListener('wheel', onBrushMoveWheel);
};

if (this.options.brush) {
this.overlayCanvas.addEventListener('mouseover', onMouseOver);
}

this.onMouseLeave = () => {
if (this.options.brush) {
this.overlayCanvas.removeEventListener('mouseover', onMouseOver);
this.brushIdx.isExecutedByWheel = false;
}

const { tooltip, dragSelection } = this.options;

if (tooltip.throttledMove) {
Expand Down
33 changes: 30 additions & 3 deletions src/components/chart/uses.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ref, computed, getCurrentInstance, nextTick, reactive, onUpdated } from 'vue';
import { ref, computed, getCurrentInstance, nextTick, reactive, onUpdated, watch } from 'vue';
import { cloneDeep, defaultsDeep, isEqual } from 'lodash-es';
import { getQuantity } from '@/common/utils';
import EvChartZoom from '@/components/chart/chartZoom.core';
Expand Down Expand Up @@ -304,7 +304,12 @@ export const useZoomModel = (
const evChartToolbarRef = ref();

const evChartZoomOptions = reactive({ zoom: evChartNormalizedOptions.zoom });
const brushIdx = reactive({ start: 0, end: 0, isExecutedByBrush: false });
const brushIdx = reactive({
start: 0,
end: 0,
isExecutedByButton: false,
isExecutedByWheel: false,
});

let evChartZoom = null;
const evChartInfo = reactive({
Expand Down Expand Up @@ -476,7 +481,7 @@ export const useZoomModel = (
};

const controlZoomIdx = (zoomStartIdx, zoomEndIdx) => {
if (evChartZoom.isExecutedByToolbar && !brushIdx.isExecutedByBrush) {
if (evChartZoom.isExecutedByToolbar) {
evChartZoom.isExecutedByToolbar = false;
return;
}
Expand All @@ -487,6 +492,28 @@ export const useZoomModel = (
}
};

watch(() => [
brushIdx.start,
brushIdx.end,
], () => {
if (!brushIdx.isExecutedByButton && !brushIdx.isExecutedByWheel) {
return;
}

evChartZoom.executeZoom(brushIdx.start, brushIdx.end);
});

watch(() => [
brushIdx.isExecutedByButton,
brushIdx.isExecutedByWheel,
], (newVal, oldVal) => {
if (oldVal[0] && !newVal[0]) {
evChartZoom.setZoomAreaMemory(brushIdx.start, brushIdx.end);
} else if (oldVal[1] && !newVal[1]) {
evChartZoom.zoomAreaMemory.current[0] = [brushIdx.start, brushIdx.end];
}
});

return {
evChartZoomOptions,
evChartInfo,
Expand Down
8 changes: 6 additions & 2 deletions src/components/chartBrush/ChartBrush.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ export default {
let evChartBrush = null;
const injectEvChartClone = inject('evChartClone', { data: [], options: [] });
const injectBrushIdx = inject('brushIdx', { start: 0, end: 0, isExecutedByBrush: false });
const injectBrushIdx = inject('brushIdx', {
start: 0,
end: 0,
isExecutedByButton: false,
isExecutedByWheel: false,
});
const injectIsUseZoomMode = inject('isUseZoomMode', false);
const {
Expand All @@ -55,7 +60,6 @@ export default {
const option = {
...(injectEvChartClone.options ?? [])[evChartBrushOptions.value.chartIdx],
brush: true,
brushButtonColor: evChartBrushOptions.value.buttonColor,
height: evChartBrushOptions.value.height,
title: {
show: false,
Expand Down
30 changes: 16 additions & 14 deletions src/components/chartBrush/chartBrush.core.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export default class EvChartBrush {
this.isUseZooMode = isUseZoomMode;
this.brushIdx = brushIdx;
this.evChartBrushRef = evChartBrushRef;

this.evChart.brushIdx = brushIdx;
this.evChart.isUseZoomMode = isUseZoomMode;
}

init(isResize) {
Expand Down Expand Up @@ -70,8 +73,8 @@ export default class EvChartBrush {
this.evBrushChartPos = {
leftX: (brushButtonLeftXPos / pixelRatio) + evChartRange.x1,
rightX: (brushButtonRightXPos / pixelRatio) + evChartRange.x1,
width: brushButtonWidth,
leftLabelX: evChartRange.x1 - (brushButtonWidth / 2),
buttonWidth: brushButtonWidth,
x1: evChartRange.x1 - (brushButtonWidth / 2),
axesXInterval,
};
this.evChart.evBrushChartPos = this.evBrushChartPos;
Expand Down Expand Up @@ -101,9 +104,6 @@ export default class EvChartBrush {
ctx.fillStyle = this.evChartOption.value.dragSelection.fillColor;
ctx.globalAlpha = this.evChartOption.value.dragSelection.opacity;
ctx.fillRect(brushRectX, 0, brushRectWidth, brushRectHeight);

ctx.globalAlpha = 1;
ctx.fillStyle = this.evChartOption.value.brushButtonColor;
ctx.fillRect(brushButtonLeftXPos, 0, brushButtonWidth, brushRectHeight);
ctx.fillRect(brushButtonRightXPos, 0, brushButtonWidth, brushRectHeight);
}
Expand Down Expand Up @@ -132,9 +132,9 @@ export default class EvChartBrush {
}

if (!curClickButtonType) {
this.brushIdx.isExecutedByBrush = true;
this.brushIdx.isExecutedByButton = true;
const calDisToCurMouseX = xPos => Math.abs(
evBrushChartPos[xPos] - evBrushChartPos.leftLabelX - e.offsetX,
evBrushChartPos[xPos] - evBrushChartPos.x1 - e.offsetX,
);

curClickButtonType = calDisToCurMouseX('rightX') > calDisToCurMouseX('leftX') ? 'leftX' : 'rightX';
Expand All @@ -144,7 +144,7 @@ export default class EvChartBrush {
const brushButtonSensitivity = evBrushChartPos.axesXInterval / 3;
if (e.offsetX > beforeMouseXPos) {
const isMoveRight = e.offsetX - (
evBrushChartPos[curClickButtonType] - evBrushChartPos.leftLabelX
evBrushChartPos[curClickButtonType] - evBrushChartPos.x1
) > brushButtonSensitivity;

if (isMoveRight && curClickButtonType === 'leftX') {
Expand All @@ -158,7 +158,7 @@ export default class EvChartBrush {
}
} else if (e.offsetX < beforeMouseXPos) {
const isMoveLeft = evBrushChartPos[curClickButtonType]
- evBrushChartPos.leftLabelX - e.offsetX > brushButtonSensitivity;
- evBrushChartPos.x1 - e.offsetX > brushButtonSensitivity;

if (isMoveLeft && curClickButtonType === 'leftX') {
if (this.brushIdx.start !== 0) {
Expand All @@ -174,9 +174,9 @@ export default class EvChartBrush {
beforeMouseXPos = e.offsetX;
} else {
const moveRight = xPos =>
e.offsetX + evBrushChartPos.leftLabelX - evBrushChartPos.width > evBrushChartPos[xPos];
e.offsetX + evBrushChartPos.x1 - evBrushChartPos.buttonWidth > evBrushChartPos[xPos];
const moveLeft = xPos =>
e.offsetX + evBrushChartPos.leftLabelX + evBrushChartPos.width < evBrushChartPos[xPos];
e.offsetX + evBrushChartPos.x1 + evBrushChartPos.buttonWidth < evBrushChartPos[xPos];

const isCurMouseXOutsideBrush = moveLeft('leftX') || moveRight('rightX');
const isCurMouseXInsideBrush = moveRight('leftX') && moveLeft('rightX');
Expand All @@ -200,18 +200,20 @@ export default class EvChartBrush {

const initState = () => {
brushCanvas.style.cursor = 'initial';
this.brushIdx.isExecutedByBrush = false;
this.brushIdx.isExecutedByButton = false;
isClickBrushButton = false;
beforeMouseXPos = 0;
curClickButtonType = null;
};

const onMouseUp = () => {
initState();
initState();
};

const onMouseLeave = () => {
initState();
if (isClickBrushButton) {
initState();
}
};

brushCanvas.addEventListener('mousemove', throttle(onMouseMove, 50));
Expand Down
1 change: 0 additions & 1 deletion src/components/chartBrush/uses.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ const DEFAULT_OPTIONS = {
show: true,
chartIdx: 0,
height: 100,
buttonColor: '',
};

// eslint-disable-next-line import/prefer-default-export
Expand Down
10 changes: 3 additions & 7 deletions src/components/chartGroup/ChartGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,11 @@ export default {
}, { deep: true });
watch(() => [props.zoomStartIdx, props.zoomEndIdx], ([zoomStartIdx, zoomEndIdx]) => {
if (!brushIdx.isExecutedByBrush) {
controlZoomIdx(zoomStartIdx, zoomEndIdx);
if (brushIdx.isExecutedByButton || brushIdx.isExecutedByWheel) {
return;
}
});
watch(() => [brushIdx.start, brushIdx.end], ([brushStartIdx, brushEndIdx]) => {
if (brushIdx.isExecutedByBrush) {
controlZoomIdx(brushStartIdx, brushEndIdx);
}
controlZoomIdx(zoomStartIdx, zoomEndIdx);
});
return {
Expand Down

0 comments on commit c39fd06

Please sign in to comment.