Commit 14ed7b3c authored by wangjianfeng.yz's avatar wangjianfeng.yz

2.0.65

parent 207a7bf0
......@@ -19,4 +19,5 @@ examples
docs
adapters
testThree
README.md
\ No newline at end of file
README.md
abandoned
\ No newline at end of file
import { ScrollPage } from "./ScrollPage";
import { DisplayObject } from "../display/DisplayObject";
import { Event } from "../events/Event";
/**
* 滚动类的Item类接口
* @class IScrollListItem
* @public
* @extends DisplayObject
* @since 1.0.9
*/
export interface IScrollListItem extends DisplayObject {
initData(id: number, data: any): void;
id: number;
data: number;
}
/**
* 滚动列表
* @class ScrollList
* @public
* @extends ScrollPage
* @since 1.0.9
*/
export class ScrollList extends ScrollPage {
private _items: Array<IScrollListItem> = null;
private _itemW: number;
private _itemH: number;
private _itemRow: number;
private _itemCol: number;
private _itemCount: number;
private _itemClass: any;
private _isInit: number = 0;
public data: Array<any> = [];
private downL: DisplayObject = null;
private _cols: number;
private _disParam: string;
private _lastFirstId: number = -1;
/**
* 获取下拉滚动的loadingView对象
* @property loadingView
* @since 1.0.9
* @return {DisplayObject}
*/
public get loadingView(): DisplayObject {
return this.downL;
}
/**
* 构造函数
* @method ScrollList
* @param {Class} itemClassName 可以做为Item的类
* @param {number} itemWidth item宽
* @param {number} itemHeight item高
* @param {number} vW 列表的宽
* @param {number} vH 列表的高
* @param {boolean} isVertical 是横向滚动还是纵向滚动 默认是纵向
* @param {number} cols 分几列,默认是1列
* @since 1.0.9
*/
constructor(itemClassName: any, itemWidth: number, itemHeight: number, vW: number, vH: number, isVertical: boolean = true, cols: number = 1) {
super(vW, vH, 0, isVertical);
let s = this;
s._instanceType = "ScrollList";
s._itemW = itemWidth;
s._itemH = itemHeight;
s._items = [];
s._itemClass = itemClassName;
s._itemCount = 0;
s._cols = cols;
s._updateViewRect();
s.addEventListener(Event.ENTER_FRAME, s.flushData.bind(s));
}
/**
* 更新列表数据
* @method updateData
* @param {Array} data
* @param {boolean} isReset 是否重围数据列表。默认为true
* @since 1.0.9
*/
public updateData(data: Array<any>, isReset: boolean = true): void {
let s: any = this;
if (!s._isInit || isReset) {
s.data = data;
} else {
s.data = s.data.concat(data);
}
s._isInit = 1;
s._lastFirstId = -1;
s._updateId = -1;//确保会刷新
s.maxDistance = Math.ceil(s.data.length / s._cols) * s._itemRow;
if (s.downL) {
s.downL[s.paramXY] = Math.max(s.distance, s.maxDistance);
var wh = s.downL.getWH();
s.maxDistance += (s.paramXY == "x" ? wh.width : wh.height);
}
}
private _updateId: number = -1;
private flushData() {
let s: ScrollList = this;
if (s._isInit > 0) {
if (s._updateId != s.view.transform._localID) {
s._updateId = s.view.transform._localID
let id: number = s.view[s.paramXY] > 0 ? 0 : (Math.abs(Math.floor(s.view[s.paramXY] / s._itemRow)) - 1) * s._cols;
id = id < 0 ? 0 : id;
if (id != s._lastFirstId) {
s._lastFirstId = id;
if (id != s._items[0].id) {
for (let r = 0; r < s._cols; r++) {
if (s.speed > 0) {
s._items.unshift(s._items.pop());
} else {
s._items.push(s._items.shift());
}
}
}
}
for (let i = 0; i < s._itemCount; i++) {
let item: any = s._items[i];
if (s._isInit == 1) {
item.sli_id = -1;
}
if (item.sli_id != id) {
item.initData(s.data[id] ? id : -1, s.data[id]);
item[s.paramXY] = Math.floor(id / s._cols) * s._itemRow;
item[s._disParam] = (id % s._cols) * s._itemCol;
//如果没有数据则隐藏
if (s.data[id]) {
item.sli_id = id;
item.visible = true;
} else {
item.sli_id = -1;
item.visible = false;
}
}
id++;
}
s._isInit = 2;
}
}
}
/**
* 设置可见区域,可见区域的坐标始终在本地坐标中0,0点位置
* @method setViewRect
* @param {number}w 设置可见区域的宽
* @param {number}h 设置可见区域的高
* @param {boolean} isVertical 方向
* @public
* @since 1.1.1
*/
public setViewRect(w: number, h: number, isVertical: boolean): void {
super.setViewRect(w, h, isVertical);
let s = this;
if (s._itemRow && s._itemCol) {
s._updateViewRect();
}
}
private _updateViewRect() {
let s: any = this;
if (s.isVertical) {
s._disParam = "x";
s._itemRow = s._itemH;
s._itemCol = s._itemW;
} else {
s._disParam = "y";
s._itemRow = s._itemW;
s._itemCol = s._itemH;
}
let newCount: number = (Math.ceil(s.distance / s._itemRow) + 1) * s._cols;
if (newCount != s._itemCount) {
if (newCount > s._itemCount) {
for (let i = s._itemCount; i < newCount; i++) {
let item = new s._itemClass();
item.id = -1;
item.data = null;
s._items.push(item);
s.view.addChild(item);
}
} else {
for (let i = 0; i < s._itemCount - newCount; i++) {
s.view.removeChild(s._items.pop());
}
}
s._itemCount = newCount;
s._lastFirstId = -1;
}
}
/**
* 设置加载数据时显示的loading对象
* @since 1.0.9
* @method setLoading
* @param {DisplayObject} downLoading
*/
public setLoading(downLoading: DisplayObject): void {
let s: any = this;
if (s.downL) {
s.view.removeChild(s.downL);
let wh = s.downL.getWH();
s.maxDistance -= (s.paramXY == "x" ? wh.width : wh.height);
s.downL = null;
}
if (downLoading) {
s.downL = downLoading;
s.view.addChild(downLoading);
s.downL[s.paramXY] = Math.max(s.distance, s.maxDistance);
let wh = s.downL.getWH();
s.maxDistance += (s.paramXY == "x" ? wh.width : wh.height);
} else {
s.isStop = false;
}
}
public destroy(): void {
let s = this;
s._items = null;
s._itemClass = null;
s.data = null;
s.downL = null;
super.destroy();
}
}
/**
* @module annieUI
*/
namespace annieUI {
/**
* 滚动视图,有些时候你的内容超过了一屏,需要上下或者左右滑动来查看内容,这个时候,你就应该用它了
* @class annieUI.Scroller
* @public
* @extends annie.AObject
* @since 3.1.0
*/
export class Scroller extends annie.EventDispatcher {
//Event
/**
* annieUI.Scroller 组件滑动到开始位置事件
* @event annie.Event.ON_SCROLL_ING
* @since 3.1.0
*/
/**
* annieUI.Scroller 组件滑动到开始位置事件
* @event annie.Event.ON_SCROLL_TO_HEAD
* @since 3.1.5
*/
/**
* annieUI.Scroller 组件停止滑动事件
* @event annie.Event.ON_SCROLL_STOP
* @since 3.1.5
*/
/**
* annieUI.Scroller 组件开始滑动事件
* @event annie.Event.ON_SCROLL_START
* @since 3.1.5
*/
/**
* annieUI.Scroller 组件滑动到结束位置事件
* @event annie.Event.ON_SCROLL_TO_END
* @since 3.1.5
*/
protected _container: annie.DisplayObject;
/**
* 是否纵向滚动
* @property isScrollY
* @type {boolean}
* @public
* @since 3.1.5
* @default true;
*/
public isScrollY: boolean = true;
/**
* 是否横向滚动
* @property isScrollX
* @type {boolean}
* @since 3.1.5
* @public
* @default true;
*/
public isScrollX: boolean = true;
/**
* 是否松开鼠标后让其自由缓冲滑动
* @property isMomentum
* @type {boolean}
* @since 3.1.5
* @public
* @default true;
*/
public isMomentum: boolean = true;
/**
* 是否滑到边界后有回弹效果
* @property isBounce
* @type {boolean}
* @since 3.1.5
* @public
* @default true;
*/
public isBounce: boolean = true;
/**
* 回弹的动效时长,单位:ms
* @property bounceTime
* @type {number}
* @public
* @since 3.1.5
* @default 300
*/
public bounceTime: number = 300;
/**
* 是否需要横向纵向保护,有些时候你想纵向滑动,但鼠标也轻微的左右飘了,如果不lock刚好左右滑动也被允许的话,则左右也会滑动,横向滑动则相反。
* 如果想鼠标不那么灵敏的话,可以加上一把锁,这样左右滑的时候上下不会滑,上下滑的时候左右不会滑
* @property isLocked
* @type {boolean}
* @public
* @since 3.1.5
* @default 300
*/
public isLocked: boolean = true;
/**
* 锁的像素范围
* @property lockDis
* @type {number}
* @since 3.1.5
* @public
* @default 5
*/
public lockDis: number = 5;
/**
* 当前滑动的x坐标 更改此参数则需要调用resetPosition()方法生效
* @property curX
* @type {number}
* @since 3.1.5
* @default 0
*/
public get curX(): number {
return this._curX;
}
protected _curX: number = 0;
/**
* 当前滑动的y坐标 更改此参数则需要调用resetPosition()方法生效
* @property curY
* @type {number}
* @since 3.1.5
* @default 0
*/
public get curY(): number {
return this._curY;
}
protected _curY: number = 0;
/**
* 当前显示范围的宽
* @property viewWidth
* @type {number}
* @since 3.1.5
* @default 0
* @readonly
*/
public get viewWidth(): number {
return this._viewWidth;
}
public _viewWidth: number = 0;
/**
* 当前显示范围的高
* @property viewHeight
* @type {number}
* @since 3.1.5
* @default 0
* @readonly
*/
public get viewHeight(): number {
return this._viewHeight;
}
public _viewHeight: number = 0;
/**
* 当前横向的滑动范围
* @property scrollWidth
* @type {number}
* @since 3.1.5
* @default 0
* @readonly
*/
public get scrollWidth(): number {
return this._scrollWidth;
}
public _scrollWidth: number = 0;
/**
* 当前纵向的滑动范围
* @property scrollHeight
* @type {number}
* @since 3.1.5
* @default 0
* @readonly
*/
public get scrollHeight(): number {
return this._scrollHeight;
}
public _scrollHeight: number = 0;
/**
* 是否正在滑动中
* @property isRunning
* @type {boolean}
* @since 3.1.5
* @default false
*/
public isRunning: boolean;
private startX: number = 0;
private startY: number = 0;
private maxScrollX: number = 0;
private maxScrollY: number = 0;
private endTime: number = 0;
private mouseStatus: number = 0;
private distX: number = 0;
private distY: number = 0;
private startTime: number = 0;
private pointX: number = 0;
private pointY: number = 0;
/**
* 滑动衰减系数,值越大衰减越快
* @property deceleration
* @type {number}
* @public
* @since 3.2.1
* @default 0.0006
*/
public deceleration: number = 0.0006;
private destTime: number = 0;
private destX: number = 0;
private destY: number = 0;
public duration: number = 0;
private easingFn: Function;
/**
* 初始化
* @method Scroller
* @param {annie.MovieClip} container
* @param {number} viewWidth
* @param {number} viewHeight
* @param {number} scrollWidth
* @param {number} scrollHeight
*/
constructor(container: annie.DisplayObject, viewWidth: number, viewHeight: number, scrollWidth: number, scrollHeight: number) {
super();
let s = this;
s._instanceType = "annieUI.Scroller";
s._mouseEvent = s.onMouseEvent.bind(s);
s._enterFrame = s.onEnterFrame.bind(s);
s.init(container, viewWidth, viewHeight, scrollWidth, scrollHeight);
}
/**
* 初始化,也可以反复调用此方法重用scroller
* @method init
* @param {annie.MovieClip} container
* @param {number} viewWidth
* @param {number} viewHeight
* @param {number} scrollWidth
* @param {number} scrollHeight
* @public
* @since 3.1.5
*/
public init(container: annie.DisplayObject, viewWidth: number, viewHeight: number, scrollWidth: number, scrollHeight: number) {
let s = this;
if (s._container && s._container != container) {
//移除
s._container.removeEventListener(annie.MouseEvent.MOUSE_DOWN, s._mouseEvent, false);
s._container.removeEventListener(annie.MouseEvent.MOUSE_MOVE, s._mouseEvent, false);
s._container.removeEventListener(annie.MouseEvent.MOUSE_UP, s._mouseEvent, false);
//这里不要加false
s._container.removeEventListener(annie.MouseEvent.MOUSE_OUT, s._mouseEvent);
s._container.removeEventListener(annie.Event.ENTER_FRAME, s._enterFrame);
}
if (s._container != container) {
s._container = container;
container.addEventListener(annie.MouseEvent.MOUSE_DOWN, s._mouseEvent, false);
container.addEventListener(annie.MouseEvent.MOUSE_MOVE, s._mouseEvent, false);
container.addEventListener(annie.MouseEvent.MOUSE_UP, s._mouseEvent, false);
//这里不要加false
container.addEventListener(annie.MouseEvent.MOUSE_OUT, s._mouseEvent);
container.addEventListener(annie.Event.ENTER_FRAME, s._enterFrame);
}
s.isRunning = false;
s.endTime = 0;
s.setViewWHAndScrollWH(viewWidth, viewHeight, scrollWidth, scrollHeight);
}
/**
* 当更改了viewWidth,viewHeight其中一个或两个同时也更改了scrollWidth,scrollHeight其中的一个或者两个
* 需要调用此方法重置,如果只是单方面更改了viewWidth,viewHeight其中一个或两个,则可以调用setViewWH()
* 如果只是更改了scrollWidth,scrollHeight其中的一个或者两个,则可以调用setScrollWH()
* @method setViewWHAndScrollWH
* @public
* @since 3.1.5
* @param {number} viewWidth
* @param {number} viewHeight
* @param {number} scrollWidth
* @param {number} scrollHeight
*/
public setViewWHAndScrollWH(viewWidth: number, viewHeight: number, scrollWidth: number, scrollHeight: number): void {
let s = this;
s._viewHeight = viewHeight;
s._viewWidth = viewWidth;
s._scrollWidth = scrollWidth;
s._scrollHeight = scrollHeight;
s._updateViewAndScroll();
}
/**
* 当更改了viewWidth,viewHeight其中一个或两个,需要调用此方法重置.
* @method setViewWH
* @public
* @since 3.1.5
* @param {number} viewWidth
* @param {number} viewHeight
*/
public setViewWH(viewWidth: number, viewHeight: number) {
let s = this;
s._viewHeight = viewHeight;
s._viewWidth = viewWidth;
s._updateViewAndScroll();
}
/**
* 当更改了scrollWidth,scrollHeight其中的一个或者两个,需要调用此方法重置.
* @method setScrollWH
* @public
* @since 3.1.5
* @param {number} scrollWidth
* @param {number} scrollHeight
*/
public setScrollWH(scrollWidth: number, scrollHeight: number) {
let s = this;
s._scrollWidth = scrollWidth;
s._scrollHeight = scrollHeight;
s._updateViewAndScroll();
}
public _updateViewAndScroll() {
let s = this;
s.maxScrollX = s.viewWidth - s.scrollWidth;
s.maxScrollY = s.viewHeight - s.scrollHeight;
if (s.maxScrollX > 0) {
s.maxScrollX = 0;
}
if (s.maxScrollY > 0) {
s.maxScrollY = 0;
}
if (!s.isScrollX) {
s.maxScrollX = 0;
s._scrollWidth = s.viewWidth;
}
if (!s.isScrollY) {
s.maxScrollY = 0;
s._scrollHeight = s.viewHeight;
}
s.resetPosition(200);
}
private _mouseEvent: Function = null;
private _enterFrame: Function = null;
protected onEnterFrame(e: annie.Event){
let s = this;
if (s.isRunning) {
let now = Date.now(),
newX:number, newY:number,
easing:number;
if (now >= s.destTime) {
s.isRunning = false;
s._translate(s.destX, s.destY);
if (!s.resetPosition(s.bounceTime)) {
s.dispatchEvent(annie.Event.ON_SCROLL_STOP);
//有可能内容区域没有滑动区域宽,这两个事件会同时触发,既滑到了头也滑到了尾,所以两个if不用else连接起来
if (s._curX == 0 && s._curY == 0) {
s.dispatchEvent(annie.Event.ON_SCROLL_TO_HEAD);
}
if (s._curX == s.maxScrollX && s._curY == s.maxScrollY) {
s.dispatchEvent(annie.Event.ON_SCROLL_TO_END);
}
}
} else {
now = (now - s.startTime) / s.duration;
easing = s.easingFn(now);
newX = (s.destX - s.startX) * easing + s.startX;
newY = (s.destY - s.startY) * easing + s.startY;
s._translate(newX, newY);
}
}
}
private onMouseEvent(e: annie.MouseEvent): void {
let s = this;
if (e.type == annie.MouseEvent.MOUSE_DOWN) {
s.isRunning = false;
s.mouseStatus = 1;
s.distX = 0;
s.distY = 0;
s.startTime = Date.now();
s.startX = s._curX;
s.startY = s._curY;
s.pointX = e.localX;
s.pointY = e.localY;
} else if (e.type == annie.MouseEvent.MOUSE_MOVE) {
if (s.mouseStatus < 1) {
return;
}
let deltaX = e.localX - s.pointX,
deltaY = e.localY - s.pointY,
timestamp = Date.now(),
newX:number, newY:number,
absDistX:number, absDistY:number;
s.pointX = e.localX;
s.pointY = e.localY;
s.distX += deltaX;
s.distY += deltaY;
absDistX = Math.abs(s.distX);
absDistY = Math.abs(s.distY);
if (timestamp - s.endTime > 300 && (absDistX < 10 && absDistY < 10)) {
return;
}
if (s.isLocked) {
if (absDistX > absDistY + s.lockDis) {
deltaY = 0;
} else if (absDistY >= absDistX + s.lockDis) {
deltaX = 0;
}
}
deltaX = s.isScrollX ? deltaX : 0;
deltaY = s.isScrollY ? deltaY : 0;
newX = s._curX + deltaX;
newY = s._curY + deltaY;
if (newX > 0 || newX < s.maxScrollX) {
newX = s.isBounce ? s._curX + deltaX / 3 : newX > 0 ? 0 : s.maxScrollX;
}
if (newY > 0 || newY < s.maxScrollY) {
newY = s.isBounce ? s._curY + deltaY / 3 : newY > 0 ? 0 : s.maxScrollY;
}
if (s.mouseStatus == 1) {
s.dispatchEvent(annie.Event.ON_SCROLL_START);
}
s.mouseStatus = 2;
s._translate(newX, newY);
if (timestamp - s.startTime > 300) {
s.startTime = timestamp;
s.startX = s._curX;
s.startY = s._curY;
}
} else {
s.endTime = Date.now();
let momentumX: any,
momentumY: any,
duration: number = s.endTime - s.startTime,
newX: number = s._curX,
newY: number = s._curY,
time: number = 0,
easing: Function = null;
if (s.resetPosition(s.bounceTime)) {
s.mouseStatus = 0;
return;
}
if (s.mouseStatus != 2) {
s.mouseStatus = 0;
return;
}
s.mouseStatus = 0;
s.scrollTo(newX, newY);
if (s.isMomentum && duration < 300) {
momentumX = s.isScrollX ? Scroller.toMomentum(s._curX, s.startX, duration, s.maxScrollX, s.isBounce ? s.viewWidth / 2 : 0, s.deceleration) : {
destination: newX,
duration: 0
};
momentumY = s.isScrollY ? Scroller.toMomentum(s._curY, s.startY, duration, s.maxScrollY, s.isBounce ? s.viewHeight / 2 : 0, s.deceleration) : {
destination: newY,
duration: 0
};
newX = momentumX.destination;
newY = momentumY.destination;
time = Math.max(momentumX.duration, momentumY.duration);
}
if (newX != s._curX || newY != s._curY) {
if (newX > 0 || newX < s.maxScrollX || newY > 0 || newY < s.maxScrollY) {
easing = annie.Tween.quadraticOut;
}
s.scrollTo(newX, newY, time, easing);
return;
}
s.dispatchEvent(annie.Event.ON_SCROLL_STOP);
}
}
public destroy(): void {
let s = this;
if (s._container) {
s._container.removeEventListener(annie.MouseEvent.MOUSE_MOVE, s._mouseEvent, false);
s._container.removeEventListener(annie.MouseEvent.MOUSE_DOWN, s._mouseEvent, false);
s._container.removeEventListener(annie.MouseEvent.MOUSE_UP, s._mouseEvent, false);
s._container.removeEventListener(annie.MouseEvent.MOUSE_OUT, s._mouseEvent);
s._container.removeEventListener(annie.Event.ENTER_FRAME, s._enterFrame);
}
s._container = null;
s.easingFn = null;
super.destroy();
}
public resetPosition(time: number = 0): boolean {
let s = this;
let x = s._curX,
y = s._curY;
time = time || 0;
if (!s.isScrollX || s._curX > 0) {
x = 0;
} else if (s._curX < s.maxScrollX) {
x = s.maxScrollX;
}
if (!s.isScrollY || s._curY > 0) {
y = 0;
} else if (s._curY < s.maxScrollY) {
y = s.maxScrollY;
}
if (x == s._curX && y == s._curY) {
return false;
}
s.scrollTo(x, y, time, null);
return true;
}
/**
* 从设置的x,y坐标滑过来。 注意x y位置是负数,想想为什么
* @method scrollBy
* @param {number} x 从哪个x坐标滑过来
* @param {number} y 从哪个y坐标滑过来
* @param {number} time 滑动时长 ms,0的话没效果直接跳
* @param {Function} easing annie.Tween中指定的缓存方法
* @public
* @since 3.1.5
*/
public scrollBy(x: number, y: number, time: number = 0, easing: Function = null) {
let s = this;
x = s._curX + x;
y = s._curY + y;
time = time || 0;
s.scrollTo(x, y, time, easing);
}
/**
* 滑动到设置的x,y坐标。 注意x y位置是负数,想想为什么
* @method scrollTo
* @param {number} x 要滑去的x坐标
* @param {number} y 要滑去的y坐标
* @param {number} time 滑动时长 ms,0的话没效果直接跳
* @param {Function} easing annie.Tween中指定的缓存方法
* @public
* @since 3.1.5
*/
public scrollTo(x: number, y: number, time: number = 0, easing: Function = null) {
let s = this;
if(isNaN(x)||isNaN(y)) {
return;
}
if (!time) {
s._translate(x, y);
} else {
easing = easing || annie.Tween.circularOut;
s.startX = s._curX;
s.startY = s._curY;
s.startTime = Date.now();
s.destTime = s.startTime + time;
s.destX = x;
s.destY = y;
s.duration = time;
s.easingFn = easing;
s.isRunning = true;
}
}
public _translate(x: number, y: number) {
let s = this;
if(this.isScrollX) {
s._curX = x;
}
if(this.isScrollY){
s._curY = y;
}
s.dispatchEvent(annie.Event.ON_SCROLL_ING, {posX: s._curX, posY: s._curY});
}
private static toMomentum(current: number, start: number, time: number, lowerMargin: number, wrapperSize: number, deceleration: number) {
let distance = current - start,
speed = Math.abs(distance) / time,
destination:number,
duration:number;
deceleration = deceleration === undefined ? 0.0006 : deceleration;
destination = current + (speed * speed) / (2 * deceleration) * (distance < 0 ? -1 : 1);
duration = speed / deceleration;
if (destination < lowerMargin) {
destination = wrapperSize ? lowerMargin - (wrapperSize / 2.5 * (speed / 8)) : lowerMargin;
distance = Math.abs(destination - current);
duration = distance / speed;
} else if (destination > 0) {
destination = wrapperSize ? wrapperSize / 2.5 * (speed / 8) : 0;
distance = Math.abs(current) + destination;
duration = distance / speed;
}
return {
destination: destination,
duration: duration
};
};
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
declare namespace FYGE{export const VERSION = "2.0.63";
declare namespace FYGE{export const VERSION = "2.0.65";
export function cos(angle: number): number;
......@@ -177,7 +177,7 @@ export class Event extends HashObject {
*/
static RESIZE: string;
/**
* ScrollPage组件滑动到开始位置事件
* Scroll组件滑动到开始位置事件
* @property SCROLL_TO_HEAD
* @static
* @since 1.1.0
......@@ -185,7 +185,7 @@ export class Event extends HashObject {
*/
static SCROLL_TO_HEAD: string;
/**
* ScrollPage组件停止滑动事件
* Scroll组件停止滑动事件
* @property SCROLL_STOP
* @static
* @since 1.1.0
......@@ -193,7 +193,7 @@ export class Event extends HashObject {
*/
static SCROLL_STOP: string;
/**
* ScrollPage组件开始滑动事件
* Scroll组件开始滑动事件
* @property SCROLL_START
* @static
* @since 1.1.0
......@@ -201,13 +201,17 @@ export class Event extends HashObject {
*/
static SCROLL_START: string;
/**
* ScrollPage组件滑动到结束位置事件
* Scroll组件滑动到结束位置事件
* @property SCROLL_TO_END
* @static
* @since 1.1.0
* @type {string}
*/
static SCROLL_TO_END: string;
/**
* Scroll组件滚动时触发
*/
static SCROLLING: string;
/**
* 舞台初始化完成后会触发的事件
* @property INIT_STAGE
......@@ -6227,11 +6231,6 @@ export class Container extends DisplayObject {
*/
containerUpdateTransform: any;
constructor();
/**
* children改变时触发,暂时没地方用到,考虑废弃
* @param {number} index
*/
onChildrenChange(index: number): void;
/**
* 添加child,在所有子级的最上层
* @param {DisplayObject} child
......@@ -6275,18 +6274,23 @@ export class Container extends DisplayObject {
*/
getChildAt(index: number): DisplayObject;
/**
* 通过名字获取子级
* @param name
* @param isOnlyOne
* @param isRecursive
* 通过名字获取一个子级,找到一个符合的就返回
* @param name 名字或正则
* @param isRecursive 是否递归往子级查找,默认false
*/
getChildByName(name: string | RegExp, isOnlyOne?: boolean, isRecursive?: boolean): any;
getChildByName(name: string | RegExp, isRecursive?: boolean): DisplayObject;
/**
* 通过名字获取子级数组
* @param name 名字或正则
* @param isRecursive 是否递归往子级查找,默认false
*/
getChildrenByName(name: string | RegExp, isRecursive?: boolean): DisplayObject[];
/**
* 移除child
* @param {DisplayObject} child
* @return {DisplayObject}
*/
removeChild(child: DisplayObject): DisplayObject;
removeChild<T extends DisplayObject>(child: T): T;
/**
* 在index索引处移除子级对象
* @param {number} index
......@@ -6302,7 +6306,7 @@ export class Container extends DisplayObject {
* 移除所有子级
* @returns 返回移除的子级的数组
*/
removeAllChildren<T extends DisplayObject>(): T[];
removeAllChildren(): DisplayObject[];
/**
* 通过索引批量移除child
* @param {number} [beginIndex=0] 开始索引,包括自己
......@@ -6315,7 +6319,7 @@ export class Container extends DisplayObject {
* @param beginIndex 开始索引
* @param count 移除数量
*/
spliceChildren<T extends DisplayObject>(beginIndex?: number, count?: number): T[];
spliceChildren(beginIndex?: number, count?: number): DisplayObject[];
/**
* 更新矩阵
*/
......@@ -6403,6 +6407,10 @@ export class Container extends DisplayObject {
* @static
*/
private static _getElementsByName;
/**
* 操作子级的所有方法,需要维护
*/
static _childrenOperationMethods: string[];
}
export class FloatDisplay extends DisplayObject {
......@@ -8682,13 +8690,225 @@ export class ScrollPage extends Container {
destroy(): void;
}
export interface IScrollListItem extends DisplayObject {
initData(id: number, data: any): void;
id: number;
data: number;
export class ScrollView extends Container {
protected _scrollWidth: number;
/**
* 滚动宽度
* 设置0表示不让滚动
*/
get scrollWidth(): number;
set scrollWidth(v: number);
protected _scrollHeight: number;
/**
* 滚动高度
* 设置0表示不让滚动
*/
get scrollHeight(): number;
set scrollHeight(v: number);
/**
* 最大滚动坐标x,为负
*/
private get maxScrollX();
/**
* 最大滚动坐标y,为负
*/
private get maxScrollY();
protected _content: Container;
/**
* 滚动内容的节点容器
* 注意滚动内容都往这上面加
*/
get view(): Container;
/**
* 可见区域的宽
* @property viewWidth
* @type {number}
* @protected
* @since 1.0.0
* @default 0
*/
protected viewWidth: number;
/**
* 可见区域的高
* @property viewHeight
* @type {number}
* @protected
* @since 1.0.0
* @default 0
*/
protected viewHeight: number;
/**
* 遮罩对象
* @property maskObj
* @since 1.0.0
* @private
* @type {Graphics}
*/
private maskObj;
private downX;
private downY;
private distX;
private distY;
private startX;
private startY;
private destX;
private destY;
private isRunning;
private startTime;
private destTime;
private duration;
private easeFn;
private static weight;
private velocitys;
private lastTouchTime;
/**
* 手指拖动超过边界时是否允许回弹。默认true
*/
isBounce: boolean;
/**
* 回弹时间,视图内容在不合理的位置时恢复的时间,比如超过边界时
*/
bounceTime: number;
/**
* 手指抬起后是否存在惯性。默认true
*/
hasMomentum: boolean;
/**
* 惯性的阻尼
*/
damping: number;
/**
* 0无交互状态
* 1点击状态
* 2移动状态
*/
private mouseStatus;
/**
* 注意滚动内容在view里加
* @method ScrollPage
* @param {number} vW 可视区域宽
* @param {number} vH 可视区域高
* @param {number} sW 最大横向滚动距离
* @param {number} sH 最大纵向滚动距离
* @param {boolean} isFullScreen 是否全屏
* @example
* var scroll=new ScrollView(750,1000,0,2000);
* stage.addChild(scroll);
* //加滚动内容
* scroll.view.addChild(new Sprite());
*/
constructor(vW: number, vH: number, sW: number, sH: number, isFullScreen?: boolean);
/**
* 设置可见区域,可见区域的坐标始终在本地坐标中0,0点位置
* @method setViewRect
* @param {number}w 设置可见区域的宽
* @param {number}h 设置可见区域的高
* @param {boolean} isVertical 方向
* @public
* @since 1.1.1
*/
setViewRect(w: number, h: number, isFull?: boolean): void;
private onMouseEvent;
private onEnterFrame;
private pushVelocitys;
/**
* 滚到指定的坐标位置
* @param {number} x 往左横向滚动距离,0到最大横向滚动距离
* @param {number} y 往上纵向滚动距离,0到最大纵向滚动距离
* @param {number} time 滚动需要的时间 默认为0 即没有缓动直接到达指定位置,毫秒计
* @param {Function} easeFn 缓动函数,不传默认用Ease.circOut,从快到慢
* @public
*/
scrollTo(x: number, y: number, time?: number, easeFn?: (t: number) => number): void;
/**
* 从当前位置继续滚动
* @param {number} x 往左滚动距离
* @param {number} y 往上滚动距离
* @param {number} time 滚动需要的时间 默认为0 即没有缓动直接到达指定位置,毫秒计
* @param {Function} easeFn 缓动函数,不传默认用Ease.circOut,从快到慢
* @public
*/
scrollBy(x: number, y: number, time?: number, easeFn?: (t: number) => number): void;
/**
* 真实的滚动,xy一般都是负数
* @param x
* @param y
* @param time
* @param easeFn 缓动函数,不传默认用Ease.circOut
* @returns
*/
private _scrollTo;
/**
* _content位置的改变都用这个方法
* @param x
* @param y
*/
private _translate;
/**
* 检查当前的位置是否合理,不合理会返回true,且滚动到对应位置
* @param time
* @returns
*/
protected checkPosition(time?: number): boolean;
/**
* 矫正坐标
* @param x
* @param y
* @returns
*/
private _modifyXY;
destroy(): void;
}
export interface IScrollData {
/**
* 横向滚动位置,通常为正
*/
x: number;
/**
* 纵向滚动位置,通常为正
*/
y: number;
/**
* 滚动横向距离,为正表示向左滚动
*/
deltaX?: number;
/**
* 滚动纵向距离,为正表示向上滚动
*/
deltaY?: number;
}
export interface ScrollEvent extends Event {
data: IScrollData;
}
export class ScrollList extends ScrollPage {
export class ScrollListItem extends Container {
data: any;
/**
* 列表滚动时各项item有数据变更时会触发
* @param data 参数会传入data,也可直接使用this.data
* @protected
*/
onDataChanged(data?: any): void;
}
export class ScrollList extends ScrollView {
private _data;
/**
* 数据列表,
*/
get data(): any[];
/**
* list里不允许改变滚动尺寸范围,只能通过数据改变
*/
get scrollWidth(): number;
set scrollWidth(v: number);
/**
* list里不允许改变滚动尺寸范围,只能通过数据改变
*/
get scrollHeight(): number;
set scrollHeight(v: number);
private _items;
private _itemW;
private _itemH;
......@@ -8697,40 +8917,31 @@ export class ScrollList extends ScrollPage {
private _itemCount;
private _itemClass;
private _isInit;
data: Array<any>;
private downL;
private _cols;
private _disParam;
private _lastFirstId;
/**
* 获取下拉滚动的loadingView对象
* @property loadingView
* @since 1.0.9
* @return {DisplayObject}
*/
get loadingView(): DisplayObject;
private _isVertical;
/**
* 构造函数
* @method ScrollList
* @param {Class} itemClassName 可以做为Item的类
* @param {Class} itemClass 可以做为Item的类,比如ScrollListItem,必须具备onDataChanged方法
* @param {number} itemWidth item宽
* @param {number} itemHeight item高
* @param {number} vW 列表的宽
* @param {number} vH 列表的高
* @param {boolean} isVertical 是横向滚动还是纵向滚动 默认是纵向
* @param {number} cols 分几列,默认是1列
* @since 1.0.9
* @since 2.0.0
*/
constructor(itemClassName: any, itemWidth: number, itemHeight: number, vW: number, vH: number, isVertical?: boolean, cols?: number);
constructor(itemClass: typeof ScrollListItem, itemWidth: number, itemHeight: number, vW: number, vH: number, isVertical?: boolean, cols?: number);
/**
* 更新列表数据
* @method updateData
* 设置列表数据
* @method setData
* @param {Array} data
* @param {boolean} isReset 是否重数据列表。默认为true
* @since 1.0.9
* @param {boolean} isReset 是否重数据列表。默认为true
* @since 2.0.0
*/
setData(data: Array<any>, isReset?: boolean): void;
updateData(data: Array<any>, isReset?: boolean): void;
private _updateId;
private flushData;
/**
* 设置可见区域,可见区域的坐标始终在本地坐标中0,0点位置
......@@ -8739,17 +8950,22 @@ export class ScrollList extends ScrollPage {
* @param {number}h 设置可见区域的高
* @param {boolean} isVertical 方向
* @public
* @since 1.1.1
* @since 2.0.0
*/
setViewRect(w: number, h: number, isVertical: boolean): void;
private _updateViewRect;
setViewRect(w: number, h: number, isVertical?: boolean): void;
private _updateRowCol;
/**
* 设置加载数据时显示的loading对象
* @since 1.0.9
* @method setLoading
* @param {DisplayObject} downLoading
* 滚动到指定位置
* @param distance 滚动距离,一般为正
* @param time 滚动时间,默认0
*/
setLoading(downLoading: DisplayObject): void;
scrollTo(distance: number, time?: number): void;
/**
* 从当前位置开始滚动
* @param distance 滚动距离,一般为正
* @param time 滚动时间,默认0
*/
scrollBy(distance: number, time?: number): void;
destroy(): void;
}
......@@ -10524,6 +10740,21 @@ export class Object3D extends EventDispatcher {
private _onDispatchBubbledEvent;
clone(recursive?: boolean): Object3D;
copy(source: Object3D, recursive?: boolean): this;
/**
* 设置物体朝向
* @param vec3 一个存在x,y,z的矢量,比如mesh.position
*/
lookAt(vec3: {
x: number;
y: number;
z: number;
}): void;
/**
* 设置物体朝向
* @param x 朝向位置x
* @param y 朝向位置y
* @param z 朝向位置z
*/
lookAt(x: number, y: number, z: number): void;
applyMatrix(matrix: Matrix4): void;
applyQuaternion(q: Quaternion): this;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
export const VERSION = "2.0.63";
export const VERSION = "2.0.65";
export function cos(angle: number): number;
......@@ -177,7 +177,7 @@ export class Event extends HashObject {
*/
static RESIZE: string;
/**
* ScrollPage组件滑动到开始位置事件
* Scroll组件滑动到开始位置事件
* @property SCROLL_TO_HEAD
* @static
* @since 1.1.0
......@@ -185,7 +185,7 @@ export class Event extends HashObject {
*/
static SCROLL_TO_HEAD: string;
/**
* ScrollPage组件停止滑动事件
* Scroll组件停止滑动事件
* @property SCROLL_STOP
* @static
* @since 1.1.0
......@@ -193,7 +193,7 @@ export class Event extends HashObject {
*/
static SCROLL_STOP: string;
/**
* ScrollPage组件开始滑动事件
* Scroll组件开始滑动事件
* @property SCROLL_START
* @static
* @since 1.1.0
......@@ -201,13 +201,17 @@ export class Event extends HashObject {
*/
static SCROLL_START: string;
/**
* ScrollPage组件滑动到结束位置事件
* Scroll组件滑动到结束位置事件
* @property SCROLL_TO_END
* @static
* @since 1.1.0
* @type {string}
*/
static SCROLL_TO_END: string;
/**
* Scroll组件滚动时触发
*/
static SCROLLING: string;
/**
* 舞台初始化完成后会触发的事件
* @property INIT_STAGE
......@@ -6227,11 +6231,6 @@ export class Container extends DisplayObject {
*/
containerUpdateTransform: any;
constructor();
/**
* children改变时触发,暂时没地方用到,考虑废弃
* @param {number} index
*/
onChildrenChange(index: number): void;
/**
* 添加child,在所有子级的最上层
* @param {DisplayObject} child
......@@ -6275,18 +6274,23 @@ export class Container extends DisplayObject {
*/
getChildAt(index: number): DisplayObject;
/**
* 通过名字获取子级
* @param name
* @param isOnlyOne
* @param isRecursive
* 通过名字获取一个子级,找到一个符合的就返回
* @param name 名字或正则
* @param isRecursive 是否递归往子级查找,默认false
*/
getChildByName(name: string | RegExp, isOnlyOne?: boolean, isRecursive?: boolean): any;
getChildByName(name: string | RegExp, isRecursive?: boolean): DisplayObject;
/**
* 通过名字获取子级数组
* @param name 名字或正则
* @param isRecursive 是否递归往子级查找,默认false
*/
getChildrenByName(name: string | RegExp, isRecursive?: boolean): DisplayObject[];
/**
* 移除child
* @param {DisplayObject} child
* @return {DisplayObject}
*/
removeChild(child: DisplayObject): DisplayObject;
removeChild<T extends DisplayObject>(child: T): T;
/**
* 在index索引处移除子级对象
* @param {number} index
......@@ -6302,7 +6306,7 @@ export class Container extends DisplayObject {
* 移除所有子级
* @returns 返回移除的子级的数组
*/
removeAllChildren<T extends DisplayObject>(): T[];
removeAllChildren(): DisplayObject[];
/**
* 通过索引批量移除child
* @param {number} [beginIndex=0] 开始索引,包括自己
......@@ -6315,7 +6319,7 @@ export class Container extends DisplayObject {
* @param beginIndex 开始索引
* @param count 移除数量
*/
spliceChildren<T extends DisplayObject>(beginIndex?: number, count?: number): T[];
spliceChildren(beginIndex?: number, count?: number): DisplayObject[];
/**
* 更新矩阵
*/
......@@ -6403,6 +6407,10 @@ export class Container extends DisplayObject {
* @static
*/
private static _getElementsByName;
/**
* 操作子级的所有方法,需要维护
*/
static _childrenOperationMethods: string[];
}
export class FloatDisplay extends DisplayObject {
......@@ -8682,13 +8690,225 @@ export class ScrollPage extends Container {
destroy(): void;
}
export interface IScrollListItem extends DisplayObject {
initData(id: number, data: any): void;
id: number;
data: number;
export class ScrollView extends Container {
protected _scrollWidth: number;
/**
* 滚动宽度
* 设置0表示不让滚动
*/
get scrollWidth(): number;
set scrollWidth(v: number);
protected _scrollHeight: number;
/**
* 滚动高度
* 设置0表示不让滚动
*/
get scrollHeight(): number;
set scrollHeight(v: number);
/**
* 最大滚动坐标x,为负
*/
private get maxScrollX();
/**
* 最大滚动坐标y,为负
*/
private get maxScrollY();
protected _content: Container;
/**
* 滚动内容的节点容器
* 注意滚动内容都往这上面加
*/
get view(): Container;
/**
* 可见区域的宽
* @property viewWidth
* @type {number}
* @protected
* @since 1.0.0
* @default 0
*/
protected viewWidth: number;
/**
* 可见区域的高
* @property viewHeight
* @type {number}
* @protected
* @since 1.0.0
* @default 0
*/
protected viewHeight: number;
/**
* 遮罩对象
* @property maskObj
* @since 1.0.0
* @private
* @type {Graphics}
*/
private maskObj;
private downX;
private downY;
private distX;
private distY;
private startX;
private startY;
private destX;
private destY;
private isRunning;
private startTime;
private destTime;
private duration;
private easeFn;
private static weight;
private velocitys;
private lastTouchTime;
/**
* 手指拖动超过边界时是否允许回弹。默认true
*/
isBounce: boolean;
/**
* 回弹时间,视图内容在不合理的位置时恢复的时间,比如超过边界时
*/
bounceTime: number;
/**
* 手指抬起后是否存在惯性。默认true
*/
hasMomentum: boolean;
/**
* 惯性的阻尼
*/
damping: number;
/**
* 0无交互状态
* 1点击状态
* 2移动状态
*/
private mouseStatus;
/**
* 注意滚动内容在view里加
* @method ScrollPage
* @param {number} vW 可视区域宽
* @param {number} vH 可视区域高
* @param {number} sW 最大横向滚动距离
* @param {number} sH 最大纵向滚动距离
* @param {boolean} isFullScreen 是否全屏
* @example
* var scroll=new ScrollView(750,1000,0,2000);
* stage.addChild(scroll);
* //加滚动内容
* scroll.view.addChild(new Sprite());
*/
constructor(vW: number, vH: number, sW: number, sH: number, isFullScreen?: boolean);
/**
* 设置可见区域,可见区域的坐标始终在本地坐标中0,0点位置
* @method setViewRect
* @param {number}w 设置可见区域的宽
* @param {number}h 设置可见区域的高
* @param {boolean} isVertical 方向
* @public
* @since 1.1.1
*/
setViewRect(w: number, h: number, isFull?: boolean): void;
private onMouseEvent;
private onEnterFrame;
private pushVelocitys;
/**
* 滚到指定的坐标位置
* @param {number} x 往左横向滚动距离,0到最大横向滚动距离
* @param {number} y 往上纵向滚动距离,0到最大纵向滚动距离
* @param {number} time 滚动需要的时间 默认为0 即没有缓动直接到达指定位置,毫秒计
* @param {Function} easeFn 缓动函数,不传默认用Ease.circOut,从快到慢
* @public
*/
scrollTo(x: number, y: number, time?: number, easeFn?: (t: number) => number): void;
/**
* 从当前位置继续滚动
* @param {number} x 往左滚动距离
* @param {number} y 往上滚动距离
* @param {number} time 滚动需要的时间 默认为0 即没有缓动直接到达指定位置,毫秒计
* @param {Function} easeFn 缓动函数,不传默认用Ease.circOut,从快到慢
* @public
*/
scrollBy(x: number, y: number, time?: number, easeFn?: (t: number) => number): void;
/**
* 真实的滚动,xy一般都是负数
* @param x
* @param y
* @param time
* @param easeFn 缓动函数,不传默认用Ease.circOut
* @returns
*/
private _scrollTo;
/**
* _content位置的改变都用这个方法
* @param x
* @param y
*/
private _translate;
/**
* 检查当前的位置是否合理,不合理会返回true,且滚动到对应位置
* @param time
* @returns
*/
protected checkPosition(time?: number): boolean;
/**
* 矫正坐标
* @param x
* @param y
* @returns
*/
private _modifyXY;
destroy(): void;
}
export interface IScrollData {
/**
* 横向滚动位置,通常为正
*/
x: number;
/**
* 纵向滚动位置,通常为正
*/
y: number;
/**
* 滚动横向距离,为正表示向左滚动
*/
deltaX?: number;
/**
* 滚动纵向距离,为正表示向上滚动
*/
deltaY?: number;
}
export interface ScrollEvent extends Event {
data: IScrollData;
}
export class ScrollList extends ScrollPage {
export class ScrollListItem extends Container {
data: any;
/**
* 列表滚动时各项item有数据变更时会触发
* @param data 参数会传入data,也可直接使用this.data
* @protected
*/
onDataChanged(data?: any): void;
}
export class ScrollList extends ScrollView {
private _data;
/**
* 数据列表,
*/
get data(): any[];
/**
* list里不允许改变滚动尺寸范围,只能通过数据改变
*/
get scrollWidth(): number;
set scrollWidth(v: number);
/**
* list里不允许改变滚动尺寸范围,只能通过数据改变
*/
get scrollHeight(): number;
set scrollHeight(v: number);
private _items;
private _itemW;
private _itemH;
......@@ -8697,40 +8917,31 @@ export class ScrollList extends ScrollPage {
private _itemCount;
private _itemClass;
private _isInit;
data: Array<any>;
private downL;
private _cols;
private _disParam;
private _lastFirstId;
/**
* 获取下拉滚动的loadingView对象
* @property loadingView
* @since 1.0.9
* @return {DisplayObject}
*/
get loadingView(): DisplayObject;
private _isVertical;
/**
* 构造函数
* @method ScrollList
* @param {Class} itemClassName 可以做为Item的类
* @param {Class} itemClass 可以做为Item的类,比如ScrollListItem,必须具备onDataChanged方法
* @param {number} itemWidth item宽
* @param {number} itemHeight item高
* @param {number} vW 列表的宽
* @param {number} vH 列表的高
* @param {boolean} isVertical 是横向滚动还是纵向滚动 默认是纵向
* @param {number} cols 分几列,默认是1列
* @since 1.0.9
* @since 2.0.0
*/
constructor(itemClassName: any, itemWidth: number, itemHeight: number, vW: number, vH: number, isVertical?: boolean, cols?: number);
constructor(itemClass: typeof ScrollListItem, itemWidth: number, itemHeight: number, vW: number, vH: number, isVertical?: boolean, cols?: number);
/**
* 更新列表数据
* @method updateData
* 设置列表数据
* @method setData
* @param {Array} data
* @param {boolean} isReset 是否重数据列表。默认为true
* @since 1.0.9
* @param {boolean} isReset 是否重数据列表。默认为true
* @since 2.0.0
*/
setData(data: Array<any>, isReset?: boolean): void;
updateData(data: Array<any>, isReset?: boolean): void;
private _updateId;
private flushData;
/**
* 设置可见区域,可见区域的坐标始终在本地坐标中0,0点位置
......@@ -8739,17 +8950,22 @@ export class ScrollList extends ScrollPage {
* @param {number}h 设置可见区域的高
* @param {boolean} isVertical 方向
* @public
* @since 1.1.1
* @since 2.0.0
*/
setViewRect(w: number, h: number, isVertical: boolean): void;
private _updateViewRect;
setViewRect(w: number, h: number, isVertical?: boolean): void;
private _updateRowCol;
/**
* 设置加载数据时显示的loading对象
* @since 1.0.9
* @method setLoading
* @param {DisplayObject} downLoading
* 滚动到指定位置
* @param distance 滚动距离,一般为正
* @param time 滚动时间,默认0
*/
setLoading(downLoading: DisplayObject): void;
scrollTo(distance: number, time?: number): void;
/**
* 从当前位置开始滚动
* @param distance 滚动距离,一般为正
* @param time 滚动时间,默认0
*/
scrollBy(distance: number, time?: number): void;
destroy(): void;
}
......@@ -10524,6 +10740,21 @@ export class Object3D extends EventDispatcher {
private _onDispatchBubbledEvent;
clone(recursive?: boolean): Object3D;
copy(source: Object3D, recursive?: boolean): this;
/**
* 设置物体朝向
* @param vec3 一个存在x,y,z的矢量,比如mesh.position
*/
lookAt(vec3: {
x: number;
y: number;
z: number;
}): void;
/**
* 设置物体朝向
* @param x 朝向位置x
* @param y 朝向位置y
* @param z 朝向位置z
*/
lookAt(x: number, y: number, z: number): void;
applyMatrix(matrix: Matrix4): void;
applyQuaternion(q: Quaternion): this;
......
......@@ -144,7 +144,6 @@
}, "./res/chapterNum" + c + ".png")
}
})
console.log(textures)
var bitmapText = stage.addChild(new FYGE.BitmapText(textures))
bitmapText.text = "12345"
bitmapText.x = 300
......@@ -153,43 +152,49 @@
bitmapText.verticalAlign = "middle"
bitmapText.gap = -6
var b = { x: 0 }
console.log(bitmapText)
// FYGE.Tween.get(b, {
// onChange: () => {//缓动改变时监听
// bitmapText.text = "" + Math.round(b.x)
// }
// })
// .to({ x: 10000 }, 100000)
FYGE.Tween.get(b, {
onChange: () => {//缓动改变时监听
bitmapText.text = "" + Math.round(b.x)
}
})
.to({ x: 10000 }, 100000)
//按钮
var btn = stage.addChild(new FYGE.Button(texture))
.addEventListener(FYGE.MouseEvent.CLICK, () => { console.log("点击了按钮") }, this)
.position.set(0, 1100)
//滚动视图
var scroll = stage.addChild(new FYGE.ScrollPage(640, 656, 100, true, false))
var scroll = stage.addChild(new FYGE.ScrollView(640, 656, 0,1000 , false))
scroll.position.set(500, 1100)
scroll.view.addChild(new FYGE.Sprite(texture))//在view里面添加
scroll.maxDistance = 1000
setTimeout(() => { scroll.scrollTo(200, 2000) }, 2000)
setTimeout(() => { scroll.scrollTo(0, 200,2000) }, 2000)
//滚动列表
var list = new FYGE.ScrollList(class extends FYGE.Sprite {
var list = new FYGE.ScrollList(class extends FYGE.ScrollListItem {
constructor() {
super()
this.txt = new FYGE.TextField();
this.txt.size = 50;
this.txt.text ="00"
this.txt.fillColor = "#ff0000";
this.addChild(this.txt)
// console.log(this)
}
initData(id, data) {
if (id < 0 || !data) return
onDataChanged( data) {
// console.log(111)
// if (id < 0 || !data) return
this.txt.text = data + ""
}
}
, 100, 60, 100, 400, true)
, 100, 60, 100, 300, true)
list.x = 100;
list.y = 300;
list.updateData([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], true)//更新数据,true覆盖原先数据
list.setData([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], true)//更新数据,true覆盖原先数据
stage.addChild(list);
setTimeout(()=>{
// list.setData([1, 2, 3, 4], true)
list.setViewRect(100,500,true)
// list.setData(null,true)
},5000)
//帧动画
var texArr = []//需要纹理的数组
......
{
"name": "fyge",
"version": "2.0.63",
"version": "2.0.65",
"description": "canvas渲染引擎",
"main": "./build/fyge.min.js",
"module": "./build/fyge.esm.js",
......
......@@ -582,6 +582,15 @@
createTextureSheet文件里新增导出类型ITextureSheetFrameData,新增方法loadSheet
新增接口Dict,并且很多按照这种方式修改,并且很多interface都导出了
2.0.65 Container去掉方法onChildrenChange,也确实没地方用到
Container区分方法getChildByName和getChildrenByName
Container的removeChild方法添加泛型,removeAllChildren和spliceChildren去掉泛型
Container添加静态属性_childrenOperationMethods
DisplayObject的destroy方法里removeAllEventListener的操作放到removeChild之后,否则移除舞台的事件触发不了
Event里添加静态属性SCROLLING
新增一个ScrollView类并导出,ScrollList也继承自它大改,待大量测试
Object3D的lookAt方法新增一个重载,可传xyz对象
Object3D的update方法去掉自身的visible判断
......@@ -589,6 +598,9 @@
destroyed啥时候要处理下
setting对象是有效的,到时全局的设置就用这个
对于lottie和svga是纯json情况下,到时用weakMap存各自的纹理
......
......@@ -7,7 +7,7 @@
* @name VERSION
* @type {string}
*/
export const VERSION = "2.0.63";
export const VERSION = "2.0.65";
/**
......
......@@ -35,13 +35,13 @@ export default class Container extends DisplayObject {
this.children = [];
}
/**
* children改变时触发,暂时没地方用到,考虑废弃
* @param {number} index
*/
onChildrenChange(index: number) {
//子类需要时重写
}
// /**
// * children改变时触发,暂时没地方用到,考虑废弃
// * @param {number} index
// */
// onChildrenChange(index: number) {
// //子类需要时重写
// }
/**
* 添加child,在所有子级的最上层
......@@ -110,7 +110,7 @@ export default class Container extends DisplayObject {
child._onDispatchBubbledEvent(Event.ADDED_TO_STAGE);
}
this.onChildrenChange(index);
// this.onChildrenChange(index);
return child;
}
......@@ -145,7 +145,7 @@ export default class Container extends DisplayObject {
s.children[id1] = s.children[id2];
s.children[id2] = temp;
this.onChildrenChange(id1 < id2 ? id1 : id2);
// this.onChildrenChange(id1 < id2 ? id1 : id2);
return true;
}
......@@ -185,14 +185,12 @@ export default class Container extends DisplayObject {
}
return this.children[index];
}
/**
* 通过名字获取子级
* @param name
* @param isOnlyOne
* @param isRecursive
* 通过名字获取一个子级,找到一个符合的就返回
* @param name 名字或正则
* @param isRecursive 是否递归往子级查找,默认false
*/
public getChildByName(name: string | RegExp, isOnlyOne: boolean = true, isRecursive: boolean = false): any {
public getChildByName(name: string | RegExp, isRecursive: boolean = false): DisplayObject {
if (!name) return null;
let s = this;
let rex: any;
......@@ -202,15 +200,26 @@ export default class Container extends DisplayObject {
rex = name;
}
let elements: Array<DisplayObject> = [];
Container._getElementsByName(rex, s, isOnlyOne, isRecursive, elements);
let len = elements.length;
if (len == 0) {
return null;
} else if (len == 1) {
return elements[0];
Container._getElementsByName(rex, s, true, isRecursive, elements);
return elements[0] || null;
}
/**
* 通过名字获取子级数组
* @param name 名字或正则
* @param isRecursive 是否递归往子级查找,默认false
*/
public getChildrenByName(name: string | RegExp, isRecursive: boolean = false): DisplayObject[] {
if (!name) return null;
let s = this;
let rex: any;
if (typeof (name) == "string") {
rex = new RegExp("^" + name + "$");
} else {
return elements;
rex = name;
}
let elements: Array<DisplayObject> = [];
Container._getElementsByName(rex, s, false, isRecursive, elements);
return elements;
}
/**
......@@ -218,7 +227,7 @@ export default class Container extends DisplayObject {
* @param {DisplayObject} child
* @return {DisplayObject}
*/
removeChild(child: DisplayObject): DisplayObject {
removeChild<T extends DisplayObject>(child: T): T {
const index = this.children.indexOf(child);
......@@ -255,7 +264,7 @@ export default class Container extends DisplayObject {
//保证包围盒重新计算
this._boundsID++;
this.onChildrenChange(index);
// this.onChildrenChange(index);
return child;
}
......@@ -265,7 +274,7 @@ export default class Container extends DisplayObject {
*/
removeChildren<T extends DisplayObject>(...children: T[]): T[] {
//待测试,arr.splice(0)会全部删除,arr.splice(0,undefined)不会,所以this.spliceChildren(0)下面执行的是splice(0,undefined)
if (!children.length) return this.spliceChildren(0, this.children.length);
if (!children.length) return this.spliceChildren(0, this.children.length) as T[];
children.forEach((child: T) => { this.removeChild(child); })
return children
......@@ -274,7 +283,7 @@ export default class Container extends DisplayObject {
* 移除所有子级
* @returns 返回移除的子级的数组
*/
removeAllChildren<T extends DisplayObject>(): T[] {
removeAllChildren(): DisplayObject[] {
return this.removeChildren()
}
/**
......@@ -302,7 +311,7 @@ export default class Container extends DisplayObject {
* @param beginIndex 开始索引
* @param count 移除数量
*/
spliceChildren<T extends DisplayObject>(beginIndex?: number, count?: number): T[] {
spliceChildren(beginIndex?: number, count?: number): DisplayObject[] {
let removed = this.children.splice(beginIndex, count);
if (!removed.length) return [];
......@@ -316,12 +325,12 @@ export default class Container extends DisplayObject {
this._boundsID++;
this.onChildrenChange(beginIndex);
// this.onChildrenChange(beginIndex);
for (let i = 0; i < removed.length; ++i) {
removed[i]._onDispatchBubbledEvent(Event.REMOVED_FROM_STAGE);
}
return removed as T[];
return removed;
}
/**
......@@ -674,6 +683,21 @@ export default class Container extends DisplayObject {
}
}
}
/**
* 操作子级的所有方法,需要维护
*/
public static _childrenOperationMethods: string[] = [
//添加子级的方法
"addChild", "addChildAt", "addChildren",
//移除子级的方法
"removeChild", "removeChildAt", "removeChildren", "removeAllChildren", "removeChildrenAt", "spliceChildren",
//获取子级的方法
"getChildAt", "getChildByName", "getChildrenByName",
//获取子级索引的方法
"getChildIndex",
//改变子级索引的方法
"setChildIndex", "swapChildren"
]
}
Container.prototype.containerUpdateTransform = Container.prototype.updateTransform;
......
......@@ -393,13 +393,13 @@ export class DisplayObject extends EventDispatcher {
* 基本销毁方法
*/
destroy() {
//移除所有监听
//如果有父级,从中移除自己
this.removeAllEventListener();
// super.destroy();//不适用继承的,里面的eventTypes置空很麻烦
//如果有父级,从中移除自己
if (this.parent) {
this.parent.removeChild(this);
}
//移除所有监听,放在父级移除自己后面,因为有舞台移除事件
this.removeAllEventListener();
//矩阵销毁
this.transform.destroy();
//对应属性都置null
......
......@@ -569,7 +569,7 @@ export default class Sprite extends Container {
// else {
// value.once('update', this._onTextureUpdate, this);//只会监听一次
// }
//都监听下,其实没加载的纹理图片纹理确实只需要监听一次,这里先不管了,后续有性能问题再考虑
//都监听下,其实没加载的纹理图片纹理确实只需要监听一次,这里先不管了,存在性能问题,当一个纹理被大量对象使用时,事件数组会很大,导致遍历性能,TODO
value.addEventListener('update', this._onTextureUpdate, this);
} else {
//624修改。如果置空纹理,_localBoundsSelf置空
......
......@@ -19,7 +19,7 @@ export class Event extends HashObject {
public static RESIZE: string = "onResize";
/**
* ScrollPage组件滑动到开始位置事件
* Scroll组件滑动到开始位置事件
* @property SCROLL_TO_HEAD
* @static
* @since 1.1.0
......@@ -27,7 +27,7 @@ export class Event extends HashObject {
*/
public static SCROLL_TO_HEAD: string = "onScrollToHead";
/**
* ScrollPage组件停止滑动事件
* Scroll组件停止滑动事件
* @property SCROLL_STOP
* @static
* @since 1.1.0
......@@ -35,7 +35,7 @@ export class Event extends HashObject {
*/
public static SCROLL_STOP: string = "onScrollStop";
/**
* ScrollPage组件开始滑动事件
* Scroll组件开始滑动事件
* @property SCROLL_START
* @static
* @since 1.1.0
......@@ -43,13 +43,17 @@ export class Event extends HashObject {
*/
public static SCROLL_START: string = "onScrollStart";
/**
* ScrollPage组件滑动到结束位置事件
* Scroll组件滑动到结束位置事件
* @property SCROLL_TO_END
* @static
* @since 1.1.0
* @type {string}
*/
public static SCROLL_TO_END: string = "onScrollToEnd";
/**
* Scroll组件滚动时触发
*/
public static SCROLLING: string = "onScrolling";
/**
* 舞台初始化完成后会触发的事件
* @property INIT_STAGE
......
import { ScrollPage } from "./ScrollPage";
import { DisplayObject } from "../display/DisplayObject";
import { Event } from "../events/Event";
import { Container } from "../display";
import { ScrollView, ScrollEvent } from "./ScrollView";
/**
* 滚动类的Item类接口
* 滚动类的Item基类
* @class IScrollListItem
* @public
* @extends DisplayObject
* @since 1.0.9
* @extends Container
* @since 2.0.0
*/
export interface IScrollListItem extends DisplayObject {
initData(id: number, data: any): void;
export class ScrollListItem extends Container {
data: any
/**
* 列表滚动时各项item有数据变更时会触发
* @param data 参数会传入data,也可直接使用this.data
* @protected
*/
onDataChanged(data?: any) {
id: number;
data: number;
};
}
/**
* 滚动列表
* @class ScrollList
* @public
* @extends ScrollPage
* @extends ScrollView
* @since 1.0.9
*/
export class ScrollList extends ScrollPage {
private _items: Array<IScrollListItem> = null;
export class ScrollList extends ScrollView {
private _data: any[];
/**
* 数据列表,
*/
public get data() {
return this._data;
};
/**
* list里不允许改变滚动尺寸范围,只能通过数据改变
*/
get scrollWidth() {
return this._scrollWidth
}
set scrollWidth(v) {
console.warn("ScrollWidth can not be set manually in ScrollLists!")
}
/**
* list里不允许改变滚动尺寸范围,只能通过数据改变
*/
get scrollHeight() {
return this._scrollHeight
}
set scrollHeight(v) {
console.warn("ScrollHeight can not set manually in ScrollLists!")
}
private _items: Array<ScrollListItem> = null;
private _itemW: number;
private _itemH: number;
private _itemRow: number;
private _itemCol: number;
private _itemCount: number;
private _itemClass: any;
private _itemClass: typeof ScrollListItem;
private _isInit: number = 0;
public data: Array<any> = [];
private downL: DisplayObject = null;
private _cols: number;
private _disParam: string;
private _lastFirstId: number = -1;
/**
* 获取下拉滚动的loadingView对象
* @property loadingView
* @since 1.0.9
* @return {DisplayObject}
*/
public get loadingView(): DisplayObject {
return this.downL;
}
private _isVertical: boolean;
/**
* 构造函数
* @method ScrollList
* @param {Class} itemClassName 可以做为Item的类
* @param {Class} itemClass 可以做为Item的类,比如ScrollListItem,必须具备onDataChanged方法
* @param {number} itemWidth item宽
* @param {number} itemHeight item高
* @param {number} vW 列表的宽
* @param {number} vH 列表的高
* @param {boolean} isVertical 是横向滚动还是纵向滚动 默认是纵向
* @param {number} cols 分几列,默认是1列
* @since 1.0.9
* @since 2.0.0
*/
constructor(itemClassName: any, itemWidth: number, itemHeight: number, vW: number, vH: number, isVertical: boolean = true, cols: number = 1) {
super(vW, vH, 0, isVertical);
constructor(
itemClass: typeof ScrollListItem,
itemWidth: number,
itemHeight: number,
vW: number,
vH: number,
isVertical: boolean = true,
cols: number = 1
) {
super(vW, vH, 0, 0);
let s = this;
s._instanceType = "ScrollList";
s._itemW = itemWidth;
s._itemH = itemHeight;
s._items = [];
s._itemClass = itemClassName;
s._itemClass = itemClass;
s._itemCount = 0;
s._cols = cols;
s._updateViewRect();
s.addEventListener(Event.ENTER_FRAME, s.flushData.bind(s));
s._isVertical = isVertical;
s._updateRowCol();
//滚动时需要刷新数据
s.addEventListener(Event.SCROLLING, s.flushData, s);
}
/**
* 更新列表数据
* @method updateData
* 设置列表数据
* @method setData
* @param {Array} data
* @param {boolean} isReset 是否重数据列表。默认为true
* @since 1.0.9
* @param {boolean} isReset 是否重数据列表。默认为true
* @since 2.0.0
*/
public updateData(data: Array<any>, isReset: boolean = true): void {
let s: any = this;
public setData(data: Array<any>, isReset: boolean = true): void {
let s = this;
data = data || [];
if (!s._isInit || isReset) {
s.data = data;
s._data = data;
} else {
s.data = s.data.concat(data);
s._data = s._data.concat(data);
}
s._isInit = 1;
s._lastFirstId = -1;
s._updateId = -1;//确保会刷新
s.maxDistance = Math.ceil(s.data.length / s._cols) * s._itemRow;
if (s.downL) {
s.downL[s.paramXY] = Math.max(s.distance, s.maxDistance);
var wh = s.downL.getWH();
s.maxDistance += (s.paramXY == "x" ? wh.width : wh.height);
}
let maxDistance = Math.ceil(s.data.length / s._cols) * s._itemRow;
s[s._isVertical ? "_scrollHeight" : "_scrollWidth"] = maxDistance;
//检查一下位置
if (!s.checkPosition(s.bounceTime)) {
//没滚动需要刷新数据
s.flushData();
};
}
public updateData(data: Array<any>, isReset: boolean = true) {
console.warn("Method updateData will be abandoned soon,use method setData instead!")
this.setData(data, isReset);
}
private _updateId: number = -1;
private flushData() {
private flushData(e?: ScrollEvent) {
let s: ScrollList = this;
if (s._isInit > 0) {
if (s._updateId != s.view.transform._localID) {
s._updateId = s.view.transform._localID
let id: number = s.view[s.paramXY] > 0 ? 0 : (Math.abs(Math.floor(s.view[s.paramXY] / s._itemRow)) - 1) * s._cols;
id = id < 0 ? 0 : id;
if (id != s._lastFirstId) {
s._lastFirstId = id;
if (id != s._items[0].id) {
for (let r = 0; r < s._cols; r++) {
if (s.speed > 0) {
s._items.unshift(s._items.pop());
} else {
s._items.push(s._items.shift());
}
}
}
if (!s._isInit) return;
let dimension: "x" | "y", antDimension: "x" | "y", speed: number;
if (s._isVertical) {
dimension = "y";
antDimension = "x";
if (e && e.data) speed = e.data.deltaY;
} else {
dimension = "x";
antDimension = "y";
if (e && e.data) speed = e.data.deltaX;
}
let dis = s._content[dimension];
let id: number = dis > 0 ? 0 : (Math.abs(Math.floor(dis / s._itemRow)) - 1) * s._cols;
//如果dis是0的时候会是-1
id = Math.max(0, id);
// console.log(id)
//确定下和之前记录第一项id是否一致,一致就没必要改了
if (id == s._lastFirstId) return
s._lastFirstId = id;
//重新排数组,尽量最少的数据刷新
if (speed) {
for (let r = 0; r < s._cols; r++) {
//向下滚动时
if (speed < 0) {
s._items.unshift(s._items.pop());
}
for (let i = 0; i < s._itemCount; i++) {
let item: any = s._items[i];
if (s._isInit == 1) {
item.sli_id = -1;
}
if (item.sli_id != id) {
item.initData(s.data[id] ? id : -1, s.data[id]);
item[s.paramXY] = Math.floor(id / s._cols) * s._itemRow;
item[s._disParam] = (id % s._cols) * s._itemCol;
//如果没有数据则隐藏
if (s.data[id]) {
item.sli_id = id;
item.visible = true;
} else {
item.sli_id = -1;
item.visible = false;
}
}
id++;
//向上滚动时
else {
s._items.push(s._items.shift());
}
s._isInit = 2;
}
}
for (let i = 0; i < s._itemCount; i++) {
let item: ScrollListItem = s._items[i];
if (s._isInit == 1) {
item["sroll_id"] = -1;
}
if (item["sroll_id"] !== id) {
//id在data数组列表内就执行
if (id < s.data.length) {
item.onDataChanged(item.data = s.data[id]);
item.visible = true;
//位置
item[dimension] = Math.floor(id / s._cols) * s._itemRow;
item[antDimension] = (id % s._cols) * s._itemCol;
item["sroll_id"] = id;
} else {
item.data = null;
item.visible = false;
item["sroll_id"] = -1;
//位置需要刷新吗?
}
}
id++;
}
s._isInit = 2;
}
/**
......@@ -151,78 +208,107 @@ export class ScrollList extends ScrollPage {
* @param {number}h 设置可见区域的高
* @param {boolean} isVertical 方向
* @public
* @since 1.1.1
* @since 2.0.0
*/
public setViewRect(w: number, h: number, isVertical: boolean): void {
super.setViewRect(w, h, isVertical);
public setViewRect(w: number, h: number, isVertical: boolean = true): void {
super.setViewRect(w, h, false);
let s = this;
let same = s._isVertical === isVertical;
s._isVertical = isVertical;
//有行列时才需要更新
if (s._itemRow && s._itemCol) {
s._updateViewRect();
s._updateRowCol();
//先这样偷懒处理
if (!same) {
let oriTime = s.bounceTime;
s.bounceTime = 0;
s.setData(s._data, true);
s.bounceTime = oriTime;
} else {
s.flushData();
}
}
}
private _updateViewRect() {
let s: any = this;
if (s.isVertical) {
s._disParam = "x";
private _updateRowCol() {
let s = this, distance: number;
if (s._isVertical) {
s._itemRow = s._itemH;
s._itemCol = s._itemW;
distance = s.viewHeight;
s._scrollWidth = 0;
} else {
s._disParam = "y";
s._itemRow = s._itemW;
s._itemCol = s._itemH;
distance = s.viewWidth;
s._scrollHeight = 0;
}
let newCount: number = (Math.ceil(s.distance / s._itemRow) + 1) * s._cols;
let newCount: number = (Math.ceil(distance / s._itemRow) + 1) * s._cols;
if (newCount != s._itemCount) {
if (newCount > s._itemCount) {
for (let i = s._itemCount; i < newCount; i++) {
let item = new s._itemClass();
item.id = -1;
item.visible = false;
item.data = null;
s._items.push(item);
s.view.addChild(item);
s._content.addChild(item);
}
} else {
for (let i = 0; i < s._itemCount - newCount; i++) {
s.view.removeChild(s._items.pop());
s._content.removeChild(s._items.pop());
}
}
s._itemCount = newCount;
s._lastFirstId = -1;
}
}
/**
* 设置加载数据时显示的loading对象
* @since 1.0.9
* @method setLoading
* @param {DisplayObject} downLoading
* 滚动到指定位置
* @param distance 滚动距离,一般为正
* @param time 滚动时间,默认0
*/
public setLoading(downLoading: DisplayObject): void {
let s: any = this;
if (s.downL) {
s.view.removeChild(s.downL);
let wh = s.downL.getWH();
s.maxDistance -= (s.paramXY == "x" ? wh.width : wh.height);
s.downL = null;
scrollTo(distance: number, time: number = 0) {
let x = 0, y = 0;
if (this._isVertical) {
y = distance;
} else {
x = distance;
}
if (downLoading) {
s.downL = downLoading;
s.view.addChild(downLoading);
s.downL[s.paramXY] = Math.max(s.distance, s.maxDistance);
let wh = s.downL.getWH();
s.maxDistance += (s.paramXY == "x" ? wh.width : wh.height);
super.scrollTo(x, y, time);
}
/**
* 从当前位置开始滚动
* @param distance 滚动距离,一般为正
* @param time 滚动时间,默认0
*/
scrollBy(distance: number, time: number = 0) {
let x = 0, y = 0;
if (this._isVertical) {
y = distance;
} else {
s.isStop = false;
x = distance;
}
super.scrollBy(x, y, time);
}
public destroy(): void {
let s = this;
s._items = null;
s._itemClass = null;
s.data = null;
s.downL = null;
s._data = null;
super.destroy();
}
}
//list不允许操作任何子级
Container._childrenOperationMethods.forEach((v) => {
Object.defineProperty(ScrollList.prototype, v, {
value: function (...arg) {
console.warn("You'd better do not operate children in a ScrollList or its view!");
return Container.prototype[v].call(this, ...arg)
//先不重写了
// console.warn("ScrollLists can not operate children any more!")
},
writable: true,
enumerable: true,
})
})
\ No newline at end of file
......@@ -161,6 +161,7 @@ export class ScrollPage extends Container {
*/
constructor(vW: number, vH: number, maxDistance: number, isVertical: boolean = true, isFull = false) {
super();
console.warn("class ScrollPage will be abandoned soon, use class ScrollView instead");
let s: ScrollPage = this;
s._instanceType = "ScrollPage";
s.addChild(s.maskObj);
......
import { Ease } from "../../tween";
import { Container } from "../display";
import { Event, MouseEvent } from "../events";
import { Graphics } from "../graphics";
/**
* 滚动视图
*/
export class ScrollView extends Container {
protected _scrollWidth: number;
/**
* 滚动宽度
* 设置0表示不让滚动
*/
get scrollWidth() {
return this._scrollWidth
}
set scrollWidth(v: number) {
if (this._scrollWidth == v) return;
this._scrollWidth = v;
//改变
this.checkPosition(this.bounceTime)
}
protected _scrollHeight: number;
/**
* 滚动高度
* 设置0表示不让滚动
*/
get scrollHeight() {
return this._scrollHeight
}
set scrollHeight(v: number) {
if (this._scrollHeight == v) return;
this._scrollHeight = v;
//改变
this.checkPosition(this.bounceTime)
}
/**
* 最大滚动坐标x,为负
*/
private get maxScrollX(): number {
//不能滚动,就是0
if (!this.scrollWidth) return 0;
//
return Math.min(this.viewWidth - this.scrollWidth, 0);
};
/**
* 最大滚动坐标y,为负
*/
private get maxScrollY(): number {
//不能滚动,就是0
if (!this.scrollHeight) return 0;
return Math.min(this.viewHeight - this.scrollHeight, 0);
};
//容器
protected _content: Container;
/**
* 滚动内容的节点容器
* 注意滚动内容都往这上面加
*/
get view() {
return this._content;
}
/**
* 可见区域的宽
* @property viewWidth
* @type {number}
* @protected
* @since 1.0.0
* @default 0
*/
protected viewWidth: number = 0;
/**
* 可见区域的高
* @property viewHeight
* @type {number}
* @protected
* @since 1.0.0
* @default 0
*/
protected viewHeight: number = 0;
/**
* 遮罩对象
* @property maskObj
* @since 1.0.0
* @private
* @type {Graphics}
*/
private maskObj: Graphics;
private downX: number
private downY: number
private distX: number;
private distY: number;
private startX: number
private startY: number
private destX: number
private destY: number
private isRunning: boolean;
private startTime: number;
private destTime: number;
private duration: number;
private easeFn: (t: number) => number;
private static weight = [1, 1.33, 1.66, 2, 2.33];
private velocitys: [number, number][] = [];
private lastTouchTime: number
/**
* 手指拖动超过边界时是否允许回弹。默认true
*/
public isBounce: boolean = true
/**
* 回弹时间,视图内容在不合理的位置时恢复的时间,比如超过边界时
*/
public bounceTime: number = 300;
/**
* 手指抬起后是否存在惯性。默认true
*/
public hasMomentum: boolean = true;
/**
* 惯性的阻尼
*/
public damping: number = 0.0006
/**
* 0无交互状态
* 1点击状态
* 2移动状态
*/
private mouseStatus: 0 | 1 | 2 = 0;
/**
* 注意滚动内容在view里加
* @method ScrollPage
* @param {number} vW 可视区域宽
* @param {number} vH 可视区域高
* @param {number} sW 最大横向滚动距离
* @param {number} sH 最大纵向滚动距离
* @param {boolean} isFullScreen 是否全屏
* @example
* var scroll=new ScrollView(750,1000,0,2000);
* stage.addChild(scroll);
* //加滚动内容
* scroll.view.addChild(new Sprite());
*/
constructor(
vW: number,
vH: number,
sW: number,
sH: number,
isFullScreen?: boolean
) {
super();
let s: ScrollView = this;
s._instanceType = "ScrollView";
//视图容器,必须用super.addChildAt,其他都被重写了
s._content = super.addChildAt(new Container(), 0);
s.maskObj = super.addChildAt(new Graphics(), 0);
s.maskObj.alpha = 0;
//有传过才赋值
if (typeof sW == "number") s._scrollWidth = sW;
if (typeof sH == "number") s._scrollHeight = sH;
//设置第一次
s.setViewRect(vW, vH, isFullScreen);
//添加到舞台,需要注意local坐标替换成stage坐标
s.addEventListener(Event.ADDED_TO_STAGE, function (e: Event) {
s.stage.addEventListener(MouseEvent.MOUSE_MOVE, s.onMouseEvent, s);
s.stage.addEventListener(MouseEvent.MOUSE_UP, s.onMouseEvent, s);
});
s.addEventListener(Event.REMOVED_FROM_STAGE, function (e: Event) {
s.stage.removeEventListener(MouseEvent.MOUSE_MOVE, s.onMouseEvent, s);
s.stage.removeEventListener(MouseEvent.MOUSE_UP, s.onMouseEvent, s);
});
s.addEventListener(MouseEvent.MOUSE_DOWN, s.onMouseEvent, s, false);
// s.addEventListener(MouseEvent.MOUSE_MOVE, s.onMouseEvent, s);
// s.addEventListener(MouseEvent.MOUSE_UP, s.onMouseEvent, s);
// s.addEventListener(MouseEvent.MOUSE_OUT, s.onMouseEvent, s);
s.addEventListener(Event.ENTER_FRAME, s.onEnterFrame, s)
}
/**
* 设置可见区域,可见区域的坐标始终在本地坐标中0,0点位置
* @method setViewRect
* @param {number}w 设置可见区域的宽
* @param {number}h 设置可见区域的高
* @param {boolean} isVertical 方向
* @public
* @since 1.1.1
*/
public setViewRect(w: number, h: number, isFull?: boolean): void {
let s = this;
//不全屏才设置mask
if (!isFull) {
//加遮罩
s._content.mask = s.maskObj;
//为了能接收鼠标事件设置_isUsedToMask
s.maskObj._isUsedToMask = false;
//绘制
s.maskObj.clear()
.beginFill(0)
.drawRect(0, 0, w, h)
.endFill();
}
//移除遮罩
else {
s._content.mask = null;
}
//视窗尺寸
s.viewWidth = w;
s.viewHeight = h;
//改变
this.checkPosition(s.bounceTime)
}
private onMouseEvent(e: MouseEvent): void {
let s = this;
//点的时候
if (e.type == MouseEvent.MOUSE_DOWN) {
s.isRunning = false;
//阻止冒泡
e.stopPropagation()
//标记一下状态
s.mouseStatus = 1;
s.lastTouchTime = Date.now();
//记录点击的位置
s.downX = e.stageX;
s.downY = e.stageY;
s.distX = 0;
s.distY = 0;
} else if (e.type == MouseEvent.MOUSE_MOVE) {
//不是down过来的
if (s.mouseStatus < 1) return;
//计算间隔
let deltaX = e.stageX - s.downX,
deltaY = e.stageY - s.downY,
timestamp = Date.now();
s.downX = e.stageX;
s.downY = e.stageY;
s.distX += deltaX;
s.distY += deltaY;
let absDistX = Math.abs(s.distX);
let absDistY = Math.abs(s.distY);
//上一步是开始的,超出10才滑动
if (s.mouseStatus == 1 &&
absDistX < 10 &&
absDistY < 10
) {
s.lastTouchTime = timestamp;
return
}
//这个先不加
// if (s.isLocked) {
// if (absDistX > absDistY + s.lockDis) {
// deltaY = 0;
// } else if (absDistY >= absDistX + s.lockDis) {
// deltaX = 0;
// }
// }
let oriX = s._content.x,
oriY = s._content.y;
deltaX = s.scrollWidth ? deltaX : 0;
deltaY = s.scrollHeight ? deltaY : 0;
//计算速度
let deltaT = timestamp - s.lastTouchTime, sx = 0, sy = 0;
let newX = oriX + deltaX;
let newY = oriY + deltaY;
if (newX > 0 || newX < s.maxScrollX) {
newX = s.isBounce ? oriX + deltaX / 3 : newX > 0 ? 0 : s.maxScrollX;
} else {
sx = deltaX / deltaT
}
if (newY > 0 || newY < s.maxScrollY) {
newY = s.isBounce ? oriY + deltaY / 3 : newY > 0 ? 0 : s.maxScrollY;
} else {
sy = deltaY / deltaT
}
//记录速度
s.pushVelocitys(sx, sy)
s.lastTouchTime = timestamp;
s._translate(newX, newY);
//事件处理
if (s.mouseStatus == 1) {
s.dispatchEvent(Event.SCROLL_START, {
x: -newX,
y: -newY,
deltaX: oriX - newX,
deltaY: oriY - newY
});
}
s.mouseStatus = 2;
} else {
//超出边界了
if (s.checkPosition(s.bounceTime)) {
s.mouseStatus = 0;
return;
}
//状态不是move过来的,重置状态后return
if (s.mouseStatus != 2) {
s.mouseStatus = 0;
return;
}
s.mouseStatus = 0;
let newX: number = s._content.x,
newY: number = s._content.y,
time: number = 0;
//有缓冲
if (s.hasMomentum && s.velocitys.length) {
//计算速度
let sum = { x: 0, y: 0 }, totalW = 0;
for (let i = 0; i < s.velocitys.length; i++) {
let v = s.velocitys[i];
let w = ScrollView.weight[i];
sum.x += v[0] * w;
sum.y += v[1] * w;
totalW += w;
}
s.velocitys.length = 0;
let momentumX = s.scrollWidth ? toMomentum(newX, sum.x / totalW, s.maxScrollX, s.damping) : {
destination: newX,
duration: 0
};
let momentumY = s.scrollHeight ? toMomentum(newY, sum.y / totalW, s.maxScrollY, s.damping) : {
destination: newY,
duration: 0
};
newX = momentumX.destination;
newY = momentumY.destination;
time = Math.max(momentumX.duration, momentumY.duration);
}
if (newX != s._content.x || newY != s._content.y) {
s._scrollTo(newX, newY, time);
return;
}
s.dispatchEvent(Event.SCROLL_STOP, {
x: -s._content.x,
y: -s._content.y,
deltaX: 0,
deltaY: 0
});
}
}
private onEnterFrame(e: Event) {
let s = this;
let now = Date.now();
//不清楚有啥用
if (s.lastTouchTime && now - s.lastTouchTime > 100 && now - s.lastTouchTime < 300) {
s.pushVelocitys(0, 0);
}
if (!s.isRunning) return;
//时间到了
if (now >= s.destTime) {
s.isRunning = false;
const { x, y } = s._content;
//移动到最终位置
s._translate(s.destX, s.destY);
//检查是否合法,
if (!s.checkPosition(s.bounceTime)) {
let data = {
x: -s.destX,
y: -s.destY,
deltaX: x - s.destX,
deltaY: y - s.destX,
};
s.dispatchEvent(Event.SCROLL_STOP, data);
if (s.destX == 0 && s.destY == 0) {
s.dispatchEvent(Event.SCROLL_TO_HEAD, data);
}
if (s.destX == s.maxScrollX && s.destY == s.maxScrollY) {
s.dispatchEvent(Event.SCROLL_TO_END, data);
}
}
} else {
now = (now - s.startTime) / s.duration;
var easing = s.easeFn(now);
s._translate(
(s.destX - s.startX) * easing + s.startX,
(s.destY - s.startY) * easing + s.startY
);
}
}
private pushVelocitys(vx: number, vy: number) {
this.velocitys.push([vx, vy]);
if (this.velocitys.length > ScrollView.weight.length) this.velocitys.shift();
}
/**
* 滚到指定的坐标位置
* @param {number} x 往左横向滚动距离,0到最大横向滚动距离
* @param {number} y 往上纵向滚动距离,0到最大纵向滚动距离
* @param {number} time 滚动需要的时间 默认为0 即没有缓动直接到达指定位置,毫秒计
* @param {Function} easeFn 缓动函数,不传默认用Ease.circOut,从快到慢
* @public
*/
public scrollTo(x: number, y: number, time: number = 0, easeFn?: (t: number) => number): void {
//xy都是相对左上角正向的,所以真正_content的坐标应该取负
//判断范围
const [nx, ny] = this._modifyXY(-x, -y);
//真实滚动
this._scrollTo(nx, ny, time, easeFn);
}
/**
* 从当前位置继续滚动
* @param {number} x 往左滚动距离
* @param {number} y 往上滚动距离
* @param {number} time 滚动需要的时间 默认为0 即没有缓动直接到达指定位置,毫秒计
* @param {Function} easeFn 缓动函数,不传默认用Ease.circOut,从快到慢
* @public
*/
public scrollBy(x: number, y: number, time: number = 0, easeFn?: (t: number) => number) {
let s = this;
//最终的位置
x = s._content.x - x;
y = s._content.y - y;
//判断范围
const [nx, ny] = this._modifyXY(x, y);
s._scrollTo(nx, ny, time, easeFn);
}
/**
* 真实的滚动,xy一般都是负数
* @param x
* @param y
* @param time
* @param easeFn 缓动函数,不传默认用Ease.circOut
* @returns
*/
private _scrollTo(
x: number,
y: number,
time: number = 0,
easeFn?: (t: number) => number
) {
let s = this;
//判断下
if (isNaN(x) || isNaN(y)) return;
if (!time) {
s.isRunning = false;
s._translate(x, y);
} else {
s.startX = s._content.x;
s.startY = s._content.y;
s.startTime = Date.now();
s.destTime = s.startTime + time;
s.destX = x;
s.destY = y;
s.duration = time;
s.easeFn = easeFn || Ease.circOut;
s.isRunning = true;
}
}
/**
* _content位置的改变都用这个方法
* @param x
* @param y
*/
private _translate(x: number, y: number) {
let s = this;
let { x: oriX, y: oriY } = s._content;
s._content.x = x;
s._content.y = y;
//事件,位置变了
if (oriX != x || oriY != y) {
s.dispatchEvent(Event.SCROLLING, {
x: -x,
y: -y,
deltaX: oriX - x,
deltaY: oriY - y
});
}
}
/**
* 检查当前的位置是否合理,不合理会返回true,且滚动到对应位置
* @param time
* @returns
*/
protected checkPosition(time: number = 0): boolean {
//原先坐标
const { x, y } = this._content;
//矫正坐标
const [nx, ny] = this._modifyXY(x, y);
// 完全一致,就不处理
if (x == nx && y == ny) return false;
//滚动
this._scrollTo(nx, ny, time);
return true
}
/**
* 矫正坐标
* @param x
* @param y
* @returns
*/
private _modifyXY(x: number, y: number) {
let { scrollWidth, maxScrollX, scrollHeight, maxScrollY } = this;
if (!scrollWidth || x > 0) {
x = 0;
} else if (x < maxScrollX) {
x = maxScrollX;
}
if (!scrollHeight || y > 0) {
y = 0;
} else if (y < maxScrollY) {
y = maxScrollY;
}
return [x, y];
}
public destroy(): void {
let s = this;
//由于操作子级方法被重写了,销毁时移除不了,所以手动操作,用removeChildAt,其他都被重写了
super.removeChildAt(0)
.destroy();
super.removeChildAt(0)
.destroy();
s.maskObj = null;
s._content = null;
s.easeFn = null;
super.destroy();
}
};
//将添加与移除的操作统统重写到_content中,待测试,需要维护,TODO。对于list直接不允许使用下面这些方法
Container._childrenOperationMethods.forEach((v) => {
Object.defineProperty(ScrollView.prototype, v, {
value: function (...arg) {
console.warn("Maybe you want to operate children in its view rather then in it when it is a ScrollView!");
return Container.prototype[v].call(this, ...arg)
//先不重写了,不方便扩展,还容易出问题,只加提示吧
// return this._content[v](...arg);
},
writable: true,
enumerable: true,
})
})
/**
*
* @param current 当前位置
* @param speed 速度。move最后位置到松开的位置/滑动到松开的时间
* @param lowerMargin
* @param deceleration
* @returns
*/
function toMomentum(
current: number,
speed: number,
lowerMargin: number,
deceleration: number = 0.0006
) {
let destination = current + (speed * speed) / (2 * deceleration) * (speed < 0 ? -1 : 1);
let duration = Math.abs(speed) / deceleration;
// console.log(current, speed)
if (destination < lowerMargin) {
destination = lowerMargin;
duration = Math.abs((destination - current) / speed);
}
else if (destination > 0) {
destination = 0;
duration = Math.abs(current / speed);
}
return {
destination,
duration
};
};
export interface IScrollData {
/**
* 横向滚动位置,通常为正
*/
x: number,
/**
* 纵向滚动位置,通常为正
*/
y: number,
/**
* 滚动横向距离,为正表示向左滚动
*/
deltaX?: number,
/**
* 滚动纵向距离,为正表示向上滚动
*/
deltaY?: number
}
export interface ScrollEvent extends Event {
data: IScrollData
}
\ No newline at end of file
......@@ -9,4 +9,6 @@ export * from "./MovieClip";//暂时只有一个项目用过换装,三只松
export * from "./SvgaAni";
export * from "./Lottie";
\ No newline at end of file
export * from "./Lottie";
export * from "./ScrollView";
\ No newline at end of file
......@@ -189,13 +189,29 @@ export class Object3D extends EventDispatcher {
return this;
}
lookAt(x: number, y: number, z: number) {
/**
* 设置物体朝向
* @param vec3 一个存在x,y,z的矢量,比如mesh.position
*/
lookAt(vec3: { x: number, y: number, z: number }): void;
/**
* 设置物体朝向
* @param x 朝向位置x
* @param y 朝向位置y
* @param z 朝向位置z
*/
lookAt(x: number, y: number, z: number): void;
lookAt(x: any, y?: number, z?: number) {
var q1 = new Quaternion();
var m1 = new Matrix4();
var target = new Vector3();
var position = new Vector3();
target.set(x, y, z);
if (typeof x == "object") {
target.copy(x);
} else {
target.set(x, y, z);
}
var parent = this.parent;
......@@ -303,7 +319,7 @@ export class Object3D extends EventDispatcher {
* 统一更新方法,子类可重写,基类用于派发监听事件
*/
update() {
if (!this.visible) return;
// if (!this.visible) return;//从root往下时block(比如下面子级的visible判断),自身不进行判断
//监听的
if (this.hasEventListener(Event.ENTER_FRAME)) {
this.dispatchEvent(Event.ENTER_FRAME);
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="viewport"
content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="full-screen" content="true" />
<meta name="screen-orientation" content="portrait" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<!-- 主引擎 -->
<script src="../build/fyge.min.js"></script>
<style>
html,
body {
padding: 0;
margin: 0;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
background-color: #eeeeee;
}
</style>
</head>
<body>
<div id="cusEngine" style="line-height:0;font-size:0;position: absolute;">
<canvas id="canvas" style="width: 100%;height: 100%"></canvas>
</div>
</body>
<script>
window.addEventListener("load", async function () {
//获取canvas
var canvas = document.getElementById("canvas");
//建舞台,定宽适配,会根据实际窗口尺寸上下裁切,所以stage实际y坐标会偏移stage.viewRect.y
var stage = new FYGE.Stage(
canvas,
750,//设计宽度,按设计搞给的就行
1624,//设计高度
document.body.clientWidth,
document.body.clientHeight,
FYGE.RENDERER_TYPE.WEBGL,
false,
false,
window.devicePixelRatio || 1//分辨率
);
window.stage = stage;
//监听窗口缩放,按需,一般移动端的不需要
window.addEventListener('resize', () => { stage.resize() });
//鼠标事件
stage.addWebMouseEvent();
//stage初始化
stage.addEventListener(FYGE.Event.INIT_STAGE, async () => {
//单图纹理
var texture = await new Promise((r) => {
FYGE.GlobalLoader.loadImage((s, image) => {
r(FYGE.Texture.fromImage(image))
}, "./res/aa.png")
})
//添加个背景矢量图
var g = new FYGE.Graphics()
.beginFill(0x000000, 0.7)
.drawRect(0, 0, 750, 1624)
.endFill()
//滚动视图
var scroll = stage.addChild(new FYGE.ScrollView(
600, 1000, 0, 20000))
scroll.position.set(100, 100)
let sp = new FYGE.Sprite(texture)
sp.height = 20000
// sp.x=-100000
scroll.view.addChild(sp)//在view里面添加
// setTimeout(() => { scroll.scrollHeight=200 }, 2000)
//滚动列表
var list = new FYGE.ScrollList(class extends FYGE.Sprite {
constructor() {
super()
this.txt = new FYGE.TextField();
this.txt.size = 50;
this.txt.text = "00"
this.txt.fillColor = "#ff0000";
this.addChild(this.txt)
// console.log(this)
}
onDataChanged(data) {
// console.log(111)
// if (id < 0 || !data) return
this.txt.text = data + ""
}
}
, 100, 60, 100, 300, true)
list.x = 0;
list.y = 300;
list.setData([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], true)//更新数据,true覆盖原先数据
stage.addChild(list);
console.log(list)
setTimeout(() => {
// list.setData([1, 2, 3, 4], true)
// list.setViewRect(100, 500, true)
// list.setViewRect(500, 100, false)
// list.setData(null,true)
list.destroy()
}, 5000)
}, this);
//循环
loop();
function loop() {
//Tween每帧刷新
FYGE.Tween.flush()
//舞台每帧刷新
stage.flush();
// FYGE.getRequestAnimationFrame()(loop);
requestAnimationFrame(loop)
}
})
</script>
</html>
\ No newline at end of file
......@@ -22,6 +22,7 @@
"exclude": [
"node_modules",
"types",
"build"//build也忽略,可以避免开发的时候,引用到build里的声明文件,不过这样build里的声明文件的代码检查就无效了
"abandoned",
"build" //build也忽略,可以避免开发的时候,引用到build里的声明文件,不过这样build里的声明文件的代码检查就无效了
]
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment