UNPKG

framework7

Version:

Full featured mobile HTML framework for building iOS & Android apps

172 lines 6.43 kB
import $ from '../../shared/dom7.js'; import { bindMethods, getTranslate, nextFrame } from '../../shared/utils.js'; const Fab = { morphOpen(fabEl, targetEl) { const app = this; const $fabEl = $(fabEl); const $targetEl = $(targetEl); if ($targetEl.length === 0) return; $targetEl.transition(0).addClass('fab-morph-target-visible'); const target = { width: $targetEl[0].offsetWidth, height: $targetEl[0].offsetHeight, offset: $targetEl.offset(), borderRadius: $targetEl.css('border-radius'), zIndex: $targetEl.css('z-index') }; const fab = { width: $fabEl[0].offsetWidth, height: $fabEl[0].offsetHeight, offset: $fabEl.offset(), translateX: getTranslate($fabEl[0], 'x'), translateY: getTranslate($fabEl[0], 'y') }; $fabEl[0].f7FabMorphData = { $targetEl, target, fab }; const diffX = fab.offset.left + fab.width / 2 - (target.offset.left + target.width / 2) - fab.translateX; const diffY = fab.offset.top + fab.height / 2 - (target.offset.top + target.height / 2) - fab.translateY; const scaleX = target.width / fab.width; const scaleY = target.height / fab.height; let borderRadius = Math.ceil(parseInt(target.borderRadius, 10) / Math.max(scaleX, scaleY)); if (borderRadius > 0) borderRadius += 2; $fabEl[0].f7FabMorphResizeHandler = function resizeHandler() { $fabEl.transition(0).transform(''); $targetEl.transition(0); target.width = $targetEl[0].offsetWidth; target.height = $targetEl[0].offsetHeight; target.offset = $targetEl.offset(); fab.offset = $fabEl.offset(); const diffXNew = fab.offset.left + fab.width / 2 - (target.offset.left + target.width / 2) - fab.translateX; const diffYNew = fab.offset.top + fab.height / 2 - (target.offset.top + target.height / 2) - fab.translateY; const scaleXNew = target.width / fab.width; const scaleYNew = target.height / fab.height; $fabEl.transform(`translate3d(${-diffXNew}px, ${-diffYNew}px, 0) scale(${scaleXNew}, ${scaleYNew})`); }; $targetEl.css('opacity', 0).transform(`scale(${1 / scaleX}, ${1 / scaleY})`); $fabEl.addClass('fab-opened').css('z-index', target.zIndex - 1).transform(`translate3d(${-diffX}px, ${-diffY}px, 0)`); $fabEl.transitionEnd(() => { $targetEl.transition(''); nextFrame(() => { $targetEl.css('opacity', 1).transform('scale(1,1)'); $fabEl.transform(`translate3d(${-diffX}px, ${-diffY}px, 0) scale(${scaleX}, ${scaleY})`).css('border-radius', `${borderRadius}px`).css('box-shadow', 'none').css('opacity', '0'); }); app.on('resize', $fabEl[0].f7FabMorphResizeHandler); if ($targetEl.parents('.page-content').length > 0) { $targetEl.parents('.page-content').on('scroll', $fabEl[0].f7FabMorphResizeHandler); } }); }, morphClose(fabEl) { const app = this; const $fabEl = $(fabEl); const morphData = $fabEl[0].f7FabMorphData; if (!morphData) return; const { $targetEl, target, fab } = morphData; if ($targetEl.length === 0) return; const diffX = fab.offset.left + fab.width / 2 - (target.offset.left + target.width / 2) - fab.translateX; const diffY = fab.offset.top + fab.height / 2 - (target.offset.top + target.height / 2) - fab.translateY; const scaleX = target.width / fab.width; const scaleY = target.height / fab.height; app.off('resize', $fabEl[0].f7FabMorphResizeHandler); if ($targetEl.parents('.page-content').length > 0) { $targetEl.parents('.page-content').off('scroll', $fabEl[0].f7FabMorphResizeHandler); } $targetEl.css('opacity', 0).transform(`scale(${1 / scaleX}, ${1 / scaleY})`); $fabEl.transition('').css('box-shadow', '').css('border-radius', '').css('opacity', '1').transform(`translate3d(${-diffX}px, ${-diffY}px, 0)`); $fabEl.transitionEnd(() => { $fabEl.css('z-index', '').removeClass('fab-opened').transform(''); nextFrame(() => { $fabEl.transitionEnd(() => { $targetEl.removeClass('fab-morph-target-visible').css('opacity', '').transform('').transition(''); }); }); }); }, open(fabEl, targetEl) { const app = this; const $fabEl = $(fabEl).eq(0); const $buttonsEl = $fabEl.find('.fab-buttons'); if (!$fabEl.length) return; if ($fabEl.hasClass('fab-opened')) return; if (!$buttonsEl.length && !$fabEl.hasClass('fab-morph')) return; if (app.fab.openedEl) { if (app.fab.openedEl === $fabEl[0]) return; app.fab.close(app.fab.openedEl); } app.fab.openedEl = $fabEl[0]; if ($fabEl.hasClass('fab-morph')) { app.fab.morphOpen($fabEl, targetEl || $fabEl.attr('data-morph-to')); } else { $fabEl.addClass('fab-opened'); } $fabEl.siblings('.fab-backdrop').addClass('backdrop-in'); $fabEl.trigger('fab:open'); }, close(fabEl) { if (fabEl === void 0) { fabEl = '.fab-opened'; } const app = this; const $fabEl = $(fabEl).eq(0); const $buttonsEl = $fabEl.find('.fab-buttons'); if (!$fabEl.length) return; if (!$fabEl.hasClass('fab-opened')) return; if (!$buttonsEl.length && !$fabEl.hasClass('fab-morph')) return; app.fab.openedEl = null; if ($fabEl.hasClass('fab-morph')) { app.fab.morphClose($fabEl); } else { $fabEl.removeClass('fab-opened'); } $fabEl.siblings('.fab-backdrop').removeClass('backdrop-in'); $fabEl.trigger('fab:close'); }, toggle(fabEl) { const app = this; const $fabEl = $(fabEl); if (!$fabEl.hasClass('fab-opened')) app.fab.open(fabEl);else app.fab.close(fabEl); } }; export default { name: 'fab', create() { const app = this; bindMethods(app, { fab: { openedEl: null, ...Fab } }); }, clicks: { '.fab > a': function open($clickedEl) { const app = this; app.fab.toggle($clickedEl.parents('.fab')); }, '.fab-open': function open($clickedEl, data) { if (data === void 0) { data = {}; } const app = this; app.fab.open(data.fab); }, '.fab-close': function close($clickedEl, data) { if (data === void 0) { data = {}; } const app = this; app.fab.close(data.fab); }, '.fab-backdrop': function close() { const app = this; app.fab.close(); } } };