@alicloud/cloud-charts
Version:

304 lines (290 loc) • 13 kB
JavaScript
import React, { useState, useEffect, useRef } from 'react';
import { PrefixName } from '../../../constants';
import themes from '../../../themes';
import { filterLegend, highlightLegend, clearHighlight } from '../../../common/chartRefs';
import WidgetsTooltip from '../../../common/Tooltip';
import LegendMarker from '../../../common/LegendMarker';
import "./index.css";
var prefix = PrefixName + "-foldable-legend";
export default function FolableLegend(_ref) {
var config = _ref.config,
chart = _ref.chart,
_ref$legendItems = _ref.legendItems,
legendItems = _ref$legendItems === void 0 ? [] : _ref$legendItems;
// @ts-ignore
var widgetsCtx = chart.widgetsCtx;
var hoverable = config.hoverable,
clickable = config.clickable,
useReverseChecked = config.useReverseChecked;
// 是否需要折叠
var _useState = useState(false),
foldable = _useState[0],
setFoldable = _useState[1];
// 当前是否折叠
var _useState2 = useState(true),
folded = _useState2[0],
setFolded = _useState2[1];
// 显示的元素个数
var _useState3 = useState(0),
num = _useState3[0],
setNum = _useState3[1];
var contentRef = useRef(null);
// legendItems的缓存,用于比较是否变化
var itemsCache = useRef([]);
var containerWidth = widgetsCtx === null || widgetsCtx === void 0 ? void 0 : widgetsCtx.size[0];
var containerHeight = (widgetsCtx === null || widgetsCtx === void 0 ? void 0 : widgetsCtx.size[1]) || 200;
var _useState4 = useState(''),
activedItem = _useState4[0],
setActivedItem = _useState4[1];
var _useState5 = useState([]),
filteredItems = _useState5[0],
setFilteredItems = _useState5[1];
var legendField = (widgetsCtx === null || widgetsCtx === void 0 ? void 0 : widgetsCtx.legendField) || 'type';
// legend items变化时,重新计算legend
useEffect(function () {
var _itemsCache$current, _itemsCache$current2;
// 深比较legend items的数量与名称是否改变
if (((_itemsCache$current = itemsCache.current) === null || _itemsCache$current === void 0 ? void 0 : _itemsCache$current.length) !== (legendItems === null || legendItems === void 0 ? void 0 : legendItems.length) || (_itemsCache$current2 = itemsCache.current) !== null && _itemsCache$current2 !== void 0 && _itemsCache$current2.some(function (item, index) {
return item.name !== legendItems[index].name;
})) {
handleFold();
setFilteredItems([]);
itemsCache.current = legendItems;
}
}, [legendItems]);
// 图表尺寸变化时,修改legend尺寸,重新变成折叠状
// useEffect(() => {
// handleFold();
// }, [containerHeight, containerWidth, config]);
useEffect(function () {
setFilteredItems([]);
}, [config]);
// 点击高亮legend
useEffect(function () {
filterLegend(chart, function (value) {
return !filteredItems.includes(value);
}, legendField);
}, [filteredItems]);
// hover高亮legend
var activeItem = function activeItem(itemName) {
highlightLegend(chart, function (value) {
return value === itemName;
}, legendField);
};
// 清除高亮
var clearActive = function clearActive() {
clearHighlight(chart);
};
useEffect(function () {
clearActive();
if (activedItem) {
activeItem(activedItem);
}
}, [activedItem]);
var renderItem = function renderItem(item, index, config) {
var name = item.name,
marker = item.marker;
var id = item.id || name;
if (config !== null && config !== void 0 && config.itemName) {
var _config$itemName, _config$itemName$form;
name = config === null || config === void 0 ? void 0 : (_config$itemName = config.itemName) === null || _config$itemName === void 0 ? void 0 : (_config$itemName$form = _config$itemName.formatter) === null || _config$itemName$form === void 0 ? void 0 : _config$itemName$form.call(_config$itemName, name, index, item);
}
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
className: prefix + "-marker",
onClick: function onClick(event) {
if (filteredItems.includes(id)) {
setFilteredItems(function (pre) {
return pre.filter(function (filteredItem) {
return filteredItem !== id;
});
});
} else if (filteredItems.length !== legendItems.length - 1) {
setFilteredItems(function (pre) {
return [].concat(pre, [id]);
});
clearActive();
} else {
setFilteredItems([]);
}
event.stopPropagation();
}
}, /*#__PURE__*/React.createElement(LegendMarker, {
marker: marker,
disable: filteredItems.includes(id)
})), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(LegendName, {
name: name,
style: {
maxWidth: containerWidth - 16 - 16 - 4
// fontWeight: activedItem === id ? 500 : 'normal',
// color:
// activedItem === id ? themes['widgets-legend-text-highlight'] : themes['widgets-legend-text-normal'],
}
})));
};
// 判断是否需要折叠及折叠的元素个数
useEffect(function () {
var _contentRef$current;
if (!(contentRef !== null && contentRef !== void 0 && contentRef.current)) {
return;
}
setFoldable((contentRef === null || contentRef === void 0 ? void 0 : (_contentRef$current = contentRef.current) === null || _contentRef$current === void 0 ? void 0 : _contentRef$current.scrollHeight) !== 20);
var childrenNodes = contentRef.current.children;
var index = 0;
for (index = 0; index < childrenNodes.length; index++) {
if (childrenNodes[index].offsetTop >= 20) {
break;
}
}
setNum(index);
}, [containerWidth, legendItems]);
// 展开所有items
var handleUnfold = function handleUnfold() {
var _chart$getCanvas$get, _chart$getCanvas$get$, _contentRef$current2;
widgetsCtx.legendFolded = false;
// 图表高度缩小
var chartDom = (_chart$getCanvas$get = chart.getCanvas().get('el')) === null || _chart$getCanvas$get === void 0 ? void 0 : (_chart$getCanvas$get$ = _chart$getCanvas$get.parentNode) === null || _chart$getCanvas$get$ === void 0 ? void 0 : _chart$getCanvas$get$.parentNode;
var height = containerHeight - Math.min(contentRef === null || contentRef === void 0 ? void 0 : (_contentRef$current2 = contentRef.current) === null || _contentRef$current2 === void 0 ? void 0 : _contentRef$current2.scrollHeight, containerHeight * 0.3);
// @ts-ignore
if (chartDom) {
chartDom.style.height = height + "px";
try {
chart.changeSize(containerWidth, height);
} catch (e) {
// 业务不透出错误,这里用于调试开放
// console.log('changeSize error', e);
}
}
setFolded(false);
};
// 折叠当前items
var handleFold = function handleFold() {
var _chart$getCanvas$get2, _chart$getCanvas$get3;
widgetsCtx.legendFolded = true;
// 图表高度恢复
var chartDom = (_chart$getCanvas$get2 = chart.getCanvas().get('el')) === null || _chart$getCanvas$get2 === void 0 ? void 0 : (_chart$getCanvas$get3 = _chart$getCanvas$get2.parentNode) === null || _chart$getCanvas$get3 === void 0 ? void 0 : _chart$getCanvas$get3.parentNode;
if (chartDom) {
var height = containerHeight - 20;
// @ts-ignore
chartDom.style.height = height + "px";
try {
chart.changeSize(containerWidth, height);
} catch (e) {
// 业务不透出错误,这里用于调试开放
// console.log('changeSize error', e);
}
// 滚动到最上方
if (contentRef.current) {
contentRef.current.scrollTop = 0;
}
setFolded(true);
}
};
return /*#__PURE__*/React.createElement("div", {
className: prefix + "-container"
}, /*#__PURE__*/React.createElement("div", {
ref: contentRef,
className: prefix + "-content",
style: {
maxHeight: folded ? 20 : containerHeight * 0.3,
overflowY: !folded ? 'auto' : 'hidden'
}
}, legendItems.map(function (item, index) {
var id = item.id || item.name;
return /*#__PURE__*/React.createElement("div", {
key: id,
className: prefix + "-item",
style: {
color: !filteredItems.includes(id) ? activedItem === id ? themes['widgets-legend-text-highlight'] : themes['widgets-legend-text-normal'] : themes['widgets-color-disable']
},
onMouseEnter: function onMouseEnter() {
if (hoverable && !filteredItems.includes(id)) {
setActivedItem(id);
}
},
onMouseLeave: function onMouseLeave() {
if (hoverable && !filteredItems.includes(id)) {
setActivedItem('');
}
},
onClick: function onClick(event) {
// 是否按Control
var hasControl = event.ctrlKey || event.metaKey;
if (clickable) {
if (!useReverseChecked && !hasControl || useReverseChecked && hasControl) {
// 正选
if ((filteredItems === null || filteredItems === void 0 ? void 0 : filteredItems.length) === (legendItems === null || legendItems === void 0 ? void 0 : legendItems.length) - 1 && !filteredItems.includes(id)) {
setFilteredItems([]);
} else {
setFilteredItems(legendItems.map(function (item) {
return item.id || item.name;
}).filter(function (legendName) {
return legendName !== id;
}));
}
} else {
// 反选
if ((filteredItems === null || filteredItems === void 0 ? void 0 : filteredItems.length) === (legendItems === null || legendItems === void 0 ? void 0 : legendItems.length) - 1 && !filteredItems.includes(id)) {
setFilteredItems([]);
} else if (filteredItems.includes(id)) {
setFilteredItems(function (pre) {
return pre.filter(function (p) {
return p !== id;
});
});
} else {
setFilteredItems(function (pre) {
return [].concat(pre, [id]);
});
}
}
}
}
}, renderItem(item, index, config));
})), foldable && folded && /*#__PURE__*/React.createElement("div", {
className: prefix + "-more",
onClick: handleUnfold
}, /*#__PURE__*/React.createElement("div", {
className: prefix + "-name",
style: {
color: themes['widgets-color-text-1']
}
}, "+", (legendItems === null || legendItems === void 0 ? void 0 : legendItems.length) - num), /*#__PURE__*/React.createElement("svg", {
fill: "none",
width: "8.149999618530273",
height: "8.487500190734863",
viewBox: "0 0 8.149999618530273 8.487500190734863"
}, /*#__PURE__*/React.createElement("g", {
transform: "matrix(0,1,-1,0,8.149999618530273,-8.149999618530273)"
}, /*#__PURE__*/React.createElement("path", {
d: "M8.812499618530273,8.15L12.887499618530274,4.075L8.812499618530273,0L8.149999618530273,0.6625L11.562499618530273,4.075L8.149999618530273,7.4875L8.812499618530273,8.15ZM15.312499618530273,4.075L11.899999618530273,7.4875L12.562499618530273,8.15L16.637499618530274,4.075L12.562499618530273,0L11.899999618530273,0.6625L15.312499618530273,4.075Z",
fill: themes['widgets-color-text-2']
})))), !folded && /*#__PURE__*/React.createElement("div", {
className: prefix + "-fold",
onClick: handleFold
}, /*#__PURE__*/React.createElement("svg", {
fill: "none",
width: "8.149999618530273",
height: "8.487500190734863",
viewBox: "0 0 8.149999618530273 8.487500190734863"
}, /*#__PURE__*/React.createElement("g", {
transform: "matrix(0,-1,-1,0,16.637499809265137,16.637499809265137)"
}, /*#__PURE__*/React.createElement("path", {
d: "M8.812499618530273,16.637500190734862L12.887499618530274,12.562500190734863L8.812499618530273,8.487500190734863L8.149999618530273,9.150000190734863L11.562499618530273,12.562500190734863L8.149999618530273,15.975000190734864L8.812499618530273,16.637500190734862ZM15.312499618530273,12.562500190734863L11.899999618530273,15.975000190734864L12.562499618530273,16.637500190734862L16.637499618530274,12.562500190734863L12.562499618530273,8.487500190734863L11.899999618530273,9.150000190734863L15.312499618530273,12.562500190734863Z",
fill: themes['widgets-color-text-2']
})))));
}
function LegendName(_ref2) {
var _ref2$name = _ref2.name,
name = _ref2$name === void 0 ? '' : _ref2$name,
_ref2$style = _ref2.style,
style = _ref2$style === void 0 ? {} : _ref2$style;
var ref = useRef(null);
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
className: prefix + "-name",
style: style,
ref: ref
}, name), /*#__PURE__*/React.createElement(WidgetsTooltip, {
ref: ref,
content: name
}));
}