UNPKG

ffcreator

Version:

FFCreator is a lightweight and flexible short video production library

260 lines (224 loc) 5.62 kB
'use strict'; /** * FFAlbum - A picture album component that supports multiple switching animation effects * * ####Example: * * const album = new FFAlbum({ * list: [a01, a02, a03, a04], * x: 100, * y: 100, * width: 500, * height: 300 * }); * * @class * */ const FFImage = require('./image'); const Utils = require('../utils/utils'); const forEach = require('lodash/forEach'); const isArray = require('lodash/isArray'); const FFLogger = require('../utils/logger'); const Effects = require('../animate/effects'); const { Container, Sprite } = require('inkpaint'); const FFAnimation = require('../animate/animation'); class FFAlbum extends FFImage { constructor(conf = { list: [] }) { super({ type: 'album', ...conf }); if (!conf.width) FFLogger.error({ pos: 'FFAlbum', error: 'This component must enter the width!' }); this.tweens = []; this.children = []; this.list = conf.list; this.width = conf.width; this.height = conf.height; this.showCover = conf.showCover; this.setDuration(conf.duration); this.setTransition(conf.transition); this.setTransTime(conf.time || conf.transTime); } /** * Set total album animation duration * * @param {number} duration album animation duration * @public */ setDuration(duration = 2) { this.duration = duration; } /** * Set the way to switch the album animation * * @param {string} transition transition type * @public */ setTransition(transition = 'random') { this.transition = transition; } /** * Set the transition time of each image * * @param {number} time transition time * @public */ setTransTime(time = 1) { this.time = time; } /** * Show album cover image * * @param {boolean} showCover Whether to show cover image * @public */ setShowCover(showCover = false) { this.showCover = showCover; } /** * Get the width and height of the album component * * @return {array} [width, height] array * @public */ getWH() { const { width = 0, height = 0 } = this.conf; return [width, height]; } /** * Get the URL that needs to be preloaded * @public */ getPreloadUrls() { return this.list; } /** * Create display object * @private */ createDisplay() { this.display = new Container(); } getTotalDuration() { return this.list.length * this.duration + this.time; } setTotalDuration(tduration) { this.duration = (tduration - this.time) / this.list.length; } /** * Fill the transition animation of each single picture * @private */ fillAlbumTweens() { const tweens = []; const aniNames = this.createAniNames(); forEach(this.children, (sprite, index) => { const type = index < aniNames.length ? aniNames[index] : aniNames[0]; const time = this.isCover(index) ? 0 : this.time; const delay = index * this.duration; const aniObj = Effects.getAnimation({ type, time, delay }, sprite); const parent = { display: sprite, offsetX: 0, offsetY: 0, id: `album_sub${index}`, }; const tween = new FFAnimation({ ...aniObj, parent }); tween.autoAlpha = true; tween.index = index; tween.on('complete', myTween => { const { index } = myTween; this.hidePrevChilds(index); }); tweens.push(tween); if (!this.isCover(index)) sprite.alpha = 0; }); return tweens; } /** * Hide useless sibling elements, to improve performance * @private */ hidePrevChilds(index) { for (let i = 0; i < index; i++) { const child = this.children[i]; child.visible = false; } } /** * Create animation name * @private */ createAniNames() { let aniNames = []; if (this.transition === 'random') this.transition = Effects.getRandomEffectName(20); if (isArray(this.transition)) { aniNames = aniNames.concat(this.transition); } else { aniNames.push(this.transition); } return aniNames; } /** * Start rendering * @public */ start() { this.animations.start(); forEach(this.list, image => this.createSingleImage(image)); this.createTweensAndStart(); } createTweensAndStart() { const tweens = this.fillAlbumTweens(); forEach(tweens, tween => tween.start()); this.tweens = tweens; } /** * Create a single image frame * @private */ createSingleImage(image) { const [width, height] = this.getWH(); const sprite = new Sprite(); sprite.anchor.set(0.5); image = this.getAsset(image); this.draw({ display: sprite, texture: image }); this.display.addChild(sprite); this.children.push(sprite); if (width) sprite.width = width; if (height) sprite.height = height; sprite.setScaleToInit(); } /** * is face cover * @private */ isCover(index) { return index === 0 && this.showCover; } destroyAlbumList() { forEach(this.children, sprite => { this.deleteTexture(sprite); sprite.destroy(); }); } destroyAlbumTweens() { forEach(this.tweens, tween => { Utils.destroyObj(tween.parent); tween.destroy(); }); } destroy() { try { this.destroyAlbumList(); this.destroyAlbumTweens(); this.display.removeAllChildren(); this.conf.list.length = 0; this.children.length = 0; this.list = null; } catch (e) { console.log(e); } super.destroy(); } } module.exports = FFAlbum;