@antv/f2
Version:
Charts for mobile visualization.
312 lines (311 loc) • 10.5 kB
JavaScript
"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;