UNPKG

@toast-ui/chart

Version:

TOAST UI Application: Chart

141 lines (140 loc) 5.8 kB
import Component from "./component"; import { isExportMenuVisible, padding } from "../store/layout"; import { execDownload, downloadSpreadSheet } from "../helpers/downloader"; import { isString } from "../helpers/utils"; import { getFontStyleString, getTranslateString } from "../helpers/style"; const EXPORT_MENU_WIDTH = 140; export const BUTTON_RECT_SIZE = 24; export default class ExportMenu extends Component { constructor() { super(...arguments); this.models = { exportMenuButton: [] }; this.opened = false; this.chartWidth = 0; this.toggleExportMenu = () => { this.opened = !this.opened; this.models.exportMenuButton[0].opened = this.opened; this.eventBus.emit('needDraw'); if (this.opened) { this.applyPanelWrapperStyle(); this.chartEl.appendChild(this.exportMenuEl); } else { this.chartEl.removeChild(this.exportMenuEl); } }; this.getCanvasExportBtnRemoved = () => { const canvas = this.chartEl.getElementsByTagName('canvas')[0]; const ctx = canvas.getContext('2d'); const { x, y, height: h, width: w } = this.rect; ['#fff', this.chartBackgroundColor].forEach((color) => { ctx.fillStyle = color; ctx.fillRect(x, y, w, h); }); return canvas; }; this.onClickExportButton = (ev) => { const { id } = ev.target; if (id === 'png' || id === 'jpeg') { const canvas = this.getCanvasExportBtnRemoved(); execDownload(this.fileName, id, canvas.toDataURL(`image/${id}`, 1)); } else { downloadSpreadSheet(this.fileName, id, this.data); } this.toggleExportMenu(); }; } applyExportButtonPanelStyle() { const exportMenuTitle = this.exportMenuEl.querySelector('.toastui-chart-export-menu-title'); const menuBtnWrapper = this.exportMenuEl.querySelector('.toastui-chart-export-menu-btn-wrapper'); exportMenuTitle.setAttribute('style', this.makePanelStyle('header')); menuBtnWrapper.setAttribute('style', this.makePanelStyle('body')); } makeExportMenuButton() { const el = document.createElement('div'); el.onclick = this.onClickExportButton; el.innerHTML = ` <div class="toastui-chart-export-menu"> <p class="toastui-chart-export-menu-title">Export to</p> <div class="toastui-chart-export-menu-btn-wrapper"> <button class="toastui-chart-export-menu-btn" id="xls">xls</button> <button class="toastui-chart-export-menu-btn" id="csv">csv</button> <button class="toastui-chart-export-menu-btn" id="png">png</button> <button class="toastui-chart-export-menu-btn" id="jpeg">jpeg</button> </div> </div> `; return el; } initialize({ chartEl }) { this.chartEl = chartEl; this.type = 'exportMenu'; this.name = 'exportMenu'; this.exportMenuEl = this.makeExportMenuButton(); } onClick({ responders }) { if (responders.length) { this.toggleExportMenu(); } } getFileName(title) { var _a, _b; return isString(title) ? title : (_b = (_a = title) === null || _a === void 0 ? void 0 : _a.text, (_b !== null && _b !== void 0 ? _b : 'toast-ui-chart')); } render({ options, layout, chart, series, rawCategories, theme }) { var _a, _b; this.isShow = isExportMenuVisible(options); this.chartWidth = chart.width; if (!this.isShow) { return; } this.chartBackgroundColor = theme.chart.backgroundColor; this.theme = theme.exportMenu; this.data = { series, categories: rawCategories }; this.fileName = this.getFileName(((_b = (_a = options) === null || _a === void 0 ? void 0 : _a.exportMenu) === null || _b === void 0 ? void 0 : _b.filename) || chart.title); this.applyExportButtonPanelStyle(); this.rect = layout.exportMenu; this.models.exportMenuButton = [ { type: 'exportMenuButton', x: 0, y: 0, opened: this.opened, theme: this.theme.button, }, ]; this.responders = [ { type: 'rect', width: BUTTON_RECT_SIZE, height: BUTTON_RECT_SIZE, x: 0, y: 0, }, ]; } applyPanelWrapperStyle() { const exportMenu = this.exportMenuEl.querySelector('.toastui-chart-export-menu'); const x = this.chartWidth - EXPORT_MENU_WIDTH - padding.X; const y = padding.Y + BUTTON_RECT_SIZE + 5; const { borderRadius, borderWidth, borderColor } = this.theme.panel; const style = ` transform: ${getTranslateString(x, y)}; border: ${borderWidth}px solid ${borderColor}; border-radius: ${borderRadius}px;`; exportMenu.setAttribute('style', style); } makePanelStyle(type) { const sectionTheme = this.theme.panel[type]; const direction = type === 'header' ? 'top' : 'bottom'; const { borderRadius, borderWidth } = this.theme.panel; const borderRadiusPx = `${borderRadius - borderWidth}px`; return [ `${getFontStyleString(sectionTheme)}`, `border-${direction}-left-radius: ${borderRadiusPx};`, `border-${direction}-right-radius: ${borderRadiusPx};`, `background-color: ${sectionTheme.backgroundColor};`, ].join(''); } }