[]
        
(Showing Draft Content)

깔때기형 차트

깔때기형 차트는 프로세스의 단계를 시각화하고 각 단계별로 진행되는 사용자 또는 항목의 수를 정량화하는 데 사용되는 시각화 도구입니다. 일반적으로 초기 단계에서 최종 단계로 갈수록 데이터 양이 점진적으로 감소하는 깔때기 형태를 취하며, 상단은 넓고 하단으로 갈수록 좁아집니다.

이 기능을 통해 애플리케이션 내에서 판매 파이프라인, 웹사이트 방문자 전환, 채용 과정 등의 흐름을 시각적으로 추적할 수 있으며, 단계별 패턴이나 이탈 지점을 쉽게 파악할 수 있습니다.

SpreadJS에서는 깔때기형 차트의 유형, 색상 팔레트, 그래프 불투명도, 테두리 스타일, 캔버스 여백, 상단 너비, 하단 너비, 목(neck) 높이, 방향, 반전 여부 등 다양한 속성을 수정하여 차트를 추가하고 사용자 지정할 수 있습니다. 이러한 조정은 코드로 프로그래밍 방식으로 수행하거나 SpreadJS 디자이너의 속성 탭을 통해 시각적으로 수행할 수 있어, 개발자와 디자이너 모두에게 유연성을 제공합니다.

아래는 깔때기형 차트의 예시입니다.

2.1.0b686a.png


예제 기반

이 문서의 모든 예제 코드는 아래의 기본 코드 기반 위에서 작성되었으며, 핵심 변수와 데이터 소스 등의 기본 구성을 포함하고 있습니다.

사용자는 필요에 따라 이 구성을 자신만의 사용 사례에 맞게 커스터마이즈할 수 있습니다.

const sheet = spread.getActiveSheet();
sheet.name("Funnel Chart");
const dataManager = spread.dataManager();

function createConversionTable (dataManager) {
    const records = [
        ['Visit', 5350],
        ['View', 3503],
        ['Cart', 1651],
        ['Checkout', 916],
        ['Pay', 587],
    ];
    const columns = ['Stage', 'Count'];

    return dataManager.addTable('Conversion', {
        data: records.map(record => {
            const item = {};
            columns.forEach((column, index) => {
                item[column] = record[index];
            });
            return item;
        })
    });
}

const ConversionTable = createConversionTable(dataManager);
await ConversionTable.fetch();

const dataChart = sheet.dataCharts.add('data-chart', 10, 10, 600, 400);

데이터 바인딩 방식 두 가지

깔때기형 차트는 데이터 바인딩 설정에 따라 두 가지 유형으로 나뉩니다.

카테고리-값(Category-Value) 바인딩

이 방식은 범주형 데이터(예: 프로세스 단계)를 깔때기 구간에 매핑하고, 수치 값을 구간 크기로 사용합니다.

각 구간은 상단 너비 기준으로 표현되며, 측면이 부드럽지 않은 모양을 가집니다.

2.2.9dcc5c.png


카테고리-값 바인딩을 사용하는 깔때기형 차트 예제 코드:

// 카테고리-값 바인딩 깔때기형 차트
dataChart.setChartConfig({
    tableName: 'Conversion',
    plots: [
        {
            type: GC.Spread.Sheets.DataCharts.DataChartType.funnel,
            encodings: {
                values: [{ field: 'Count', aggregate: GC.Spread.Sheets.DataCharts.Aggregate.sum }],
                category: { field: 'Stage' },
            },
        }
    ],
    config: {
        header: {
            title: "Funnel Chart Using Category-Value Binding",
            padding: { left: 10, right: 10, top: 10, bottom: 10 },
            style: {
                fill: { type: 'CssColor', color: 'rgba(255,255,255,0.9)' },
                shadow: { blur: 4, color: 'rgba(0,0,0,0.05)' }
            },
            textStyle: {
                color: 'rgba(30,30,30,1)',
                fontSize: 24,
                fontFamily: 'Calibri',
                fontStyle: GC.Spread.Sheets.DataCharts.FontStyle.italic,
                fontWeight: 'Bold',
                alignment: GC.Spread.Sheets.DataCharts.HAlign.left,
            },
        },
        plotAreas: [{
            legends: [{
                type: GC.Spread.Sheets.DataCharts.LegendType.color,
                textStyle: {
                    fontFamily: 'Calibri',
                    fontSize: 18,
                    fontStyle: GC.Spread.Sheets.DataCharts.FontStyle.italic,
                    fontWeight: 'Bold',
                },
            }],
        }],
    },
});

상세-값(Detail-Value) 바인딩

이 방식은 세부 데이터 필드(예: 하위 단계 메트릭)를 구간 속성에 바인딩하면서, 수치 값은 크기 표현에 사용합니다.

각 구간은 높이 기준으로 표현되며, 상하 구간 너비와 높이 옵션을 조절하여 부드러운 측면을 갖는 형태를 만들 수 있습니다.

2.3.918710.png


상세-값 바인딩을 사용하는 깔때기형 차트 예제 코드:

// 상세-값 바인딩 깔때기형 차트
dataChart.setChartConfig({
    tableName: 'Conversion',
    plots: [
        {
            type: GC.Spread.Sheets.DataCharts.DataChartType.funnel,
            encodings: {
                values: [{ field: 'Count', aggregate: GC.Spread.Sheets.DataCharts.Aggregate.sum }],
                details: [{ field: 'Stage' }],
            },
        }
    ],
    config: {
        header: {
            title: "Funnel Chart Using Detail-Value Binding",
            padding: { left: 10, right: 10, top: 10, bottom: 10 },
            style: {
                fill: { type: 'CssColor', color: 'rgba(255,255,255,0.9)' },
                shadow: { blur: 4, color: 'rgba(0,0,0,0.05)' }
            },
            textStyle: {
                color: 'rgba(30,30,30,1)',
                fontSize: 24,
                fontFamily: 'Calibri',
                fontStyle: GC.Spread.Sheets.DataCharts.FontStyle.italic,
                fontWeight: 'Bold',
                alignment: GC.Spread.Sheets.DataCharts.HAlign.left,
            },
        },
        plotAreas: [{
            legends: [{
                type: GC.Spread.Sheets.DataCharts.LegendType.color,
                textStyle: {
                    fontFamily: 'Calibri',
                    fontSize: 18,
                    fontStyle: GC.Spread.Sheets.DataCharts.FontStyle.italic,
                    fontWeight: 'Bold',
                },
            }],
        }],
    },
});

참고:

카테고리, 세부(detail), 값 데이터를 동시에 바인딩할 경우, 카테고리-값 바인딩만 적용됩니다.


고유 설정

깔때기형 차트는 plots.config.funnel 하위의 특화된 설정을 통해 시각적 구조와 분석 초점을 맞출 수 있습니다.

topWidth, bottomWidth, neckHeight 등의 속성으로 깔때기 구간의 기하학적 진행을 정의하여, 전환율 추세나 자원 분포 패턴을 강조할 수 있습니다.

방향 설정(vertical/horizontal) 및 반전(reversed) 옵션으로 다양한 데이터 스토리텔링에 적합하게 차트를 조정할 수 있으며, funnelType(예: trapezoid, rectangle, triangle) 옵션으로 판매 파이프라인이나 사용자 이탈 분석 등 여러 사용 사례에 적용 가능합니다.

아래 표는 깔때기형 차트 사용자 지정용 속성을 정리한 내용입니다.

속성

설명

지원 모드

샘플 미리보기

funnelType

깔때기형 차트 유형 지정:

  • default: 상단 구간은 사다리꼴, 하단 구간은 직사각형

  • bar: 직사각형으로 렌더링

  • pyramid: 상단 구간은 사다리꼴, 하단 구간은 삼각형

카테고리-값 바인딩

2.4.5cfec7.png

2.5.88a3b5.png

2.6.4e5a65.png

topWidth

깔때기 상단 구간의 상대 너비 설정

상세-값 바인딩

2.7.e337d8.png

bottomWidth

깔때기 하단 구간의 상대 너비 설정

상세-값 바인딩

2.8.bb40c1.png

neckHeight

깔때기 목 구간의 상대 높이 설정

상세-값 바인딩

2.9.fc16a6.png

orientation

깔때기 방향 지정 (horizontal/vertical)

카테고리-값, 상세-값 바인딩

2.10.643ec9.png

reversed

깔때기 반전

카테고리-값, 상세-값 바인딩

2.11.2c49f5.png


코드 사용 예시

아래 코드는 위 속성을 활용하여 카테고리-값 바인딩과 상세-값 바인딩 깔때기형 차트에 맞춤형 모양과 방향 설정을 적용한 예제입니다.

const dataChart1 = sheet.dataCharts.add('data-chart1', 10, 10, 600, 400);
const dataChart2 = sheet.dataCharts.add('data-chart2', 10, 10, 600, 400);

// 카테고리-값 바인딩: 피라미드형 수평 깔때기형 차트
dataChart1.setChartConfig({
    tableName: 'Conversion',
    plots: [
        {
            type: GC.Spread.Sheets.DataCharts.DataChartType.funnel,
            encodings: {
                values: [{ field: 'Count', aggregate: GC.Spread.Sheets.DataCharts.Aggregate.sum }],
                category: { field: 'Stage' },
            },
            config: {
                funnel: {
                    funnelType: GC.Spread.Sheets.DataCharts.FunnelType.pyramid,
                    orientation: GC.Spread.Sheets.DataCharts.Orientation.horizontal,
                },
                palette: ['#2A5CAA', '#4ECDC4', '#FFD700', '#E63946', '#22B573'],
                style: {
                    stroke: { type: 'CssColor', color: '#96CEB4' },
                    strokeWidth: 1,
                    strokeOpacity: 0.5,
                },
                text: [{
                    template: '{valueField.value}',
                    position: GC.Spread.Sheets.DataCharts.TextPosition.center,
                    textStyle: {
                        fontFamily: 'Calibri',
                        fontSize: 20,
                        fontWeight: 'Bold',
                        fontStyle: GC.Spread.Sheets.DataCharts.FontStyle.italic,
                        color: 'rgba(51,51,51,1)',
                    },
                }],
            }
        }
    ],
    config: {
        header: {
            title: "Category-Value Binding: Horizontal Funnel Chart Using Pyramid Type",
            padding: { left: 10, right: 10, top: 10, bottom: 10 },
            textStyle: {
                color: 'rgba(255,255,255,0.9)',
                fontSize: 24,
                fontFamily: 'Calibri',
                fontStyle: GC.Spread.Sheets.DataCharts.FontStyle.italic,
                fontWeight: 'Bold',
                alignment: GC.Spread.Sheets.DataCharts.HAlign.left,
            },
        },
        plotAreas: [{
            padding: { left: 40, right: 40, top: 40, bottom: 40 },
            legends: [{
                type: GC.Spread.Sheets.DataCharts.LegendType.color,
                position: GC.Spread.Sheets.DataCharts.LegendPosition.bottom,
                hAlign: GC.Spread.Sheets.DataCharts.HAlign.center,
                textStyle: {
                    fontFamily: 'Calibri',
                    fontSize: 18,
                    fontStyle: GC.Spread.Sheets.DataCharts.FontStyle.italic,
                    fontWeight: 'Bold',
                    color: 'rgba(255,255,255,1)'
                },
            }],
        }],
        dvStyle: {
            fill: { type: 'CssColor', color: 'black' },
            stroke: { type: 'CssColor', color: 'grey' },
            strokeWidth: 2,
        },
    },
});

// 상세-값 바인딩: 반전 깔때기형 차트 + 커스텀 크기
dataChart2.setChartConfig({
    tableName: 'Conversion',
    plots: [
        {
            type: GC.Spread.Sheets.DataCharts.DataChartType.funnel,
            encodings: {
                values: [{ field: 'Count', aggregate: GC.Spread.Sheets.DataCharts.Aggregate.sum }],
                details: [{ field: 'Stage' }],
            },
            config: {
                funnel: {
                    bottomWidth: 0.4,
                    neckHeight: 0.4,
                    topWidth: 0.8,
                    reversed: true,
                },
                palette: ['#2A5CAA', '#4ECDC4', '#FFD700', '#E63946', '#22B573'],
                style: {
                    stroke: { type: 'CssColor', color: '#96CEB4' },
                    strokeWidth: 1,
                    strokeOpacity: 0.5,
                },
                text: [{
                    template: '{valueField.value}',
                    position: GC.Spread.Sheets.DataCharts.TextPosition.center,
                    textStyle: {
                        fontFamily: 'Calibri',
                        fontSize: 20,
                        fontWeight: 'Bold',
                        fontStyle: GC.Spread.Sheets.DataCharts.FontStyle.italic,
                        color: 'rgba(51,51,51,1)',
                    },
                }],
            }
        }
    ],
    config: {
        header: {
            title: "Detail-Value Binding: Reversed Funnel Chart with Custom Size",
            padding: { left: 10, right: 10, top: 10, bottom: 10 },
            textStyle: {
                color: 'rgba(255,255,255,0.9)',
                fontSize: 24,
                fontFamily: 'Calibri',
                fontStyle: GC.Spread.Sheets.DataCharts.FontStyle.italic,
                fontWeight: 'Bold',
                alignment: GC.Spread.Sheets.DataCharts.HAlign.left,
            },
        },
        plotAreas: [{
            padding: { left: 40, right: 40, top: 40, bottom: 40 },
            legends: [{
                type: GC.Spread.Sheets.DataCharts.LegendType.color,
                textStyle: {
                    fontFamily: 'Calibri',
                    fontSize: 18,
                    fontStyle: GC.Spread.Sheets.DataCharts.FontStyle.italic,
                    fontWeight: 'Bold',
                    color: 'rgba(255,255,255,1)'
                },
            }],
        }],
        dvStyle: {
            fill: { type: 'CssColor', color: 'black' },
        },
    },
});

2.12.824f30.png

2.13.eccb31.png