|
- -- 用来实现自动倒计时,并可以做数据绑定,具体用法参考VT_RemainTime.lua
- local RemainTime = class("RemainTime");
-
- function RemainTime:ctor()
- -- 当前剩余秒数,每秒更新一次,可绑定
- self.Value = 0;
- -- 总剩余时间(单位秒,外部设置),可绑定
- self.RemainTime = 0;
- -- 上次更新的本地时间
- self.LastTime = 0
- -- 总共流失了多少时间
- self.TotalElapse = 0
- -- 开始倒计时的时间(os.time()获取)
- self.StartTime = 0;
- -- 计时到0后,回调OnTimeOver(self)
- self.OnTimeOver = nil;
- -- 数据绑定列表,key是变量名(Value或RemainTime),value是Binder表
- self.BindsByName = {}
- -- 根据索引排序的绑定列表,key是BindIndex,value是Binder表
- self.BindsByIndex = {}
- -- 绑定索引
- self.BindIndex = 0;
- -- 每隔多久触发一次
- self.Interval = 1;
- -- 定时器速度
- self.Speed = 1;
- -- 暂停状态
- self.Pause = false;
- end
-
- function RemainTime:setInterval(interval)
- if self.Interval ~= interval then
- self.Interval = interval;
- if self.TimerID then
- self:stopTimer();
- self:startTimer();
- end
- end
- end
-
- -- 设置加速速度
- function RemainTime:setSpeed(speed)
- self.Speed = speed
- end
-
- -- 设置剩余秒数多少
- function RemainTime:setRemainTime(seconds)
- --print("设置倒计时" , seconds);
- if type(seconds) == "table" then
- seconds = seconds:getRemainTime();
- end
-
- self.RemainTime = seconds;
- self.Value = seconds;
- self.StartTime = os.time()
- self.LastTime = self.StartTime
- self.TotalElapse = 0
- self:triggerBinder("RemainTime");
- self:triggerBinder("Value");
-
- -- 开始计时
- if self.Value > 0 and next(self.BindsByIndex) ~= nil and self.Pause == false then
- self:startTimer();
- end
- end
-
- function RemainTime:getRemainTime()
- return self.RemainTime;
- end
-
- function RemainTime:updateTo(target)
- target.Value = self.Value;
- target.RemainTime = self.RemainTime;
- target.StartTime = self.StartTime;
- target.LastTime = self.LastTime
- target.TotalElapse = self.TotalElapse
- target.Speed = self.Speed
- if target.startTimer and target.Value > 0 and next(target.BindsByIndex) ~= nil and target.Pause == false then
- target:startTimer()
- end
-
- return target;
- end;
-
- -- 获取一个绑定实例
- function RemainTime:getBinder(valueName)
- local bindTable = self.BindsByName[valueName];
- -- 根据名字创建绑定表,一个名字可以绑定多次
- if bindTable == nil then
- bindTable = {};
- self.BindsByName[valueName] = bindTable;
- end
-
- self.BindIndex = self.BindIndex + 1
- -- 创建单个绑定实例
- local binder =
- {
- TargetNode = nil;
- ValueName = valueName;
- BindIndex = self.BindIndex;
- OnPropChanged = nil
- };
-
- self.BindsByIndex[binder.BindIndex] = binder;
-
- bindTable[binder.BindIndex] = binder;
-
- return binder;
- end
-
- -- 每秒回调一次
- function RemainTime:onTimer()
- local now = os.time()
- local elapse = (now - self.LastTime) * self.Speed;
- self.TotalElapse = self.TotalElapse + elapse
- self.LastTime = now
- -- 计算剩余时间
- self.Value = self.RemainTime - self.TotalElapse;
- if self.Value <= 0 then
- self.Value = 0;
- end
- --print("计算剩余时间:" , self.Value , self.RemainTime , seconds , now , self.StartTime);
- -- 触发数据修改通知
- self:triggerBinder("Value");
-
- -- 倒计时结束
- if self.Value <= 0 then
- --print("倒计时结束" , self.Value);
- self:stopTimer();
- if self.OnTimeOver then
- self.OnTimeOver(self);
- end;
- end;
- end
-
- -- 触发数据修改通知
- function RemainTime:triggerBinder(valueName)
- local value = self[valueName];
- --print("值改变:" , valueName , value);
- local binders = self.BindsByName[valueName];
- if binders then
- for i , v in pairs(binders) do
- v.OnPropChanged(valueName , value);
- end
- end
- end
-
- -- 开始计时器
- function RemainTime:startTimer()
- if self.Pause then
- return
- end
-
- if self.TimerID == nil then
- self.TimerID = cc.Director:getInstance():getScheduler():scheduleScriptFunc(function()self:onTimer()end, self.Interval, false);
- end
- end
-
- -- 停止计时器
- function RemainTime:stopTimer()
- if self.TimerID then
- cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.TimerID);
- self.TimerID = nil;
- end
- end
-
- -- 暂停计时器(计时器就不走了)
- function RemainTime:pause()
- if self.Pause then
- return
- end
-
- self:stopTimer()
- -- 执行一次时间
- self:onTimer()
- self.Pause = true
- end
-
- -- 恢复计时器
- function RemainTime:resume()
- if not self.Pause then
- return
- end
-
- self.Pause = false
- -- 如果时间完了就不能开始了
- if self.Value <= 0 then
- print("计时器时间已经流失完了,恢复失败")
- return
- end
-
- -- 重新设置下时间
- self:setRemainTime(self.Value)
- end
-
- -- 实现自动绑定数据的函数
- -- @valueName 需要绑定哪个变量名
- -- @propertyNameOrFunc , 当添加事件发生时的回调或设置什么属性,回调格式是func(key , value);
- -- @return 返回绑定索引
- function RemainTime:bind(valueName , propertyNameOrFunc , targetNode)
- local onPropChange;
- local typeP = type(propertyNameOrFunc);
-
- if typeP == "function" then
- onPropChange = function(key , value)
- propertyNameOrFunc(self , value);
- end
- elseif typeP == "string" then
- local function onChange(key , value)
- self[propertyNameOrFunc](self , value);
- end
- onPropChange = onChange
- else
- error("绑定数据" .. tostring(valueName) .. "时第三个参数错误,必须是属性名或函数" .. tostring(propertyNameOrFunc))
- return;
- end
-
- local binder = self:getBinder(valueName);
- binder.TargetNode = targetNode;
- binder.OnPropChanged = onPropChange;
-
- -- 开始计时
- if self.Value > 0 then
- self:startTimer();
- end
- self:triggerBinder(valueName);
- return binder.BindIndex;
- end
-
- -- 解除绑定
- function RemainTime:unbind(bindIndex)
- local binder = self.BindsByIndex[bindIndex];
- if binder == nil then
- print("找不到绑定索引" .. tostring(bindIndex));
- return;
- end
- self.BindsByName[binder.ValueName][bindIndex] = nil;
- self.BindsByIndex[bindIndex] = nil;
-
- -- 没人绑定了,就停止计时器
- if next(self.BindsByIndex) == nil then
- self:stopTimer();
- end
- end
-
- return RemainTime;
|