cc.Class({ extends: cc.Component, properties: { itemTemplate: { // item template to instantiate other items default: null, type: cc.Prefab }, scrollView: { default: null, type: cc.ScrollView }, spawnCount: 0, // how many items we actually spawn totalCount: 0, // how many items we need for the whole list spacing: 0, // space between each item bufferZone: 0, // when item is away from bufferZone, we relocate it }, // use this for initialization onLoad: function () { this.index = 0; this.content = this.scrollView.content; this.items = []; // array to store spawned items this.initialize(); this.updateTimer = 0; this.updateInterval = 0.2; this.lastContentPosY = 0; // use this variable to detect if we are scrolling up or down }, initialize: function () { this.height = this.itemTemplate.data.height; this.content.height = this.totalCount * (this.height + this.spacing) + this.spacing; // get total content height for (let i = 0; i < this.spawnCount; ++i) { // spawn items, we only need to do this once let item = cc.instantiate(this.itemTemplate); item.parent = this.content; item.setPosition(0, -item.height * (0.5 + i) - this.spacing * (i + 1)); this.items.push(item); item.getChildByName('CodeLabel').getComponent(cc.Label).string = this.index; this.index++; } }, shutDown() { this.node.active = false }, getPositionInView: function (item) { // get item position in scrollview's node space let worldPos = item.parent.convertToWorldSpaceAR(item.position); let viewPos = this.scrollView.node.convertToNodeSpaceAR(worldPos); return viewPos; }, update: function(dt) { this.updateTimer += dt; if (this.updateTimer < this.updateInterval) return; // we don't need to do the math every frame this.updateTimer = 0; let items = this.items; let buffer = this.bufferZone; let isDown = this.scrollView.content.y < this.lastContentPosY; // scrolling direction let offset = (this.height + this.spacing) * items.length; for (let i = 0; i < items.length; ++i) { let viewPos = this.getPositionInView(items[i]); if (isDown) { // if away from buffer zone and not reaching top of content if (viewPos.y < -buffer && items[i].y + offset < 0) { items[i].y = items[i].y + offset; let item = items[i].getComponent('Item'); // let itemId = item.itemID - items.length; // update item id // item.updateItem(itemId); } } else { // if away from buffer zone and not reaching bottom of content if (viewPos.y > buffer && items[i].y - offset > -this.content.height) { items[i].y = items[i].y - offset; let item = items[i].getComponent('Item'); // let itemId = item.itemID + items.length; // item.updateItem(itemId); } } } // update lastContentPosY this.lastContentPosY = this.scrollView.content.y; // this.lblTotalItems.textKey = "Total Items: " + this.totalCount; }, // scrollEvent: function(sender, event) { // switch(event) { // case 0: // this.lblScrollEvent.string = "Scroll to Top"; // break; // case 1: // this.lblScrollEvent.string = "Scroll to Bottom"; // break; // case 2: // this.lblScrollEvent.string = "Scroll to Left"; // break; // case 3: // this.lblScrollEvent.string = "Scroll to Right"; // break; // case 4: // this.lblScrollEvent.string = "Scrolling"; // break; // case 5: // this.lblScrollEvent.string = "Bounce Top"; // break; // case 6: // this.lblScrollEvent.string = "Bounce bottom"; // break; // case 7: // this.lblScrollEvent.string = "Bounce left"; // break; // case 8: // this.lblScrollEvent.string = "Bounce right"; // break; // case 9: // this.lblScrollEvent.string = "Auto scroll ended"; // break; // } // }, addItem: function() { this.content.height = (this.totalCount + 1) * (this.height + this.spacing) + this.spacing; // get total content height this.totalCount = this.totalCount + 1; }, removeItem: function() { if (this.totalCount - 1 < 30) { cc.error("can't remove item less than 30!"); return; } this.content.height = (this.totalCount - 1) * (this.height + this.spacing) + this.spacing; // get total content height this.totalCount = this.totalCount - 1; this.moveBottomItemToTop(); }, moveBottomItemToTop () { let offset = (this.height + this.spacing) * this.items.length; let length = this.items.length; let item = this.getItemAtBottom(); // whether need to move to top if (item.y + offset < 0) { item.y = item.y + offset; let itemComp = item.getComponent('Item'); // let itemId = itemComp.itemID - length; // itemComp.updateItem(itemId); } }, getItemAtBottom () { let item = this.items[0]; for (let i = 1; i < this.items.length; ++i) { if (item.y > this.items[i].y) { item = this.items[i]; } } return item; }, scrollToFixedPosition: function () { this.scrollView.scrollToOffset(cc.v2(0, 500), 2); } });