大侠
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

6867 lines
295 KiB

/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ([
/* 0 */,
/* 1 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
if (typeof GameGlobal !== 'undefined') {
GameGlobal.__env = GameGlobal.wx || GameGlobal.tt || GameGlobal.swan;
}
var domEventMap = {
touchstart: 'mousedown',
touchmove: 'mousemove',
touchend: 'mouseup',
touchcancel: 'mouseleave',
};
var eventType;
(function (eventType) {
eventType["on"] = "on";
eventType["off"] = "off";
})(eventType || (eventType = {}));
function genDomTouchEvent(event, type) {
if (typeof document !== 'undefined') {
return function (listener) {
type === eventType.on ?
document.addEventListener(event, listener, false)
: document.removeEventListener(event, listener, false);
};
}
}
function getOnTouchHandler(event, type) {
if (typeof GameGlobal !== 'undefined') {
return GameGlobal.__env["".concat(type).concat(event)];
}
else {
return genDomTouchEvent(domEventMap[event.toLowerCase()], type);
}
}
/**
* Layout 可能用在不用的平台,而Layout会依赖平台下面的一些方法来实现具体的功能,比如创建图片
* 为了更好做平台适配,统一封装 env 模块,不同平台要做适配,替换 env 的具体方法即可
*/
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
// 监听触摸相关事件
onTouchStart: getOnTouchHandler('TouchStart', eventType.on),
onTouchMove: getOnTouchHandler('TouchMove', eventType.on),
onTouchEnd: getOnTouchHandler('TouchEnd', eventType.on),
onTouchCancel: getOnTouchHandler('TouchCancel', eventType.on),
// 取消监听触摸相关事件
offTouchStart: getOnTouchHandler('TouchStart', eventType.off),
offTouchMove: getOnTouchHandler('TouchMove', eventType.off),
offTouchEnd: getOnTouchHandler('TouchEnd', eventType.off),
offTouchCancel: getOnTouchHandler('TouchCancel', eventType.off),
// Layout 支持百分比样式,如果根节点样式设置为 100%,直接取 Canvas 的尺寸,不同平台的取法不一样,因此单独提供函数
getRootCanvasSize: function () {
if (typeof __env !== 'undefined' && __env.getSharedCanvas) {
var cvs = __env.getSharedCanvas();
return {
width: cvs.width,
height: cvs.height,
};
}
else {
return {
width: 300,
height: 150,
};
}
},
// 取当前设备的 devicePixelRatio,不同平台的取法不一样
getDevicePixelRatio: function () {
if (typeof __env !== 'undefined' && __env.getSystemInfoSync) {
return __env.getSystemInfoSync().devicePixelRatio;
}
else if (window.devicePixelRatio) {
return window.devicePixelRatio;
}
else {
return 1;
}
},
// 创建Canvas
createCanvas: function () {
if (typeof __env !== 'undefined') {
return __env.createCanvas();
}
return document.createElement('canvas');
},
// 创建图片
createImage: function () {
if (typeof __env !== 'undefined') {
return __env.createImage();
}
return document.createElement('img');
}
});
/***/ }),
/* 2 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ StyleOpType: () => (/* binding */ StyleOpType),
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
/* harmony export */ getElementById: () => (/* binding */ getElementById),
/* harmony export */ getElementsByClassName: () => (/* binding */ getElementsByClassName),
/* harmony export */ getElementsById: () => (/* binding */ getElementsById),
/* harmony export */ setDirty: () => (/* binding */ setDirty)
/* harmony export */ });
/* harmony import */ var _style__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
/* harmony import */ var _common_rect__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
/* harmony import */ var _common_imageManager__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
/* harmony import */ var tiny_emitter__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8);
/* harmony import */ var tiny_emitter__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(tiny_emitter__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _styleParser__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9);
/* harmony import */ var _common_util__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7);
/* harmony import */ var _env__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1);
var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
/* eslint-disable no-param-reassign */
function getElementsById(tree, list, id) {
if (list === void 0) { list = []; }
tree.children.forEach(function (child) {
if (child.idName === id) {
list.push(child);
}
if (child.children.length) {
getElementsById(child, list, id);
}
});
return list;
}
function getElementById(tree, id) {
var list = getElementsById(tree, [], id);
return (list === null || list === void 0 ? void 0 : list[0]) || null;
}
function getElementsByClassName(tree, list, className) {
if (list === void 0) { list = []; }
tree.children.forEach(function (child) {
if (child.classList.contains(className)) {
list.push(child);
}
if (child.children.length) {
getElementsByClassName(child, list, className);
}
});
return list;
}
/**
* 将当前节点置脏,Layout 的 ticker 会根据这个标记位执行 reflow
*/
function setDirty(ele, reason) {
// for debug
// console.log('[Layout] trigger reflow cause', ele, reason);
ele.isDirty = true;
var parent = ele.parent;
while (parent) {
parent.isDirty = true;
parent = parent.parent;
}
}
// 全局事件管道
var EE = new (tiny_emitter__WEBPACK_IMPORTED_MODULE_3___default().TinyEmitter)();
var uuid = 0;
var toEventName = function (event, id) {
var elementEvent = [
'click',
'touchstart',
'touchmove',
'touchend',
'touchcancel',
];
if (elementEvent.indexOf(event) !== -1) {
return "element-".concat(id, "-").concat(event);
}
return "element-".concat(id, "-").concat(event);
};
;
var StyleOpType;
(function (StyleOpType) {
StyleOpType[StyleOpType["Set"] = 0] = "Set";
StyleOpType[StyleOpType["Delete"] = 1] = "Delete";
})(StyleOpType || (StyleOpType = {}));
var ElementClassList = /** @class */ (function () {
function ElementClassList(ele, initialTokens) {
this.element = ele;
this.tokens = new Set(initialTokens || []);
}
Object.defineProperty(ElementClassList.prototype, "length", {
get: function () {
return this.tokens.size;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ElementClassList.prototype, "value", {
get: function () {
return Array.from(this.tokens).join(' ');
},
enumerable: false,
configurable: true
});
ElementClassList.prototype.changeHandler = function () {
var ele = this.element;
var oldStyle = Object.assign({}, ele.style);
// 根据 className 从样式表中算出当前应该作用的样式
// @ts-ignore
var newStyle = Array.from(this.tokens).reduce(function (res, oneClass) { return Object.assign(res, ele.root.styleSheet[oneClass]); }, {});
// console.log('newStyle', newStyle)
var parentStyle;
if (ele.parent) {
parentStyle = ele.parent.style;
}
else {
parentStyle = _env__WEBPACK_IMPORTED_MODULE_6__["default"].getRootCanvasSize();
}
if (typeof newStyle.opacity === 'undefined') {
newStyle.opacity = 1;
}
Object.keys(newStyle).concat(Object.keys(oldStyle)).forEach(function (key) {
// 手动通过this.style设置过的样式认为是内联样式,优先级最高,也就是 className 的属性不影响
if (!Reflect.has(ele.innerStyle, key)) {
// 根据 className 计算出来的新增或者修改的样式
if (Reflect.has(newStyle, key)) {
/**
* 新增的样式,需要区分出是 className 导致的还是开发者手动修改的
* 临时占位,因为后续的 reflow 和 repaint 逻辑在 style Proxy 处理,这样做在 style Proxy 也不会认为是开发者手动设置的样式
*/
if (!Reflect.has(oldStyle, key)) {
Reflect.set(ele.originStyle, key, undefined);
}
// @ts-ignore
var newValue = newStyle[key];
if (key === 'width') {
newValue = parentStyle.width ? (0,_common_util__WEBPACK_IMPORTED_MODULE_5__.convertPercent)(newValue, parentStyle.width) : 0;
}
if (key === 'height') {
newValue = parentStyle.height ? (0,_common_util__WEBPACK_IMPORTED_MODULE_5__.convertPercent)(newValue, parentStyle.height) : 0;
}
if (key === 'opacity' && parentStyle && parentStyle.opacity !== 1 && typeof parentStyle.opacity === 'number') {
newValue = parentStyle.opacity * newValue;
}
// @ts-ignore
// 根据 className 计算出的样式覆盖当前样式
ele.style[key] = newValue;
}
else {
// console.log('del', key)
// 不在内联样式,根据 className 计算出的样式又没有,认为这些样式都应该删除了
delete ele.style[key];
}
}
});
};
ElementClassList.prototype.add = function (className) {
if (!this.contains(className)) {
this.tokens.add(className);
this.changeHandler();
}
};
// 检查列表中是否存在指定的令牌
ElementClassList.prototype.contains = function (className) {
return this.tokens.has(className);
};
ElementClassList.prototype.remove = function (className) {
if (this.contains(className)) {
this.tokens.delete(className);
this.changeHandler();
}
};
return ElementClassList;
}());
var Element = /** @class */ (function () {
function Element(_a) {
var _b = _a.style, style = _b === void 0 ? {} : _b, _c = _a.idName, idName = _c === void 0 ? '' : _c, _d = _a.className, className = _d === void 0 ? '' : _d, _e = _a.id, id = _e === void 0 ? uuid += 1 : _e, _f = _a.dataset, dataset = _f === void 0 ? {} : _f;
var _this = this;
/**
* 子节点列表
*/
this.children = [];
/**
* 当前节点的父节点
*/
this.parent = null;
/**
* 当前节点所在节点树的根节点,指向 Layout
*/
this.root = null;
// public EE: any;
/**
* 用于标识当前节点是否已经执行销毁逻辑,销毁之后原先的功能都会异常,一般业务侧不用关心这个
*/
this.isDestroyed = false;
this.ctx = null;
/**
* 置脏标记位,目前当修改会影响布局属性的时候,会自动置脏
*/
this.isDirty = false;
/**
* css-layout 节点属性,业务侧无需关心
*/
this.shouldUpdate = false;
/**
* 有些 style 属性并不能直接用来渲染,需要经过解析之后才能进行渲染,这些值不会存储在 style 上
* 比如 style.transform,如果每次都解析性能太差了
*/
this.renderForLayout = {};
this.innerStyle = {};
this.id = id;
this.idName = idName;
this.className = className;
this.layoutBox = {
left: 0,
top: 0,
width: 0,
height: 0,
absoluteX: 0,
absoluteY: 0,
originalAbsoluteX: 0,
originalAbsoluteY: 0,
};
this.dataset = dataset;
_style__WEBPACK_IMPORTED_MODULE_0__.renderAffectStyles.forEach(function (prop) {
var val = style[prop];
if (typeof val !== 'undefined') {
_this.calculateRenderForLayout(true, prop, StyleOpType.Set, val);
}
});
this.originStyle = style;
this.style = style;
this.rect = null;
var initialTokens = className.split(/\s+/).filter(function (item) { return !!item; });
initialTokens.push(idName);
this.classList = new ElementClassList(this, initialTokens);
}
Element.prototype.styleChangeHandler = function (prop, styleOpType, val) {
};
Element.prototype.calculateRenderForLayout = function (init, prop, styleOpType, val) {
var _this = this;
var _a;
if (!init) {
this.styleChangeHandler(prop, styleOpType, val);
}
if (styleOpType === StyleOpType.Set) {
switch (prop) {
case 'backgroundImage':
var url = (0,_styleParser__WEBPACK_IMPORTED_MODULE_4__.backgroundImageParser)(val);
if (url) {
_common_imageManager__WEBPACK_IMPORTED_MODULE_2__["default"].loadImage(url, function (img) {
var _a;
if (!_this.isDestroyed) {
_this.renderForLayout.backgroundImage = img;
// 当图片加载完成,实例可能已经被销毁了
(_a = _this.root) === null || _a === void 0 ? void 0 : _a.emit('repaint');
}
});
}
break;
case 'transform':
delete this.renderForLayout.scaleX;
delete this.renderForLayout.scaleY;
delete this.renderForLayout.rotate;
Object.assign(this.renderForLayout, (0,_styleParser__WEBPACK_IMPORTED_MODULE_4__.parseTransform)(val));
break;
}
}
else {
switch (prop) {
case 'backgroundImage':
this.renderForLayout.backgroundImage = undefined;
break;
case 'transform':
delete this.renderForLayout.scaleX;
delete this.renderForLayout.scaleY;
delete this.renderForLayout.rotate;
break;
}
}
// 初始化的逻辑不需要做这些判断
if (!init) {
if (_style__WEBPACK_IMPORTED_MODULE_0__.reflowAffectedStyles.indexOf(prop) > -1) {
// setDirty(this, `change prop ${prop} from ${oldVal} to ${val}`);
setDirty(this);
}
else if (_style__WEBPACK_IMPORTED_MODULE_0__.repaintAffectedStyles.indexOf(prop) > -1) {
(_a = this.root) === null || _a === void 0 ? void 0 : _a.emit('repaint');
}
}
};
Element.prototype.observeStyleAndEvent = function () {
var _this = this;
if (typeof Proxy === 'function') {
var ele_1 = this;
var innerStyle_1 = this.innerStyle;
this.style = new Proxy(this.originStyle, {
get: function (target, prop, receiver) {
return Reflect.get(target, prop, receiver);
},
set: function (target, prop, val, receiver) {
// 判断初始化的className是否包含该属性
var isSetForInnerStyle = !Reflect.has(target, prop);
var oldVal = Reflect.get(target, prop, receiver);
if (typeof prop === 'string' && oldVal !== val) {
// console.log('set', prop, oldVal, val)
ele_1.calculateRenderForLayout(false, prop, StyleOpType.Set, val);
}
if (isSetForInnerStyle) {
// console.log('set innerStyle', prop, val)
// 将私有属性同步一份到 innerStyle
Reflect.set(innerStyle_1, prop, val);
}
return Reflect.set(target, prop, val, receiver);
},
deleteProperty: function (target, prop) {
ele_1.calculateRenderForLayout(false, prop, StyleOpType.Delete);
return Reflect.deleteProperty(target, prop);
},
});
}
// 事件冒泡逻辑
['touchstart', 'touchmove', 'touchcancel', 'touchend', 'click'].forEach(function (eventName) {
_this.on(eventName, function (e, touchMsg) {
// 处理伪类逻辑
if (eventName === 'touchstart') {
_this.activeHandler(e);
if (_this !== _this.root) {
// @ts-ignore
_this.root.activeElements.push(_this);
}
}
else if (eventName === 'touchend' || eventName === 'touchcancel') {
_this.deactiveHandler(e);
// @ts-ignore
var index = _this.root.activeElements.indexOf(_this);
if (index > -1) {
// @ts-ignore
_this.root.activeElements.splice(index, 1);
}
}
_this.parent && _this.parent.emit(eventName, e, touchMsg);
});
});
// this.classNameList = this.innerClassName.split(/\s+/);
};
Element.prototype.activeHandler = function (e) {
var activeStyle = this.style[':active'];
if (activeStyle) {
// 将当前的style缓存起来,在 active 取消的时候重置回去
this.cacheStyle = Object.assign({}, this.style);
Object.assign(this.style, activeStyle);
}
};
Element.prototype.deactiveHandler = function (e) {
var _this = this;
var activeStyle = this.style[':active'];
if (activeStyle) {
Object.keys(activeStyle).forEach(function (key) {
if (!_this.cacheStyle) {
return;
}
if (_this.cacheStyle[key]) {
// @ts-ignore
_this.style[key] = _this.cacheStyle[key];
}
else {
delete _this.style[key];
}
});
}
};
/**
* 节点重绘接口,子类填充实现
*/
Element.prototype.repaint = function () { };
/**
* 节点渲染接口子类填充实现
*/
Element.prototype.render = function () { };
/**
* 节点构造函数初始化后调用的方法,子类填充实现
*/
Element.prototype.afterCreate = function () { };
/**
* 参照 Web 规范:https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
*/
Element.prototype.getBoundingClientRect = function () {
if (!this.rect) {
this.rect = new _common_rect__WEBPACK_IMPORTED_MODULE_1__["default"](this.layoutBox.absoluteX, this.layoutBox.absoluteY, this.layoutBox.width, this.layoutBox.height);
}
this.rect.set(this.layoutBox.absoluteX, this.layoutBox.absoluteY, this.layoutBox.width, this.layoutBox.height);
return this.rect;
};
/**
* 查询当前节点树下,idName 为给定参数的的节点
* 节点的 id 唯一性 Layout 并不保证,但这里只返回符合条件的第一个节点
*/
Element.prototype.getElementById = function (id) {
return getElementById(this, id);
};
/**
* 查询当前节点树下,idName 为给定参数的的节点
* 节点的 id 唯一性 Layout 并不保证,这里返回符合条件的节点集合
*/
Element.prototype.getElementsById = function (id) {
return getElementsById(this, [], id);
};
/**
* 查询当前节点树下,className 包含给定参数的的节点集合
*/
Element.prototype.getElementsByClassName = function (className) {
return getElementsByClassName(this, [], className);
};
/**
* 布局计算完成,准备执行渲染之前执行的操作,不同的子类有不同的行为
* 比如 ScrollView 在渲染之前还需要初始化滚动相关的能力
*
*/
Element.prototype.insert = function (ctx, needRender) {
this.shouldUpdate = false;
this.ctx = ctx;
if (needRender) {
this.render();
}
};
/**
* 节点解除事件绑定
*/
Element.prototype.unBindEvent = function () {
var _this = this;
[
'touchstart',
'touchmove',
'touchcancel',
'touchend',
'click',
'repaint',
].forEach(function (eventName) {
_this.off(eventName);
});
};
/**
* 将节点从当前节点树中删除
*/
Element.prototype.remove = function () {
var parent = this.parent;
if (!parent) {
return;
}
var index = parent.children.indexOf(this);
if (index !== -1) {
parent.children.splice(index, 1);
this.unBindEvent();
setDirty(this, "remove");
this.parent = null;
this.ctx = null;
}
else {
console.warn('[Layout] this element has been removed');
}
};
Element.prototype.setDirty = function () {
setDirty(this);
};
// 子类填充实现
Element.prototype.destroySelf = function () {
};
// 子类填充实现
Element.prototype.destroy = function () {
this.unBindEvent();
this.isDestroyed = true;
// this.EE = null;
this.parent = null;
this.ctx = null;
this.classList = null;
};
Element.prototype.add = function (element) {
element.parent = this;
this.children.push(element);
};
/**
* 将一个节点添加作为当前节点的子节点
*/
Element.prototype.appendChild = function (element) {
this.add(element);
setDirty(this, "appendChild ".concat(element));
};
/**
* 移除给定的子节点,只有一级节点能够移除
*/
Element.prototype.removeChild = function (element) {
var index = this.children.indexOf(element);
if (index !== -1) {
element.remove();
setDirty(this, "removeChild ".concat(element));
}
else {
console.warn('[Layout] the element to be removed is not a child of this element');
}
};
Element.prototype.emit = function (event) {
var theArgs = [];
for (var _i = 1; _i < arguments.length; _i++) {
theArgs[_i - 1] = arguments[_i];
}
EE.emit.apply(EE, __spreadArray([toEventName(event, this.id)], theArgs, false));
};
Element.prototype.on = function (event, callback) {
EE.on(toEventName(event, this.id), callback);
};
Element.prototype.once = function (event, callback) {
EE.once(toEventName(event, this.id), callback);
};
Element.prototype.off = function (event, callback) {
EE.off(toEventName(event, this.id), callback);
};
/**
* 渲染 border 相关能力抽象,子类可按需调用
* 由于支持了rotate特性,所以所有的渲染都需要方向减去transform的中间点
*/
Element.prototype.renderBorder = function (ctx, originX, originY) {
if (originX === void 0) { originX = 0; }
if (originY === void 0) { originY = 0; }
var style = this.style || {};
var radius = style.borderRadius || 0;
var _a = style.borderWidth, borderWidth = _a === void 0 ? 0 : _a;
var tlr = style.borderTopLeftRadius || radius;
var trr = style.borderTopRightRadius || radius;
var bbr = style.borderBottomLeftRadius || radius;
var brr = style.borderBottomRightRadius || radius;
var box = this.layoutBox;
var _b = style.borderColor, borderColor = _b === void 0 ? '' : _b;
var x = box.absoluteX;
var y = box.absoluteY;
var width = box.width, height = box.height;
var hasRadius = radius || tlr || trr || bbr || brr;
// borderWidth 和 radius 都没有,不需要执行后续逻辑,提升性能
if (!borderWidth && !hasRadius) {
return { needClip: false, needStroke: false };
}
ctx.lineWidth = borderWidth;
ctx.strokeStyle = borderColor;
// 左上角的点
ctx.beginPath();
ctx.moveTo(x + tlr - originX, y - originY);
ctx.lineTo(x + width - trr - originX, y - originY);
// 右上角的圆角
ctx.arcTo(x + width - originX, y - originY, x + width - originX, y + trr - originY, trr);
// 右下角的点
ctx.lineTo(x + width - originX, y + height - brr - originY);
// 右下角的圆角
ctx.arcTo(x + width - originX, y + height - originY, x + width - brr - originX, y + height - originY, brr);
// 左下角的点
ctx.lineTo(x + bbr - originX, y + height - originY);
// 左下角的圆角
ctx.arcTo(x - originX, y + height - originY, x - originX, y + height - bbr - originY, bbr);
// 左上角的点
ctx.lineTo(x - originX, y + tlr - originY);
// 左上角的圆角
ctx.arcTo(x - originX, y - originY, x + tlr - originX, y - originY, tlr);
ctx.closePath();
return { needClip: !!hasRadius, needStroke: !!borderWidth };
};
/**
* 每个子类都会有自己的渲染逻辑,但他们都有些通用的处理,比如透明度、旋转和border的处理,baseRender 用于处理通用的渲染逻辑
*/
Element.prototype.baseRender = function (type) {
var ctx = this.ctx;
var style = this.style;
var box = this.layoutBox;
var drawX = box.absoluteX, drawY = box.absoluteY, width = box.width, height = box.height;
if (style.opacity !== undefined) {
ctx.globalAlpha = style.opacity;
}
var originX = 0;
var originY = 0;
if (this.renderForLayout.rotate !== undefined || this.renderForLayout.scaleX !== undefined || this.renderForLayout.scaleY !== undefined) {
originX = drawX + box.width / 2;
originY = drawY + box.height / 2;
ctx.translate(originX, originY);
}
/**
* 请注意,这里暂时仅支持没有子节点的元素发生旋转,如果父节点旋转了子节点并不会跟着旋转
* 要实现父节点带动子节点旋转的能力,需要引入矩阵库,对代码改动也比较大,暂时不做改造。
*/
if (this.renderForLayout.rotate !== undefined) {
ctx.rotate(this.renderForLayout.rotate);
}
if (this.renderForLayout.scaleX !== undefined || this.renderForLayout.scaleY !== undefined) {
ctx.scale(this.renderForLayout.scaleX !== undefined ? this.renderForLayout.scaleX : 1, this.renderForLayout.scaleY !== undefined ? this.renderForLayout.scaleY : 1);
}
if (style.borderColor) {
ctx.strokeStyle = style.borderColor;
}
ctx.lineWidth = style.borderWidth || 0;
// for clip
var _a = this.renderBorder(ctx, originX, originY), needClip = _a.needClip, needStroke = _a.needStroke;
if (needClip) {
ctx.clip();
}
if (style.backgroundColor) {
ctx.fillStyle = style.backgroundColor;
ctx.fillRect(drawX - originX, drawY - originY, box.width, box.height);
}
if (this.renderForLayout.backgroundImage) {
ctx.drawImage(this.renderForLayout.backgroundImage, drawX - originX, drawY - originY, box.width, box.height);
}
return { needStroke: needStroke, needClip: needClip, originX: originX, originY: originY, drawX: drawX, drawY: drawY, width: width, height: height };
};
return Element;
}());
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Element);
/***/ }),
/* 3 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ reflowAffectedStyles: () => (/* binding */ reflowAffectedStyles),
/* harmony export */ renderAffectStyles: () => (/* binding */ renderAffectStyles),
/* harmony export */ repaintAffectedStyles: () => (/* binding */ repaintAffectedStyles)
/* harmony export */ });
var reflowAffectedStyles = [
'width', 'height',
'minWidth', 'minHeight',
'maxWidth', 'maxHeight',
'left', 'right', 'top', 'bottom',
'margin', 'marginLeft', 'marginRight', 'marginTop', 'marginBottom',
'padding', 'paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom',
'borderWidth', 'borderLeftWidth', 'borderRightWidth', 'borderTopWidth', 'borderBottomWidth',
'flexDirection',
'flexShrink',
'flexGrow',
'justifyContent',
'alignItems', 'alignSelf',
'flex',
'flexWrap',
'position',
'fontWeight',
];
var repaintAffectedStyles = [
'fontSize',
'lineHeight',
'textAlign',
'verticalAlign',
'color',
'backgroundColor',
'textOverflow',
'letterSpacing',
'borderRadius',
'borderColor',
'opacity',
'transform',
'textStrokeColor',
'textStrokeWidth',
'textShadow',
];
var renderAffectStyles = [
'textShadow',
'transform',
'backgroundImage',
];
/***/ }),
/* 4 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
var Rect = /** @class */ (function () {
function Rect(left, top, width, height) {
if (left === void 0) { left = 0; }
if (top === void 0) { top = 0; }
if (width === void 0) { width = 0; }
if (height === void 0) { height = 0; }
this.width = 0;
this.height = 0;
this.left = 0;
this.right = 0;
this.top = 0;
this.bottom = 0;
this.set(left, top, width, height);
}
Rect.prototype.set = function (left, top, width, height) {
if (left === void 0) { left = 0; }
if (top === void 0) { top = 0; }
if (width === void 0) { width = 0; }
if (height === void 0) { height = 0; }
this.left = left;
this.top = top;
this.width = width;
this.height = height;
this.right = this.left + this.width;
this.bottom = this.top + this.height;
};
/**
* 判断两个矩形是否相交
* 原理可见: https://zhuanlan.zhihu.com/p/29704064
*/
Rect.prototype.intersects = function (rect) {
return !(this.right < rect.left || rect.right < this.left || this.bottom < rect.top || rect.bottom < this.top);
};
return Rect;
}());
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Rect);
/***/ }),
/* 5 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _pool__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
/* harmony import */ var _env__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(1);
var ImageManager = /** @class */ (function () {
function ImageManager() {
this.imgPool = new _pool__WEBPACK_IMPORTED_MODULE_0__["default"]('imgPool');
}
ImageManager.prototype.getRes = function (src) {
return this.imgPool.get(src);
};
ImageManager.prototype.loadImagePromise = function (src) {
var _this = this;
return new Promise(function (resolve, reject) {
_this.loadImage(src, resolve, reject);
});
};
ImageManager.prototype.loadImage = function (src, success, fail) {
if (success === void 0) { success = _util__WEBPACK_IMPORTED_MODULE_1__.none; }
if (fail === void 0) { fail = _util__WEBPACK_IMPORTED_MODULE_1__.none; }
if (!src) {
return null;
}
var img;
var cache = this.getRes(src);
// 图片已经被加载过,直接返回图片并且执行回调
if (cache && cache.loadDone) {
img = cache.img;
success(img, true);
}
else if (cache && !cache.loadDone) {
// 图片正在加载过程中,返回图片并且等待图片加载完成执行回调
img = cache.img;
cache.onloadcbks.push(success);
cache.onerrorcbks.push(fail);
}
else {
// 创建图片,将回调函数推入回调函数栈
img = _env__WEBPACK_IMPORTED_MODULE_2__["default"].createImage();
var newCache_1 = {
img: img,
loadDone: false,
onloadcbks: [success],
onerrorcbks: [fail],
};
this.imgPool.set(src, newCache_1);
img.onload = function () {
newCache_1.loadDone = true;
newCache_1.onloadcbks.forEach(function (fn) { return fn(img, false); });
newCache_1.onloadcbks = [];
newCache_1.onerrorcbks = [];
};
img.onerror = function () {
newCache_1.onerrorcbks.forEach(function (fn) { return fn(img, false); });
newCache_1.onerrorcbks = [];
newCache_1.onloadcbks = [];
};
img.src = src;
}
return img;
};
return ImageManager;
}());
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (new ImageManager());
/***/ }),
/* 6 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
var pools = [];
var Pool = /** @class */ (function () {
function Pool(name) {
if (name === void 0) { name = 'pool'; }
this.name = 'pool';
this.pool = {};
var curr = pools.find(function (item) { return item.name === name; });
if (curr) {
return curr;
}
this.name = name;
this.pool = {};
pools.push(this);
}
Pool.prototype.get = function (key) {
return this.pool[key];
};
Pool.prototype.set = function (key, value) {
this.pool[key] = value;
};
Pool.prototype.clear = function () {
this.pool = {};
};
Pool.prototype.getList = function () {
return Object.values(this.pool);
};
return Pool;
}());
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Pool);
/***/ }),
/* 7 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ STATE: () => (/* binding */ STATE),
/* harmony export */ clamp: () => (/* binding */ clamp),
/* harmony export */ clearCanvas: () => (/* binding */ clearCanvas),
/* harmony export */ convertPercent: () => (/* binding */ convertPercent),
/* harmony export */ copyTouchArray: () => (/* binding */ copyTouchArray),
/* harmony export */ isClick: () => (/* binding */ isClick),
/* harmony export */ isGameTouchEvent: () => (/* binding */ isGameTouchEvent),
/* harmony export */ isPercent: () => (/* binding */ isPercent),
/* harmony export */ lerp: () => (/* binding */ lerp),
/* harmony export */ none: () => (/* binding */ none)
/* harmony export */ });
/* istanbul ignore next */
function none() { }
/**
* 根据触摸时长和触摸位置变化来判断是否属于点击事件
*/
function isClick(touchMsg) {
var start = touchMsg.touchstart;
var end = touchMsg.touchend;
if (!start
|| !end
|| !start.timeStamp
|| !end.timeStamp
|| start.pageX === undefined
|| start.pageY === undefined
|| end.pageX === undefined
|| end.pageY === undefined) {
return false;
}
var startPosX = start.pageX;
var startPosY = start.pageY;
var endPosX = end.pageX;
var endPosY = end.pageY;
var touchTimes = end.timeStamp - start.timeStamp;
return !!(Math.abs(endPosY - startPosY) < 30
&& Math.abs(endPosX - startPosX) < 30
&& touchTimes < 300);
}
var STATE;
(function (STATE) {
STATE["UNINIT"] = "UNINIT";
STATE["INITED"] = "INITED";
STATE["RENDERED"] = "RENDERED";
STATE["CLEAR"] = "CLEAR";
})(STATE || (STATE = {}));
;
function clearCanvas(ctx) {
ctx && ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
function copyTouchArray(touches) {
return touches.map(function (touch) { return ({
identifier: touch.identifier,
pageX: touch.pageX,
pageY: touch.pageY,
clientX: touch.clientX,
clientY: touch.clientY,
}); });
}
function isGameTouchEvent(e) {
return 'touches' in e;
}
/**
* 取最小值和最大值之间的区间限定值
* @param {number} number 需要被处理的数字
* @param {number} min 最小值
* @param {number} max 最大值
*/
function clamp(number, min, max) {
return Math.max(min, Math.min(number, max));
}
/**
* 两个数之间的线性插值。
*/
function lerp(from, to, ratio) {
return from + (to - from) * ratio;
}
function convertPercent(data, parentData) {
if (typeof data === 'number' || data === null) {
return data;
}
var matchData = data.match(/(\d+(?:\.\d+)?)%/);
if (matchData && matchData[1]) {
return parentData * parseFloat(matchData[1]) * 0.01;
}
}
function isPercent(data) {
return typeof data === 'string' && /\d+(?:\.\d+)?%/.test(data);
}
/***/ }),
/* 8 */
/***/ ((module) => {
function E () {
// Keep this empty so it's easier to inherit from
// (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
}
E.prototype = {
on: function (name, callback, ctx) {
var e = this.e || (this.e = {});
(e[name] || (e[name] = [])).push({
fn: callback,
ctx: ctx
});
return this;
},
once: function (name, callback, ctx) {
var self = this;
function listener () {
self.off(name, listener);
callback.apply(ctx, arguments);
};
listener._ = callback
return this.on(name, listener, ctx);
},
emit: function (name) {
var data = [].slice.call(arguments, 1);
var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
var i = 0;
var len = evtArr.length;
for (i; i < len; i++) {
evtArr[i].fn.apply(evtArr[i].ctx, data);
}
return this;
},
off: function (name, callback) {
var e = this.e || (this.e = {});
var evts = e[name];
var liveEvents = [];
if (evts && callback) {
for (var i = 0, len = evts.length; i < len; i++) {
if (evts[i].fn !== callback && evts[i].fn._ !== callback)
liveEvents.push(evts[i]);
}
}
// Remove event from queue to prevent memory leak
// Suggested by https://github.com/lazd
// Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
(liveEvents.length)
? e[name] = liveEvents
: delete e[name];
return this;
}
};
module.exports = E;
module.exports.TinyEmitter = E;
/***/ }),
/* 9 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ backgroundImageParser: () => (/* binding */ backgroundImageParser),
/* harmony export */ isValidTextShadow: () => (/* binding */ isValidTextShadow),
/* harmony export */ parseTransform: () => (/* binding */ parseTransform)
/* harmony export */ });
function degreesToRadians(degrees) {
return degrees * Math.PI / 180;
}
// 背景图正则表达式
var isValidUrlPropReg = /\s*url\((.*?)\)\s*/;
// 解析背景图片
function backgroundImageParser(val) {
if (typeof val === 'string') {
var list = val.match(isValidUrlPropReg);
if (list) {
var url = list[1].replace(/('|")/g, '');
return url;
}
}
console.error("[Layout]: ".concat(val, " is not a valid backgroundImage"));
return null;
}
var textShadowReg = /^(\d+px\s){2}\d+px\s(?:[a-zA-Z]+|#[0-9a-fA-F]{3,6})(,\s*(\d+px\s){2}\d+px\s(?:[a-zA-Z]+|#[0-9a-fA-F]{3,6}))*$/;
function isValidTextShadow(textShadow) {
return textShadowReg.test(textShadow);
}
function isValidTransformValue(value) {
// 使用正则表达式验证数字或逗号分隔的数字,后面可以跟可选的角度单位(deg)
return /^(-?\d+(\.\d+)?)(deg)?(,\s*(-?\d+(\.\d+)?)(deg)?)*$/.test(value);
// return /^(-?\d+(\.\d+)?)(deg)?(,\s*(-?\d+(\.\d+)?)(deg)?)*(,\s*(true|false))?$/.test(value);
}
var transformRegex = /(\w+)\(([^)]+)\)/g;
function parseTransform(transform) {
var result = {};
var match;
while ((match = transformRegex.exec(transform))) {
var name_1 = match[1], value = match[2];
if (!isValidTransformValue(value)) {
throw new Error("[Layout]: invalid value for ".concat(name_1, ": ").concat(value));
}
var values = value
.split(',')
.map(function (val) { return val.trim().replace('deg', ''); })
.map(Number);
switch (name_1) {
case 'rotate':
result.rotate = degreesToRadians(values[0]);
break;
case 'scale':
result.scaleX = values[0];
result.scaleY = values[1] || values[0];
break;
default:
break;
}
}
return result;
}
/***/ }),
/* 10 */
/***/ (function(module, exports) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// UMD (Universal Module Definition)
// See https://github.com/umdjs/umd for reference
//
// This file uses the following specific UMD implementation:
// https://github.com/umdjs/umd/blob/master/returnExports.js
(function(root, factory) {
if (true) {
// AMD. Register as an anonymous module.
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else {}
}(this, function() {
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
var computeLayout = (function() {
var CSS_UNDEFINED;
var CSS_DIRECTION_INHERIT = 'inherit';
var CSS_DIRECTION_LTR = 'ltr';
var CSS_DIRECTION_RTL = 'rtl';
var CSS_FLEX_DIRECTION_ROW = 'row';
var CSS_FLEX_DIRECTION_ROW_REVERSE = 'row-reverse';
var CSS_FLEX_DIRECTION_COLUMN = 'column';
var CSS_FLEX_DIRECTION_COLUMN_REVERSE = 'column-reverse';
var CSS_JUSTIFY_FLEX_START = 'flex-start';
var CSS_JUSTIFY_CENTER = 'center';
var CSS_JUSTIFY_FLEX_END = 'flex-end';
var CSS_JUSTIFY_SPACE_BETWEEN = 'space-between';
var CSS_JUSTIFY_SPACE_AROUND = 'space-around';
var CSS_ALIGN_FLEX_START = 'flex-start';
var CSS_ALIGN_CENTER = 'center';
var CSS_ALIGN_FLEX_END = 'flex-end';
var CSS_ALIGN_STRETCH = 'stretch';
var CSS_POSITION_RELATIVE = 'relative';
var CSS_POSITION_ABSOLUTE = 'absolute';
var leading = {
'row': 'left',
'row-reverse': 'right',
'column': 'top',
'column-reverse': 'bottom'
};
var trailing = {
'row': 'right',
'row-reverse': 'left',
'column': 'bottom',
'column-reverse': 'top'
};
var pos = {
'row': 'left',
'row-reverse': 'right',
'column': 'top',
'column-reverse': 'bottom'
};
var dim = {
'row': 'width',
'row-reverse': 'width',
'column': 'height',
'column-reverse': 'height'
};
// When transpiled to Java / C the node type has layout, children and style
// properties. For the JavaScript version this function adds these properties
// if they don't already exist.
function fillNodes(node) {
if (!node.layout || node.isDirty) {
node.layout = {
width: undefined,
height: undefined,
top: 0,
left: 0,
right: 0,
bottom: 0
};
}
if (!node.style) {
node.style = {};
}
if (!node.children) {
node.children = [];
}
node.children.forEach(fillNodes);
return node;
}
function isUndefined(value) {
return value === undefined;
}
function isRowDirection(flexDirection) {
return flexDirection === CSS_FLEX_DIRECTION_ROW ||
flexDirection === CSS_FLEX_DIRECTION_ROW_REVERSE;
}
function isColumnDirection(flexDirection) {
return flexDirection === CSS_FLEX_DIRECTION_COLUMN ||
flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE;
}
function getLeadingMargin(node, axis) {
if (node.style.marginStart !== undefined && isRowDirection(axis)) {
return node.style.marginStart;
}
var value = null;
switch (axis) {
case 'row': value = node.style.marginLeft; break;
case 'row-reverse': value = node.style.marginRight; break;
case 'column': value = node.style.marginTop; break;
case 'column-reverse': value = node.style.marginBottom; break;
}
if (value !== undefined) {
return value;
}
if (node.style.margin !== undefined) {
return node.style.margin;
}
return 0;
}
function getTrailingMargin(node, axis) {
if (node.style.marginEnd !== undefined && isRowDirection(axis)) {
return node.style.marginEnd;
}
var value = null;
switch (axis) {
case 'row': value = node.style.marginRight; break;
case 'row-reverse': value = node.style.marginLeft; break;
case 'column': value = node.style.marginBottom; break;
case 'column-reverse': value = node.style.marginTop; break;
}
if (value != null) {
return value;
}
if (node.style.margin !== undefined) {
return node.style.margin;
}
return 0;
}
function getLeadingPadding(node, axis) {
if (node.style.paddingStart !== undefined && node.style.paddingStart >= 0
&& isRowDirection(axis)) {
return node.style.paddingStart;
}
var value = null;
switch (axis) {
case 'row': value = node.style.paddingLeft; break;
case 'row-reverse': value = node.style.paddingRight; break;
case 'column': value = node.style.paddingTop; break;
case 'column-reverse': value = node.style.paddingBottom; break;
}
if (value != null && value >= 0) {
return value;
}
if (node.style.padding !== undefined && node.style.padding >= 0) {
return node.style.padding;
}
return 0;
}
function getTrailingPadding(node, axis) {
if (node.style.paddingEnd !== undefined && node.style.paddingEnd >= 0
&& isRowDirection(axis)) {
return node.style.paddingEnd;
}
var value = null;
switch (axis) {
case 'row': value = node.style.paddingRight; break;
case 'row-reverse': value = node.style.paddingLeft; break;
case 'column': value = node.style.paddingBottom; break;
case 'column-reverse': value = node.style.paddingTop; break;
}
if (value != null && value >= 0) {
return value;
}
if (node.style.padding !== undefined && node.style.padding >= 0) {
return node.style.padding;
}
return 0;
}
function getLeadingBorder(node, axis) {
if (node.style.borderStartWidth !== undefined && node.style.borderStartWidth >= 0
&& isRowDirection(axis)) {
return node.style.borderStartWidth;
}
var value = null;
switch (axis) {
case 'row': value = node.style.borderLeftWidth; break;
case 'row-reverse': value = node.style.borderRightWidth; break;
case 'column': value = node.style.borderTopWidth; break;
case 'column-reverse': value = node.style.borderBottomWidth; break;
}
if (value != null && value >= 0) {
return value;
}
if (node.style.borderWidth !== undefined && node.style.borderWidth >= 0) {
return node.style.borderWidth;
}
return 0;
}
function getTrailingBorder(node, axis) {
if (node.style.borderEndWidth !== undefined && node.style.borderEndWidth >= 0
&& isRowDirection(axis)) {
return node.style.borderEndWidth;
}
var value = null;
switch (axis) {
case 'row': value = node.style.borderRightWidth; break;
case 'row-reverse': value = node.style.borderLeftWidth; break;
case 'column': value = node.style.borderBottomWidth; break;
case 'column-reverse': value = node.style.borderTopWidth; break;
}
if (value != null && value >= 0) {
return value;
}
if (node.style.borderWidth !== undefined && node.style.borderWidth >= 0) {
return node.style.borderWidth;
}
return 0;
}
function getLeadingPaddingAndBorder(node, axis) {
return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);
}
function getTrailingPaddingAndBorder(node, axis) {
return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);
}
function getBorderAxis(node, axis) {
return getLeadingBorder(node, axis) + getTrailingBorder(node, axis);
}
function getMarginAxis(node, axis) {
return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);
}
function getPaddingAndBorderAxis(node, axis) {
return getLeadingPaddingAndBorder(node, axis) +
getTrailingPaddingAndBorder(node, axis);
}
function getJustifyContent(node) {
if (node.style.justifyContent) {
return node.style.justifyContent;
}
return 'flex-start';
}
function getAlignContent(node) {
if (node.style.alignContent) {
return node.style.alignContent;
}
return 'flex-start';
}
function getAlignItem(node, child) {
if (child.style.alignSelf) {
return child.style.alignSelf;
}
if (node.style.alignItems) {
return node.style.alignItems;
}
return 'stretch';
}
function resolveAxis(axis, direction) {
if (direction === CSS_DIRECTION_RTL) {
if (axis === CSS_FLEX_DIRECTION_ROW) {
return CSS_FLEX_DIRECTION_ROW_REVERSE;
} else if (axis === CSS_FLEX_DIRECTION_ROW_REVERSE) {
return CSS_FLEX_DIRECTION_ROW;
}
}
return axis;
}
function resolveDirection(node, parentDirection) {
var direction;
if (node.style.direction) {
direction = node.style.direction;
} else {
direction = CSS_DIRECTION_INHERIT;
}
if (direction === CSS_DIRECTION_INHERIT) {
direction = (parentDirection === undefined ? CSS_DIRECTION_LTR : parentDirection);
}
return direction;
}
function getFlexDirection(node) {
if (node.style.flexDirection) {
return node.style.flexDirection;
}
return CSS_FLEX_DIRECTION_COLUMN;
}
function getCrossFlexDirection(flexDirection, direction) {
if (isColumnDirection(flexDirection)) {
return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
} else {
return CSS_FLEX_DIRECTION_COLUMN;
}
}
function getPositionType(node) {
if (node.style.position) {
return node.style.position;
}
return 'relative';
}
function isFlex(node) {
return (
getPositionType(node) === CSS_POSITION_RELATIVE &&
node.style.flex > 0
);
}
function isFlexWrap(node) {
return node.style.flexWrap === 'wrap';
}
function getDimWithMargin(node, axis) {
return node.layout[dim[axis]] + getMarginAxis(node, axis);
}
function isDimDefined(node, axis) {
return node.style[dim[axis]] !== undefined && node.style[dim[axis]] >= 0;
}
function isPosDefined(node, pos) {
return node.style[pos] !== undefined;
}
function isMeasureDefined(node) {
return node.style.measure !== undefined;
}
function getPosition(node, pos) {
if (node.style[pos] !== undefined) {
return node.style[pos];
}
return 0;
}
function boundAxis(node, axis, value) {
var min = {
'row': node.style.minWidth,
'row-reverse': node.style.minWidth,
'column': node.style.minHeight,
'column-reverse': node.style.minHeight
}[axis];
var max = {
'row': node.style.maxWidth,
'row-reverse': node.style.maxWidth,
'column': node.style.maxHeight,
'column-reverse': node.style.maxHeight
}[axis];
var boundValue = value;
if (max !== undefined && max >= 0 && boundValue > max) {
boundValue = max;
}
if (min !== undefined && min >= 0 && boundValue < min) {
boundValue = min;
}
return boundValue;
}
function fmaxf(a, b) {
if (a > b) {
return a;
}
return b;
}
// When the user specifically sets a value for width or height
function setDimensionFromStyle(node, axis) {
// The parent already computed us a width or height. We just skip it
if (node.layout[dim[axis]] !== undefined) {
return;
}
// We only run if there's a width or height defined
if (!isDimDefined(node, axis)) {
return;
}
// The dimensions can never be smaller than the padding and border
node.layout[dim[axis]] = fmaxf(
boundAxis(node, axis, node.style[dim[axis]]),
getPaddingAndBorderAxis(node, axis)
);
}
function setTrailingPosition(node, child, axis) {
child.layout[trailing[axis]] = node.layout[dim[axis]] -
child.layout[dim[axis]] - child.layout[pos[axis]];
}
// If both left and right are defined, then use left. Otherwise return
// +left or -right depending on which is defined.
function getRelativePosition(node, axis) {
if (node.style[leading[axis]] !== undefined) {
return getPosition(node, leading[axis]);
}
return -getPosition(node, trailing[axis]);
}
function layoutNodeImpl(node, parentMaxWidth, /*css_direction_t*/parentDirection) {
var/*css_direction_t*/ direction = resolveDirection(node, parentDirection);
var/*(c)!css_flex_direction_t*//*(java)!int*/ mainAxis = resolveAxis(getFlexDirection(node), direction);
var/*(c)!css_flex_direction_t*//*(java)!int*/ crossAxis = getCrossFlexDirection(mainAxis, direction);
var/*(c)!css_flex_direction_t*//*(java)!int*/ resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
// Handle width and height style attributes
setDimensionFromStyle(node, mainAxis);
setDimensionFromStyle(node, crossAxis);
// Set the resolved resolution in the node's layout
node.layout.direction = direction;
// The position is set by the parent, but we need to complete it with a
// delta composed of the margin and left/top/right/bottom
node.layout[leading[mainAxis]] += getLeadingMargin(node, mainAxis) +
getRelativePosition(node, mainAxis);
node.layout[trailing[mainAxis]] += getTrailingMargin(node, mainAxis) +
getRelativePosition(node, mainAxis);
node.layout[leading[crossAxis]] += getLeadingMargin(node, crossAxis) +
getRelativePosition(node, crossAxis);
node.layout[trailing[crossAxis]] += getTrailingMargin(node, crossAxis) +
getRelativePosition(node, crossAxis);
// Inline immutable values from the target node to avoid excessive method
// invocations during the layout calculation.
var/*int*/ childCount = node.children.length;
var/*float*/ paddingAndBorderAxisResolvedRow = getPaddingAndBorderAxis(node, resolvedRowAxis);
if (isMeasureDefined(node)) {
var/*bool*/ isResolvedRowDimDefined = !isUndefined(node.layout[dim[resolvedRowAxis]]);
var/*float*/ width = CSS_UNDEFINED;
if (isDimDefined(node, resolvedRowAxis)) {
width = node.style.width;
} else if (isResolvedRowDimDefined) {
width = node.layout[dim[resolvedRowAxis]];
} else {
width = parentMaxWidth -
getMarginAxis(node, resolvedRowAxis);
}
width -= paddingAndBorderAxisResolvedRow;
// We only need to give a dimension for the text if we haven't got any
// for it computed yet. It can either be from the style attribute or because
// the element is flexible.
var/*bool*/ isRowUndefined = !isDimDefined(node, resolvedRowAxis) && !isResolvedRowDimDefined;
var/*bool*/ isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&
isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]);
// Let's not measure the text if we already know both dimensions
if (isRowUndefined || isColumnUndefined) {
var/*css_dim_t*/ measureDim = node.style.measure(
/*(c)!node->context,*/
/*(java)!layoutContext.measureOutput,*/
width
);
if (isRowUndefined) {
node.layout.width = measureDim.width +
paddingAndBorderAxisResolvedRow;
}
if (isColumnUndefined) {
node.layout.height = measureDim.height +
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
}
}
if (childCount === 0) {
return;
}
}
var/*bool*/ isNodeFlexWrap = isFlexWrap(node);
var/*css_justify_t*/ justifyContent = getJustifyContent(node);
var/*float*/ leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(node, mainAxis);
var/*float*/ leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);
var/*float*/ paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);
var/*float*/ paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);
var/*bool*/ isMainDimDefined = !isUndefined(node.layout[dim[mainAxis]]);
var/*bool*/ isCrossDimDefined = !isUndefined(node.layout[dim[crossAxis]]);
var/*bool*/ isMainRowDirection = isRowDirection(mainAxis);
var/*int*/ i;
var/*int*/ ii;
var/*css_node_t**/ child;
var/*(c)!css_flex_direction_t*//*(java)!int*/ axis;
var/*css_node_t**/ firstAbsoluteChild = null;
var/*css_node_t**/ currentAbsoluteChild = null;
var/*float*/ definedMainDim = CSS_UNDEFINED;
if (isMainDimDefined) {
definedMainDim = node.layout[dim[mainAxis]] - paddingAndBorderAxisMain;
}
// We want to execute the next two loops one per line with flex-wrap
var/*int*/ startLine = 0;
var/*int*/ endLine = 0;
// var/*int*/ nextOffset = 0;
var/*int*/ alreadyComputedNextLayout = 0;
// We aggregate the total dimensions of the container in those two variables
var/*float*/ linesCrossDim = 0;
var/*float*/ linesMainDim = 0;
var/*int*/ linesCount = 0;
while (endLine < childCount) {
// <Loop A> Layout non flexible children and count children by type
// mainContentDim is accumulation of the dimensions and margin of all the
// non flexible children. This will be used in order to either set the
// dimensions of the node if none already exist, or to compute the
// remaining space left for the flexible children.
var/*float*/ mainContentDim = 0;
// There are three kind of children, non flexible, flexible and absolute.
// We need to know how many there are in order to distribute the space.
var/*int*/ flexibleChildrenCount = 0;
var/*float*/ totalFlexible = 0;
var/*int*/ nonFlexibleChildrenCount = 0;
// Use the line loop to position children in the main axis for as long
// as they are using a simple stacking behaviour. Children that are
// immediately stacked in the initial loop will not be touched again
// in <Loop C>.
var/*bool*/ isSimpleStackMain =
(isMainDimDefined && justifyContent === CSS_JUSTIFY_FLEX_START) ||
(!isMainDimDefined && justifyContent !== CSS_JUSTIFY_CENTER);
var/*int*/ firstComplexMain = (isSimpleStackMain ? childCount : startLine);
// Use the initial line loop to position children in the cross axis for
// as long as they are relatively positioned with alignment STRETCH or
// FLEX_START. Children that are immediately stacked in the initial loop
// will not be touched again in <Loop D>.
var/*bool*/ isSimpleStackCross = true;
var/*int*/ firstComplexCross = childCount;
var/*css_node_t**/ firstFlexChild = null;
var/*css_node_t**/ currentFlexChild = null;
var/*float*/ mainDim = leadingPaddingAndBorderMain;
var/*float*/ crossDim = 0;
var/*float*/ maxWidth;
for (i = startLine; i < childCount; ++i) {
child = node.children[i];
child.lineIndex = linesCount;
child.nextAbsoluteChild = null;
child.nextFlexChild = null;
var/*css_align_t*/ alignItem = getAlignItem(node, child);
// Pre-fill cross axis dimensions when the child is using stretch before
// we call the recursive layout pass
if (alignItem === CSS_ALIGN_STRETCH &&
getPositionType(child) === CSS_POSITION_RELATIVE &&
isCrossDimDefined &&
!isDimDefined(child, crossAxis)) {
child.layout[dim[crossAxis]] = fmaxf(
boundAxis(child, crossAxis, node.layout[dim[crossAxis]] -
paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),
// You never want to go smaller than padding
getPaddingAndBorderAxis(child, crossAxis)
);
} else if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {
// Store a private linked list of absolutely positioned children
// so that we can efficiently traverse them later.
if (firstAbsoluteChild === null) {
firstAbsoluteChild = child;
}
if (currentAbsoluteChild !== null) {
currentAbsoluteChild.nextAbsoluteChild = child;
}
currentAbsoluteChild = child;
// Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both
// left and right or top and bottom).
for (ii = 0; ii < 2; ii++) {
axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
if (!isUndefined(node.layout[dim[axis]]) &&
!isDimDefined(child, axis) &&
isPosDefined(child, leading[axis]) &&
isPosDefined(child, trailing[axis])) {
child.layout[dim[axis]] = fmaxf(
boundAxis(child, axis, node.layout[dim[axis]] -
getPaddingAndBorderAxis(node, axis) -
getMarginAxis(child, axis) -
getPosition(child, leading[axis]) -
getPosition(child, trailing[axis])),
// You never want to go smaller than padding
getPaddingAndBorderAxis(child, axis)
);
}
}
}
var/*float*/ nextContentDim = 0;
// It only makes sense to consider a child flexible if we have a computed
// dimension for the node.
if (isMainDimDefined && isFlex(child)) {
flexibleChildrenCount++;
totalFlexible += child.style.flex;
// Store a private linked list of flexible children so that we can
// efficiently traverse them later.
if (firstFlexChild === null) {
firstFlexChild = child;
}
if (currentFlexChild !== null) {
currentFlexChild.nextFlexChild = child;
}
currentFlexChild = child;
// Even if we don't know its exact size yet, we already know the padding,
// border and margin. We'll use this partial information, which represents
// the smallest possible size for the child, to compute the remaining
// available space.
nextContentDim = getPaddingAndBorderAxis(child, mainAxis) +
getMarginAxis(child, mainAxis);
} else {
maxWidth = CSS_UNDEFINED;
if (!isMainRowDirection) {
if (isDimDefined(node, resolvedRowAxis)) {
maxWidth = node.layout[dim[resolvedRowAxis]] -
paddingAndBorderAxisResolvedRow;
} else {
maxWidth = parentMaxWidth -
getMarginAxis(node, resolvedRowAxis) -
paddingAndBorderAxisResolvedRow;
}
}
// This is the main recursive call. We layout non flexible children.
if (alreadyComputedNextLayout === 0) {
layoutNode(/*(java)!layoutContext, */child, maxWidth, direction);
}
// Absolute positioned elements do not take part of the layout, so we
// don't use them to compute mainContentDim
if (getPositionType(child) === CSS_POSITION_RELATIVE) {
nonFlexibleChildrenCount++;
// At this point we know the final size and margin of the element.
nextContentDim = getDimWithMargin(child, mainAxis);
}
}
// The element we are about to add would make us go to the next line
if (isNodeFlexWrap &&
isMainDimDefined &&
mainContentDim + nextContentDim > definedMainDim &&
// If there's only one element, then it's bigger than the content
// and needs its own line
i !== startLine) {
nonFlexibleChildrenCount--;
alreadyComputedNextLayout = 1;
break;
}
// Disable simple stacking in the main axis for the current line as
// we found a non-trivial child. The remaining children will be laid out
// in <Loop C>.
if (isSimpleStackMain &&
(getPositionType(child) !== CSS_POSITION_RELATIVE || isFlex(child))) {
isSimpleStackMain = false;
firstComplexMain = i;
}
// Disable simple stacking in the cross axis for the current line as
// we found a non-trivial child. The remaining children will be laid out
// in <Loop D>.
if (isSimpleStackCross &&
(getPositionType(child) !== CSS_POSITION_RELATIVE ||
(alignItem !== CSS_ALIGN_STRETCH && alignItem !== CSS_ALIGN_FLEX_START) ||
isUndefined(child.layout[dim[crossAxis]]))) {
isSimpleStackCross = false;
firstComplexCross = i;
}
if (isSimpleStackMain) {
child.layout[pos[mainAxis]] += mainDim;
if (isMainDimDefined) {
setTrailingPosition(node, child, mainAxis);
}
mainDim += getDimWithMargin(child, mainAxis);
crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));
}
if (isSimpleStackCross) {
child.layout[pos[crossAxis]] += linesCrossDim + leadingPaddingAndBorderCross;
if (isCrossDimDefined) {
setTrailingPosition(node, child, crossAxis);
}
}
alreadyComputedNextLayout = 0;
mainContentDim += nextContentDim;
endLine = i + 1;
}
// <Loop B> Layout flexible children and allocate empty space
// In order to position the elements in the main axis, we have two
// controls. The space between the beginning and the first element
// and the space between each two elements.
var/*float*/ leadingMainDim = 0;
var/*float*/ betweenMainDim = 0;
// The remaining available space that needs to be allocated
var/*float*/ remainingMainDim = 0;
if (isMainDimDefined) {
remainingMainDim = definedMainDim - mainContentDim;
} else {
remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim;
}
// If there are flexible children in the mix, they are going to fill the
// remaining space
if (flexibleChildrenCount !== 0) {
var/*float*/ flexibleMainDim = remainingMainDim / totalFlexible;
var/*float*/ baseMainDim;
var/*float*/ boundMainDim;
// If the flex share of remaining space doesn't meet min/max bounds,
// remove this child from flex calculations.
currentFlexChild = firstFlexChild;
while (currentFlexChild !== null) {
baseMainDim = flexibleMainDim * currentFlexChild.style.flex +
getPaddingAndBorderAxis(currentFlexChild, mainAxis);
boundMainDim = boundAxis(currentFlexChild, mainAxis, baseMainDim);
if (baseMainDim !== boundMainDim) {
remainingMainDim -= boundMainDim;
totalFlexible -= currentFlexChild.style.flex;
}
currentFlexChild = currentFlexChild.nextFlexChild;
}
flexibleMainDim = remainingMainDim / totalFlexible;
// The non flexible children can overflow the container, in this case
// we should just assume that there is no space available.
if (flexibleMainDim < 0) {
flexibleMainDim = 0;
}
currentFlexChild = firstFlexChild;
while (currentFlexChild !== null) {
// At this point we know the final size of the element in the main
// dimension
currentFlexChild.layout[dim[mainAxis]] = boundAxis(currentFlexChild, mainAxis,
flexibleMainDim * currentFlexChild.style.flex +
getPaddingAndBorderAxis(currentFlexChild, mainAxis)
);
maxWidth = CSS_UNDEFINED;
if (isDimDefined(node, resolvedRowAxis)) {
maxWidth = node.layout[dim[resolvedRowAxis]] -
paddingAndBorderAxisResolvedRow;
} else if (!isMainRowDirection) {
maxWidth = parentMaxWidth -
getMarginAxis(node, resolvedRowAxis) -
paddingAndBorderAxisResolvedRow;
}
// And we recursively call the layout algorithm for this child
layoutNode(/*(java)!layoutContext, */currentFlexChild, maxWidth, direction);
child = currentFlexChild;
currentFlexChild = currentFlexChild.nextFlexChild;
child.nextFlexChild = null;
}
// We use justifyContent to figure out how to allocate the remaining
// space available
} else if (justifyContent !== CSS_JUSTIFY_FLEX_START) {
if (justifyContent === CSS_JUSTIFY_CENTER) {
leadingMainDim = remainingMainDim / 2;
} else if (justifyContent === CSS_JUSTIFY_FLEX_END) {
leadingMainDim = remainingMainDim;
} else if (justifyContent === CSS_JUSTIFY_SPACE_BETWEEN) {
remainingMainDim = fmaxf(remainingMainDim, 0);
if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 !== 0) {
betweenMainDim = remainingMainDim /
(flexibleChildrenCount + nonFlexibleChildrenCount - 1);
} else {
betweenMainDim = 0;
}
} else if (justifyContent === CSS_JUSTIFY_SPACE_AROUND) {
// Space on the edges is half of the space between elements
betweenMainDim = remainingMainDim /
(flexibleChildrenCount + nonFlexibleChildrenCount);
leadingMainDim = betweenMainDim / 2;
}
}
// <Loop C> Position elements in the main axis and compute dimensions
// At this point, all the children have their dimensions set. We need to
// find their position. In order to do that, we accumulate data in
// variables that are also useful to compute the total dimensions of the
// container!
mainDim += leadingMainDim;
for (i = firstComplexMain; i < endLine; ++i) {
child = node.children[i];
if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&
isPosDefined(child, leading[mainAxis])) {
// In case the child is position absolute and has left/top being
// defined, we override the position to whatever the user said
// (and margin/border).
child.layout[pos[mainAxis]] = getPosition(child, leading[mainAxis]) +
getLeadingBorder(node, mainAxis) +
getLeadingMargin(child, mainAxis);
} else {
// If the child is position absolute (without top/left) or relative,
// we put it at the current accumulated offset.
child.layout[pos[mainAxis]] += mainDim;
// Define the trailing position accordingly.
if (isMainDimDefined) {
setTrailingPosition(node, child, mainAxis);
}
// Now that we placed the element, we need to update the variables
// We only need to do that for relative elements. Absolute elements
// do not take part in that phase.
if (getPositionType(child) === CSS_POSITION_RELATIVE) {
// The main dimension is the sum of all the elements dimension plus
// the spacing.
mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);
// The cross dimension is the max of the elements dimension since there
// can only be one element in that cross dimension.
crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));
}
}
}
var/*float*/ containerCrossAxis = node.layout[dim[crossAxis]];
if (!isCrossDimDefined) {
containerCrossAxis = fmaxf(
// For the cross dim, we add both sides at the end because the value
// is aggregate via a max function. Intermediate negative values
// can mess this computation otherwise
boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross),
paddingAndBorderAxisCross
);
}
// <Loop D> Position elements in the cross axis
for (i = firstComplexCross; i < endLine; ++i) {
child = node.children[i];
if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&
isPosDefined(child, leading[crossAxis])) {
// In case the child is absolutely positionned and has a
// top/left/bottom/right being set, we override all the previously
// computed positions to set it correctly.
child.layout[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +
getLeadingBorder(node, crossAxis) +
getLeadingMargin(child, crossAxis);
} else {
var/*float*/ leadingCrossDim = leadingPaddingAndBorderCross;
// For a relative children, we're either using alignItems (parent) or
// alignSelf (child) in order to determine the position in the cross axis
if (getPositionType(child) === CSS_POSITION_RELATIVE) {
/*eslint-disable */
// This variable is intentionally re-defined as the code is transpiled to a block scope language
var/*css_align_t*/ alignItem = getAlignItem(node, child);
/*eslint-enable */
if (alignItem === CSS_ALIGN_STRETCH) {
// You can only stretch if the dimension has not already been set
// previously.
if (isUndefined(child.layout[dim[crossAxis]])) {
child.layout[dim[crossAxis]] = fmaxf(
boundAxis(child, crossAxis, containerCrossAxis -
paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),
// You never want to go smaller than padding
getPaddingAndBorderAxis(child, crossAxis)
);
}
} else if (alignItem !== CSS_ALIGN_FLEX_START) {
// The remaining space between the parent dimensions+padding and child
// dimensions+margin.
var/*float*/ remainingCrossDim = containerCrossAxis -
paddingAndBorderAxisCross - getDimWithMargin(child, crossAxis);
if (alignItem === CSS_ALIGN_CENTER) {
leadingCrossDim += remainingCrossDim / 2;
} else { // CSS_ALIGN_FLEX_END
leadingCrossDim += remainingCrossDim;
}
}
}
// And we apply the position
child.layout[pos[crossAxis]] += linesCrossDim + leadingCrossDim;
// Define the trailing position accordingly.
if (isCrossDimDefined) {
setTrailingPosition(node, child, crossAxis);
}
}
}
linesCrossDim += crossDim;
linesMainDim = fmaxf(linesMainDim, mainDim);
linesCount += 1;
startLine = endLine;
}
// <Loop E>
//
// Note(prenaux): More than one line, we need to layout the crossAxis
// according to alignContent.
//
// Note that we could probably remove <Loop D> and handle the one line case
// here too, but for the moment this is safer since it won't interfere with
// previously working code.
//
// See specs:
// http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm
// section 9.4
//
if (linesCount > 1 && isCrossDimDefined) {
var/*float*/ nodeCrossAxisInnerSize = node.layout[dim[crossAxis]] -
paddingAndBorderAxisCross;
var/*float*/ remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim;
var/*float*/ crossDimLead = 0;
var/*float*/ currentLead = leadingPaddingAndBorderCross;
var/*css_align_t*/ alignContent = getAlignContent(node);
if (alignContent === CSS_ALIGN_FLEX_END) {
currentLead += remainingAlignContentDim;
} else if (alignContent === CSS_ALIGN_CENTER) {
currentLead += remainingAlignContentDim / 2;
} else if (alignContent === CSS_ALIGN_STRETCH) {
if (nodeCrossAxisInnerSize > linesCrossDim) {
crossDimLead = (remainingAlignContentDim / linesCount);
}
}
var/*int*/ endIndex = 0;
for (i = 0; i < linesCount; ++i) {
var/*int*/ startIndex = endIndex;
// compute the line's height and find the endIndex
var/*float*/ lineHeight = 0;
for (ii = startIndex; ii < childCount; ++ii) {
child = node.children[ii];
if (getPositionType(child) !== CSS_POSITION_RELATIVE) {
continue;
}
if (child.lineIndex !== i) {
break;
}
if (!isUndefined(child.layout[dim[crossAxis]])) {
lineHeight = fmaxf(
lineHeight,
child.layout[dim[crossAxis]] + getMarginAxis(child, crossAxis)
);
}
}
endIndex = ii;
lineHeight += crossDimLead;
for (ii = startIndex; ii < endIndex; ++ii) {
child = node.children[ii];
if (getPositionType(child) !== CSS_POSITION_RELATIVE) {
continue;
}
var/*css_align_t*/ alignContentAlignItem = getAlignItem(node, child);
if (alignContentAlignItem === CSS_ALIGN_FLEX_START) {
child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);
} else if (alignContentAlignItem === CSS_ALIGN_FLEX_END) {
child.layout[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child.layout[dim[crossAxis]];
} else if (alignContentAlignItem === CSS_ALIGN_CENTER) {
var/*float*/ childHeight = child.layout[dim[crossAxis]];
child.layout[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2;
} else if (alignContentAlignItem === CSS_ALIGN_STRETCH) {
child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);
// TODO(prenaux): Correctly set the height of items with undefined
// (auto) crossAxis dimension.
}
}
currentLead += lineHeight;
}
}
var/*bool*/ needsMainTrailingPos = false;
var/*bool*/ needsCrossTrailingPos = false;
// If the user didn't specify a width or height, and it has not been set
// by the container, then we set it via the children.
if (!isMainDimDefined) {
node.layout[dim[mainAxis]] = fmaxf(
// We're missing the last padding at this point to get the final
// dimension
boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)),
// We can never assign a width smaller than the padding and borders
paddingAndBorderAxisMain
);
if (mainAxis === CSS_FLEX_DIRECTION_ROW_REVERSE ||
mainAxis === CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
needsMainTrailingPos = true;
}
}
if (!isCrossDimDefined) {
node.layout[dim[crossAxis]] = fmaxf(
// For the cross dim, we add both sides at the end because the value
// is aggregate via a max function. Intermediate negative values
// can mess this computation otherwise
boundAxis(node, crossAxis, linesCrossDim + paddingAndBorderAxisCross),
paddingAndBorderAxisCross
);
if (crossAxis === CSS_FLEX_DIRECTION_ROW_REVERSE ||
crossAxis === CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
needsCrossTrailingPos = true;
}
}
// <Loop F> Set trailing position if necessary
if (needsMainTrailingPos || needsCrossTrailingPos) {
for (i = 0; i < childCount; ++i) {
child = node.children[i];
if (needsMainTrailingPos) {
setTrailingPosition(node, child, mainAxis);
}
if (needsCrossTrailingPos) {
setTrailingPosition(node, child, crossAxis);
}
}
}
// <Loop G> Calculate dimensions for absolutely positioned elements
currentAbsoluteChild = firstAbsoluteChild;
while (currentAbsoluteChild !== null) {
// Pre-fill dimensions when using absolute position and both offsets for
// the axis are defined (either both left and right or top and bottom).
for (ii = 0; ii < 2; ii++) {
axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
if (!isUndefined(node.layout[dim[axis]]) &&
!isDimDefined(currentAbsoluteChild, axis) &&
isPosDefined(currentAbsoluteChild, leading[axis]) &&
isPosDefined(currentAbsoluteChild, trailing[axis])) {
currentAbsoluteChild.layout[dim[axis]] = fmaxf(
boundAxis(currentAbsoluteChild, axis, node.layout[dim[axis]] -
getBorderAxis(node, axis) -
getMarginAxis(currentAbsoluteChild, axis) -
getPosition(currentAbsoluteChild, leading[axis]) -
getPosition(currentAbsoluteChild, trailing[axis])
),
// You never want to go smaller than padding
getPaddingAndBorderAxis(currentAbsoluteChild, axis)
);
}
if (isPosDefined(currentAbsoluteChild, trailing[axis]) &&
!isPosDefined(currentAbsoluteChild, leading[axis])) {
currentAbsoluteChild.layout[leading[axis]] =
node.layout[dim[axis]] -
currentAbsoluteChild.layout[dim[axis]] -
getPosition(currentAbsoluteChild, trailing[axis]);
}
}
child = currentAbsoluteChild;
currentAbsoluteChild = currentAbsoluteChild.nextAbsoluteChild;
child.nextAbsoluteChild = null;
}
}
function layoutNode(node, parentMaxWidth, parentDirection) {
node.shouldUpdate = true;
var direction = node.style.direction || CSS_DIRECTION_LTR;
var skipLayout =
!node.isDirty &&
node.lastLayout &&
node.lastLayout.requestedHeight === node.layout.height &&
node.lastLayout.requestedWidth === node.layout.width &&
node.lastLayout.parentMaxWidth === parentMaxWidth &&
node.lastLayout.direction === direction;
if (skipLayout) {
node.layout.width = node.lastLayout.width;
node.layout.height = node.lastLayout.height;
node.layout.top = node.lastLayout.top;
node.layout.left = node.lastLayout.left;
} else {
if (!node.lastLayout) {
node.lastLayout = {};
}
node.lastLayout.requestedWidth = node.layout.width;
node.lastLayout.requestedHeight = node.layout.height;
node.lastLayout.parentMaxWidth = parentMaxWidth;
node.lastLayout.direction = direction;
// Reset child layouts
node.children.forEach(function(child) {
child.layout.width = undefined;
child.layout.height = undefined;
child.layout.top = 0;
child.layout.left = 0;
});
layoutNodeImpl(node, parentMaxWidth, parentDirection);
node.lastLayout.width = node.layout.width;
node.lastLayout.height = node.layout.height;
node.lastLayout.top = node.layout.top;
node.lastLayout.left = node.layout.left;
}
}
return {
layoutNodeImpl: layoutNodeImpl,
computeLayout: layoutNode,
fillNodes: fillNodes
};
})();
// This module export is only used for the purposes of unit testing this file. When
// the library is packaged this file is included within css-layout.js which forms
// the public API.
if (true) {
module.exports = computeLayout;
}
return function(node) {
/*eslint-disable */
// disabling ESLint because this code relies on the above include
computeLayout.fillNodes(node);
computeLayout.computeLayout(node);
/*eslint-enable */
};
}));
/***/ }),
/* 11 */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
var nodeToJson = __webpack_require__(12);
var xmlToNodeobj = __webpack_require__(14);
var x2xmlnode = __webpack_require__(14);
var buildOptions = (__webpack_require__(13).buildOptions);
var validator = __webpack_require__(16);
exports.parse = function (xmlData, options, validationOption) {
if (validationOption) {
if (validationOption === true)
validationOption = {};
var result = validator.validate(xmlData, validationOption);
if (result !== true) {
throw Error(result.err.msg);
}
}
options = buildOptions(options, x2xmlnode.defaultOptions, x2xmlnode.props);
return nodeToJson.convertToJson(xmlToNodeobj.getTraversalObj(xmlData, options), options);
};
/***/ }),
/* 12 */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
var util = __webpack_require__(13);
var convertToJson = function (node, options) {
var jObj = {
name: node.tagname
};
//when no child node or attr is present
if ((!node.child || util.isEmptyObject(node.child)) && (!node.attrsMap || util.isEmptyObject(node.attrsMap))) {
return util.isExist(node.val) && !!node.val ? node.val : jObj;
}
else {
//otherwise create a textnode if node has some text
if (util.isExist(node.val)) {
if (!(typeof node.val === 'string' && (node.val === '' || node.val === options.cdataPositionChar))) {
if (options.arrayMode === "strict") {
jObj[options.textNodeName] = [node.val];
}
else {
jObj[options.textNodeName] = node.val;
}
}
}
}
util.merge(jObj, node.attrsMap, options.arrayMode);
jObj.children = [];
node.children.forEach(function (child) {
jObj.children.push(convertToJson(child, options));
});
//add value
return jObj;
};
exports.convertToJson = convertToJson;
/***/ }),
/* 13 */
/***/ ((__unused_webpack_module, exports) => {
"use strict";
var getAllMatches = function (string, regex) {
var matches = [];
var match = regex.exec(string);
while (match) {
var allmatches = [];
var len = match.length;
for (var index = 0; index < len; index++) {
allmatches.push(match[index]);
}
matches.push(allmatches);
match = regex.exec(string);
}
return matches;
};
var doesMatch = function (string, regex) {
var match = regex.exec(string);
return !(match === null || typeof match === 'undefined');
};
var doesNotMatch = function (string, regex) {
return !doesMatch(string, regex);
};
exports.isExist = function (v) {
return typeof v !== 'undefined';
};
exports.isEmptyObject = function (obj) {
return Object.keys(obj).length === 0;
};
/**
* Copy all the properties of a into b.
* @param {*} target
* @param {*} a
*/
exports.merge = function (target, a, arrayMode) {
if (a) {
var keys = Object.keys(a); // will return an array of own properties
var len = keys.length; //don't make it inline
for (var i = 0; i < len; i++) {
if (arrayMode === 'strict') {
target[keys[i]] = [a[keys[i]]];
}
else {
target[keys[i]] = a[keys[i]];
}
}
}
};
/* exports.merge =function (b,a){
return Object.assign(b,a);
} */
exports.getValue = function (v) {
if (exports.isExist(v)) {
return v;
}
else {
return '';
}
};
// const fakeCall = function(a) {return a;};
// const fakeCallNoReturn = function() {};
exports.buildOptions = function (options, defaultOptions, props) {
var newOptions = {};
if (!options) {
return defaultOptions; //if there are not options
}
for (var i = 0; i < props.length; i++) {
if (options[props[i]] !== undefined) {
newOptions[props[i]] = options[props[i]];
}
else {
newOptions[props[i]] = defaultOptions[props[i]];
}
}
return newOptions;
};
exports.doesMatch = doesMatch;
exports.doesNotMatch = doesNotMatch;
exports.getAllMatches = getAllMatches;
/***/ }),
/* 14 */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
var util = __webpack_require__(13);
var buildOptions = (__webpack_require__(13).buildOptions);
var xmlNode = __webpack_require__(15);
var TagType = { OPENING: 1, CLOSING: 2, SELF: 3, CDATA: 4 };
var regx = '<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|(([\\w:\\-._]*:)?([\\w:\\-._]+))([^>]*)>|((\\/)(([\\w:\\-._]*:)?([\\w:\\-._]+))\\s*>))([^<]*)';
//const tagsRegx = new RegExp("<(\\/?[\\w:\\-\._]+)([^>]*)>(\\s*"+cdataRegx+")*([^<]+)?","g");
//const tagsRegx = new RegExp("<(\\/?)((\\w*:)?([\\w:\\-\._]+))([^>]*)>([^<]*)("+cdataRegx+"([^<]*))*([^<]+)?","g");
//polyfill
if (!Number.parseInt && window.parseInt) {
Number.parseInt = window.parseInt;
}
if (!Number.parseFloat && window.parseFloat) {
Number.parseFloat = window.parseFloat;
}
var defaultOptions = {
attributeNamePrefix: '@_',
attrNodeName: false,
textNodeName: '#text',
ignoreAttributes: true,
ignoreNameSpace: false,
allowBooleanAttributes: false, //a tag can have attributes without any value
//ignoreRootElement : false,
parseNodeValue: true,
parseAttributeValue: false,
arrayMode: false,
trimValues: true, //Trim string values of tag and attributes
cdataTagName: false,
cdataPositionChar: '\\c',
localeRange: '',
tagValueProcessor: function (a) {
return a;
},
attrValueProcessor: function (a) {
return a;
},
stopNodes: []
//decodeStrict: false,
};
exports.defaultOptions = defaultOptions;
var props = [
'attributeNamePrefix',
'attrNodeName',
'textNodeName',
'ignoreAttributes',
'ignoreNameSpace',
'allowBooleanAttributes',
'parseNodeValue',
'parseAttributeValue',
'arrayMode',
'trimValues',
'cdataTagName',
'cdataPositionChar',
'localeRange',
'tagValueProcessor',
'attrValueProcessor',
'parseTrueNumberOnly',
'stopNodes'
];
exports.props = props;
var getTraversalObj = function (xmlData, options) {
options = buildOptions(options, defaultOptions, props);
//xmlData = xmlData.replace(/\r?\n/g, " ");//make it single line
xmlData = xmlData.replace(/<!--[\s\S]*?-->/g, ''); //Remove comments
var xmlObj = new xmlNode('!xml');
var currentNode = xmlObj;
regx = regx.replace(/\[\\w/g, '[' + options.localeRange + '\\w');
var tagsRegx = new RegExp(regx, 'g');
var tag = tagsRegx.exec(xmlData);
var nextTag = tagsRegx.exec(xmlData);
while (tag) {
var tagType = checkForTagType(tag);
if (tagType === TagType.CLOSING) {
//add parsed data to parent node
if (currentNode.parent && tag[14]) {
currentNode.parent.val = util.getValue(currentNode.parent.val) + '' + processTagValue(tag, options, currentNode.parent.tagname);
}
if (options.stopNodes.length && options.stopNodes.includes(currentNode.tagname)) {
currentNode.child = [];
if (currentNode.attrsMap == undefined) {
currentNode.attrsMap = {};
}
currentNode.val = xmlData.substr(currentNode.startIndex + 1, tag.index - currentNode.startIndex - 1);
}
currentNode = currentNode.parent;
}
else if (tagType === TagType.CDATA) {
if (options.cdataTagName) {
//add cdata node
var childNode = new xmlNode(options.cdataTagName, currentNode, tag[3]);
childNode.attrsMap = buildAttributesMap(tag[8], options);
currentNode.addChild(childNode);
//for backtracking
currentNode.val = util.getValue(currentNode.val) + options.cdataPositionChar;
//add rest value to parent node
if (tag[14]) {
currentNode.val += processTagValue(tag, options);
}
}
else {
currentNode.val = (currentNode.val || '') + (tag[3] || '') + processTagValue(tag, options);
}
}
else if (tagType === TagType.SELF) {
if (currentNode && tag[14]) {
currentNode.val = util.getValue(currentNode.val) + '' + processTagValue(tag, options);
}
var childNode = new xmlNode(options.ignoreNameSpace ? tag[7] : tag[5], currentNode, '');
if (tag[8] && tag[8].length > 0) {
tag[8] = tag[8].substr(0, tag[8].length - 1);
}
childNode.attrsMap = buildAttributesMap(tag[8], options);
currentNode.addChild(childNode);
}
else {
//TagType.OPENING
var childNode = new xmlNode(options.ignoreNameSpace ? tag[7] : tag[5], currentNode, processTagValue(tag, options));
if (options.stopNodes.length && options.stopNodes.includes(childNode.tagname)) {
childNode.startIndex = tag.index + tag[1].length;
}
childNode.attrsMap = buildAttributesMap(tag[8], options);
currentNode.addChild(childNode);
currentNode = childNode;
}
tag = nextTag;
nextTag = tagsRegx.exec(xmlData);
}
return xmlObj;
};
function processTagValue(parsedTags, options, parentTagName) {
var tagName = parsedTags[7] || parentTagName;
var val = parsedTags[14];
if (val) {
if (options.trimValues) {
val = val.trim();
}
val = options.tagValueProcessor(val, tagName);
val = parseValue(val, options.parseNodeValue, options.parseTrueNumberOnly);
}
return val;
}
function checkForTagType(match) {
if (match[4] === ']]>') {
return TagType.CDATA;
}
else if (match[10] === '/') {
return TagType.CLOSING;
}
else if (typeof match[8] !== 'undefined' && match[8].substr(match[8].length - 1) === '/') {
return TagType.SELF;
}
else {
return TagType.OPENING;
}
}
function resolveNameSpace(tagname, options) {
if (options.ignoreNameSpace) {
var tags = tagname.split(':');
var prefix = tagname.charAt(0) === '/' ? '/' : '';
if (tags[0] === 'xmlns') {
return '';
}
if (tags.length === 2) {
tagname = prefix + tags[1];
}
}
return tagname;
}
function parseValue(val, shouldParse, parseTrueNumberOnly) {
if (shouldParse && typeof val === 'string') {
var parsed = void 0;
if (val.trim() === '' || isNaN(val)) {
parsed = val === 'true' ? true : val === 'false' ? false : val;
}
else {
if (val.indexOf('0x') !== -1) {
//support hexa decimal
parsed = Number.parseInt(val, 16);
}
else if (val.indexOf('.') !== -1) {
parsed = Number.parseFloat(val);
}
else {
parsed = Number.parseInt(val, 10);
}
if (parseTrueNumberOnly) {
parsed = String(parsed) === val ? parsed : val;
}
}
return parsed;
}
else {
if (util.isExist(val)) {
return val;
}
else {
return '';
}
}
}
//TODO: change regex to capture NS
//const attrsRegx = new RegExp("([\\w\\-\\.\\:]+)\\s*=\\s*(['\"])((.|\n)*?)\\2","gm");
var attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])(.*?)\\3)?', 'g');
function buildAttributesMap(attrStr, options) {
if (!options.ignoreAttributes && typeof attrStr === 'string') {
attrStr = attrStr.replace(/\r?\n/g, ' ');
//attrStr = attrStr || attrStr.trim();
var matches = util.getAllMatches(attrStr, attrsRegx);
var len = matches.length; //don't make it inline
var attrs = {};
for (var i = 0; i < len; i++) {
var attrName = resolveNameSpace(matches[i][1], options);
if (attrName.length) {
if (matches[i][4] !== undefined) {
if (options.trimValues) {
matches[i][4] = matches[i][4].trim();
}
matches[i][4] = options.attrValueProcessor(matches[i][4], attrName);
attrs[options.attributeNamePrefix + attrName] = parseValue(matches[i][4], options.parseAttributeValue, options.parseTrueNumberOnly);
}
else if (options.allowBooleanAttributes) {
attrs[options.attributeNamePrefix + attrName] = true;
}
}
}
if (!Object.keys(attrs).length) {
return;
}
if (options.attrNodeName) {
var attrCollection = {};
attrCollection[options.attrNodeName] = attrs;
return attrCollection;
}
return attrs;
}
}
exports.getTraversalObj = getTraversalObj;
/***/ }),
/* 15 */
/***/ ((module) => {
"use strict";
module.exports = function (tagname, parent, val) {
this.tagname = tagname;
this.parent = parent;
this.child = {}; //child tags
this.attrsMap = {}; //attributes map
this.children = [];
this.val = val; //text only
this.addChild = function (child) {
this.children.push(child);
if (Array.isArray(this.child[child.tagname])) {
//already presents
this.child[child.tagname].push(child);
}
else {
this.child[child.tagname] = [child];
}
};
};
/***/ }),
/* 16 */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
var util = __webpack_require__(13);
var defaultOptions = {
allowBooleanAttributes: false, //A tag can have attributes without any value
localeRange: 'a-zA-Z',
};
var props = ['allowBooleanAttributes', 'localeRange'];
//const tagsPattern = new RegExp("<\\/?([\\w:\\-_\.]+)\\s*\/?>","g");
exports.validate = function (xmlData, options) {
options = util.buildOptions(options, defaultOptions, props);
//xmlData = xmlData.replace(/(\r\n|\n|\r)/gm,"");//make it single line
//xmlData = xmlData.replace(/(^\s*<\?xml.*?\?>)/g,"");//Remove XML starting tag
//xmlData = xmlData.replace(/(<!DOCTYPE[\s\w\"\.\/\-\:]+(\[.*\])*\s*>)/g,"");//Remove DOCTYPE
var tags = [];
var tagFound = false;
if (xmlData[0] === '\ufeff') {
// check for byte order mark (BOM)
xmlData = xmlData.substr(1);
}
var regxAttrName = new RegExp('^[_w][\\w\\-.:]*$'.replace('_w', '_' + options.localeRange));
var regxTagName = new RegExp('^([w]|_)[\\w.\\-_:]*'.replace('([w', '([' + options.localeRange));
for (var i = 0; i < xmlData.length; i++) {
if (xmlData[i] === '<') {
//starting of tag
//read until you reach to '>' avoiding any '>' in attribute value
i++;
if (xmlData[i] === '?') {
i = readPI(xmlData, ++i);
if (i.err) {
return i;
}
}
else if (xmlData[i] === '!') {
i = readCommentAndCDATA(xmlData, i);
continue;
}
else {
var closingTag = false;
if (xmlData[i] === '/') {
//closing tag
closingTag = true;
i++;
}
//read tagname
var tagName = '';
for (; i < xmlData.length &&
xmlData[i] !== '>' &&
xmlData[i] !== ' ' &&
xmlData[i] !== '\t' &&
xmlData[i] !== '\n' &&
xmlData[i] !== '\r'; i++) {
tagName += xmlData[i];
}
tagName = tagName.trim();
//console.log(tagName);
if (tagName[tagName.length - 1] === '/') {
//self closing tag without attributes
tagName = tagName.substring(0, tagName.length - 1);
continue;
}
if (!validateTagName(tagName, regxTagName)) {
return { err: { code: 'InvalidTag', msg: 'Tag ' + tagName + ' is an invalid name.' } };
}
var result = readAttributeStr(xmlData, i);
if (result === false) {
return { err: { code: 'InvalidAttr', msg: 'Attributes for "' + tagName + '" have open quote.' } };
}
var attrStr = result.value;
i = result.index;
if (attrStr[attrStr.length - 1] === '/') {
//self closing tag
attrStr = attrStr.substring(0, attrStr.length - 1);
var isValid = validateAttributeString(attrStr, options, regxAttrName);
if (isValid === true) {
tagFound = true;
//continue; //text may presents after self closing tag
}
else {
return isValid;
}
}
else if (closingTag) {
if (!result.tagClosed) {
return {
err: { code: 'InvalidTag', msg: 'closing tag "' + tagName + "\" don't have proper closing." },
};
}
else if (attrStr.trim().length > 0) {
return {
err: { code: 'InvalidTag', msg: 'closing tag "' + tagName + "\" can't have attributes or invalid starting." },
};
}
else {
var otg = tags.pop();
if (tagName !== otg) {
return {
err: { code: 'InvalidTag', msg: 'closing tag ' + otg + ' is expected inplace of ' + tagName + '.' },
};
}
}
}
else {
var isValid = validateAttributeString(attrStr, options, regxAttrName);
if (isValid !== true) {
return isValid;
}
tags.push(tagName);
tagFound = true;
}
//skip tag text value
//It may include comments and CDATA value
for (i++; i < xmlData.length; i++) {
if (xmlData[i] === '<') {
if (xmlData[i + 1] === '!') {
//comment or CADATA
i++;
i = readCommentAndCDATA(xmlData, i);
continue;
}
else {
break;
}
}
} //end of reading tag text value
if (xmlData[i] === '<') {
i--;
}
}
}
else {
if (xmlData[i] === ' ' || xmlData[i] === '\t' || xmlData[i] === '\n' || xmlData[i] === '\r') {
continue;
}
return { err: { code: 'InvalidChar', msg: 'char ' + xmlData[i] + ' is not expected .' } };
}
}
if (!tagFound) {
return { err: { code: 'InvalidXml', msg: 'Start tag expected.' } };
}
else if (tags.length > 0) {
return {
err: { code: 'InvalidXml', msg: 'Invalid ' + JSON.stringify(tags, null, 4).replace(/\r?\n/g, '') + ' found.' },
};
}
return true;
};
/**
* Read Processing insstructions and skip
* @param {*} xmlData
* @param {*} i
*/
function readPI(xmlData, i) {
var start = i;
for (; i < xmlData.length; i++) {
if (xmlData[i] == '?' || xmlData[i] == ' ') {
//tagname
var tagname = xmlData.substr(start, i - start);
if (i > 5 && tagname === 'xml') {
return { err: { code: 'InvalidXml', msg: 'XML declaration allowed only at the start of the document.' } };
}
else if (xmlData[i] == '?' && xmlData[i + 1] == '>') {
//check if valid attribut string
i++;
break;
}
else {
continue;
}
}
}
return i;
}
function readCommentAndCDATA(xmlData, i) {
if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') {
//comment
for (i += 3; i < xmlData.length; i++) {
if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') {
i += 2;
break;
}
}
}
else if (xmlData.length > i + 8 &&
xmlData[i + 1] === 'D' &&
xmlData[i + 2] === 'O' &&
xmlData[i + 3] === 'C' &&
xmlData[i + 4] === 'T' &&
xmlData[i + 5] === 'Y' &&
xmlData[i + 6] === 'P' &&
xmlData[i + 7] === 'E') {
var angleBracketsCount = 1;
for (i += 8; i < xmlData.length; i++) {
if (xmlData[i] === '<') {
angleBracketsCount++;
}
else if (xmlData[i] === '>') {
angleBracketsCount--;
if (angleBracketsCount === 0) {
break;
}
}
}
}
else if (xmlData.length > i + 9 &&
xmlData[i + 1] === '[' &&
xmlData[i + 2] === 'C' &&
xmlData[i + 3] === 'D' &&
xmlData[i + 4] === 'A' &&
xmlData[i + 5] === 'T' &&
xmlData[i + 6] === 'A' &&
xmlData[i + 7] === '[') {
for (i += 8; i < xmlData.length; i++) {
if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') {
i += 2;
break;
}
}
}
return i;
}
var doubleQuote = '"';
var singleQuote = "'";
/**
* Keep reading xmlData until '<' is found outside the attribute value.
* @param {string} xmlData
* @param {number} i
*/
function readAttributeStr(xmlData, i) {
var attrStr = '';
var startChar = '';
var tagClosed = false;
for (; i < xmlData.length; i++) {
if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {
if (startChar === '') {
startChar = xmlData[i];
}
else if (startChar !== xmlData[i]) {
//if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa
continue;
}
else {
startChar = '';
}
}
else if (xmlData[i] === '>') {
if (startChar === '') {
tagClosed = true;
break;
}
}
attrStr += xmlData[i];
}
if (startChar !== '') {
return false;
}
return { value: attrStr, index: i, tagClosed: tagClosed };
}
/**
* Select all the attributes whether valid or invalid.
*/
var validAttrStrRegxp = new RegExp('(\\s*)([^\\s=]+)(\\s*=)?(\\s*([\'"])(([\\s\\S])*?)\\5)?', 'g');
//attr, ="sd", a="amit's", a="sd"b="saf", ab cd=""
function validateAttributeString(attrStr, options, regxAttrName) {
//console.log("start:"+attrStr+":end");
//if(attrStr.trim().length === 0) return true; //empty string
var matches = util.getAllMatches(attrStr, validAttrStrRegxp);
var attrNames = {};
for (var i = 0; i < matches.length; i++) {
//console.log(matches[i]);
if (matches[i][1].length === 0) {
//nospace before attribute name: a="sd"b="saf"
return { err: { code: 'InvalidAttr', msg: 'attribute ' + matches[i][2] + ' has no space in starting.' } };
}
else if (matches[i][3] === undefined && !options.allowBooleanAttributes) {
//independent attribute: ab
return { err: { code: 'InvalidAttr', msg: 'boolean attribute ' + matches[i][2] + ' is not allowed.' } };
}
/* else if(matches[i][6] === undefined){//attribute without value: ab=
return { err: { code:"InvalidAttr",msg:"attribute " + matches[i][2] + " has no value assigned."}};
} */
var attrName = matches[i][2];
if (!validateAttrName(attrName, regxAttrName)) {
return { err: { code: 'InvalidAttr', msg: 'attribute ' + attrName + ' is an invalid name.' } };
}
/*if (!attrNames.hasOwnProperty(attrName)) {*/
if (!Object.prototype.hasOwnProperty.call(attrNames, attrName)) {
//check for duplicate attribute.
attrNames[attrName] = 1;
}
else {
return { err: { code: 'InvalidAttr', msg: 'attribute ' + attrName + ' is repeated.' } };
}
}
return true;
}
// const validAttrRegxp = /^[_a-zA-Z][\w\-.:]*$/;
function validateAttrName(attrName, regxAttrName) {
// const validAttrRegxp = new RegExp(regxAttrName);
return util.doesMatch(attrName, regxAttrName);
}
//const startsWithXML = new RegExp("^[Xx][Mm][Ll]");
// startsWith = /^([a-zA-Z]|_)[\w.\-_:]*/;
function validateTagName(tagname, regxTagName) {
/*if(util.doesMatch(tagname,startsWithXML)) return false;
else*/
return !util.doesNotMatch(tagname, regxTagName);
}
/***/ }),
/* 17 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _imageManager__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5);
/* harmony import */ var tiny_emitter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8);
/* harmony import */ var tiny_emitter__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tiny_emitter__WEBPACK_IMPORTED_MODULE_1__);
/**
* http://www.angelcode.com/products/bmfont/doc/file_format.html
*/
var BitMapFont = /** @class */ (function () {
// pool的实现放到类里面实现并不优雅,先去掉了
function BitMapFont(name, src, config) {
var _this = this;
this.ready = false;
this.config = config;
this.chars = this.parseConfig(config);
this.event = new (tiny_emitter__WEBPACK_IMPORTED_MODULE_1___default().TinyEmitter)();
this.texture = _imageManager__WEBPACK_IMPORTED_MODULE_0__["default"].loadImage(src, function (texture, fromCache) {
if (fromCache) {
_this.texture = texture;
}
_this.ready = true;
_this.event.emit('text__load__done');
});
}
BitMapFont.prototype.parseConfig = function (fntText) {
fntText = fntText.split('\r\n').join('\n');
var lines = fntText.split('\n');
var linesParsed = lines.map(function (line) { return line.trim().split(' '); });
var charsLine = this.getConfigByLineName(linesParsed, 'chars');
var charsCount = this.getConfigByKeyInOneLine(charsLine.line, 'count');
var commonLine = this.getConfigByLineName(linesParsed, 'common');
this.lineHeight = this.getConfigByKeyInOneLine(commonLine.line, 'lineHeight');
var infoLine = this.getConfigByLineName(linesParsed, 'info');
this.fontSize = this.getConfigByKeyInOneLine(infoLine.line, 'size');
// 接卸 kernings
var kerningsLine = this.getConfigByLineName(linesParsed, 'kernings');
var kerningsCount = 0;
var kerningsStart = -1;
if (kerningsLine.line) {
kerningsCount = this.getConfigByKeyInOneLine(kerningsLine.line, 'count');
kerningsStart = kerningsLine.index + 1;
}
var chars = {};
for (var i = 4; i < 4 + charsCount; i++) {
var charText = lines[i];
var letter = String.fromCharCode(this.getConfigByKeyInOneLine(charText, 'id'));
var c = {
x: this.getConfigByKeyInOneLine(charText, 'x'),
y: this.getConfigByKeyInOneLine(charText, 'y'),
w: this.getConfigByKeyInOneLine(charText, 'width'),
h: this.getConfigByKeyInOneLine(charText, 'height'),
offX: this.getConfigByKeyInOneLine(charText, 'xoffset'),
offY: this.getConfigByKeyInOneLine(charText, 'yoffset'),
xadvance: this.getConfigByKeyInOneLine(charText, 'xadvance'),
kerning: {}
};
chars[letter] = c;
}
// parse kernings
if (kerningsCount) {
for (var i = kerningsStart; i <= kerningsStart + kerningsCount; i++) {
var line = linesParsed[i];
var first = String.fromCharCode(this.getConfigByKeyInOneLine(line, 'first'));
var second = String.fromCharCode(this.getConfigByKeyInOneLine(line, 'second'));
var amount = this.getConfigByKeyInOneLine(line, 'amount');
if (chars[second]) {
chars[second].kerning[first] = amount;
}
}
}
return chars;
};
BitMapFont.prototype.getConfigByLineName = function (linesParsed, lineName) {
if (lineName === void 0) { lineName = ''; }
var index = -1;
var line = [];
var len = linesParsed.length;
for (var i = 0; i < len; i++) {
var item = linesParsed[i];
if (item[0] === lineName) {
index = i;
line = item;
}
}
return {
line: line,
index: index,
};
};
BitMapFont.prototype.getConfigByKeyInOneLine = function (configText, key) {
var itemConfigTextList = Array.isArray(configText) ? configText : configText.split(' ');
for (var i = 0, length_1 = itemConfigTextList.length; i < length_1; i++) {
var itemConfigText = itemConfigTextList[i];
if (key === itemConfigText.substring(0, key.length)) {
var value = itemConfigText.substring(key.length + 1);
return parseInt(value);
}
}
return 0;
};
return BitMapFont;
}());
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BitMapFont);
/***/ }),
/* 18 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
var DebugInfo = /** @class */ (function () {
function DebugInfo() {
this.info = {};
this.totalStart = 0;
this.totalCost = 0;
this.reset();
}
DebugInfo.prototype.start = function (name, isInner) {
if (isInner === void 0) { isInner = false; }
if (this.totalStart === 0) {
this.totalStart = Date.now();
}
this.info[name] = {
start: Date.now(),
isInner: isInner,
};
};
DebugInfo.prototype.end = function (name) {
if (this.info[name]) {
this.info[name].end = Date.now();
this.info[name].cost = this.info[name].end - this.info[name].start;
this.totalCost = this.info[name].end - this.totalStart;
}
};
DebugInfo.prototype.reset = function () {
this.info = {};
this.totalStart = 0;
this.totalCost = 0;
};
DebugInfo.prototype.log = function (needInner) {
var _this = this;
if (needInner === void 0) { needInner = false; }
var logInfo = 'Layout debug info: \n';
logInfo += Object.keys(this.info).reduce(function (sum, curr) {
if (_this.info[curr].isInner && !needInner) {
return sum;
}
sum += "".concat(curr, ": ").concat(_this.info[curr].cost, "\n");
return sum;
}, '');
logInfo += "totalCost: ".concat(this.totalCost, "\n");
return logInfo;
};
return DebugInfo;
}());
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DebugInfo);
/***/ }),
/* 19 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
var Ticker = /** @class */ (function () {
function Ticker() {
var _this = this;
this.count = 0;
this.started = false;
this.animationId = null;
this.cbs = [];
this.innerCbs = [];
this.nextCbs = [];
this.innerNextCbs = [];
this.update = function () {
var time = Date.now();
var deltaTime = time - _this.lastTime;
_this.lastTime = time;
// console.log(dt)
// 优先执行业务的ticker回调,因为有可能会触发reflow
_this.cbs.forEach(function (cb) {
cb(deltaTime);
});
_this.innerCbs.forEach(function (cb) {
cb(deltaTime);
});
if (_this.innerNextCbs.length) {
_this.innerNextCbs.forEach(function (cb) { return cb(deltaTime); });
_this.innerNextCbs = [];
}
if (_this.nextCbs.length) {
_this.nextCbs.forEach(function (cb) { return cb(deltaTime); });
_this.nextCbs = [];
}
_this.count += 1;
_this.animationId = requestAnimationFrame(_this.update);
};
}
Ticker.prototype.cancelIfNeed = function () {
if (this.animationId !== null) {
cancelAnimationFrame(this.animationId);
this.animationId = null;
}
};
Ticker.prototype.add = function (cb, isInner) {
if (isInner === void 0) { isInner = false; }
if (typeof cb === 'function' && this.cbs.indexOf(cb) === -1) {
isInner ? this.innerCbs.push(cb) : this.cbs.push(cb);
}
};
Ticker.prototype.next = function (cb, isInner) {
if (isInner === void 0) { isInner = false; }
if (typeof cb === 'function') {
isInner ? this.innerNextCbs.push(cb) : this.nextCbs.push(cb);
}
};
Ticker.prototype.removeInner = function () {
this.innerCbs = [];
this.innerNextCbs = [];
};
Ticker.prototype.remove = function (cb, isInner) {
if (isInner === void 0) { isInner = false; }
if (cb === undefined) {
this.cbs = [];
this.innerCbs = [];
this.nextCbs = [];
this.innerNextCbs = [];
}
if (typeof cb === 'function' && (this.cbs.indexOf(cb) > -1 || this.innerCbs.indexOf(cb) > -1)) {
var list = isInner ? this.innerCbs : this.cbs;
list.splice(this.cbs.indexOf(cb), 1);
}
if (!this.cbs.length && !this.innerCbs.length) {
this.cancelIfNeed();
}
};
Ticker.prototype.start = function () {
if (!this.started) {
this.started = true;
this.lastTime = Date.now();
if (this.animationId === null && (this.cbs.length || this.innerCbs.length)) {
this.animationId = requestAnimationFrame(this.update);
}
}
};
Ticker.prototype.stop = function () {
if (this.started) {
this.started = false;
this.cancelIfNeed();
}
};
return Ticker;
}());
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Ticker);
/***/ }),
/* 20 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ clone: () => (/* binding */ clone),
/* harmony export */ create: () => (/* binding */ create),
/* harmony export */ iterateTree: () => (/* binding */ iterateTree),
/* harmony export */ layoutChildren: () => (/* binding */ layoutChildren),
/* harmony export */ registerComponent: () => (/* binding */ registerComponent),
/* harmony export */ renderChildren: () => (/* binding */ renderChildren),
/* harmony export */ repaintChildren: () => (/* binding */ repaintChildren),
/* harmony export */ repaintTree: () => (/* binding */ repaintTree)
/* harmony export */ });
/* harmony import */ var _components_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(21);
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
/* harmony import */ var _env__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(1);
/* eslint-disable no-param-reassign */
// components
var constructorMap = {
view: _components_index__WEBPACK_IMPORTED_MODULE_0__.View,
text: _components_index__WEBPACK_IMPORTED_MODULE_0__.Text,
image: _components_index__WEBPACK_IMPORTED_MODULE_0__.Image,
scrollview: _components_index__WEBPACK_IMPORTED_MODULE_0__.ScrollView,
bitmaptext: _components_index__WEBPACK_IMPORTED_MODULE_0__.BitMapText,
canvas: _components_index__WEBPACK_IMPORTED_MODULE_0__.Canvas,
button: _components_index__WEBPACK_IMPORTED_MODULE_0__.Button,
};
function registerComponent(name, Constructor) {
constructorMap[name] = Constructor;
}
function create(node, style, parent) {
var _this = this;
var Constructor = constructorMap[node.name];
if (!Constructor) {
console.error("[Layout] \u4E0D\u652F\u6301\u7EC4\u4EF6 ".concat(node.name));
return null;
}
var children = node.children || [];
var attr = node.attr || {};
var dataset = {};
var id = attr.id || '';
var args = Object.keys(attr).reduce(function (obj, key) {
var value = attr[key];
var attribute = key;
if (key === 'id') {
obj.style = Object.assign(obj.style || {}, style[id] || {});
return obj;
}
if (key === 'class') {
obj.style = value.split(/\s+/).reduce(function (res, oneClass) { return Object.assign(res, style[oneClass]); }, obj.style || {});
return obj;
}
if (value === 'true') {
obj[attribute] = true;
}
else if (value === 'false') {
obj[attribute] = false;
}
else {
obj[attribute] = value;
}
if (attribute.startsWith('data-')) {
var dataKey = attribute.substring(5);
dataset[dataKey] = value;
}
obj.dataset = dataset;
return obj;
}, {});
// 用于后续元素查询
args.idName = id;
// @ts-ignore
this.eleCount += 1;
// @ts-ignore
args.id = this.eleCount;
args.className = attr.class || '';
var thisStyle = args.style;
if (thisStyle) {
var parentStyle = void 0;
if (parent) {
parentStyle = parent.style;
}
else {
parentStyle = _env__WEBPACK_IMPORTED_MODULE_2__["default"].getRootCanvasSize();
}
if ((0,_util__WEBPACK_IMPORTED_MODULE_1__.isPercent)(thisStyle.width)) {
thisStyle.width = parentStyle.width ? (0,_util__WEBPACK_IMPORTED_MODULE_1__.convertPercent)(thisStyle.width, parentStyle.width) : 0;
}
if ((0,_util__WEBPACK_IMPORTED_MODULE_1__.isPercent)(thisStyle.height)) {
thisStyle.height = parentStyle.height ? (0,_util__WEBPACK_IMPORTED_MODULE_1__.convertPercent)(thisStyle.height, parentStyle.height) : 0;
}
if (typeof thisStyle.opacity === 'undefined') {
thisStyle.opacity = 1;
}
if (parentStyle && parentStyle.opacity !== 1 && typeof parentStyle.opacity === 'number') {
thisStyle.opacity = parentStyle.opacity * thisStyle.opacity;
}
}
// console.log(args);
var element = new Constructor(args);
// @ts-ignore
element.root = this;
element.tagName = node.name;
element.afterCreate();
children.forEach(function (childNode) {
// @ts-ignore
var childElement = create.call(_this, childNode, style, args);
if (childElement) {
element.add(childElement);
}
});
return element;
}
function renderChildren(children, context, needRender) {
if (needRender === void 0) { needRender = true; }
children.forEach(function (child) {
// child.shouldUpdate = false;
child.isDirty = false;
child.insert(context, needRender);
// ScrollView的子节点渲染交给ScrollView自己,不支持嵌套ScrollView
return renderChildren(child.children, context, child.type === 'ScrollView' ? false : needRender);
});
}
/**
* 将布局树的布局信息加工赋值到渲染树
*/
function layoutChildren(element) {
element.children.forEach(function (child) {
child.layoutBox = child.layoutBox || {};
['left', 'top', 'width', 'height'].forEach(function (prop) {
var _a;
// @ts-ignore
child.layoutBox[prop] = (_a = child.layout) === null || _a === void 0 ? void 0 : _a[prop];
});
if (child.parent) {
child.layoutBox.absoluteX = (child.parent.layoutBox.absoluteX || 0) + child.layoutBox.left;
child.layoutBox.absoluteY = (child.parent.layoutBox.absoluteY || 0) + child.layoutBox.top;
}
else {
child.layoutBox.absoluteX = child.layoutBox.left;
child.layoutBox.absoluteY = child.layoutBox.top;
}
child.layoutBox.originalAbsoluteY = child.layoutBox.absoluteY;
child.layoutBox.originalAbsoluteX = child.layoutBox.absoluteX;
layoutChildren(child);
});
}
function none() { }
function iterateTree(element, callback) {
if (callback === void 0) { callback = none; }
callback(element);
element.children.forEach(function (child) {
iterateTree(child, callback);
});
}
var repaintChildren = function (children) {
children.forEach(function (child) {
child.repaint();
if (child.type !== 'ScrollView') {
repaintChildren(child.children);
}
});
};
var repaintTree = function (tree) {
tree.repaint();
tree.children.forEach(function (child) {
child.repaint();
repaintTree(child);
});
};
function clone(root, element, deep, parent) {
if (deep === void 0) { deep = true; }
var Constructor = constructorMap[element.tagName];
// @ts-ignore
root.eleCount += 1;
var args = {
style: Object.assign({}, element.style),
idName: element.idName,
className: element.className,
// @ts-ignore
id: root.eleCount,
dataset: Object.assign({}, element.dataset),
name: element.tagName,
};
if (element instanceof _components_index__WEBPACK_IMPORTED_MODULE_0__.Image) {
args.src = element.src;
}
else if (element instanceof _components_index__WEBPACK_IMPORTED_MODULE_0__.Text || element instanceof _components_index__WEBPACK_IMPORTED_MODULE_0__.BitMapText) {
args.value = element.value;
}
var newElemenet = new Constructor(args);
newElemenet.root = root;
// @ts-ignore
newElemenet.insert(root.renderContext, false);
newElemenet.observeStyleAndEvent();
if (parent) {
parent.add(newElemenet);
}
if (deep) {
element.children.forEach(function (child) {
clone(root, child, deep, newElemenet);
});
}
return newElemenet;
}
/***/ }),
/* 21 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ BitMapText: () => (/* reexport safe */ _bitmaptext__WEBPACK_IMPORTED_MODULE_4__["default"]),
/* harmony export */ Button: () => (/* reexport safe */ _button__WEBPACK_IMPORTED_MODULE_7__["default"]),
/* harmony export */ Canvas: () => (/* reexport safe */ _canvas__WEBPACK_IMPORTED_MODULE_5__["default"]),
/* harmony export */ Element: () => (/* reexport safe */ _elements__WEBPACK_IMPORTED_MODULE_6__["default"]),
/* harmony export */ Image: () => (/* reexport safe */ _image__WEBPACK_IMPORTED_MODULE_1__["default"]),
/* harmony export */ ScrollView: () => (/* reexport safe */ _scrollview__WEBPACK_IMPORTED_MODULE_3__["default"]),
/* harmony export */ Text: () => (/* reexport safe */ _text__WEBPACK_IMPORTED_MODULE_2__["default"]),
/* harmony export */ View: () => (/* reexport safe */ _view__WEBPACK_IMPORTED_MODULE_0__["default"])
/* harmony export */ });
/* harmony import */ var _view__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(22);
/* harmony import */ var _image__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(23);
/* harmony import */ var _text__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(24);
/* harmony import */ var _scrollview__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(25);
/* harmony import */ var _bitmaptext__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(29);
/* harmony import */ var _canvas__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(30);
/* harmony import */ var _elements__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(2);
/* harmony import */ var _button__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(31);
/***/ }),
/* 22 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _elements__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var View = /** @class */ (function (_super) {
__extends(View, _super);
function View(_a) {
var _b = _a.style, style = _b === void 0 ? {} : _b, _c = _a.idName, idName = _c === void 0 ? '' : _c, _d = _a.className, className = _d === void 0 ? '' : _d, dataset = _a.dataset;
var _this = _super.call(this, {
idName: idName,
className: className,
style: style,
dataset: dataset,
}) || this;
_this.type = 'View';
_this.ctx = null;
return _this;
}
View.prototype.destroySelf = function () {
this.isDestroyed = true;
this.children = [];
this.root = null;
};
View.prototype.render = function () {
var ctx = this.ctx;
ctx.save();
var _a = this.baseRender(), needStroke = _a.needStroke, needClip = _a.needClip, originX = _a.originX, originY = _a.originY;
if (needStroke) {
ctx.stroke();
}
ctx.translate(-originX, -originY);
ctx.restore();
};
View.prototype.repaint = function () {
this.render();
};
return View;
}(_elements__WEBPACK_IMPORTED_MODULE_0__["default"]));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (View);
/***/ }),
/* 23 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _elements__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var _common_imageManager__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Image = /** @class */ (function (_super) {
__extends(Image, _super);
function Image(opts) {
var _this = this;
var _a = opts.style, style = _a === void 0 ? {} : _a, _b = opts.idName, idName = _b === void 0 ? '' : _b, _c = opts.className, className = _c === void 0 ? '' : _c, _d = opts.src, src = _d === void 0 ? '' : _d, dataset = opts.dataset;
_this = _super.call(this, {
idName: idName,
className: className,
dataset: dataset,
style: style,
}) || this;
_this.type = 'Image';
_this.imgsrc = src;
_this.img = _common_imageManager__WEBPACK_IMPORTED_MODULE_1__["default"].loadImage(_this.src, function (img, fromCache) {
var _a;
if (fromCache) {
_this.img = img;
}
else {
if (!_this.isDestroyed) {
_this.img = img;
// 当图片加载完成,实例可能已经被销毁了
(_a = _this.root) === null || _a === void 0 ? void 0 : _a.emit('repaint');
}
}
});
return _this;
}
Object.defineProperty(Image.prototype, "src", {
get: function () {
return this.imgsrc;
},
set: function (newValue) {
var _this = this;
if (newValue !== this.imgsrc) {
this.imgsrc = newValue;
_common_imageManager__WEBPACK_IMPORTED_MODULE_1__["default"].loadImage(this.src, function (img) {
var _a;
if (!_this.isDestroyed) {
_this.img = img;
// 当图片加载完成,实例可能已经被销毁了
(_a = _this.root) === null || _a === void 0 ? void 0 : _a.emit('repaint');
}
});
}
},
enumerable: false,
configurable: true
});
Image.prototype.repaint = function () {
this.render();
};
// 子类填充实现
Image.prototype.destroySelf = function () {
this.isDestroyed = true;
this.img = null;
this.src = '';
this.root = null;
};
Image.prototype.render = function () {
var _a;
if (!this.img || !((_a = this.img) === null || _a === void 0 ? void 0 : _a.complete)) {
return;
}
var ctx = this.ctx;
ctx.save();
var _b = this.baseRender(), needStroke = _b.needStroke, needClip = _b.needClip, originX = _b.originX, originY = _b.originY, drawX = _b.drawX, drawY = _b.drawY, width = _b.width, height = _b.height;
// 自定义渲染逻辑 开始
// ===
// 九宫格
if (this.style.slice) {
const [top, bottom, left, right] = this.style.slice.split(',').map(v => parseInt(v.trim()));
const drawWidth = width;
const drawHeight = height;
const imgW = this.img.width;
const imgH = this.img.height;
// 计算原始九宫格区域
const centerW = imgW - left - right; // 中间部分宽度
const centerH = imgH - top - bottom; // 中间部分高度
// 计算目标区域大小
const targetCenterW = drawWidth - left - right;
const targetCenterH = drawHeight - top - bottom;
// Scale9 格式: 9 个区域 (left, center, right) x (top, middle, bottom)
const parts = [
// sx, sy, sw, sh, dx, dy, dw, dh
// 左上角
[0, 0, left, top, drawX, drawY, left, top],
// 上边
[left, 0, centerW, top, drawX + left, drawY, targetCenterW, top],
// 右上角
[imgW - right, 0, right, top, drawX + left + targetCenterW, drawY, right, top],
// 左边
[0, top, left, centerH, drawX, drawY + top, left, targetCenterH],
// 中间
[left, top, centerW, centerH, drawX + left, drawY + top, targetCenterW, targetCenterH],
// 右边
[imgW - right, top, right, centerH, drawX + left + targetCenterW, drawY + top, right, targetCenterH],
// 左下角
[0, imgH - bottom, left, bottom, drawX, drawY + top + targetCenterH, left, bottom],
// 下边
[left, imgH - bottom, centerW, bottom, drawX + left, drawY + top + targetCenterH, targetCenterW, bottom],
// 右下角
[imgW - right, imgH - bottom, right, bottom, drawX + left + targetCenterW, drawY + top + targetCenterH, right, bottom],
];
// 绘制所有部分
parts.forEach(([sx, sy, sw, sh, dx, dy, dw, dh]) => {
ctx.drawImage(this.img, sx, sy, sw, sh, dx, dy, dw, dh);
});
}
// 放大缩小
else if (this.style.scale) {
const [scaleX, scaleY] = this.style.scale.split(',').map(v => parseFloat(v.trim()));
const offsetX = (1 - scaleX) / 2 * width;
const offsetY = (1 - scaleY) / 2 * height;
ctx.drawImage(this.img, drawX - originX + offsetX, drawY - originY + offsetY, width * scaleX, height * scaleY);
}
// 正常绘制
else {
ctx.drawImage(this.img, drawX - originX, drawY - originY, width, height);
}
// 颜色混合
if (this.style.color) {
const imageData = ctx.getImageData(0, 0, this.img.width, this.img.height);
// console.log('xxx', ctx, this.img);
// console.log('xxx', 'log');
// const [x, y, z, w] = this.style.color.split(',').map(v => parseInt(v.trim()) / 255);
// // 获取像素数据
// const imageData = ctx.getImageData(drawX - originX, drawY - originY, width, height);
// const data = imageData.data;
// // 遍历像素数据
// for (let i = 0; i < data.length; i += 4) {
// const r = data[i + 0];
// const g = data[i + 1];
// const b = data[i + 2];
// const a = data[i + 3];
// data[i + 0] = r * a + x * (1 - a);
// data[i + 1] = g * a + y * (1 - w);
// data[i + 2] = b * a + z * (1 - w);
// data[i + 3] = w;
// }
// // 将修改后的像素数据放回 Canvas
// ctx.putImageData(imageData, 0, 0);
}
// ===
//ctx.drawImage(this.img, drawX - originX, drawY - originY, width, height);
// 自定义渲染逻辑 结束
if (needClip) {
this.renderBorder(ctx, originX, originY);
}
if (needStroke) {
ctx.stroke();
}
ctx.translate(-originX, -originY);
ctx.restore();
};
return Image;
}(_elements__WEBPACK_IMPORTED_MODULE_0__["default"]));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Image);
/***/ }),
/* 24 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _elements__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var _env__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
/* harmony import */ var _styleParser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9);
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var DEFAULT_FONT_FAMILY = 'sans-serif';
var context = null;
var getContext = function () {
if (context) {
return context;
}
var canvas = _env__WEBPACK_IMPORTED_MODULE_1__["default"].createCanvas();
canvas.width = 1;
canvas.height = 1;
context = canvas.getContext('2d');
return context;
};
function getTextWidth(style, value) {
var context = getContext();
context.font = "".concat(style.fontWeight || 'normal', " ").concat(style.fontSize || 12, "px ").concat(style.fontFamily || DEFAULT_FONT_FAMILY);
return context.measureText(value).width || 0;
}
function getTextWidthWithoutSetFont(value) {
return getContext().measureText(value).width || 0;
}
function parseText(style, value) {
value = String(value);
var maxWidth = style.width;
var wordWidth = getTextWidth(style, value);
// 对文字溢出的处理,默认用...
var textOverflow = style.textOverflow || 'ellipsis';
// 文字最大长度不超限制
if (wordWidth <= maxWidth) {
return value;
}
// 对于用点点点处理的情况,先将最大宽度减去...的宽度
if (textOverflow === 'ellipsis') {
maxWidth -= getTextWidthWithoutSetFont('...');
}
var length = value.length - 1;
var str = value.substring(0, length);
while (getTextWidthWithoutSetFont(str) > maxWidth && length > 0) {
length -= 1;
str = value.substring(0, length);
}
return (length && textOverflow === 'ellipsis'
? "".concat(str, "...")
: str);
}
var Text = /** @class */ (function (_super) {
__extends(Text, _super);
function Text(_a) {
var _b = _a.style, style = _b === void 0 ? {} : _b, _c = _a.idName, idName = _c === void 0 ? '' : _c, _d = _a.className, className = _d === void 0 ? '' : _d, _e = _a.value, value = _e === void 0 ? '' : _e, dataset = _a.dataset;
var _this = this;
var originStyleWidth = style.width;
// 没有设置宽度的时候通过canvas计算出文字宽度
if (originStyleWidth === undefined) {
style.width = getTextWidth(style, value);
}
else if (style.textOverflow === 'ellipsis') {
value = parseText(style, value);
}
if (style.height === undefined) {
style.height = style.lineHeight || style.fontSize || 12;
}
_this = _super.call(this, {
idName: idName,
className: className,
style: style,
dataset: dataset,
}) || this;
_this.valuesrc = '';
_this.textBaseline = 'bottom';
_this.font = '';
_this.textAlign = 'left';
_this.fillStyle = '#000000';
_this.renderForLayout = {};
_this.type = 'Text';
_this.ctx = null;
_this.valuesrc = value;
_this.originStyleWidth = originStyleWidth;
if (style.textShadow) {
_this.parseTextShadow(style.textShadow);
}
return _this;
}
Text.prototype.styleChangeHandler = function (prop, styleOpType, val) {
if (prop === 'textShadow') {
if (styleOpType === _elements__WEBPACK_IMPORTED_MODULE_0__.StyleOpType.Set) {
this.parseTextShadow(val);
}
else {
this.renderForLayout.textShadows = null;
}
}
};
Text.prototype.parseTextShadow = function (textShadow) {
if (!(0,_styleParser__WEBPACK_IMPORTED_MODULE_2__.isValidTextShadow)(textShadow)) {
console.error("[Layout]: ".concat(textShadow, " is not a valid textShadow"));
}
else {
// 解析 text-shadow 字符串
this.renderForLayout.textShadows = textShadow.split(',').map(function (shadow) {
var parts = shadow.trim().split(/\s+/);
var offsetX = parseFloat(parts[0]);
var offsetY = parseFloat(parts[1]);
var blurRadius = parseFloat(parts[2]);
var color = parts[3];
return { offsetX: offsetX, offsetY: offsetY, blurRadius: blurRadius, color: color };
});
}
};
Object.defineProperty(Text.prototype, "value", {
get: function () {
return this.valuesrc;
},
set: function (newValue) {
if (newValue !== this.valuesrc) {
if (this.originStyleWidth === undefined) {
this.style.width = getTextWidth(this.style, newValue);
}
else if (this.style.textOverflow === 'ellipsis') {
newValue = parseText(this.style, newValue);
}
this.valuesrc = newValue;
(0,_elements__WEBPACK_IMPORTED_MODULE_0__.setDirty)(this, 'value change');
}
},
enumerable: false,
configurable: true
});
Text.prototype.toCanvasData = function () {
var style = this.style || {};
this.fontSize = style.fontSize || 12;
this.textBaseline = 'top';
this.font = "".concat(style.fontWeight || '', " ").concat(style.fontSize || 12, "px ").concat(style.fontFamily || DEFAULT_FONT_FAMILY);
this.textAlign = style.textAlign || 'left';
this.fillStyle = style.color || '#000';
};
Text.prototype.repaint = function () {
this.render();
};
Text.prototype.destroySelf = function () {
this.root = null;
};
Text.prototype.insert = function (ctx, needRender) {
this.ctx = ctx;
this.shouldUpdate = false;
// this.toCanvasData();
if (needRender) {
this.render();
}
};
Text.prototype.render = function () {
var _this = this;
var style = this.style;
var ctx = this.ctx;
ctx.save();
this.toCanvasData();
var _a = this.baseRender('test'), needStroke = _a.needStroke, originX = _a.originX, originY = _a.originY, drawX = _a.drawX, drawY = _a.drawY, width = _a.width, height = _a.height;
ctx.textBaseline = this.textBaseline;
ctx.font = this.font;
ctx.textAlign = this.textAlign;
if (needStroke) {
ctx.stroke();
}
ctx.fillStyle = this.fillStyle;
if (this.textAlign === 'center') {
drawX += width / 2;
}
else if (this.textAlign === 'right') {
drawX += width;
}
if (style.lineHeight) {
ctx.textBaseline = 'middle';
drawY += style.lineHeight / 2;
}
// 纹理文字描边
if (style.textStrokeColor) {
ctx.lineWidth = style.textStrokeWidth || 1;
ctx.strokeStyle = style.textStrokeColor;
ctx.strokeText(this.value, drawX - originX, drawY - originY);
}
// 处理文字阴影
if (this.renderForLayout.textShadows) {
this.renderForLayout.textShadows.forEach(function (_a) {
var offsetX = _a.offsetX, offsetY = _a.offsetY, blurRadius = _a.blurRadius, color = _a.color;
ctx.shadowOffsetX = offsetX;
ctx.shadowOffsetY = offsetY;
ctx.shadowBlur = blurRadius;
ctx.shadowColor = color;
ctx.fillText(_this.value, drawX - originX, drawY - originY);
});
}
else {
ctx.fillText(this.value, drawX - originX, drawY - originY);
}
ctx.translate(-originX, -originY);
ctx.restore();
};
return Text;
}(_elements__WEBPACK_IMPORTED_MODULE_0__["default"]));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Text);
/***/ }),
/* 25 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _view__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(22);
/* harmony import */ var _common_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
/* harmony import */ var _libs_scroller_index_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(26);
/* harmony import */ var _common_vd__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(20);
/* harmony import */ var _elements__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2);
/* harmony import */ var _scrollbar__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(28);
/* harmony import */ var _env__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1);
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
/* eslint-disable no-underscore-dangle */
/* eslint-disable no-param-reassign */
var dpr = _env__WEBPACK_IMPORTED_MODULE_6__["default"].getDevicePixelRatio();
;
var ScrollView = /** @class */ (function (_super) {
__extends(ScrollView, _super);
function ScrollView(_a) {
var _b = _a.style, style = _b === void 0 ? {} : _b, _c = _a.idName, idName = _c === void 0 ? '' : _c, _d = _a.className, className = _d === void 0 ? '' : _d, scrollX = _a.scrollX, scrollY = _a.scrollY, dataset = _a.dataset;
var _this = _super.call(this, {
style: style,
idName: idName,
dataset: dataset,
className: className,
}) || this;
_this.scrollTop = 0;
_this.scrollLeft = 0;
_this.hasEventBind = false;
_this.currentEvent = null;
_this.type = 'ScrollView';
_this.vertivalScrollbar = null;
_this.horizontalScrollbar = null;
_this.scrollYProp = scrollY;
_this.innerScrollerOption = {
scrollingX: !!scrollX,
scrollingY: !!scrollY,
};
return _this;
}
Object.defineProperty(ScrollView.prototype, "scrollHeight", {
/**
* 获取滚动列表内所有元素的高度和
* 这里不能简单将所有子元素的高度累加,因为每个元素之间可能是有空隙的
*/
get: function () {
var maxHeight = 0;
this.children.forEach(function (item) {
if (!(item instanceof _scrollbar__WEBPACK_IMPORTED_MODULE_5__["default"])) {
maxHeight = Math.max(maxHeight, item.layoutBox.top + item.layoutBox.height);
}
});
return maxHeight;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ScrollView.prototype, "scrollWidth", {
get: function () {
var maxWidth = 0;
this.children.forEach(function (item) {
if (!(item instanceof _scrollbar__WEBPACK_IMPORTED_MODULE_5__["default"])) {
maxWidth = Math.max(maxWidth, item.layoutBox.left + item.layoutBox.width);
}
});
return maxWidth;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ScrollView.prototype, "scrollX", {
get: function () {
return this.innerScrollerOption.scrollingX;
},
set: function (value) {
this.scrollerObj.scrollTo(0, this.scrollTop, true, 1);
this.scrollerOption = {
scrollingX: value,
};
this.updateScrollBar('scrollX', 'horizontalScrollbar');
},
enumerable: false,
configurable: true
});
Object.defineProperty(ScrollView.prototype, "scrollY", {
get: function () {
return this.innerScrollerOption.scrollingY;
},
set: function (value) {
if (value !== this.scrollY) {
this.scrollerObj.scrollTo(this.scrollLeft, 0, true, 1);
this.scrollerOption = {
scrollingY: value,
};
this.scrollerObj && this.updateScrollBar('scrollY', 'vertivalScrollbar');
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(ScrollView.prototype, "scrollerOption", {
get: function () {
return this.innerScrollerOption;
},
set: function (value) {
Object.assign(this.innerScrollerOption, value);
if (this.scrollerObj) {
Object.assign(this.scrollerObj.options, this.scrollerOption);
}
},
enumerable: false,
configurable: true
});
ScrollView.prototype.repaint = function () {
this.scrollRender();
};
ScrollView.prototype.destroySelf = function () {
// this.touch = null;
this.isDestroyed = true;
this.ctx = null;
this.children = [];
this.root.off('touchend');
this.root = null;
};
ScrollView.prototype.renderTreeWithTop = function (tree) {
var _this = this;
if (!(tree instanceof _scrollbar__WEBPACK_IMPORTED_MODULE_5__["default"])) {
tree.render();
}
tree.children.forEach(function (child) {
_this.renderTreeWithTop(child);
});
};
ScrollView.prototype.clear = function () {
var box = this.layoutBox;
this.ctx.clearRect(box.absoluteX, box.absoluteY, box.width, box.height);
};
ScrollView.prototype.scrollRender = function () {
var _this = this;
var _a, _b;
var box = this.layoutBox;
var startX = box.absoluteX, startY = box.absoluteY, width = box.width, height = box.height;
var ctx = this.ctx;
// 根据滚动值获取裁剪区域
var endX = startX + width;
var endY = startY + height;
// ScrollView 作为容器本身的渲染
this.render();
/**
* 开始裁剪,只有仔 ScrollView layoutBox 区域内的元素才是可见的
* 这样 ScrollView 不用单独占用一个 canvas,内存合渲染都会得到优化
*/
ctx.save();
ctx.beginPath();
ctx.rect(startX, startY, width, height);
ctx.clip();
this.children.forEach(function (child) {
var _a = child.layoutBox, width = _a.width, height = _a.height, absoluteX = _a.absoluteX, absoluteY = _a.absoluteY;
// 判断处于可视窗口内的子节点,递归渲染该子节点
if (absoluteY + height >= startY && absoluteY <= endY
&& absoluteX + width >= startX && absoluteX <= endX) {
_this.renderTreeWithTop(child);
}
});
// 上面的渲染应该先跳过滚动条,否则可能出现渲染顺序问题,ScrollView的节点反而把滚动条盖住了
(_a = this.vertivalScrollbar) === null || _a === void 0 ? void 0 : _a.render();
(_b = this.horizontalScrollbar) === null || _b === void 0 ? void 0 : _b.render();
ctx.restore();
};
ScrollView.prototype.scrollHandler = function (left, top) {
var _this = this;
var _a, _b;
// 可能被销毁了或者节点树还没准备好
if (!this.isDestroyed && !this.isFirstScroll) {
(0,_common_vd__WEBPACK_IMPORTED_MODULE_3__.iterateTree)(this, function (ele) {
if (ele !== _this && !(ele instanceof _scrollbar__WEBPACK_IMPORTED_MODULE_5__["default"])) {
ele.layoutBox.absoluteY = ele.layoutBox.originalAbsoluteY - top;
ele.layoutBox.absoluteX = ele.layoutBox.originalAbsoluteX - left;
}
});
// 这里要把滚动状态保存起来,因为在reflow的时候需要做重置,渲染并不依赖这两个信息
this.scrollTop = top;
this.scrollLeft = left;
(_a = this.vertivalScrollbar) === null || _a === void 0 ? void 0 : _a.onScroll(left, top);
(_b = this.horizontalScrollbar) === null || _b === void 0 ? void 0 : _b.onScroll(left, top);
this.root.emit('repaint');
if (this.currentEvent) {
this.emit('scroll', this.currentEvent);
}
}
if (this.isFirstScroll) {
this.isFirstScroll = false;
}
};
/**
* 当执行reflow之后,滚动列表的高度可能发生了变化,滚动条也需要同步进行更新
*/
ScrollView.prototype.updateScrollBar = function (scrollProp, scrollBarName) {
var _this = this;
var dimensions = {
width: this.layoutBox.width,
height: this.layoutBox.height,
contentWidth: this.scrollerObj.__contentWidth,
contentHeight: this.scrollerObj.__contentHeight,
maxScrollLeft: this.scrollerObj.__maxScrollLeft,
maxScrollTop: this.scrollerObj.__maxScrollTop,
scrollLeft: this.scrollerObj.__scrollLeft,
scrollTop: this.scrollerObj.__scrollTop,
};
// console.log('updateScrollBar', JSON.stringify(dimensions))
// 非第一次创建的情况,一般是 reflow 执行到这里
if (this[scrollProp]) {
if (this[scrollBarName]) {
this[scrollBarName].setDimensions(dimensions);
}
else {
var scrollBar = new _scrollbar__WEBPACK_IMPORTED_MODULE_5__["default"]({
dimensions: dimensions,
direction: scrollProp === 'scrollY' ? _scrollbar__WEBPACK_IMPORTED_MODULE_5__.ScrollBarDirection.Vertival : _scrollbar__WEBPACK_IMPORTED_MODULE_5__.ScrollBarDirection.Horizontal,
});
// this.appendChild(scrollbar);
scrollBar.root = this.root;
scrollBar.init();
// @ts-ignore
scrollBar.insert(this.root.renderContext, true);
scrollBar.observeStyleAndEvent();
this.add(scrollBar);
(0,_elements__WEBPACK_IMPORTED_MODULE_4__.setDirty)(scrollBar, 'appendToScrollView');
// @ts-ignore
this[scrollBarName] = scrollBar;
// @ts-ignore
this.root.ticker.next(function () {
var _a, _b;
// @ts-ignore
(_a = _this[scrollBarName]) === null || _a === void 0 ? void 0 : _a.onScroll(_this.scrollerObj.__scrollLeft, _this.scrollerObj.__scheduledTop);
(_b = _this.root) === null || _b === void 0 ? void 0 : _b.emit('repaint');
}, true);
}
}
else {
// 当不再需要纵向滚动的时候销毁纵向滚动条
if (this[scrollBarName]) {
var scrollBar = this[scrollBarName];
scrollBar.remove();
scrollBar.destroy();
scrollBar.destroySelf();
// @ts-ignore
this[scrollBarName] = null;
}
}
};
ScrollView.prototype.insert = function (context) {
var _this = this;
this.shouldUpdate = false;
this.ctx = context;
/**
* 这里有个非常特殊的兼容逻辑,在低版本没有重构 ScrollView之前,并没有提供单独的 ScrollX 和 ScrollY 属性
* 而是判断 scrollHeiht 大于容器高度的时候自动实现了纵向滚动(且没有横向滚动能力)
* 因此这里做一个兼容逻辑,如果 scrollHeight > this.layoutBox.height 自动开启纵向滚动
*/
if (this.scrollHeight > this.layoutBox.height && typeof this.scrollYProp === 'undefined') {
console.log("[Layout] \u81EA\u52A8\u5F00\u542F scrollY");
this.scrollY = true;
}
if (this.hasEventBind) {
// reflow 高度可能会变化,因此需要执行 setDimensions 刷新可滚动区域
if (this.layoutBox.width !== this.scrollerObj.__clientWidth
|| this.layoutBox.height !== this.scrollerObj.__clientHeight
|| this.scrollWidth !== this.scrollerObj.__contentWidth
|| this.scrollHeight !== this.scrollerObj.__contentHeight) {
this.scrollerObj.setDimensions(this.layoutBox.width, this.layoutBox.height, this.scrollWidth, this.scrollHeight);
/**
* 这里之所以要延迟一帧是因为这里的变动来自 reflow 之后,正在做 reflow 之后的后续事情
* 如果立即修改滚动条的样式,实际上并不会生效。
*/
// @ts-ignore
this.root.ticker.next(function () {
_this.updateScrollBar('scrollY', 'vertivalScrollbar');
_this.updateScrollBar('scrollX', 'horizontalScrollbar');
}, true);
}
// reflow 之后,会从 csslayout 同步布局信息,原先的滚动信息会丢失,这里需要一个复位的操作
(0,_common_vd__WEBPACK_IMPORTED_MODULE_3__.iterateTree)(this, function (ele) {
if (ele !== _this && !(ele instanceof _scrollbar__WEBPACK_IMPORTED_MODULE_5__["default"])) {
ele.layoutBox.absoluteY = ele.layoutBox.originalAbsoluteY - _this.scrollTop;
ele.layoutBox.absoluteX = ele.layoutBox.originalAbsoluteX - _this.scrollLeft;
}
});
return;
}
this.hasEventBind = true;
this.isFirstScroll = true;
// @ts-ignore
this.scrollerObj = new _libs_scroller_index_js__WEBPACK_IMPORTED_MODULE_2__["default"](this.scrollHandler.bind(this), this.scrollerOption);
this.scrollerObj.setDimensions(this.layoutBox.width, this.layoutBox.height, this.scrollWidth, this.scrollHeight);
// @ts-ignore
this.root.ticker.next(function () {
_this.updateScrollBar('scrollY', 'vertivalScrollbar');
_this.updateScrollBar('scrollX', 'horizontalScrollbar');
}, true);
this.on('touchstart', function (e) {
if (!e.touches) {
e.touches = [e];
}
var touches = (0,_common_util__WEBPACK_IMPORTED_MODULE_1__.copyTouchArray)(e.touches);
touches.forEach(function (touch) {
if (dpr !== 1) {
touch.pageX *= dpr;
touch.pageY *= dpr;
}
});
_this.scrollerObj.doTouchStart(touches, e.timeStamp);
_this.currentEvent = e;
});
this.on('touchmove', function (e) {
if (!e.touches) {
e.touches = [e];
}
var touches = (0,_common_util__WEBPACK_IMPORTED_MODULE_1__.copyTouchArray)(e.touches);
touches.forEach(function (touch) {
if (dpr !== 1) {
touch.pageX *= dpr;
touch.pageY *= dpr;
}
});
_this.scrollerObj.doTouchMove(touches, e.timeStamp, undefined);
_this.currentEvent = e;
});
// 这里不应该是监听scrollview的touchend事件而是屏幕的touchend事件
this.root.on('touchend', function (e) {
_this.scrollerObj.doTouchEnd(e.timeStamp);
_this.currentEvent = e;
});
};
ScrollView.prototype.scrollTo = function (left, top, animate) {
if (left === void 0) { left = 0; }
if (top === void 0) { top = 0; }
if (animate === void 0) { animate = true; }
this.scrollerObj.scrollTo(left, top, animate, 1);
};
return ScrollView;
}(_view__WEBPACK_IMPORTED_MODULE_0__["default"]));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ScrollView);
/***/ }),
/* 26 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _animate__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(27);
/* harmony import */ var _animate__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_animate__WEBPACK_IMPORTED_MODULE_0__);
/*
* Scroller
* http://github.com/zynga/scroller
*
* Copyright 2011, Zynga Inc.
* Licensed under the MIT License.
* https://raw.github.com/zynga/scroller/master/MIT-LICENSE.txt
*
* Based on the work of: Unify Project (unify-project.org)
* http://unify-project.org
* Copyright 2011, Deutsche Telekom AG
* License: MIT + Apache (V2)
*/
var NOOP = function () { };
// Easing Equations (c) 2003 Robert Penner, all rights reserved.
// Open source under the BSD License.
/**
* @param pos {Number} position between 0 (start of effect) and 1 (end of effect)
**/
var easeOutCubic = function (pos) {
return (Math.pow((pos - 1), 3) + 1);
};
/**
* @param pos {Number} position between 0 (start of effect) and 1 (end of effect)
**/
var easeInOutCubic = function (pos) {
if ((pos /= 0.5) < 1) {
return 0.5 * Math.pow(pos, 3);
}
return 0.5 * (Math.pow((pos - 2), 3) + 2);
};
/**
* A pure logic 'component' for 'virtual' scrolling/zooming.
*/
var Scroller = /** @class */ (function () {
function Scroller(callback, options) {
/*
---------------------------------------------------------------------------
INTERNAL FIELDS :: STATUS
---------------------------------------------------------------------------
*/
/** {Boolean} Whether only a single finger is used in touch handling */
this.__isSingleTouch = false;
/** {Boolean} Whether a touch event sequence is in progress */
this.__isTracking = false;
/** {Boolean} Whether a deceleration animation went to completion. */
this.__didDecelerationComplete = false;
/**
* {Boolean} Whether a gesture zoom/rotate event is in progress. Activates when
* a gesturestart event happens. This has higher priority than dragging.
*/
this.__isGesturing = false;
/**
* {Boolean} Whether the user has moved by such a distance that we have enabled
* dragging mode. Hint = It's only enabled after some pixels of movement t;
* not interrupt with clicks etc.
*/
this.__isDragging = false;
/**
* {Boolean} Not touching and dragging anymore, and smoothly animating the
* touch sequence using deceleration.
*/
this.__isDecelerating = false;
/**
* {Boolean} Smoothly animating the currently configured change
*/
this.__isAnimating = false;
/*
---------------------------------------------------------------------------
INTERNAL FIELDS :: DIMENSIONS
---------------------------------------------------------------------------
*/
/** {Integer} Viewport left boundary */
this.__clientLeft = 0;
/** {Integer} Viewport right boundary */
this.__clientTop = 0;
/** {Integer} Viewport width */
this.__clientWidth = 0;
/** {Integer} Viewport height */
this.__clientHeight = 0;
/** {Integer} Full content's width */
this.__contentWidth = 0;
/** {Integer} Full content's height */
this.__contentHeight = 0;
/** {Integer} Snapping width for content */
this.__snapWidth = 100;
/** {Integer} Snapping height for content */
this.__snapHeight = 100;
/** {Number} Zoom level */
this.__zoomLevel = 1;
/** {Number} Scroll position on x-axis */
this.__scrollLeft = 0;
/** {Number} Scroll position on y-axis */
this.__scrollTop = 0;
/** {Integer} Maximum allowed scroll position on x-axis */
this.__maxScrollLeft = 0;
/** {Integer} Maximum allowed scroll position on y-axis */
this.__maxScrollTop = 0;
/* {Number} Scheduled left position (final position when animating) */
this.__scheduledLeft = 0;
/* {Number} Scheduled top position (final position when animating) */
this.__scheduledTop = 0;
/* {Number} Scheduled zoom level (final scale when animating) */
this.__scheduledZoom = 0;
/*
---------------------------------------------------------------------------
INTERNAL FIELDS :: LAST POSITIONS
---------------------------------------------------------------------------
*/
/** {Number} Left position of finger at start */
this.__lastTouchLeft = null;
/** {Number} Top position of finger at start */
this.__lastTouchTop = null;
/** {Date} Timestamp of last move of finger. Used to limit tracking range for deceleration speed. */
this.__lastTouchMove = null;
/** {Array} List of positions, uses three indexes for each state = left, top, timestamp *;
__positions = null;
/*
---------------------------------------------------------------------------
INTERNAL FIELDS : = DECELERATION SUPPOR;
---------------------------------------------------------------------------
*/
/** {Integer} Minimum left scroll position during deceleration */
this.__minDecelerationScrollLeft = null;
/** {Integer} Minimum top scroll position during deceleration */
this.__minDecelerationScrollTop = null;
/** {Integer} Maximum left scroll position during deceleration */
this.__maxDecelerationScrollLeft = null;
/** {Integer} Maximum top scroll position during deceleration */
this.__maxDecelerationScrollTop = null;
/** {Number} Current factor to modify horizontal scroll position with on every step */
this.__decelerationVelocityX = null;
/** {Number} Current factor to modify vertical scroll position with on every step */
this.__decelerationVelocityY = null;
this.__callback = callback;
this.options = {
/** Enable scrolling on x-axis */
scrollingX: true,
/** Enable scrolling on y-axis */
scrollingY: true,
/** Enable animations for deceleration, snap back, zooming and scrolling */
animating: true,
/** duration for animations triggered by scrollTo/zoomTo */
animationDuration: 250,
/** Enable bouncing (content can be slowly moved outside and jumps back after releasing) */
bouncing: true,
/** Enable locking to the main axis if user moves only slightly on one of them at start */
locking: true,
/** Enable pagination mode (switching between full page content panes) */
paging: false,
/** Enable snapping of content to a configured pixel grid */
snapping: false,
/** Enable zooming of content via API, fingers and mouse wheel */
zooming: false,
/** Minimum zoom level */
minZoom: 0.5,
/** Maximum zoom level */
maxZoom: 3,
/** Multiply or decrease scrolling speed **/
speedMultiplier: 1,
/** Callback that is fired on the later of touch end or deceleration end,
provided that another scrolling action has not begun. Used to know
when to fade out a scrollbar. */
scrollingComplete: NOOP,
/** This configures the amount of change applied to deceleration when reaching boundaries **/
penetrationDeceleration: 0.03,
/** This configures the amount of change applied to acceleration when reaching boundaries **/
penetrationAcceleration: 0.08
};
for (var key in options) {
this.options[key] = options[key];
}
}
/*
---------------------------------------------------------------------------
PUBLIC API
---------------------------------------------------------------------------
*/
/**
* Configures the dimensions of the client (outer) and content (inner) elements.
* Requires the available space for the outer element and the outer size of the inner element.
* All values which are falsy (null or zero etc.) are ignored and the old value is kept.
*
* @param clientWidth {Integer ? null} Inner width of outer element
* @param clientHeight {Integer ? null} Inner height of outer element
* @param contentWidth {Integer ? null} Outer width of inner element
* @param contentHeight {Integer ? null} Outer height of inner element
*/
Scroller.prototype.setDimensions = function (clientWidth, clientHeight, contentWidth, contentHeight) {
// Only update values which are defined
if (clientWidth !== null) {
this.__clientWidth = clientWidth;
}
if (clientHeight !== null) {
this.__clientHeight = clientHeight;
}
if (contentWidth !== null) {
this.__contentWidth = contentWidth;
}
if (contentHeight !== null) {
this.__contentHeight = contentHeight;
}
// Refresh maximums
this.__computeScrollMax();
// Refresh scroll position
this.scrollTo(this.__scrollLeft, this.__scrollTop, false);
};
/**
* Sets the client coordinates in relation to the document.
*
* @param left {Integer ? 0} Left position of outer element
* @param top {Integer ? 0} Top position of outer element
*/
Scroller.prototype.setPosition = function (left, top) {
this.__clientLeft = left || 0;
this.__clientTop = top || 0;
};
/**
* Configures the snapping (when snapping is active)
*
* @param width {Integer} Snapping width
* @param height {Integer} Snapping height
*/
Scroller.prototype.setSnapSize = function (width, height) {
this.__snapWidth = width;
this.__snapHeight = height;
};
/**
* Returns the scroll position and zooming values
*
* @return {Map} `left` and `top` scroll position and `zoom` level
*/
Scroller.prototype.getValues = function () {
return {
left: this.__scrollLeft,
top: this.__scrollTop,
right: this.__scrollLeft + this.__clientWidth / this.__zoomLevel,
bottom: this.__scrollTop + this.__clientHeight / this.__zoomLevel,
zoom: this.__zoomLevel
};
};
/**
* Get point in in content space from scroll coordinates.
*/
Scroller.prototype.getPoint = function (scrollLeft, scrollTop) {
var values = this.getValues();
return {
left: scrollLeft / values.zoom,
top: scrollTop / values.zoom
};
};
/**
* Returns the maximum scroll values
*
* @return {Map} `left` and `top` maximum scroll values
*/
Scroller.prototype.getScrollMax = function () {
return {
left: this.__maxScrollLeft,
top: this.__maxScrollTop
};
};
/**
* Zooms to the given level. Supports optional animation. Zooms
* the center when no coordinates are given.
*
* @param level {Number} Level to zoom to
* @param isAnimated {Boolean ? false} Whether to use animation
* @param fixedLeft {Number ? undefined} Stationary point's left coordinate (vector in client space)
* @param fixedTop {Number ? undefined} Stationary point's top coordinate (vector in client space)
* @param callback {Function ? null} A callback that gets fired when the zoom is complete.
*/
Scroller.prototype.zoomTo = function (level, isAnimated, fixedLeft, fixedTop, callback) {
if (!this.options.zooming) {
throw new Error("Zooming is not enabled!");
}
// Add callback if exists
if (callback) {
this.__zoomComplete = callback;
}
// Stop deceleration
if (this.__isDecelerating) {
_animate__WEBPACK_IMPORTED_MODULE_0___default().stop(this.__isDecelerating);
this.__isDecelerating = false;
}
var oldLevel = this.__zoomLevel;
// Normalize fixed point to center of viewport if not defined
if (fixedLeft === undefined) {
fixedLeft = this.__clientWidth / 2;
}
if (fixedTop === undefined) {
fixedTop = this.__clientHeight / 2;
}
// Limit level according to configuration
level = Math.max(Math.min(level, this.options.maxZoom), this.options.minZoom);
// Recompute maximum values while temporary tweaking maximum scroll ranges
this.__computeScrollMax(level);
// Recompute left and top scroll positions based on new zoom level.
// Choosing the new viewport so that the origin's position remains
// fixed, we have central dilation about the origin.
// * Fixed point, $F$, remains stationary in content space and in the
// viewport.
// * Initial scroll position, $S_i$, in content space.
// * Final scroll position, $S_f$, in content space.
// * Initial scaling factor, $k_i$.
// * Final scaling factor, $k_f$.
//
// * $S_i \mapsto S_f$.
// * $(S_i - F) k_i = (S_f - F) k_f$.
// * $(S_i - F) k_i/k_f = (S_f - F)$.
// * $S_f = F + (S_i - F) k_i/k_f$.
//
// Fixed point location, $\vector{f} = (F - S_i) k_i$.
// * $F = S_i + \vector{f}/k_i$.
// * $S_f = S_i + \vector{f}/k_i + (S_i - S_i - \vector{f}/k_i) k_i/k_f$.
// * $S_f = S_i + \vector{f}/k_i - \vector{f}/k_f$.
// * $S_f k_f = S_i k_f + (k_f/k_i - 1)\vector{f}$.
// * $S_f k_f = (k_f/k_i)(S_i k_i) + (k_f/k_i - 1) \vector{f}$.
var k = level / oldLevel;
var left = k * (this.__scrollLeft + fixedLeft) - fixedLeft;
var top = k * (this.__scrollTop + fixedTop) - fixedTop;
// Limit x-axis
if (left > this.__maxScrollLeft) {
left = this.__maxScrollLeft;
}
else if (left < 0) {
left = 0;
}
// Limit y-axis
if (top > this.__maxScrollTop) {
top = this.__maxScrollTop;
}
else if (top < 0) {
top = 0;
}
// Push values out
this.__publish(left, top, level, isAnimated);
};
/**
* Zooms the content by the given factor.
*
* @param factor {Number} Zoom by given factor
* @param isAnimated {Boolean ? false} Whether to use animation
* @param originLeft {Number ? 0} Zoom in at given left coordinate
* @param originTop {Number ? 0} Zoom in at given top coordinate
* @param callback {Function ? null} A callback that gets fired when the zoom is complete.
*/
Scroller.prototype.zoomBy = function (factor, isAnimated, originLeft, originTop, callback) {
this.zoomTo(this.__zoomLevel * factor, isAnimated, originLeft, originTop, callback);
};
/**
* Scrolls to the given position. Respect limitations and snapping automatically.
*
* @param left {Number?null} Horizontal scroll position, keeps current if value is <code>null</code>
* @param top {Number?null} Vertical scroll position, keeps current if value is <code>null</code>
* @param isAnimated {Boolean?false} Whether the scrolling should happen using an animation
* @param zoom {Number} [1.0] Zoom level to go to
*/
Scroller.prototype.scrollTo = function (left, top, isAnimated, zoom) {
// Stop deceleration
if (this.__isDecelerating) {
_animate__WEBPACK_IMPORTED_MODULE_0___default().stop(this.__isDecelerating);
this.__isDecelerating = false;
}
// Correct coordinates based on new zoom level
if (zoom !== undefined && zoom !== this.__zoomLevel) {
if (!this.options.zooming) {
throw new Error("Zooming is not enabled!");
}
left *= zoom;
top *= zoom;
// Recompute maximum values while temporary tweaking maximum scroll ranges
this.__computeScrollMax(zoom);
}
else {
// Keep zoom when not defined
zoom = this.__zoomLevel;
}
if (!this.options.scrollingX) {
left = this.__scrollLeft;
}
else {
if (this.options.paging) {
left = Math.round(left / this.__clientWidth) * this.__clientWidth;
}
else if (this.options.snapping) {
left = Math.round(left / this.__snapWidth) * this.__snapWidth;
}
}
if (!this.options.scrollingY) {
top = this.__scrollTop;
}
else {
if (this.options.paging) {
top = Math.round(top / this.__clientHeight) * this.__clientHeight;
}
else if (this.options.snapping) {
top = Math.round(top / this.__snapHeight) * this.__snapHeight;
}
}
// Limit for allowed ranges
left = Math.max(Math.min(this.__maxScrollLeft, left), 0);
top = Math.max(Math.min(this.__maxScrollTop, top), 0);
// Don't animate when no change detected, still call publish to make sure
// that rendered position is really in-sync with internal data
if (left === this.__scrollLeft && top === this.__scrollTop) {
isAnimated = false;
}
// Publish new values
this.__publish(left, top, zoom, isAnimated);
};
/**
* Scroll by the given offset
*
* @param left {Number ? 0} Scroll x-axis by given offset
* @param top {Number ? 0} Scroll x-axis by given offset
* @param isAnimated {Boolean ? false} Whether to animate the given change
*/
Scroller.prototype.scrollBy = function (left, top, isAnimated) {
var startLeft = this.__isAnimating ? this.__scheduledLeft : this.__scrollLeft;
var startTop = this.__isAnimating ? this.__scheduledTop : this.__scrollTop;
this.scrollTo(startLeft + (left || 0), startTop + (top || 0), isAnimated);
};
/*
---------------------------------------------------------------------------
EVENT CALLBACKS
---------------------------------------------------------------------------
*/
/**
* Mouse wheel handler for zooming support
*/
Scroller.prototype.doMouseZoom = function (wheelDelta, timeStamp, pageX, pageY) {
var change = wheelDelta > 0 ? 0.97 : 1.03;
return this.zoomTo(this.__zoomLevel * change, false, pageX - this.__clientLeft, pageY - this.__clientTop);
};
/**
* Touch start handler for scrolling support
*/
Scroller.prototype.doTouchStart = function (touches, timeStamp) {
// Array-like check is enough here
if (touches.length === undefined) {
throw new Error("Invalid touch list: " + touches);
}
if (timeStamp instanceof Date) {
timeStamp = timeStamp.valueOf();
}
if (typeof timeStamp !== "number") {
throw new Error("Invalid timestamp value: " + timeStamp);
}
// Reset interruptedAnimation flag
this.__interruptedAnimation = true;
// Stop deceleration
if (this.__isDecelerating) {
_animate__WEBPACK_IMPORTED_MODULE_0___default().stop(this.__isDecelerating);
this.__isDecelerating = false;
this.__interruptedAnimation = true;
}
// Stop animation
if (this.__isAnimating) {
_animate__WEBPACK_IMPORTED_MODULE_0___default().stop(this.__isAnimating);
this.__isAnimating = false;
this.__interruptedAnimation = true;
}
// Use center point when dealing with two fingers
var currentTouchLeft, currentTouchTop;
var isSingleTouch = touches.length === 1;
if (isSingleTouch) {
currentTouchLeft = touches[0].pageX;
currentTouchTop = touches[0].pageY;
}
else {
currentTouchLeft = Math.abs(touches[0].pageX + touches[1].pageX) / 2;
currentTouchTop = Math.abs(touches[0].pageY + touches[1].pageY) / 2;
}
// Store initial positions
this.__initialTouchLeft = currentTouchLeft;
this.__initialTouchTop = currentTouchTop;
// Store current zoom level
this.__zoomLevelStart = this.__zoomLevel;
// Store initial touch positions
this.__lastTouchLeft = currentTouchLeft;
this.__lastTouchTop = currentTouchTop;
// Store initial move time stamp
this.__lastTouchMove = timeStamp;
// Reset initial scale
this.__lastScale = 1;
// Reset locking flags
this.__enableScrollX = !isSingleTouch && this.options.scrollingX;
this.__enableScrollY = !isSingleTouch && this.options.scrollingY;
// Reset tracking flag
this.__isTracking = true;
// Reset deceleration complete flag
this.__didDecelerationComplete = false;
// Dragging starts directly with two fingers, otherwise lazy with an offset
this.__isDragging = !isSingleTouch;
// Some features are disabled in multi touch scenarios
this.__isSingleTouch = isSingleTouch;
// Clearing data structure
this.__positions = [];
};
/**
* Touch move handler for scrolling support
* @param {Number} [1.0] scale - ....
*/
Scroller.prototype.doTouchMove = function (touches, timeStamp, scale) {
// Array-like check is enough here
if (touches.length === undefined) {
throw new Error("Invalid touch list: " + touches);
}
if (timeStamp instanceof Date) {
timeStamp = timeStamp.valueOf();
}
if (typeof timeStamp !== "number") {
throw new Error("Invalid timestamp value: " + timeStamp);
}
// Ignore event when tracking is not enabled (event might be outside of element)
if (!this.__isTracking) {
return;
}
var currentTouchLeft, currentTouchTop;
// Compute move based around of center of fingers
if (touches.length === 2) {
currentTouchLeft = Math.abs(touches[0].pageX + touches[1].pageX) / 2;
currentTouchTop = Math.abs(touches[0].pageY + touches[1].pageY) / 2;
}
else {
currentTouchLeft = touches[0].pageX;
currentTouchTop = touches[0].pageY;
}
var positions = this.__positions;
// Are we already is dragging mode?
if (this.__isDragging) {
// Compute move distance
var moveX = currentTouchLeft - this.__lastTouchLeft;
var moveY = currentTouchTop - this.__lastTouchTop;
// Read previous scroll position and zooming
var scrollLeft = this.__scrollLeft;
var scrollTop = this.__scrollTop;
var level = this.__zoomLevel;
// Work with scaling
if (scale !== undefined && this.options.zooming) {
var oldLevel = level;
// Recompute level based on previous scale and new scale
level = level / this.__lastScale * scale;
// Limit level according to configuration
level = Math.max(Math.min(level, this.options.maxZoom), this.options.minZoom);
// Only do further compution when change happened
if (oldLevel !== level) {
// Compute relative event position to container
var currentTouchLeftRel = currentTouchLeft - this.__clientLeft;
var currentTouchTopRel = currentTouchTop - this.__clientTop;
// Recompute left and top coordinates based on new zoom level
scrollLeft = ((currentTouchLeftRel + scrollLeft) * level / oldLevel) - currentTouchLeftRel;
scrollTop = ((currentTouchTopRel + scrollTop) * level / oldLevel) - currentTouchTopRel;
// Recompute max scroll values
this.__computeScrollMax(level);
}
}
if (this.__enableScrollX) {
scrollLeft -= moveX * this.options.speedMultiplier;
var maxScrollLeft = this.__maxScrollLeft;
if (scrollLeft > maxScrollLeft || scrollLeft < 0) {
// Slow down on the edges
if (this.options.bouncing) {
scrollLeft += (moveX / 2 * this.options.speedMultiplier);
}
else if (scrollLeft > maxScrollLeft) {
scrollLeft = maxScrollLeft;
}
else {
scrollLeft = 0;
}
}
}
// Compute new vertical scroll position
if (this.__enableScrollY) {
scrollTop -= moveY * this.options.speedMultiplier;
// console.log(moveY)
var maxScrollTop = this.__maxScrollTop;
if (scrollTop > maxScrollTop || scrollTop < 0) {
// Slow down on the edges
if (this.options.bouncing) {
scrollTop += (moveY / 2 * this.options.speedMultiplier);
}
else if (scrollTop > maxScrollTop) {
scrollTop = maxScrollTop;
}
else {
scrollTop = 0;
}
}
}
// Keep list from growing infinitely (holding min 10, max 20 measure points)
if (positions.length > 60) {
positions.splice(0, 30);
}
// Track scroll movement for decleration
positions.push(scrollLeft, scrollTop, timeStamp);
// Sync scroll position
this.__publish(scrollLeft, scrollTop, level);
// Otherwise figure out whether we are switching into dragging mode now.
}
else {
var minimumTrackingForScroll = this.options.locking ? 3 : 0;
var minimumTrackingForDrag = 5;
var distanceX = Math.abs(currentTouchLeft - this.__initialTouchLeft);
var distanceY = Math.abs(currentTouchTop - this.__initialTouchTop);
this.__enableScrollX = this.options.scrollingX && distanceX >= minimumTrackingForScroll;
this.__enableScrollY = this.options.scrollingY && distanceY >= minimumTrackingForScroll;
positions.push(this.__scrollLeft, this.__scrollTop, timeStamp);
this.__isDragging = (this.__enableScrollX || this.__enableScrollY) && (distanceX >= minimumTrackingForDrag || distanceY >= minimumTrackingForDrag);
if (this.__isDragging) {
this.__interruptedAnimation = false;
}
}
// Update last touch positions and time stamp for next event
this.__lastTouchLeft = currentTouchLeft;
this.__lastTouchTop = currentTouchTop;
this.__lastTouchMove = timeStamp;
this.__lastScale = scale;
};
/**
* Touch end handler for scrolling support
*/
Scroller.prototype.doTouchEnd = function (timeStamp) {
if (timeStamp instanceof Date) {
timeStamp = timeStamp.valueOf();
}
if (typeof timeStamp !== "number") {
throw new Error("Invalid timestamp value: " + timeStamp);
}
// Ignore event when tracking is not enabled (no touchstart event on element)
// This is required as this listener ('touchmove') sits on the document and not on the element itself.
if (!this.__isTracking) {
return;
}
// Not touching anymore (when two finger hit the screen there are two touch end events)
this.__isTracking = false;
// Be sure to reset the dragging flag now. Here we also detect whether
// the finger has moved fast enough to switch into a deceleration animation.
if (this.__isDragging) {
// Reset dragging flag
this.__isDragging = false;
// Start deceleration
// Verify that the last move detected was in some relevant time frame
if (this.__isSingleTouch && this.options.animating && (timeStamp - this.__lastTouchMove) <= 100) {
// Then figure out what the scroll position was about 100ms ago
var positions = this.__positions;
var endPos = positions.length - 1;
var startPos = endPos;
// Move pointer to position measured 100ms ago
for (var i = endPos; i > 0 && positions[i] > (this.__lastTouchMove - 100); i -= 3) {
startPos = i;
}
// If start and stop position is identical in a 100ms timeframe,
// we cannot compute any useful deceleration.
if (startPos !== endPos) {
// Compute relative movement between these two points
var timeOffset = positions[endPos] - positions[startPos];
var movedLeft = this.__scrollLeft - positions[startPos - 2];
var movedTop = this.__scrollTop - positions[startPos - 1];
// Based on 50ms compute the movement to apply for each render step
this.__decelerationVelocityX = movedLeft / timeOffset * (1000 / 60);
this.__decelerationVelocityY = movedTop / timeOffset * (1000 / 60);
// How much velocity is required to start the deceleration
var minVelocityToStartDeceleration = this.options.paging || this.options.snapping ? 4 : 1;
// Verify that we have enough velocity to start deceleration
if (Math.abs(this.__decelerationVelocityX) > minVelocityToStartDeceleration || Math.abs(this.__decelerationVelocityY) > minVelocityToStartDeceleration) {
this.__startDeceleration(timeStamp);
}
}
else {
this.options.scrollingComplete();
}
}
else if ((timeStamp - this.__lastTouchMove) > 100) {
this.options.scrollingComplete();
}
}
// If this was a slower move it is per default non decelerated, but this
// still means that we want snap back to the bounds which is done here.
// This is placed outside the condition above to improve edge case stability
// e.g. touchend fired without enabled dragging. This should normally do not
// have modified the scroll positions or even showed the scrollbars though.
if (!this.__isDecelerating) {
if (this.__interruptedAnimation || this.__isDragging) {
this.options.scrollingComplete();
}
this.scrollTo(this.__scrollLeft, this.__scrollTop, true, this.__zoomLevel);
}
// Fully cleanup list
this.__positions.length = 0;
};
/*
---------------------------------------------------------------------------
PRIVATE API
---------------------------------------------------------------------------
*/
/**
* Applies the scroll position to the content element
*
* @param left {Number} Left scroll position
* @param top {Number} Top scroll position
* @param isAnimated {Boolean?false} Whether animation should be used to move to the new coordinates
*/
Scroller.prototype.__publish = function (left, top, zoom, isAnimated) {
// Remember whether we had an animation, then we try to continue
// based on the current "drive" of the animation.
var wasAnimating = this.__isAnimating;
if (wasAnimating) {
_animate__WEBPACK_IMPORTED_MODULE_0___default().stop(wasAnimating);
this.__isAnimating = false;
}
if (isAnimated && this.options.animating) {
// Keep scheduled positions for scrollBy/zoomBy functionality.
this.__scheduledLeft = left;
this.__scheduledTop = top;
this.__scheduledZoom = zoom;
var oldLeft = this.__scrollLeft;
var oldTop = this.__scrollTop;
var oldZoom = this.__zoomLevel;
var diffLeft = left - oldLeft;
var diffTop = top - oldTop;
var diffZoom = zoom - oldZoom;
var step = function (percent, now, render) {
if (render) {
this.__scrollLeft = oldLeft + (diffLeft * percent);
this.__scrollTop = oldTop + (diffTop * percent);
this.__zoomLevel = oldZoom + (diffZoom * percent);
// Push values out
if (this.__callback) {
this.__callback(this.__scrollLeft, this.__scrollTop, this.__zoomLevel);
}
}
}.bind(this);
var verify = function (id) {
return this.__isAnimating === id;
}.bind(this);
var completed = function (renderedFramesPerSecond, animationId, wasFinished) {
if (animationId === this.__isAnimating) {
this.__isAnimating = false;
}
if (this.__didDecelerationComplete || wasFinished) {
this.options.scrollingComplete();
}
if (this.options.zooming) {
this.__computeScrollMax();
if (this.__zoomComplete) {
this.__zoomComplete();
this.__zoomComplete = null;
}
}
}.bind(this);
// When continuing based on previous animation we choose an ease-out animation instead of ease-in-out
this.__isAnimating = _animate__WEBPACK_IMPORTED_MODULE_0___default().start(step, verify, completed, this.options.animationDuration, wasAnimating ? easeOutCubic : easeInOutCubic);
}
else {
this.__scheduledLeft = this.__scrollLeft = left;
this.__scheduledTop = this.__scrollTop = top;
this.__scheduledZoom = this.__zoomLevel = zoom;
// Push values out
if (this.__callback) {
this.__callback(left, top, zoom);
}
// Fix max scroll ranges
if (this.options.zooming) {
this.__computeScrollMax();
if (this.__zoomComplete) {
this.__zoomComplete();
this.__zoomComplete = null;
}
}
}
};
/**
* Recomputes scroll minimum values based on client dimensions and content dimensions.
*/
Scroller.prototype.__computeScrollMax = function (zoomLevel) {
if (zoomLevel === undefined) {
zoomLevel = this.__zoomLevel;
}
this.__maxScrollLeft = Math.max(this.__contentWidth * zoomLevel - this.__clientWidth, 0);
this.__maxScrollTop = Math.max(this.__contentHeight * zoomLevel - this.__clientHeight, 0);
};
/*
---------------------------------------------------------------------------
ANIMATION (DECELERATION) SUPPORT
---------------------------------------------------------------------------
*/
/**
* Called when a touch sequence end and the speed of the finger was high enough
* to switch into deceleration mode.
*/
Scroller.prototype.__startDeceleration = function (timeStamp) {
if (this.options.paging) {
var scrollLeft = Math.max(Math.min(this.__scrollLeft, this.__maxScrollLeft), 0);
var scrollTop = Math.max(Math.min(this.__scrollTop, this.__maxScrollTop), 0);
var clientWidth = this.__clientWidth;
var clientHeight = this.__clientHeight;
// We limit deceleration not to the min/max values of the allowed range, but to the size of the visible client area.
// Each page should have exactly the size of the client area.
this.__minDecelerationScrollLeft = Math.floor(scrollLeft / clientWidth) * clientWidth;
this.__minDecelerationScrollTop = Math.floor(scrollTop / clientHeight) * clientHeight;
this.__maxDecelerationScrollLeft = Math.ceil(scrollLeft / clientWidth) * clientWidth;
this.__maxDecelerationScrollTop = Math.ceil(scrollTop / clientHeight) * clientHeight;
}
else {
this.__minDecelerationScrollLeft = 0;
this.__minDecelerationScrollTop = 0;
this.__maxDecelerationScrollLeft = this.__maxScrollLeft;
this.__maxDecelerationScrollTop = this.__maxScrollTop;
}
// Wrap class method
var step = function (percent, now, render) {
this.__stepThroughDeceleration(render);
}.bind(this);
// How much velocity is required to keep the deceleration running
var minVelocityToKeepDecelerating = this.options.snapping ? 4 : 0.1;
// Detect whether it's still worth to continue animating steps
// If we are already slow enough to not being user perceivable anymore, we stop the whole process here.
var verify = function () {
var shouldContinue = Math.abs(this.__decelerationVelocityX) >= minVelocityToKeepDecelerating || Math.abs(this.__decelerationVelocityY) >= minVelocityToKeepDecelerating;
if (!shouldContinue) {
this.__didDecelerationComplete = true;
}
return shouldContinue;
}.bind(this);
var completed = function (renderedFramesPerSecond, animationId, wasFinished) {
this.__isDecelerating = false;
if (this.__didDecelerationComplete) {
this.options.scrollingComplete();
}
// Animate to grid when snapping is active, otherwise just fix out-of-boundary positions
this.scrollTo(this.__scrollLeft, this.__scrollTop, this.options.snapping);
}.bind(this);
// Start animation and switch on flag
this.__isDecelerating = _animate__WEBPACK_IMPORTED_MODULE_0___default().start(step, verify, completed);
};
/**
* Called on every step of the animation
*
* @param inMemory {Boolean?false} Whether to not render the current step, but keep it in memory only. Used internally only!
*/
Scroller.prototype.__stepThroughDeceleration = function (render) {
//
// COMPUTE NEXT SCROLL POSITION
//
// Add deceleration to scroll position
var scrollLeft = this.__scrollLeft + this.__decelerationVelocityX;
var scrollTop = this.__scrollTop + this.__decelerationVelocityY;
//
// HARD LIMIT SCROLL POSITION FOR NON BOUNCING MODE
//
if (!this.options.bouncing) {
var scrollLeftFixed = Math.max(Math.min(this.__maxDecelerationScrollLeft, scrollLeft), this.__minDecelerationScrollLeft);
if (scrollLeftFixed !== scrollLeft) {
scrollLeft = scrollLeftFixed;
this.__decelerationVelocityX = 0;
}
var scrollTopFixed = Math.max(Math.min(this.__maxDecelerationScrollTop, scrollTop), this.__minDecelerationScrollTop);
if (scrollTopFixed !== scrollTop) {
scrollTop = scrollTopFixed;
this.__decelerationVelocityY = 0;
}
}
//
// UPDATE SCROLL POSITION
//
if (render) {
this.__publish(scrollLeft, scrollTop, this.__zoomLevel);
}
else {
this.__scrollLeft = scrollLeft;
this.__scrollTop = scrollTop;
}
//
// SLOW DOWN
//
// Slow down velocity on every iteration
if (!this.options.paging) {
// This is the factor applied to every iteration of the animation
// to slow down the process. This should emulate natural behavior where
// objects slow down when the initiator of the movement is removed
var frictionFactor = 0.95;
this.__decelerationVelocityX *= frictionFactor;
this.__decelerationVelocityY *= frictionFactor;
}
//
// BOUNCING SUPPORT
//
if (this.options.bouncing) {
var scrollOutsideX = 0;
var scrollOutsideY = 0;
// This configures the amount of change applied to deceleration/acceleration when reaching boundaries
var penetrationDeceleration = this.options.penetrationDeceleration;
var penetrationAcceleration = this.options.penetrationAcceleration;
// Check limits
if (scrollLeft < this.__minDecelerationScrollLeft) {
scrollOutsideX = this.__minDecelerationScrollLeft - scrollLeft;
}
else if (scrollLeft > this.__maxDecelerationScrollLeft) {
scrollOutsideX = this.__maxDecelerationScrollLeft - scrollLeft;
}
if (scrollTop < this.__minDecelerationScrollTop) {
scrollOutsideY = this.__minDecelerationScrollTop - scrollTop;
}
else if (scrollTop > this.__maxDecelerationScrollTop) {
scrollOutsideY = this.__maxDecelerationScrollTop - scrollTop;
}
// Slow down until slow enough, then flip back to snap position
if (scrollOutsideX !== 0) {
if (scrollOutsideX * this.__decelerationVelocityX <= 0) {
this.__decelerationVelocityX += scrollOutsideX * penetrationDeceleration;
}
else {
this.__decelerationVelocityX = scrollOutsideX * penetrationAcceleration;
}
}
if (scrollOutsideY !== 0) {
if (scrollOutsideY * this.__decelerationVelocityY <= 0) {
this.__decelerationVelocityY += scrollOutsideY * penetrationDeceleration;
}
else {
this.__decelerationVelocityY = scrollOutsideY * penetrationAcceleration;
}
}
}
};
return Scroller;
}());
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Scroller);
/***/ }),
/* 27 */
/***/ (function(module, exports) {
"use strict";
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
/*
* Scroller
* http://github.com/zynga/scroller
*
* Copyright 2011, Zynga Inc.
* Licensed under the MIT License.
* https://raw.github.com/zynga/scroller/master/MIT-LICENSE.txt
*
* Based on the work of: Unify Project (unify-project.org)
* http://unify-project.org
* Copyright 2011, Deutsche Telekom AG
* License: MIT + Apache (V2)
*/
/**
* Generic animation class with support for dropped frames both optional easing and duration.
*
* Optional duration is useful when the lifetime is defined by another condition than time
* e.g. speed of an animating object, etc.
*
* Dropped frame logic allows to keep using the same updater logic independent from the actual
* rendering. This eases a lot of cases where it might be pretty complex to break down a state
* based on the pure time difference.
*/
(function (root, factory) {
if (true) {
// AMD. Register as an anonymous module.
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
}
else {}
}(this, function (exports) {
var global = typeof window === 'undefined' ? this : window;
var time = Date.now || function () {
return +new Date();
};
var desiredFrames = 60;
var millisecondsPerSecond = 1000;
var running = {};
var counter = 1;
/**
* Stops the given animation.
*
* @param id {Integer} Unique animation ID
* @return {Boolean} Whether the animation was stopped (aka, was running before)
*/
exports.stop = function (id) {
var cleared = (running[id] !== null);
if (cleared) {
running[id] = null;
}
return cleared;
};
/**
* Whether the given animation is still running.
*
* @param id {Integer} Unique animation ID
* @return {Boolean} Whether the animation is still running
*/
exports.isRunning = function (id) {
return running[id] !== null;
};
/**
* Start the animation.
*
* @param stepCallback {Function} Pointer to function which is executed on every step.
* Signature of the method should be `function(percent, now, virtual) { return continueWithAnimation; }`
* @param verifyCallback {Function} Executed before every animation step.
* Signature of the method should be `function() { return continueWithAnimation; }`
* @param completedCallback {Function}
* Signature of the method should be `function(droppedFrames, finishedAnimation, optional wasFinished) {}`
* @param duration {Integer} Milliseconds to run the animation
* @param easingMethod {Function} Pointer to easing function
* Signature of the method should be `function(percent) { return modifiedValue; }`
* @param root {Element} Render root. Used for internal usage of requestAnimationFrame.
* @return {Integer} Identifier of animation. Can be used to stop it any time.
*/
exports.start = function (stepCallback, verifyCallback, completedCallback, duration, easingMethod, root) {
var start = time();
var lastFrame = start;
var percent = 0;
var dropCounter = 0;
var id = counter++;
// Compacting running db automatically every few new animations
if (id % 20 === 0) {
var newRunning = {};
for (var usedId in running) {
newRunning[usedId] = true;
}
running = newRunning;
}
// This is the internal step method which is called every few milliseconds
var step = function (virtual) {
// Normalize virtual value
var render = virtual !== true;
// Get current time
var now = time();
// Verification is executed before next animation step
if (!running[id] || (verifyCallback && !verifyCallback(id))) {
running[id] = null;
completedCallback(desiredFrames - (dropCounter / ((now - start) / millisecondsPerSecond)), id, false);
return;
}
// For the current rendering to apply let's update omitted steps in memory.
// This is important to bring internal state variables up-to-date with progress in time.
if (render) {
var droppedFrames = Math.round((now - lastFrame) / (millisecondsPerSecond / desiredFrames)) - 1;
for (var j = 0; j < Math.min(droppedFrames, 4); j++) {
step(true);
dropCounter++;
}
}
// Compute percent value
if (duration) {
percent = (now - start) / duration;
if (percent > 1) {
percent = 1;
}
}
// Execute step callback, then...
var value = easingMethod ? easingMethod(percent) : percent;
if ((stepCallback(value, now, render) === false || percent === 1) && render) {
running[id] = null;
completedCallback(desiredFrames - (dropCounter / ((now - start) / millisecondsPerSecond)), id, percent === 1 || duration === undefined);
}
else if (render) {
lastFrame = now;
requestAnimationFrame(step, root);
}
};
// Mark as running
running[id] = true;
// Init first step
requestAnimationFrame(step, root);
// Return unique animation ID
return id;
};
}));
/***/ }),
/* 28 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ ScrollBarDirection: () => (/* binding */ ScrollBarDirection),
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _view__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(22);
/* harmony import */ var _common_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var ScrollBarDirection;
(function (ScrollBarDirection) {
ScrollBarDirection[ScrollBarDirection["Vertival"] = 0] = "Vertival";
ScrollBarDirection[ScrollBarDirection["Horizontal"] = 1] = "Horizontal";
})(ScrollBarDirection || (ScrollBarDirection = {}));
/**
* 根据滚动条的尺寸、ScrollView 视口和滚动窗口尺寸、滚动防线信息确认滚动条的样式信息
*/
function updateStyleFromDimensions(width, direction, dimensions) {
var isVertical = direction === ScrollBarDirection.Vertival;
var scrollWidth = dimensions.width, scrollHeight = dimensions.height, contentWidth = dimensions.contentWidth, contentHeight = dimensions.contentHeight;
return {
width: isVertical ? width : scrollWidth * (scrollWidth / contentWidth),
height: isVertical ? scrollHeight * (scrollHeight / contentHeight) : width,
left: isVertical ? scrollWidth - width : 0,
top: isVertical ? 0 : scrollHeight - width,
};
}
function checkNeedHideScrollBar(direction, dimensions) {
return !!(direction === ScrollBarDirection.Vertival && dimensions.maxScrollTop === 0
|| direction === ScrollBarDirection.Horizontal && dimensions.maxScrollLeft === 0);
}
/**
* 滚动组件的滚动条组件,滚动条本身也是Layout的一个节点
*/
var ScrollBar = /** @class */ (function (_super) {
__extends(ScrollBar, _super);
function ScrollBar(_a) {
var direction = _a.direction, dimensions = _a.dimensions, _b = _a.backgroundColor, backgroundColor = _b === void 0 ? 'rgba(162, 162, 162, 0.7)' : _b, _c = _a.width, width = _c === void 0 ? 10 : _c;
var _this = this;
var style = Object.assign({
backgroundColor: backgroundColor,
position: 'absolute',
borderRadius: width / 2,
opacity: 0,
}, updateStyleFromDimensions(width, direction, dimensions));
_this = _super.call(this, {
style: style,
}) || this;
// 滚动完毕后一段时间后自动隐藏
_this.autoHide = true;
// 滚动完毕后自动隐藏时间
_this.autoHideTime = 2000;
_this.autoHideDelayTime = 1500;
_this.autoHideRemainingTime = 0;
_this.innerWidth = 10;
_this.isHide = false;
_this.currLeft = 0;
_this.currTop = 0;
_this.update = function (dt) {
if (!_this.autoHide || _this.autoHideRemainingTime <= 0 || _this.isHide) {
return;
}
_this.autoHideRemainingTime -= dt;
if (_this.autoHideRemainingTime <= _this.autoHideTime) {
_this.autoHideRemainingTime = Math.max(0, _this.autoHideRemainingTime);
_this.style.opacity = _this.style.opacity * (_this.autoHideRemainingTime / _this.autoHideTime);
}
};
_this.direction = direction;
_this.dimensions = dimensions;
_this.innerWidth = width;
// FIXME: yxu 强行关闭滚动条
if (true || checkNeedHideScrollBar(direction, dimensions)) {
_this.hide();
}
return _this;
}
Object.defineProperty(ScrollBar.prototype, "width", {
get: function () {
return this.innerWidth;
},
/**
* 滚动条的粗细,因为要兼容横竖滚动,所以 style.width 在不同模式下代表的意思不一样
* 因此通过单独的 width 属性来代表滚动条的粗细
*/
set: function (value) {
if (value !== this.innerWidth) {
this.innerWidth = value;
}
this.style.borderRadius = this.innerWidth / 2;
this.setDimensions(this.dimensions);
},
enumerable: false,
configurable: true
});
ScrollBar.prototype.init = function () {
var _this = this;
if (!this.root) {
console.warn('[Layout]: please set root for scrollbar');
}
else {
// @ts-ignore
this.root.ticker.add(this.update, true);
this.root.on('before_reflow', function () {
// console.log('before_reflow')
var _a = _this.calculteScrollValue(_this.currLeft, _this.currTop), scrollLeft = _a.scrollLeft, scrollTop = _a.scrollTop;
// console.log(this, scrollLeft, scrollTop)
if (_this.direction === ScrollBarDirection.Vertival) {
_this.style.top = scrollTop;
}
else {
_this.style.left = scrollLeft;
}
});
}
};
ScrollBar.prototype.hide = function () {
this.isHide = true;
this.style.opacity = 0;
};
ScrollBar.prototype.show = function () {
this.isHide = false;
this.style.opacity = 1;
};
/**
* 根据 ScrollView 容器宽高和实际内容宽高决定滚动条的位置和尺寸信息
* 但核心需要考虑的情况是:
* 1. 在不断地 reflow 过程中,ScrollBar 也会存在需要切换展示和隐藏的情况
* 2. reflow 之后,ScrollBar 的位置不是简单的设置为 ScrollView 顶部和左边,还可能是滚动了一段距离后执行的 reflow
*/
ScrollBar.prototype.setDimensions = function (dimensions) {
var style = updateStyleFromDimensions(this.width, this.direction, dimensions);
Object.assign(this.style, style);
if (checkNeedHideScrollBar(this.direction, dimensions)) {
this.hide();
}
else if (this.isHide) {
this.show();
}
this.dimensions = dimensions;
// 已经滚动过一段距离的情况,重新计算新的滚动位置
var _a = this.calculteScrollValue(dimensions.scrollLeft, dimensions.scrollTop), scrollLeft = _a.scrollLeft, scrollTop = _a.scrollTop;
if (this.direction === ScrollBarDirection.Vertival) {
this.style.top = scrollTop;
}
else {
this.style.left = scrollLeft;
}
this.autoHideRemainingTime = this.autoHideTime + this.autoHideDelayTime;
};
ScrollBar.prototype.calculteScrollValue = function (left, top) {
var scrollLeft = 0;
var scrollTop = 0;
if (this.direction === ScrollBarDirection.Vertival) {
var canScrollPercent = 1 - this.dimensions.height / this.dimensions.contentHeight;
// 滚动条最大滚动高度
var scrollBarMaxScrollTop = this.dimensions.height * canScrollPercent;
var percent = top / this.dimensions.maxScrollTop;
var percentTop = scrollBarMaxScrollTop * percent;
scrollTop = (0,_common_util__WEBPACK_IMPORTED_MODULE_1__.clamp)(percentTop, 0, scrollBarMaxScrollTop);
}
else {
var canScrollPercent = 1 - this.dimensions.width / this.dimensions.contentWidth;
var scrollBarMaxScrollLeft = this.dimensions.width * canScrollPercent;
var percent = left / this.dimensions.maxScrollLeft;
scrollLeft = (0,_common_util__WEBPACK_IMPORTED_MODULE_1__.clamp)(scrollBarMaxScrollLeft * percent, 0, scrollBarMaxScrollLeft);
}
return { scrollLeft: scrollLeft, scrollTop: scrollTop };
};
ScrollBar.prototype.onScroll = function (left, top) {
if (this.isHide) {
return;
}
this.currLeft = left;
this.currTop = top;
var _a = this.calculteScrollValue(left, top), scrollLeft = _a.scrollLeft, scrollTop = _a.scrollTop;
if (this.direction === ScrollBarDirection.Vertival) {
this.layoutBox.absoluteY = this.parent.layoutBox.originalAbsoluteY + scrollTop;
}
else {
this.layoutBox.absoluteX = this.parent.layoutBox.originalAbsoluteX + scrollLeft;
}
if (this.autoHide) {
// this.autoHideRemainingTime = this.autoHideTime;
this.autoHideRemainingTime = this.autoHideTime + this.autoHideDelayTime;
}
this.style.opacity = 1;
};
ScrollBar.prototype.destroySelf = function () {
// @ts-ignore
this.root.ticker.remove(this.update, true);
this.isDestroyed = true;
this.root = null;
};
return ScrollBar;
}(_view__WEBPACK_IMPORTED_MODULE_0__["default"]));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ScrollBar);
/***/ }),
/* 29 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _elements__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var _common_pool__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6);
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var bitMapPool = new _common_pool__WEBPACK_IMPORTED_MODULE_1__["default"]('bitMapPool');
var BitMapText = /** @class */ (function (_super) {
__extends(BitMapText, _super);
function BitMapText(opts) {
var _this = this;
var _a = opts.style, style = _a === void 0 ? {} : _a, _b = opts.idName, idName = _b === void 0 ? '' : _b, _c = opts.className, className = _c === void 0 ? '' : _c, _d = opts.value, value = _d === void 0 ? '' : _d, _e = opts.font, font = _e === void 0 ? '' : _e, dataset = opts.dataset;
_this = _super.call(this, {
idName: idName,
className: className,
style: style,
dataset: dataset,
}) || this;
_this.type = 'BitMapText';
_this.ctx = null;
_this.valuesrc = value;
_this.font = bitMapPool.get(font);
if (!_this.font) {
console.error("Missing BitmapFont \"".concat(font, "\", please invoke API \"registBitMapFont\" before using \"BitMapText\""));
}
return _this;
}
Object.defineProperty(BitMapText.prototype, "value", {
get: function () {
return this.valuesrc;
},
set: function (newValue) {
if (newValue !== this.valuesrc) {
this.valuesrc = newValue;
this.emit('repaint');
}
},
enumerable: false,
configurable: true
});
BitMapText.prototype.repaint = function () {
this.render();
};
BitMapText.prototype.destroySelf = function () {
this.root = null;
};
BitMapText.prototype.render = function () {
var _this = this;
if (!this.font) {
return;
}
if (this.font.ready) {
this.renderText(this.ctx);
}
else {
this.font.event.on('text__load__done', function () {
if (!_this.isDestroyed) {
_this.renderText(_this.ctx);
}
});
}
};
BitMapText.prototype.getTextBounds = function () {
var style = this.style;
var _a = style.letterSpacing, letterSpacing = _a === void 0 ? 0 : _a;
var width = 0;
// 记录上一个字符,方便处理 kerning
var prevCharCode = null;
for (var i = 0, len = this.value.length; i < len; i++) {
var char = this.value[i];
var cfg = this.font.chars[char];
if (cfg) {
if (prevCharCode && cfg.kerning[prevCharCode]) {
width += cfg.kerning[prevCharCode];
}
width += cfg.xadvance;
if (i < len - 1) {
width += letterSpacing;
}
}
}
return { width: width, height: this.font.lineHeight };
};
BitMapText.prototype.renderText = function (ctx) {
var bounds = this.getTextBounds();
var defaultLineHeight = this.font.lineHeight;
ctx.save();
var _a = this.baseRender(), needStroke = _a.needStroke, originX = _a.originX, originY = _a.originY, drawX = _a.drawX, drawY = _a.drawY;
var style = this.style;
var _b = style.width, width = _b === void 0 ? 0 : _b, // 没有设置采用计算出来的宽度
_c = style.height, // 没有设置采用计算出来的宽度
height = _c === void 0 ? 0 : _c, // 没有设置则采用计算出来的宽度
textAlign = style.textAlign, // 文字左右对齐方式
verticalAlign = style.verticalAlign, _d = style.letterSpacing, letterSpacing = _d === void 0 ? 0 : _d;
// 没有设置则采用计算出来的高度
var lineHeight = (style.lineHeight || defaultLineHeight);
var scaleY = lineHeight / defaultLineHeight;
var realWidth = scaleY * bounds.width;
// 如果文字的渲染区域高度小于盒子高度,采用对齐方式
if (lineHeight < height) {
if (verticalAlign === 'middle') {
drawY += (height - lineHeight) / 2;
}
else if (verticalAlign === 'bottom') {
drawY = drawY + height - lineHeight;
}
}
if (width > realWidth) {
if (textAlign === 'center') {
drawX += (width - realWidth) / 2;
}
else if (textAlign === 'right') {
drawX += (width - realWidth);
}
}
// 记录上一个字符,方便处理 kerning
var prevCharCode = null;
for (var i = 0; i < this.value.length; i++) {
var char = this.value[i];
var cfg = this.font.chars[char];
if (prevCharCode && cfg.kerning[prevCharCode]) {
drawX += cfg.kerning[prevCharCode];
}
if (cfg) {
ctx.drawImage(this.font.texture, cfg.x, cfg.y, cfg.w, cfg.h, drawX + cfg.offX * scaleY - originX, drawY + cfg.offY * scaleY - originY, cfg.w * scaleY, cfg.h * scaleY);
drawX += (cfg.xadvance * scaleY + letterSpacing);
prevCharCode = char;
}
}
if (needStroke) {
ctx.stroke();
}
ctx.translate(-originX, -originY);
ctx.restore();
};
return BitMapText;
}(_elements__WEBPACK_IMPORTED_MODULE_0__["default"]));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BitMapText);
/***/ }),
/* 30 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _elements__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var _env__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Canvas = /** @class */ (function (_super) {
__extends(Canvas, _super);
function Canvas(opts) {
var _this = this;
var _a = opts.style, style = _a === void 0 ? {} : _a, _b = opts.idName, idName = _b === void 0 ? '' : _b, _c = opts.className, className = _c === void 0 ? '' : _c, dataset = opts.dataset, _d = opts.width, width = _d === void 0 ? 100 : _d, _e = opts.height, height = _e === void 0 ? 100 : _e, _f = opts.autoCreateCanvas, autoCreateCanvas = _f === void 0 ? false : _f;
_this = _super.call(this, {
idName: idName,
className: className,
dataset: dataset,
style: style,
}) || this;
_this.canvasInstance = null;
/**
* 微信小游戏场景下,sharedCanvas 实例不方便自动创建,提供 setter 手动设置
*/
if (autoCreateCanvas) {
_this.canvasInstance = _env__WEBPACK_IMPORTED_MODULE_1__["default"].createCanvas();
_this.canvasInstance.width = Number(width);
_this.canvasInstance.height = Number(height);
}
return _this;
}
Object.defineProperty(Canvas.prototype, "canvas", {
get: function () {
return this.canvasInstance;
},
set: function (cvs) {
this.canvasInstance = cvs;
},
enumerable: false,
configurable: true
});
Canvas.prototype.update = function () {
this.root.emit('repaint');
};
Canvas.prototype.repaint = function () {
this.render();
};
// 子类填充实现
Canvas.prototype.destroySelf = function () {
this.isDestroyed = true;
this.root = null;
this.canvasInstance = null;
};
Canvas.prototype.render = function () {
if (!this.canvasInstance) {
return;
}
var ctx = this.ctx;
ctx.save();
var _a = this.baseRender(), needStroke = _a.needStroke, originX = _a.originX, originY = _a.originY, drawX = _a.drawX, drawY = _a.drawY, width = _a.width, height = _a.height;
// 自定义渲染逻辑 开始
ctx.drawImage(this.canvasInstance, drawX - originX, drawY - originY, width, height);
// 自定义渲染逻辑 结束
if (needStroke) {
ctx.stroke();
}
if (this.renderForLayout.rotate) {
ctx.translate(-originX, -originY);
}
ctx.restore();
};
return Canvas;
}(_elements__WEBPACK_IMPORTED_MODULE_0__["default"]));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Canvas);
/***/ }),
/* 31 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _text__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(24);
/* harmony import */ var _common_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (undefined && undefined.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var Button = /** @class */ (function (_super) {
__extends(Button, _super);
function Button(_a) {
var _b = _a.style, style = _b === void 0 ? {} : _b, _c = _a.idName, idName = _c === void 0 ? '' : _c, _d = _a.className, className = _d === void 0 ? '' : _d, _e = _a.value, value = _e === void 0 ? '' : _e, dataset = _a.dataset;
var _this = _super.call(this, {
idName: idName,
className: className,
style: __assign(__assign({ width: 300, height: 60, lineHeight: 60, fontSize: 30, borderRadius: 10, backgroundColor: '#34a123', color: '#ffffff', textAlign: 'center' }, style), { ':active': __assign({ transform: 'scale(1.05, 1.05)' }, style[':active']) }),
value: value,
dataset: dataset,
}) || this;
// 缩放动画的时长
_this.scaleDuration = 100;
// 当前缩放动画是否播放完毕
_this.scaleDone = true;
// 缩放动画开始的时间
_this.timeClick = 0;
// 缩放动画的 scale 初始值,这并不是固定不变的,当点击结束,可能需要从大到小变换
_this.fromScale = 1;
// 缩放动画的 scale 目标值
_this.toScale = 1;
_this.update = function (dt) {
if (_this.scaleDone) {
return;
}
_this.timeClick += dt;
var ratio = 1;
ratio = _this.timeClick / _this.scaleDuration;
if (ratio > 1) {
ratio = 1;
}
var scale = (0,_common_util__WEBPACK_IMPORTED_MODULE_1__.lerp)(_this.fromScale, _this.toScale, ratio);
var transform = "scale(".concat(scale, ", ").concat(scale, ")");
_this.style.transform = transform;
if (ratio === 1) {
_this.scaleDone = true;
}
};
return _this;
}
Button.prototype.afterCreate = function () {
// @ts-ignore
this.root.ticker.add(this.update);
};
Button.prototype.destroySelf = function () {
// @ts-ignore
this.root.ticker.remove(this.update);
this.isDestroyed = true;
this.root = null;
};
return Button;
}(_text__WEBPACK_IMPORTED_MODULE_0__["default"]));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Button);
/***/ })
/******/ ]);
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
(() => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ BitMapText: () => (/* reexport safe */ _components__WEBPACK_IMPORTED_MODULE_13__.BitMapText),
/* harmony export */ Button: () => (/* reexport safe */ _components__WEBPACK_IMPORTED_MODULE_13__.Button),
/* harmony export */ Canvas: () => (/* reexport safe */ _components__WEBPACK_IMPORTED_MODULE_13__.Canvas),
/* harmony export */ EE: () => (/* binding */ EE),
/* harmony export */ Element: () => (/* reexport safe */ _components_elements__WEBPACK_IMPORTED_MODULE_1__["default"]),
/* harmony export */ Image: () => (/* reexport safe */ _components__WEBPACK_IMPORTED_MODULE_13__.Image),
/* harmony export */ Layout: () => (/* binding */ Layout),
/* harmony export */ ScrollView: () => (/* reexport safe */ _components__WEBPACK_IMPORTED_MODULE_13__.ScrollView),
/* harmony export */ Text: () => (/* reexport safe */ _components__WEBPACK_IMPORTED_MODULE_13__.Text),
/* harmony export */ View: () => (/* reexport safe */ _components__WEBPACK_IMPORTED_MODULE_13__.View),
/* harmony export */ "default": () => (/* binding */ layout),
/* harmony export */ env: () => (/* reexport safe */ _env__WEBPACK_IMPORTED_MODULE_0__["default"])
/* harmony export */ });
/* harmony import */ var _env__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var _components_elements__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
/* harmony import */ var _common_pool__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6);
/* harmony import */ var tiny_emitter__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8);
/* harmony import */ var tiny_emitter__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(tiny_emitter__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var css_layout__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(10);
/* harmony import */ var css_layout__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(css_layout__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var _common_util__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7);
/* harmony import */ var _libs_fast_xml_parser_parser_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(11);
/* harmony import */ var _common_bitMapFont__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(17);
/* harmony import */ var _common_debugInfo__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(18);
/* harmony import */ var _common_ticker__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(19);
/* harmony import */ var _common_vd__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(20);
/* harmony import */ var _common_rect__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(4);
/* harmony import */ var _common_imageManager__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(5);
/* harmony import */ var _components__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(21);
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
// 全局事件管道
var EE = new (tiny_emitter__WEBPACK_IMPORTED_MODULE_3___default().TinyEmitter)();
var imgPool = new _common_pool__WEBPACK_IMPORTED_MODULE_2__["default"]('imgPool');
var bitMapPool = new _common_pool__WEBPACK_IMPORTED_MODULE_2__["default"]('bitMapPool');
var debugInfo = new _common_debugInfo__WEBPACK_IMPORTED_MODULE_8__["default"]();
/**
* 默认暴露 Layout 的实例,但在某些场景下,可能需要多个 Layout 实例,因此 Layout 类也暴露出去
* const myLayout = new Layout({
* style: {
* width: 0,
* height: 0,
* },
* name: 'myLayoutName',
* });
*/
var Layout = /** @class */ (function (_super) {
__extends(Layout, _super);
function Layout(_a) {
var style = _a.style;
var _this = _super.call(this, {
style: style,
id: 0,
}) || this;
/**
* 当前 Layout 版本,一般跟小游戏插件版本对齐
*/
_this.version = '1.0.14';
_this.env = _env__WEBPACK_IMPORTED_MODULE_0__["default"];
/**
* Layout 渲染的目标画布对应的 2d context
*/
_this.renderContext = null;
_this.renderport = {
width: 0,
height: 0,
};
_this.viewport = {
width: 0,
height: 0,
x: 0,
y: 0,
};
/**
* 画布尺寸和实际被渲染到屏幕的物理尺寸比
*/
_this.viewportScale = 1;
/**
* 用于标识updateViewPort方法是否被调用过了,这在小游戏环境非常重要
*/
_this.hasViewPortSet = false;
/**
* 最终渲染到屏幕的左上角物理坐标
*/
_this.realLayoutBox = {
realX: 0,
realY: 0,
};
_this.bitMapFonts = [];
_this.eleCount = 0;
_this.state = _common_util__WEBPACK_IMPORTED_MODULE_5__.STATE.UNINIT;
/**
* 用于在 ticker 的循环里面标识当前帧是否需要重绘
* 重绘一般是图片加载完成、文字修改等场景
*/
_this.isNeedRepaint = false;
_this.ticker = new _common_ticker__WEBPACK_IMPORTED_MODULE_9__["default"]();
_this.tickerFunc = function () {
if (_this.isDirty) {
// console.log('before_reflow')
_this.emit('before_reflow', '');
_this.reflow();
}
else if (_this.isNeedRepaint) {
_this.repaint();
}
};
_this.styleSheet = {};
_this.activeElements = [];
_this.eventHandler = function (eventName) {
return function (e) {
var touch;
if ((0,_common_util__WEBPACK_IMPORTED_MODULE_5__.isGameTouchEvent)(e)) {
touch = (e.touches && e.touches[0]) || (e.changedTouches && e.changedTouches[0]);
}
else {
touch = e;
}
// const touch = (e.touches && e.touches[0]) || (e.changedTouches && e.changedTouches[0]) || e;
if (!touch || !touch.pageX || !touch.pageY) {
return;
}
if (!touch.timeStamp) {
// @ts-ignore
touch.timeStamp = e.timeStamp;
}
var list = [];
if (touch) {
_this.getChildByPos(_this, touch.pageX, touch.pageY, list);
}
if (!list.length) {
list.push(_this);
}
var item = list[list.length - 1];
item && item.emit(eventName, e);
if (eventName === 'touchstart' || eventName === 'touchend') {
_this.eventHandlerData.touchMsg[eventName] = touch;
}
if (eventName === 'touchend' && (0,_common_util__WEBPACK_IMPORTED_MODULE_5__.isClick)(_this.eventHandlerData.touchMsg)) {
item && item.emit('click', e);
}
};
};
/**
* 将组件挂到Layout
*/
_this.Element = _components_elements__WEBPACK_IMPORTED_MODULE_1__["default"];
_this.View = _components__WEBPACK_IMPORTED_MODULE_13__.View;
_this.Text = _components__WEBPACK_IMPORTED_MODULE_13__.Text;
_this.Image = _components__WEBPACK_IMPORTED_MODULE_13__.Image;
_this.ScrollView = _components__WEBPACK_IMPORTED_MODULE_13__.ScrollView;
_this.BitMapText = _components__WEBPACK_IMPORTED_MODULE_13__.BitMapText;
_this.Canvas = _components__WEBPACK_IMPORTED_MODULE_13__.Canvas;
_this.Button = _components__WEBPACK_IMPORTED_MODULE_13__.Button;
_this.registerComponent = _common_vd__WEBPACK_IMPORTED_MODULE_10__.registerComponent;
_this.eventHandlerData = {
hasEventBind: false,
touchMsg: {},
handlers: {
touchStart: _this.eventHandler('touchstart').bind(_this),
touchMove: _this.eventHandler('touchmove').bind(_this),
touchEnd: _this.eventHandler('touchend').bind(_this),
touchCancel: _this.eventHandler('touchcancel').bind(_this),
},
};
/**
* 对于不会影响布局的改动,比如图片只是改个地址、加个背景色之类的改动,会触发 Layout 的 repaint 操作
* 触发的方式是给 Layout 抛个 `repaint` 的事件,为了性能,每次接收到 repaint 请求不会执行真正的渲染
* 而是执行一个置脏操作,ticker 每一次执行 update 会检查这个标记位,进而执行真正的重绘操作
*/
_this.on('repaint', function () {
_this.isNeedRepaint = true;
});
/**
* 将 Tween 挂载到 Layout,对于 Tween 的使用完全遵循 Tween.js 的文档
* https://github.com/tweenjs/tween.js/
* 只不过当 Tween 改动了节点会触发 repaint、reflow 的属性时,Layout 会执行相应的操作
* 业务侧不用感知到 repaint 和 reflow
*/
// this.TWEEN = TWEEN;
console.log("[Layout] v".concat(_this.version));
return _this;
}
Object.defineProperty(Layout.prototype, "debugInfo", {
// 与老版本兼容
get: function () {
var info = debugInfo.log();
info += "elementCount: ".concat(this.eleCount, "\n");
return info;
},
enumerable: false,
configurable: true
});
/**
* 更新被绘制canvas的窗口信息,本渲染引擎并不关心是否会和其他游戏引擎共同使用
* 而本身又需要支持事件处理,因此,如果被渲染内容是绘制到离屏canvas,需要将最终绘制在屏幕上
* 的绝对尺寸和位置信息更新到本渲染引擎。
* 其中,width为物理像素宽度,height为物理像素高度,x为距离屏幕左上角的物理像素x坐标,y为距离屏幕左上角的物理像素
* y坐标
*/
Layout.prototype.updateViewPort = function (box) {
this.viewport.width = box.width || 0;
this.viewport.height = box.height || 0;
this.viewport.x = box.x || 0;
this.viewport.y = box.y || 0;
this.realLayoutBox = {
realX: this.viewport.x,
realY: this.viewport.y,
};
this.hasViewPortSet = true;
};
Layout.prototype.init = function (template, style, attrValueProcessor) {
debugInfo.start('init');
var elementArray = this.insertElementArray(template, style, attrValueProcessor, true);
this.add(elementArray[0]);
this.state = _common_util__WEBPACK_IMPORTED_MODULE_5__.STATE.INITED;
this.ticker.add(this.tickerFunc, true);
this.ticker.start();
debugInfo.end('init');
};
Layout.prototype.reflow = function (isFirst) {
if (isFirst === void 0) { isFirst = false; }
if (!isFirst) {
debugInfo.reset();
}
debugInfo.start('layout_reflow');
/**
* 计算布局树
* 经过 Layout 计算,节点树带上了 layout、lastLayout、shouldUpdate 布局信息
* Layout本身并不作为布局计算,只是作为节点树的容器
*/
debugInfo.start('computeLayout', true);
css_layout__WEBPACK_IMPORTED_MODULE_4___default()(this.children[0]);
debugInfo.end('computeLayout');
var rootEle = this.children[0];
if (rootEle.style.width === undefined || rootEle.style.height === undefined) {
console.error('[Layout] Please set width and height property for root element');
}
else {
this.renderport.width = rootEle.style.width;
this.renderport.height = rootEle.style.height;
}
// 将布局树的布局信息加工赋值到渲染树
debugInfo.start('layoutChildren', true);
(0,_common_vd__WEBPACK_IMPORTED_MODULE_10__.layoutChildren)(this);
debugInfo.end('layoutChildren');
this.viewportScale = this.viewport.width / this.renderport.width;
(0,_common_util__WEBPACK_IMPORTED_MODULE_5__.clearCanvas)(this.renderContext);
// 遍历节点树,依次调用节点的渲染接口实现渲染
debugInfo.start('renderChildren', true);
(0,_common_vd__WEBPACK_IMPORTED_MODULE_10__.renderChildren)(this.children, this.renderContext, false);
debugInfo.end('renderChildren');
debugInfo.start('repaint', true);
this.repaint();
debugInfo.end('repaint');
this.isDirty = false;
// iterateTree(this.children[0], (ele) => {
// console.log(ele.props);
// });
debugInfo.end('layout_reflow');
};
/**
* init阶段核心仅仅是根据xml和css创建了节点树
* 要实现真正的渲染,需要调用 layout 函数,之所以将 layout 单独抽象为一个函数,是因为 layout 应当是可以重复调用的
* 比如改变了一个元素的尺寸,实际上节点树是没变的,仅仅是需要重新计算布局,然后渲染
* 一个完整的 layout 分成下面的几步:
* 1. 执行画布清理,因为布局变化页面需要重绘,这里没有做很高级的剔除等操作,一律清除重画,实际上性能已经很好
* 2. 节点树都含有 style 属性,css-layout 能够根据这些信息计算出最终布局,详情可见 https://www.npmjs.com/package/css-layout
* 3. 经过 Layout 计算,节点树带上了 layout、lastLayout、shouldUpdate 布局信息,但这些信息并不是能够直接用的
* 比如 layout.top 是指在一个父容器内的 top,最终要实现渲染,实际上要递归加上复容器的 top
* 这样每次 repaint 的时候只需要直接使用计算好的值即可,不需要每次都递归计算
* 这一步称为 layoutChildren,目的在于将 css-layout 进一步处理为可以渲染直接用的布局信息
* 4. renderChildren:执行渲染
* 5. bindEvents:执行事件绑定
*/
// @ts-ignore
Layout.prototype.layout = function (context) {
this.renderContext = context;
if (!this.hasViewPortSet) {
console.error('[Layout] Please invoke method `updateViewPort` before method `layout`');
}
debugInfo.start('layout');
this.reflow(true);
debugInfo.start('layout_other');
this.bindEvents();
debugInfo.start('layout_observeStyleAndEvent', true);
(0,_common_vd__WEBPACK_IMPORTED_MODULE_10__.iterateTree)(this.children[0], function (element) { return element.observeStyleAndEvent(); });
debugInfo.end('layout_observeStyleAndEvent');
this.state = _common_util__WEBPACK_IMPORTED_MODULE_5__.STATE.RENDERED;
debugInfo.end('layout');
debugInfo.end('layout_other');
};
/**
* 执行节点数的重绘制,一般业务侧无需调用该方法
*/
Layout.prototype.repaint = function () {
(0,_common_util__WEBPACK_IMPORTED_MODULE_5__.clearCanvas)(this.renderContext);
this.isNeedRepaint = false;
(0,_common_vd__WEBPACK_IMPORTED_MODULE_10__.repaintChildren)(this.children);
};
/**
* 返回一个节点在屏幕中的位置和尺寸信息,前提是正确调用updateViewPort。
*/
Layout.prototype.getElementViewportRect = function (element) {
var _a = this, realLayoutBox = _a.realLayoutBox, viewportScale = _a.viewportScale;
var _b = element.layoutBox, absoluteX = _b.absoluteX, absoluteY = _b.absoluteY, width = _b.width, height = _b.height;
var realX = absoluteX * viewportScale + realLayoutBox.realX;
var realY = absoluteY * viewportScale + realLayoutBox.realY;
var realWidth = width * viewportScale;
var realHeight = height * viewportScale;
return new _common_rect__WEBPACK_IMPORTED_MODULE_11__["default"](realX, realY, realWidth, realHeight);
};
Layout.prototype.getChildByPos = function (tree, x, y, itemList) {
var _this = this;
tree.children.forEach(function (ele) {
var _a = ele.layoutBox, absoluteX = _a.absoluteX, absoluteY = _a.absoluteY, width = _a.width, height = _a.height;
var realX = absoluteX * _this.viewportScale + _this.realLayoutBox.realX;
var realY = absoluteY * _this.viewportScale + _this.realLayoutBox.realY;
var realWidth = width * _this.viewportScale;
var realHeight = height * _this.viewportScale;
if ((realX <= x && x <= realX + realWidth) && (realY <= y && y <= realY + realHeight)) {
/**
* 相关issue:https://github.com/wechat-miniprogram/minigame-canvas-engine/issues/17
* 这里只要满足条件的都要记录,否则可能出现 issue 里面提到的问题
*/
itemList.push(ele);
if (ele.children.length) {
_this.getChildByPos(ele, x, y, itemList);
}
}
});
};
/**
* 执行全局的事件绑定逻辑
*/
Layout.prototype.bindEvents = function () {
var _this = this;
if (this.eventHandlerData.hasEventBind) {
return;
}
this.eventHandlerData.hasEventBind = true;
_env__WEBPACK_IMPORTED_MODULE_0__["default"].onTouchStart(this.eventHandlerData.handlers.touchStart);
_env__WEBPACK_IMPORTED_MODULE_0__["default"].onTouchMove(this.eventHandlerData.handlers.touchMove);
_env__WEBPACK_IMPORTED_MODULE_0__["default"].onTouchEnd(this.eventHandlerData.handlers.touchEnd);
_env__WEBPACK_IMPORTED_MODULE_0__["default"].onTouchCancel(this.eventHandlerData.handlers.touchCancel);
/**
* 当触发 touchstart 事件的时候,如果手指移除元素外,不会触发 touchend,这就导致 deactiveHandler 不能触发
* 要做到比较完善,事件系统要做较大改用,目前比较好的做法就是根节点在监听到 touchend 和 touchcancel 的时候兜底
* 触发下 deactiveHandler
*/
this.on('touchend', function () {
_this.activeElements.forEach(function (ele) {
ele.deactiveHandler();
});
_this.activeElements = [];
});
this.on('touchcancel', function () {
_this.activeElements.forEach(function (ele) {
ele.deactiveHandler();
});
_this.activeElements = [];
});
};
/**
* 全局事件解绑
*/
Layout.prototype.unBindEvents = function () {
_env__WEBPACK_IMPORTED_MODULE_0__["default"].offTouchStart(this.eventHandlerData.handlers.touchStart);
_env__WEBPACK_IMPORTED_MODULE_0__["default"].offTouchMove(this.eventHandlerData.handlers.touchMove);
_env__WEBPACK_IMPORTED_MODULE_0__["default"].offTouchEnd(this.eventHandlerData.handlers.touchEnd);
_env__WEBPACK_IMPORTED_MODULE_0__["default"].offTouchCancel(this.eventHandlerData.handlers.touchCancel);
this.eventHandlerData.hasEventBind = false;
};
Layout.prototype.emit = function (event, data) {
EE.emit(event, data);
};
Layout.prototype.on = function (event, callback) {
EE.on(event, callback);
};
Layout.prototype.once = function (event, callback) {
EE.once(event, callback);
};
Layout.prototype.off = function (event, callback) {
EE.off(event, callback);
};
Layout.prototype.destroyAll = function (tree) {
var _this = this;
var children = tree.children;
children.forEach(function (child) {
child.destroy();
_this.destroyAll(child);
child.destroySelf && child.destroySelf();
});
};
/**
* 清理画布,之前的计算出来的渲染树也会一并清理,此时可以再次执行init和layout方法渲染界面。
*/
Layout.prototype.clear = function (options) {
if (options === void 0) { options = {}; }
var _a = options.removeTicker, removeTicker = _a === void 0 ? true : _a;
debugInfo.reset();
this.destroyAll(this);
// this.elementTree = null;
this.children = [];
this.state = _common_util__WEBPACK_IMPORTED_MODULE_5__.STATE.CLEAR;
this.isDirty = false;
(0,_common_util__WEBPACK_IMPORTED_MODULE_5__.clearCanvas)(this.renderContext);
this.eleCount = 0;
this.unBindEvents();
if (removeTicker) {
this.ticker.remove();
this.ticker.stop();
}
else {
// inner的应该默认都移除,否则前后两次初始化会导致前后状态有问题
this.ticker.removeInner();
}
this.activeElements = [];
};
Layout.prototype.clearPool = function () {
imgPool.clear();
};
/**
* 比起 Layout.clear 更彻底的清理,会清空图片对象池,减少内存占用。
*/
Layout.prototype.clearAll = function () {
this.clear();
this.clearPool();
};
/**
* 对于图片资源,如果不提前加载,渲染过程中可能出现挨个出现图片效果,影响体验
* 通过Layout.loadImgs可以预加载图片资源,在调用Layout.layout的时候渲染性能更好,体验更佳。
*/
Layout.prototype.loadImgs = function (arr) {
if (arr === void 0) { arr = []; }
return Promise.all(arr.map(function (src) { return _common_imageManager__WEBPACK_IMPORTED_MODULE_12__["default"].loadImagePromise(src); }));
};
/**
* 注册 bitmaptext 可用的字体。
*/
Layout.prototype.registBitMapFont = function (name, src, config) {
if (!bitMapPool.get(name)) {
var font = new _common_bitMapFont__WEBPACK_IMPORTED_MODULE_7__["default"](name, src, config);
this.bitMapFonts.push(font);
bitMapPool.set(name, font);
}
};
/**
* 创建节点,创建之后会返回Element列表,可以传入parent立刻插入节点,也可以稍后主动appendChild到需要的节点下
*/
Layout.prototype.insertElement = function (template, style, parent) {
var elementArray = this.insertElementArray(template, style);
elementArray.forEach(function (it) {
(0,_common_vd__WEBPACK_IMPORTED_MODULE_10__.iterateTree)(it, function (element) { return element.observeStyleAndEvent(); });
if (parent) {
parent.appendChild(it);
}
});
return elementArray;
};
/**
* 克隆节点,克隆后的节点可以添加到 Layout 的某个节点中
* 该方法可以在数据有变化的时候避免重新执行 Layout.init 流程。
*/
Layout.prototype.cloneNode = function (element, deep) {
if (deep === void 0) { deep = true; }
return (0,_common_vd__WEBPACK_IMPORTED_MODULE_10__.clone)(this, element, deep);
};
/**
* 安装给定的插件
*/
Layout.prototype.use = function (plugin) {
var options = [];
for (var _i = 1; _i < arguments.length; _i++) {
options[_i - 1] = arguments[_i];
}
if (Layout.installedPlugins.includes(plugin)) {
console.warn('[Layout] 该插件已安装.');
return;
}
plugin.install.apply(plugin, __spreadArray([this], options, false));
Layout.installedPlugins.push(plugin);
// console.log(`[Layout] 插件 ${plugin.name || ''} 已安装`)
};
/**
* 卸载给定插件
*/
Layout.prototype.unUse = function (plugin) {
var options = [];
for (var _i = 1; _i < arguments.length; _i++) {
options[_i - 1] = arguments[_i];
}
var pluginIndex = Layout.installedPlugins.indexOf(plugin);
if (pluginIndex === -1) {
console.warn('[Layout] This plugin is not installed.');
return;
}
if (plugin.uninstall) {
plugin.uninstall.apply(plugin, __spreadArray([this], options, false));
}
// console.log(`[Layout] 插件 ${plugin.name || ''} 已卸载`)
Layout.installedPlugins.splice(pluginIndex, 1);
};
/**
* 创建节点,创建之后会返回Element列表
*/
Layout.prototype.insertElementArray = function (template, style, attrValueProcessor, onlyFirst) {
var _this = this;
// 样式表存到全局
this.styleSheet = Object.assign(this.styleSheet, style);
var parseConfig = {
attributeNamePrefix: '',
attrNodeName: 'attr', // default is 'false'
textNodeName: '#text',
ignoreAttributes: false,
ignoreNameSpace: true,
allowBooleanAttributes: true,
parseNodeValue: false,
parseAttributeValue: false,
trimValues: true,
parseTrueNumberOnly: false,
alwaysCreateTextNode: true,
};
if (attrValueProcessor && typeof attrValueProcessor === 'function') {
// @ts-ignore
parseConfig.attrValueProcessor = attrValueProcessor;
}
debugInfo.start('insert_xmlParse');
// 将xml字符串解析成xml节点树
var jsonObj = _libs_fast_xml_parser_parser_js__WEBPACK_IMPORTED_MODULE_6__.parse(template, parseConfig, true);
// console.log(jsonObj)
debugInfo.end('insert_xmlParse');
var getElements = [];
jsonObj.children.forEach(function (xmlTree, index) {
if (onlyFirst && index > 0) {
return;
}
// XML树生成渲染树
debugInfo.start('insert_xml2Layout');
var layoutTree = _common_vd__WEBPACK_IMPORTED_MODULE_10__.create.call(_this, xmlTree, _this.styleSheet);
debugInfo.end('insert_xml2Layout');
getElements.push(layoutTree);
});
return getElements;
};
Layout.installedPlugins = [];
return Layout;
}(_components_elements__WEBPACK_IMPORTED_MODULE_1__["default"]));
var layout = new Layout({
style: {
width: 0,
height: 0,
},
name: 'layout',
});
})();
module.exports = __webpack_exports__;
/******/ })()
;