From 6cf4916174f0454ba6c6196ebc03c6ea2668fa46 Mon Sep 17 00:00:00 2001 From: bingling-sama Date: Tue, 15 Apr 2025 22:01:17 +0800 Subject: [PATCH 1/4] docs: add cell-calendar demo --- .../general/cell/demo/cell-calendar.ts | 83 +++++++++++++++++++ site/examples/general/cell/demo/meta.json | 8 ++ 2 files changed, 91 insertions(+) create mode 100644 site/examples/general/cell/demo/cell-calendar.ts diff --git a/site/examples/general/cell/demo/cell-calendar.ts b/site/examples/general/cell/demo/cell-calendar.ts new file mode 100644 index 0000000000..5499f076be --- /dev/null +++ b/site/examples/general/cell/demo/cell-calendar.ts @@ -0,0 +1,83 @@ +import { Chart } from '@antv/g2'; + +fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/github-commit.json') + .then((res) => res.json()) + .then((data) => { + const chart = new Chart({ + container: 'container', + autoFit: true, + height: 500, + paddingTop: 150, + paddingRight: 30, + paddingBottom: 150, + paddingLeft: 70, + }); + + chart + .scale('x', { type: 'band' }) + .scale('y', { type: 'band' }) + .scale('color', { + domain: [0, 10, 20], + range: ['#BAE7FF', '#1890FF', '#0050B3'], + }); + + // Configure axes + chart.axis('x', { + title: false, + tick: false, + line: false, + label: true, + labelFontSize: 12, + labelFill: '#666', + labelFormatter: (val: string) => { + if (val === '2') return 'MAY'; + if (val === '6') return 'JUN'; + if (val === '10') return 'JUL'; + if (val === '15') return 'AUG'; + if (val === '19') return 'SEP'; + if (val === '24') return 'OCT'; + return ''; + }, + }); + + chart.axis('y', { + title: false, + label: true, + tick: false, + grid: false, + labelFormatter: (val: string) => { + const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; + return days[parseInt(val)]; + }, + }); + + chart.legend(false); + + chart.interaction('tooltip', { + title: 'date', + showMarkers: false, + }); + + chart + .cell() + .data(data) + .encode('x', 'week') + .encode('y', 'day') + .encode('color', 'commits') + .style('inset', 0.5) + .style('stroke', (d: any) => { + if (d.lastWeek && d.lastDay) return '#404040'; + if (d.lastWeek) return '#404040'; + return '#fff'; + }) + .style('lineWidth', (d: any) => { + if (d.lastWeek || d.lastDay) return 2; + return 1; + }) + .state('active', { stroke: '#000', lineWidth: 2 }) + .state('inactive', { opacity: 0.6 }); + + chart.interaction('elementHighlight', true); + + chart.render(); + }); diff --git a/site/examples/general/cell/demo/meta.json b/site/examples/general/cell/demo/meta.json index 4d725574aa..967be50f01 100644 --- a/site/examples/general/cell/demo/meta.json +++ b/site/examples/general/cell/demo/meta.json @@ -12,6 +12,14 @@ }, "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*F8DLSYJAyKQAAAAAAAAAAAAADmJ7AQ/original" }, + { + "filename": "cell-calendar.ts", + "title": { + "zh": "水平日历色块图", + "en": "Calendar heatmap" + }, + "screenshot": "https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*_GtkQo1vCHcAAAAAAAAAAABkARQnAQ" + }, { "filename": "cell-heatmap.ts", "title": { From 337c77e480967290bdc081b2d8ac74fe55c1a412 Mon Sep 17 00:00:00 2001 From: bingling-sama Date: Fri, 18 Apr 2025 18:56:12 +0800 Subject: [PATCH 2/4] docs: add horizontal calendar heatmap example --- .../cell/demo/cell-calendar-horizontal.ts | 82 +++++++++++ .../general/cell/demo/cell-calendar.ts | 128 +++++++++--------- site/examples/general/cell/demo/meta.json | 10 +- 3 files changed, 154 insertions(+), 66 deletions(-) create mode 100644 site/examples/general/cell/demo/cell-calendar-horizontal.ts diff --git a/site/examples/general/cell/demo/cell-calendar-horizontal.ts b/site/examples/general/cell/demo/cell-calendar-horizontal.ts new file mode 100644 index 0000000000..a5c3733044 --- /dev/null +++ b/site/examples/general/cell/demo/cell-calendar-horizontal.ts @@ -0,0 +1,82 @@ +import { Chart } from '@antv/g2'; + +fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/github-commit.json') + .then((res) => res.json()) + .then((data) => { + const chart = new Chart({ + container: 'container', + autoFit: true, + height: 500, + paddingTop: 150, + paddingRight: 30, + paddingBottom: 150, + paddingLeft: 70, + }); + + chart + .scale('x', { type: 'band' }) + .scale('y', { type: 'band' }) + .scale('color', { + domain: [0, 10, 20], + range: ['#BAE7FF', '#1890FF', '#0050B3'], + }); + + chart.axis('x', { + title: false, + tick: false, + line: false, + label: true, + labelFontSize: 12, + labelFill: '#666', + labelFormatter: (val: string) => { + if (val === '2') return 'MAY'; + if (val === '6') return 'JUN'; + if (val === '10') return 'JUL'; + if (val === '15') return 'AUG'; + if (val === '19') return 'SEP'; + if (val === '24') return 'OCT'; + return ''; + }, + }); + + chart.axis('y', { + title: false, + label: true, + tick: false, + grid: false, + labelFormatter: (val: string) => { + const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; + return days[parseInt(val)]; + }, + }); + + chart.legend(false); + + chart.interaction('tooltip', { + title: 'date', + showMarkers: false, + }); + + chart + .cell() + .data(data) + .encode('x', 'week') + .encode('y', 'day') + .encode('color', 'commits') + .style('inset', 0.5) + .style('stroke', (d: any) => { + if (d.lastWeek && d.lastDay) return '#404040'; + if (d.lastWeek) return '#404040'; + return '#fff'; + }) + .style('lineWidth', (d: any) => { + if (d.lastWeek || d.lastDay) return 2; + return 1; + }) + .state('active', { stroke: '#000', lineWidth: 2 }) + .state('inactive', { opacity: 0.6 }); + + chart.interaction('elementHighlight', true); + + chart.render(); + }); diff --git a/site/examples/general/cell/demo/cell-calendar.ts b/site/examples/general/cell/demo/cell-calendar.ts index 5499f076be..7bd41a3360 100644 --- a/site/examples/general/cell/demo/cell-calendar.ts +++ b/site/examples/general/cell/demo/cell-calendar.ts @@ -1,81 +1,79 @@ import { Chart } from '@antv/g2'; -fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/github-commit.json') +// 定义月份名称 +const MONTHS = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', +]; + +fetch( + 'https://gw.alipayobjects.com/os/antvdemo/assets/data/stock-calendar.json', +) .then((res) => res.json()) .then((data) => { + // 获取当前月的第几周,从 0 开始 + function getMonthWeek(date) { + const year = date.getFullYear(); + const month = date.getMonth(); + const monthFirst = new Date(year, month, 0); + const intervalDays = Math.round( + (date.getTime() - monthFirst.getTime()) / 86400000, + ); + const index = Math.floor((intervalDays + monthFirst.getDay()) / 7); + return index; + } + // 加工数据 + // 添加所属月、周几、每个月的第几周 + data.forEach(function (obj) { + const date = new Date(obj['日期']); + const month = date.getMonth(); + obj.month = MONTHS[month]; + obj.day = date.getDay(); + obj.week = getMonthWeek(date).toString(); + }); + const chart = new Chart({ container: 'container', autoFit: true, - height: 500, - paddingTop: 150, - paddingRight: 30, - paddingBottom: 150, - paddingLeft: 70, - }); - - chart - .scale('x', { type: 'band' }) - .scale('y', { type: 'band' }) - .scale('color', { - domain: [0, 10, 20], - range: ['#BAE7FF', '#1890FF', '#0050B3'], - }); - - // Configure axes - chart.axis('x', { - title: false, - tick: false, - line: false, - label: true, - labelFontSize: 12, - labelFill: '#666', - labelFormatter: (val: string) => { - if (val === '2') return 'MAY'; - if (val === '6') return 'JUN'; - if (val === '10') return 'JUL'; - if (val === '15') return 'AUG'; - if (val === '19') return 'SEP'; - if (val === '24') return 'OCT'; - return ''; - }, }); - chart.axis('y', { - title: false, - label: true, - tick: false, - grid: false, - labelFormatter: (val: string) => { - const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; - return days[parseInt(val)]; - }, + chart.scale('涨跌幅', { + domain: [-10, -5, -2, -1, 0, 1, 2, 5, 10], + range: [ + '#F51D27', + '#FA541C', + '#FFBE15', + '#FFF2D1', + '#FFFFFF', + '#E3F6FF', + '#85C6FF', + '#0086FA', + '#0A61D7', + ], }); - chart.legend(false); - - chart.interaction('tooltip', { - title: 'date', - showMarkers: false, - }); + const facetRect = chart + .facetRect() + .data(data) + .encode('x', 'month') + .style('gap', 20); - chart + facetRect .cell() - .data(data) - .encode('x', 'week') - .encode('y', 'day') - .encode('color', 'commits') - .style('inset', 0.5) - .style('stroke', (d: any) => { - if (d.lastWeek && d.lastDay) return '#404040'; - if (d.lastWeek) return '#404040'; - return '#fff'; - }) - .style('lineWidth', (d: any) => { - if (d.lastWeek || d.lastDay) return 2; - return 1; - }) - .state('active', { stroke: '#000', lineWidth: 2 }) - .state('inactive', { opacity: 0.6 }); + .encode('x', 'day') + .encode('y', 'week') + .transform({ type: 'sortY', reverse: true }) + .encode('color', '涨跌幅'); chart.interaction('elementHighlight', true); diff --git a/site/examples/general/cell/demo/meta.json b/site/examples/general/cell/demo/meta.json index 967be50f01..1ef600ea4c 100644 --- a/site/examples/general/cell/demo/meta.json +++ b/site/examples/general/cell/demo/meta.json @@ -13,13 +13,21 @@ "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*F8DLSYJAyKQAAAAAAAAAAAAADmJ7AQ/original" }, { - "filename": "cell-calendar.ts", + "filename": "cell-calendar-horizontal.ts", "title": { "zh": "水平日历色块图", "en": "Calendar heatmap" }, "screenshot": "https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*_GtkQo1vCHcAAAAAAAAAAABkARQnAQ" }, + { + "filename": "cell-calendar.ts", + "title": { + "zh": "日历色块图", + "en": "Calendar heatmap" + }, + "screenshot": "https://gw.alipayobjects.com/mdn/rms_f5c722/afts/img/A*-2ggQ6U5_dIAAAAAAAAAAABkARQnAQ" + }, { "filename": "cell-heatmap.ts", "title": { From f39a8dc118365ba2fa43f58bdac07baa55c7ab1c Mon Sep 17 00:00:00 2001 From: bingling-sama Date: Sat, 19 Apr 2025 00:06:08 +0800 Subject: [PATCH 3/4] docs: improve cell-calendar style --- .../general/cell/demo/cell-calendar.ts | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/site/examples/general/cell/demo/cell-calendar.ts b/site/examples/general/cell/demo/cell-calendar.ts index 7bd41a3360..a638170c54 100644 --- a/site/examples/general/cell/demo/cell-calendar.ts +++ b/site/examples/general/cell/demo/cell-calendar.ts @@ -39,12 +39,19 @@ fetch( const month = date.getMonth(); obj.month = MONTHS[month]; obj.day = date.getDay(); - obj.week = getMonthWeek(date).toString(); + obj.week = getMonthWeek(date); }); + console.log(data); + const chart = new Chart({ container: 'container', autoFit: true, + height: 500, + paddingTop: 150, + paddingRight: 30, + paddingBottom: 150, + paddingLeft: 70, }); chart.scale('涨跌幅', { @@ -65,14 +72,39 @@ fetch( const facetRect = chart .facetRect() .data(data) + .scale('x', { + type: 'band', + compare: (a: string, b: string) => + MONTHS.indexOf(a) - MONTHS.indexOf(b), + }) .encode('x', 'month') .style('gap', 20); facetRect .cell() + .scale('x', { + type: 'band', + compare: (a: number, b: number) => a - b, + }) + .scale('y', { + type: 'band', + compare: (a: number, b: number) => a - b, + }) .encode('x', 'day') + .axis('x', { + title: false, + label: false, + tick: false, + grid: false, + }) .encode('y', 'week') - .transform({ type: 'sortY', reverse: true }) + .axis('y', { + title: false, + label: false, + tick: false, + grid: false, + }) + .transform({ type: 'sortY', by: 'x' }) .encode('color', '涨跌幅'); chart.interaction('elementHighlight', true); From 3836d12c72f9e377d33b5ecba963f79cf0c8da54 Mon Sep 17 00:00:00 2001 From: bingling-sama Date: Sun, 4 May 2025 15:03:01 +0800 Subject: [PATCH 4/4] feat: improve cell calendar style --- .../general/cell/demo/cell-calendar.ts | 76 +++++++++++-------- site/examples/general/cell/demo/meta.json | 12 +-- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/site/examples/general/cell/demo/cell-calendar.ts b/site/examples/general/cell/demo/cell-calendar.ts index a638170c54..ecb698bb89 100644 --- a/site/examples/general/cell/demo/cell-calendar.ts +++ b/site/examples/general/cell/demo/cell-calendar.ts @@ -1,6 +1,6 @@ import { Chart } from '@antv/g2'; -// 定义月份名称 +// 定义月份名称及分类 const MONTHS = [ 'January', 'February', @@ -16,42 +16,52 @@ const MONTHS = [ 'December', ]; +// 预计算月份位置 (1-12月分4行3列排列) +const MONTH_POSITIONS = Array.from({ length: 12 }, (_, month) => { + const monthNum = month + 1; + const row = Math.ceil(monthNum / 3); + const col = ((monthNum - 1) % 3) + 1; + return { + row: String(row), + col: String(col), + }; +}); + fetch( 'https://gw.alipayobjects.com/os/antvdemo/assets/data/stock-calendar.json', ) .then((res) => res.json()) .then((data) => { - // 获取当前月的第几周,从 0 开始 - function getMonthWeek(date) { - const year = date.getFullYear(); - const month = date.getMonth(); - const monthFirst = new Date(year, month, 0); - const intervalDays = Math.round( - (date.getTime() - monthFirst.getTime()) / 86400000, - ); - const index = Math.floor((intervalDays + monthFirst.getDay()) / 7); - return index; - } - // 加工数据 - // 添加所属月、周几、每个月的第几周 - data.forEach(function (obj) { + // 优化数据处理: 减少Date对象创建和计算 + const processedData = data.map((obj) => { const date = new Date(obj['日期']); const month = date.getMonth(); - obj.month = MONTHS[month]; - obj.day = date.getDay(); - obj.week = getMonthWeek(date); - }); + const dayOfMonth = date.getDate(); + + // 计算当前月的第一天是星期几(只计算一次) + const firstDayWeek = new Date(date.getFullYear(), month, 1).getDay(); + const monthPosition = MONTH_POSITIONS[month]; - console.log(data); + return { + ...obj, + date, + month: MONTHS[month], + monthXCategory: monthPosition.col, + monthYCategory: monthPosition.row, + position: `${month + 1}月`, + day: date.getDay(), + week: Math.floor((dayOfMonth + firstDayWeek - 1) / 7), + }; + }); const chart = new Chart({ container: 'container', autoFit: true, - height: 500, - paddingTop: 150, - paddingRight: 30, - paddingBottom: 150, - paddingLeft: 70, + height: 800, + paddingTop: 100, + paddingRight: 40, + paddingBottom: 100, + paddingLeft: 80, }); chart.scale('涨跌幅', { @@ -71,14 +81,13 @@ fetch( const facetRect = chart .facetRect() - .data(data) - .scale('x', { - type: 'band', - compare: (a: string, b: string) => - MONTHS.indexOf(a) - MONTHS.indexOf(b), - }) - .encode('x', 'month') - .style('gap', 20); + .data(processedData) + .scale('x', { type: 'band', compare: (a, b) => Number(a) - Number(b) }) + .scale('y', { type: 'band', compare: (a, b) => Number(a) - Number(b) }) + .encode('x', 'monthXCategory') + .encode('y', 'monthYCategory') + .axis('x', { title: false, label: false, tick: false }) + .axis('y', { title: false, label: false, tick: false }); facetRect .cell() @@ -105,6 +114,7 @@ fetch( grid: false, }) .transform({ type: 'sortY', by: 'x' }) + .attr('frame', false) .encode('color', '涨跌幅'); chart.interaction('elementHighlight', true); diff --git a/site/examples/general/cell/demo/meta.json b/site/examples/general/cell/demo/meta.json index 1ef600ea4c..125f2ca4fb 100644 --- a/site/examples/general/cell/demo/meta.json +++ b/site/examples/general/cell/demo/meta.json @@ -13,20 +13,20 @@ "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*F8DLSYJAyKQAAAAAAAAAAAAADmJ7AQ/original" }, { - "filename": "cell-calendar-horizontal.ts", + "filename": "cell-calendar.ts", "title": { - "zh": "水平日历色块图", + "zh": "日历色块图", "en": "Calendar heatmap" }, - "screenshot": "https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*_GtkQo1vCHcAAAAAAAAAAABkARQnAQ" + "screenshot": "https://gw.alipayobjects.com/mdn/rms_f5c722/afts/img/A*-2ggQ6U5_dIAAAAAAAAAAABkARQnAQ" }, { - "filename": "cell-calendar.ts", + "filename": "cell-calendar-horizontal.ts", "title": { - "zh": "日历色块图", + "zh": "水平日历色块图", "en": "Calendar heatmap" }, - "screenshot": "https://gw.alipayobjects.com/mdn/rms_f5c722/afts/img/A*-2ggQ6U5_dIAAAAAAAAAAABkARQnAQ" + "screenshot": "https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*_GtkQo1vCHcAAAAAAAAAAABkARQnAQ" }, { "filename": "cell-heatmap.ts",