import { GIF, FileType, GIFCache } from "./GIF"; const { ccclass, property, requireComponent, disallowMultiple, executeInEditMode } = cc._decorator; @ccclass @executeInEditMode @disallowMultiple @requireComponent(cc.Sprite) export default class GIFSprite extends cc.Component { @property({ visible: false }) private _path: cc.RawAsset = null; @property({ type: cc.Asset }) get path() { return this._path; } set path(path: cc.RawAsset) { if (path == null) return; this._path = path; this.innerPath = path.toString() this.clear(); this.applayChange(); } public sprite: cc.Sprite = null; public _inited: boolean; private _length: number = 0; private _action: cc.ActionInterval; private _delays: Array; private _index: number = 0; private _spriteFrames: Array; _positions: Array private innerPath: string @property(Number) private maxWith = 0; @property(Number) private maxHeight = 0; @property(Boolean) private stayAtFirstFrame = false; @property(Boolean) private fitHeight = true; @property(Boolean) private fitWidth = true; public setInnerPath(path: string) { this.innerPath = path this.clear(); this.applayChange(); } protected onLoad() { this.sprite = this.node.getComponent(cc.Sprite); if (CC_EDITOR) { if (this.maxWith == 0) this.maxWith = this.node.width; if (this.maxHeight == 0) this.maxHeight = this.node.height; } } protected start() { if(this.path){ this.setInnerPath(this.path.toString()) } } // protected update(dt) { // } // onDestroy() { // } public setDefaultSpriteFrame(spriteFrame: cc.SpriteFrame) { let size = spriteFrame.getOriginalSize() var scale = 0 var width = 0 var height = 0 if (this.fitHeight && !this.fitWidth) { scale = this.maxHeight / size.height width = scale * size.width height = this.maxHeight } else if (!this.fitHeight && this.fitWidth) { scale = this.maxWith / size.width width = this.maxWith height = scale * size.height } else { let defaultWidthHeightScale = this.maxWith / this.maxHeight let newWidthHeightScale = size.width / size.height if (defaultWidthHeightScale > newWidthHeightScale) { scale = this.maxHeight / size.height width = scale * size.width height = this.maxHeight } else { scale = this.maxWith / size.width width = this.maxWith height = scale * size.height } } this.node.setContentSize(cc.size(width, height)) this.sprite.spriteFrame = spriteFrame } inited() { this._index++ if (this._index >= this._spriteFrames.length) { this._index = 0 } let sp = this._spriteFrames[this._index]; this.sprite.spriteFrame = sp; let delay = this._delays[this._index] if (!delay || delay < 0.01) { delay = 0.06 } else { delay = delay * 0.01 } this.scheduleOnce(() => { this.inited() }, delay) } private getType(): FileType { let format = FileType.UNKNOWN if (CC_JSB) { if(this.innerPath.indexOf("/") == 0){ let buffer = jsb.fileUtils.getDataFromFile(this.innerPath) let hexString = GIF.bytes2HexString(buffer.slice(0, 50)) format = GIF.detectFormat(hexString) } } return format } private applayChange() { let gifCache = GIFCache.getInstance() let callback = (error, data) => { if (error) { cc.error("gif load error") return } if (data instanceof cc.Texture2D) { this.setDefaultSpriteFrame(new cc.SpriteFrame(data)) } else { this._delays = data.delays; this._spriteFrames = data.spriteFrames; this._spriteFrames = data.spriteFrames; this._positions = data.positions this.setDefaultSpriteFrame(data.spriteFrames[0]) if (!this.stayAtFirstFrame) { this.scheduleOnce(() => { this.inited() }, 0.1) } this._inited = true; gifCache.addItemFrame(this.innerPath, data) } } let format = FileType.UNKNOWN let item = gifCache.get(this.innerPath) if (item) { format = item.type } else { format = this.getType() gifCache.addItemType(this.innerPath, format) } if (format == FileType.GIF) { if (gifCache.hasFrame(this.innerPath)) { callback(null, item.frameData) } else { cc.loader.load({ url: this.innerPath, type: 'gif' }, callback) } } else { cc.loader.load(this.innerPath, callback) } } private clear() { this.node.stopAllActions(); this._index = 0; this._inited = null; this._delays = null; this._spriteFrames = null; this.unscheduleAllCallbacks() } } /** */ export interface GIFMessage { target: GIFSprite, buffer: ArrayBuffer, initOneSpriteFrameFunc: { ( data: { delays: Array, spriteFrames: Array, length: number } ) }, initFinishedFunc: { ( data: { delays: Array, spriteFrames: Array, length: number } ) } }