感谢「潘旭」老师来公众号分享他的技术与经验,这是潘老师公众号的第一篇文章,感谢他的分享,愿我们一起进步!
演示链接 : http://
scroll.yougexi.net
这是我制作这种的控件的第5遍了,当年用MFC,hge,CEGUI,Cocos2dx的时候都写过,当然时间周期在10年之间.这回又用js写了一遍,我发现开发速度是越来越快了.
这样无限循环的ScrollView控件,CocoCreator是没有的,需要你自己定制开发,所以这篇教程就诞生了,使用很简单.js脚本拖到node上,设置好要循环的node,默认参数执行工程就ok了.
虽然卡通头像辨识度比较高,经常看我视频教程的朋友一眼就能认出来,但是这个例子里,如果你拖动速度很快的话....你可以自己试试.
先来说说怎么用:
看上图,好了就这么简单,然后你就可以执行了。
1.创建个node,设置一下node的触摸区域.960*640.
2.添加自定义组件.
3.创建一些图片.
4.将你创建的图片拖过去.
5.执行工程.
下面视频是详细讲解控件开发过程,和控件原理,代码一点一点敲出来的,并伴随着我的东北话的讲解.
B站空间还有一些免费教程:
https://space.bilibili.com/214677808
网易云课堂有些收费视频课程:
当然还有工程的百度网盘地址链接
https://pan.baidu.com/s/1IYPiXgpE_SLJMkGmxiHYiQ
提取码:dn2e
js代码如下:
cc.Class({
extends: cc.Component,
properties: {
Direction: {
default: 0,
type: cc.Enum({
Horizontal: 0,
Vertical: 1,
}),
tooltip: '方向',
notify() {
this._initItemPos();
}
},
//每个item的间隔
itemOffset: {
default: 0,
type: cc.Integer,
tooltip: 'node 间隔',
notify() {
this._initItemPos();
}
},
speed: {
default: 500,
type: cc.Integer,
tooltip: '移动速度',
notify() {
this._initItemPos();
}
},
rub: {
default: 1.0,
type: cc.Float,
tooltip: '减速频率'
},
scaleMin: {
default: 0.5,
type: cc.Float,
tooltip: '缩放最小值'
},
scaleMax: {
default: 1.0,
type: cc.Float,
tooltip: '缩放最大值'
},
//滚动item
item: {
default: [],
type: [cc.Node],
notify() {
this._initItemPos();
}
},
// anchor:cc.Node,
_startTime: {
default: 0,
type: cc.Integer,
},
_moveSpeed: {
default: 0,
type: cc.Integer,
}
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
this._initItemPos();
this.updateScale();
this.node.on('touchstart', function (event) {
this._moveSpeed = 0;
this._startTime = new Date().getTime();
}.bind(this));
this.node.on('touchmove', function (event) {
var movePos = event.getDelta();
this.itemMoveBy(movePos);
}.bind(this));
this.node.on('touchend', function (event) {
this.touchEnd(event)
}.bind(this));
this.node.on('touchcancel', function (event) {
this.touchEnd(event)
}.bind(this));
},
touchEnd(event) {
var curpos = event.getLocation();
var startpos = event.getStartLocation();
var dis;
if (this.Direction == 0) {
dis = startpos.x - curpos.x;
} else {
dis = startpos.y - curpos.y;
}
var curTime = new Date().getTime();
var disTime = curTime - this._startTime;
//v = s/t
this._moveSpeed = dis / disTime;
},
_initItemPos() {
this.node.anchorY = 0.5;
this.node.anchorX = 0.5;
this._maxSize = new cc.Size(0, 0);
for (let i = 0; i < this.item.length; i++) {
this._maxSize.width += this.item[i].width;
this._maxSize.height += this.item[i].height;
this._maxSize.width += this.itemOffset;
this._maxSize.height += this.itemOffset;
}
var startPos;
if (this.Direction == 0) {
startPos = cc.v2(-this._maxSize.width * this.node.anchorX, -this._maxSize.height * this.node.anchorY);
} else {
startPos = cc.v2(this._maxSize.width * this.node.anchorX, this._maxSize.height * this.node.anchorY);
}
this._screenRect = new cc.Rect(startPos.x, startPos.y, this._maxSize.width, this._maxSize.height);
this.itemList = [];
for (let i = 0; i < this.item.length; i++) {
var anchor = this.item[i].getAnchorPoint();
var itemSize = this.item[i].getContentSize();
if (this.Direction == 0) {
startPos.addSelf(cc.v2(itemSize.width * anchor.x, itemSize.height * anchor.y));
this.item[i].x = startPos.x;
// cc.log('x:'+startPos.x);
this.item[i].y = 0;
startPos.addSelf(cc.v2(itemSize.width * anchor.x, itemSize.height * anchor.y));
startPos.addSelf(cc.v2(this.itemOffset, this.itemOffset));
} else {
startPos.subSelf(cc.v2(itemSize.width * anchor.x, itemSize.height * anchor.y));
this.item[i].x = 0;
this.item[i].y = startPos.y;
startPos.subSelf(cc.v2(itemSize.width * anchor.x, itemSize.height * anchor.y));
startPos.subSelf(cc.v2(this.itemOffset, this.itemOffset));
}
this.itemList[i] = this.item[i];
}
},
start() {
},
itemMoveBy(pos) {
for (let i = 0; i < this.item.length; i++) {
if (this.Direction == 0) {
this.item[i].x += pos.x;
} else {
this.item[i].y += pos.y;
}
}
this.updatePos();
},
updatePos() {
var startItem = this.itemList[0];
var endItem = this.itemList[this.itemList.length - 1];
var startout = false;
if( this.Direction == 0 ){
if( startItem.x < -this._maxSize.width/2 ){
startout = true;
}
}else{
if( startItem.y > this._maxSize.width/2 ){
startout = true;
}
}
//left
if (startout) {
var item = this.itemList.shift();
this.itemList.push(item);
if (this.Direction == 0) {
item.x = endItem.x + endItem.width + this.itemOffset;
} else {
item.y = endItem.y - endItem.height - this.itemOffset;
}
}
var endout = false;
if( this.Direction == 0 ){
if( endItem.x > this._maxSize.width/2 ){
endout = true;
}
}else{
if( endItem.y < -this._maxSize.height/2 ){
endout = true;
}
}
//right
if (endout) {
var item = this.itemList.pop();
this.itemList.unshift(item);
if (this.Direction == 0) {
item.x = startItem.x - startItem.width - this.itemOffset;
} else {
item.y = startItem.y + startItem.height + this.itemOffset;
}
}
this.updateScale();
},
updateScale() {
if (this.scaleMax < this.scaleMin || this.scaleMax == 0) {
return;
}
for (let i = 0; i < this.item.length; i++) {
var pre;
if (this.Direction == 0) {
var x = this.item[i].x + this._maxSize.width / 2;
if (this.item[i].x < 0) {
pre = x / this._maxSize.width;
}
else {
pre = 1 - x / this._maxSize.width;
}
} else {
var y = this.item[i].y + this._maxSize.height / 2;
if (this.item[i].y < 0) {
pre = y / this._maxSize.height;
}
else {
pre = 1 - y / this._maxSize.height;
}
}
pre *= 2;
var scaleTo = this.scaleMax - this.scaleMin;
scaleTo *= pre;
scaleTo += this.scaleMin;
scaleTo = Math.abs(scaleTo);
this.item[i].scaleX = scaleTo;
this.item[i].scaleY = scaleTo;
}
},
update(dt) {
if (this._moveSpeed == 0) return;
for (let i = 0; i < this.item.length; i++) {
if (this.Direction == 0) {
this.item[i].x -= this._moveSpeed * dt * this.speed;
} else {
this.item[i].y -= this._moveSpeed * dt * this.speed;
}
}
if (this._moveSpeed > 0) {
this._moveSpeed -= dt * this.rub;
if (this._moveSpeed < 0) {
this._moveSpeed = 0;
}
} else {
this._moveSpeed += dt * this.rub;
if (this._moveSpeed > 0) {
this._moveSpeed = 0;
}
}
var moveTo = -this._moveSpeed * dt * this.speed;
this.itemMoveBy(cc.v2(moveTo, moveTo))
this.updatePos();
},
});