UNPKG

framework7

Version:

Full featured mobile HTML framework for building iOS & Android apps

214 lines (199 loc) 6.91 kB
import $ from 'dom7'; import Utils from '../../utils/utils'; 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: Utils.getTranslate($fabEl[0], 'x'), translateY: Utils.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(''); Utils.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(''); Utils.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 = '.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; Utils.extend(app, { fab: { openedEl: null, morphOpen: Fab.morphOpen.bind(app), morphClose: Fab.morphClose.bind(app), open: Fab.open.bind(app), close: Fab.close.bind(app), toggle: Fab.toggle.bind(app), }, }); }, clicks: { '.fab > a': function open($clickedEl) { const app = this; app.fab.toggle($clickedEl.parents('.fab')); }, '.fab-open': function open($clickedEl, data = {}) { const app = this; app.fab.open(data.fab); }, '.fab-close': function close($clickedEl, data = {}) { const app = this; app.fab.close(data.fab); }, '.fab-backdrop': function close() { const app = this; app.fab.close(); }, }, };