/** * z轴堆叠列表展开收缩动画 * 堆叠项类名为 `${this.selector}-${index}`,列表容器类名为`${this.selector}-wrap` * @param {*} options */ function ZTranslate(options) { let { content, selector, size, margin } = options; this.content = content; this.selector = selector; this.size = size; this.margin = margin; this.toggleList = []; this.expanded = false; this.init(); } ZTranslate.prototype = { init() { this.keyframes = []; let len = 0; for (let i = 0; i < this.size; i++) { let keyframe = []; keyframe.push({ translateY: '0px', top: i * 3 + 'px', left: i * 2 + 'px', right: 0 - i * 2 + 'px', ease: 'ease', }); this._getEndY(i, res => { len += res + this.margin * (i == 0 ? 0 : 1); let translateY = len - res + 'px'; keyframe.push({ translateY: translateY, top: '0px', left: '0px', right: '0px', ease: 'ease', }); if (i == this.size - 1) { this.wrapKeyframe = [ { height: '0px', ease: 'ease' }, { height: len + 'px', ease: 'ease' }, ]; } }); this.keyframes.push(keyframe); } }, expand(callback) { if (this.toggleList.length < this.size) return; this.content.animate(`${this.selector}-wrap`, this.wrapKeyframe, 200); let length = this.keyframes.length; for (let i = 0; i < this.keyframes.length; i++) { const k = this.keyframes[i]; this.content.animate( `${this.selector}-${i}`, k, 200, function () { if (i == length - 1 && typeof callback === 'function') { callback(); } }.bind(this.content), ); } this.expanded = true; }, collapse(callback) { if (this.toggleList.length < this.size) return; this.content.animate( `${this.selector}-wrap`, [...this.wrapKeyframe].reverse(), 200, ); let length = this.keyframes.length; for (let i = 0; i < this.keyframes.length; i++) { const k = this.keyframes[i]; this.content.animate( `${this.selector}-${i}`, [...k].reverse(), 200, function () { if (i == length - 1 && typeof callback === 'function') { callback(); } }.bind(this.content), ); } this.expanded = false; }, slideOut(i, callback) { const selector = `${this.selector}-${i}`; const keyframe = this._getCurrentKeyframe(i); this.content.animate( selector, [ { ...keyframe, translateX: '0%' }, { ...keyframe, translateX: '100%' }, ], 250, function () { this.clearAnimation(selector, { translateX: true }, () => { if (typeof callback === 'function') { callback(); } }); }.bind(this.content), ); }, slideIn(i, callback) { const selector = `${this.selector}-${i}`; const keyframe = this._getCurrentKeyframe(i); this.content.animate( selector, [ { ...keyframe, translateX: '100%' }, { ...keyframe, translateX: '0%' }, ], 250, function () { this.clearAnimation(selector, { translateX: true }, () => { if (typeof callback === 'function') { callback(); } }); }.bind(this.content), ); }, // 获取动画结束Y轴位置 _getEndY(index, callback) { wx.createSelectorQuery() .in(this.content) .select(`${this.selector}-${index}`) .boundingClientRect(res => { callback(res.height); this.toggleList.push(true); }) .exec(); }, _getCurrentKeyframe(i) { let keyframe; if (this.expanded) { keyframe = this.keyframes[i][1]; } else { keyframe = this.keyframes[i][0]; } return keyframe; }, }; function animation1(options) { return new ZTranslate(options); } export { animation1 };