UNPKG

@antv/f2

Version:

Charts for mobile visualization.

312 lines (311 loc) 10.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2")); var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _children = _interopRequireDefault(require("../children")); var _util = require("@antv/util"); var _elementStatus = require("./elementStatus"); var _excluded = ["children", "animation"], _excluded2 = ["children", "animation"], _excluded3 = ["children", "animation"], _excluded4 = ["animation"], _excluded5 = ["animation"]; // 比较2颗shape树,并返回新的渲染树 // 处理删除的元素 function deleteElement(element) { // 是否有非空的子元素 var hasElement = false; var receiveElement = _children.default.map(element, function (item) { if (!item) return item; var ref = item.ref, key = item.key, type = item.type, props = item.props, _cache = item._cache; var children = props.children, animation = props.animation, receiveProps = (0, _objectWithoutProperties2.default)(props, _excluded); var status = _elementStatus.ELEMENT_DELETE; var receiveAnimation = animation && animation.leave; var receiveChildren = deleteElement(children); // 没有子元素,且自身也不需要动画,则直接删除 if (!receiveChildren && !receiveAnimation) { return null; } hasElement = true; return { ref: ref, key: key, type: type, props: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, receiveProps), {}, { children: receiveChildren }), _cache: _cache, animation: receiveAnimation, status: status }; }); // 如果没有非空的子元素,都删除 if (!hasElement) { return null; } return receiveElement; } function appearElement(element) { return _children.default.map(element, function (item) { if (!item) return item; var ref = item.ref, key = item.key, type = item.type, props = item.props, _cache = item._cache; var children = props.children, animation = props.animation, receiveProps = (0, _objectWithoutProperties2.default)(props, _excluded2); var status = _elementStatus.ELEMENT_APPEAR; var receiveAnimation = animation && animation.appear; var receiveChildren = appearElement(children); return { ref: ref, key: key, type: type, props: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, receiveProps), {}, { children: receiveChildren }), _cache: _cache, animation: receiveAnimation, status: status }; }); } function updateElement(nextElement, lastElement) { var ref = nextElement.ref, key = nextElement.key, type = nextElement.type, _nextCache = nextElement._cache, nextProps = nextElement.props; var _lastCache = lastElement._cache, lastProps = lastElement.props; var nextChildren = nextProps.children, nextAnimation = nextProps.animation, nextReceiveProps = (0, _objectWithoutProperties2.default)(nextProps, _excluded3); var lastChildren = lastProps.children; // 继续比较子元素 var children = compareElement(nextChildren, lastChildren); // 保留缓存值 var _cache = (0, _util.mix)(_nextCache, _lastCache); // 动画 var animation = nextAnimation && nextAnimation.update; // 生成新对象 return { ref: ref, key: key, type: type, props: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, nextReceiveProps), {}, { children: children }), _cache: _cache, animation: animation, status: _elementStatus.ELEMENT_UPDATE }; } // 形变动画, TODO function morphElement(nextElement, lastElement) { return [deleteElement(lastElement), appearElement(nextElement)]; } function changeTypeToGroup(nextGroupElement, lastShapeElement) { var key = nextGroupElement.key, type = nextGroupElement.type, ref = nextGroupElement.ref, groupProps = nextGroupElement.props, _groupCache = nextGroupElement._cache; var lastType = lastShapeElement.type, _lastCache = lastShapeElement._cache; var groupChildren = groupProps.children; // let existTransform = false; var children = _children.default.map(groupChildren, function (nextElement) { if (!nextElement) return nextElement; var key = nextElement.key, ref = nextElement.ref, nextType = nextElement.type, nextProps = nextElement.props, _nextCache = nextElement._cache; // if (nextType === 'group') { // return changeTypeToGroup(nextElement, lastShapeElement); // } if (nextType !== lastType) { return morphElement(nextElement, lastShapeElement); } // existTransform = true; var nextAnimation = nextProps.animation, nextReceiveProps = (0, _objectWithoutProperties2.default)(nextProps, _excluded4); var animation = nextAnimation && nextAnimation.update; return { ref: ref, key: key, type: nextType, props: nextReceiveProps, _cache: (0, _util.mix)(_nextCache, _lastCache), animation: animation, status: _elementStatus.ELEMENT_UPDATE }; }); return { key: key, type: type, ref: ref, props: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, groupProps), {}, { children: children }), _cache: _groupCache, status: _elementStatus.ELEMENT_UPDATE }; } function changeTypeFromGroup(nextShapeElement, lastGroupElement) { var nextRef = nextShapeElement.ref, nextKey = nextShapeElement.key, nextType = nextShapeElement.type, nextShapeProps = nextShapeElement.props, _nextCache = nextShapeElement._cache; var lastType = lastGroupElement.type, lastProps = lastGroupElement.props; var nextAnimation = nextShapeProps.animation, nextReceiveProps = (0, _objectWithoutProperties2.default)(nextShapeProps, _excluded5); var groupChildren = lastProps.children; var animation = nextAnimation && nextAnimation.update; if (!animation) { return [deleteElement(lastGroupElement), appearElement[nextShapeElement]]; } var transformChild = null; var children = _children.default.map(groupChildren, function (child) { if (!child) return child; var childType = child.type, _childCache = child._cache; if (childType !== nextType) { // TODO: child 形变 return deleteElement(child); } if (!transformChild) { transformChild = child; } return { type: nextType, props: nextShapeProps, _cache: _childCache, animation: animation, status: _elementStatus.ELEMENT_UPDATE }; }); if (!transformChild) { return [deleteElement(lastGroupElement), appearElement(nextShapeElement)]; } var nextElement = { ref: nextRef, key: nextKey, type: nextType, props: nextReceiveProps, _cache: (0, _util.mix)(_nextCache, transformChild._cache), animation: animation, status: _elementStatus.ELEMENT_UPDATE }; // 保留group 结构 return [{ type: lastType, props: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, lastProps), {}, { children: children }), status: _elementStatus.ELEMENT_DELETE }, nextElement]; } function changeElementType(nextElement, lastElement) { var nextType = nextElement.type; var lastType = lastElement.type; if (nextType === 'group') { return changeTypeToGroup(nextElement, lastElement); } if (lastType === 'group') { return changeTypeFromGroup(nextElement, lastElement); } // 都不是group, 形变动画 TODO return morphElement(nextElement, lastElement); } // 对比2个数组 function compareArray(nextElements, lastElements) { var keyed = {}; var nextLength = nextElements.length; var lastLength = lastElements.length; for (var i = 0; i < lastLength; i++) { var element = lastElements[i]; if (element && !(0, _util.isNil)(element.key)) { var key = element.key; keyed[key] = element; } } // 比较元素 var maxLength = Math.max(nextLength, lastLength); var returnElements = []; for (var _i = 0; _i < maxLength; _i++) { var nextElement = nextElements[_i]; if (!nextElement) { returnElements.push(compareElement(nextElement, lastElements[_i])); continue; } var _key = nextElement.key; // 有key值定义 if (!(0, _util.isNil)(_key)) { var lastElement = keyed[_key]; if (lastElement) delete keyed[_key]; returnElements.push(compareElement(nextElement, lastElement)); continue; } returnElements.push(compareElement(nextElement, lastElements[_i])); } // 说明是删除的元素 Object.keys(keyed).forEach(function (key) { returnElements.push(compareElement(null, keyed[key])); }); return returnElements; } // 比较2个元素,会被递归执行 function compareElement(nextElement, lastElement) { // 都为空 if (!nextElement && !lastElement) { return null; } // 新增 if (!lastElement) { return appearElement(nextElement); } // 删除 if (!nextElement) { return deleteElement(lastElement); } // nextElement & lastElement 都不为空了 // 如果有数组,比较数组 if ((0, _util.isArray)(nextElement) || (0, _util.isArray)(lastElement)) { var nextElementArray = (0, _util.isArray)(nextElement) ? nextElement : [nextElement]; var lastElementArray = (0, _util.isArray)(lastElement) ? lastElement : [lastElement]; return compareArray(nextElementArray, lastElementArray); } // 普通的jsx元素, 且都非空 var nextKey = nextElement.key, nextType = nextElement.type; var lastKey = lastElement.key, lastType = lastElement.type; // key 值不相等 if (!(0, _util.isNil)(nextKey) && nextKey !== lastKey) { return [deleteElement(lastElement), appearElement(nextElement)]; } // shape 类型的变化 if (nextType !== lastType) { // return [deleteElement(lastElement), nextElement]; return changeElementType(nextElement, lastElement); } return updateElement(nextElement, lastElement); } // 因为要实现删除元素的动画,所以需要保留删除的元素,diff 后需要创建一颗新树, 实际渲染也需要拿这颗树来进行 var _default = compareElement; exports.default = _default;