当前位置: 首页 > 工具软件 > Popmotion > 使用案例 >

html5 原生 弹窗,HTML5 Popmotion.js实现的弹窗控件

姚高韵
2023-12-01

JavaScript

语言:

JaveScriptBabelCoffeeScript

确定

const { css, transform, chain, delay, tween, easing, parallel } = window.popmotion;

const { interpolate } = transform;

let trigger;

let isClosing = false;

// Select DOM

const modalTriggersDom = document.querySelectorAll('.modal-trigger');

const dimmer = document.querySelector('.overlay');

const modalContainer = document.querySelector('.modal-container');

const modal = document.querySelector('.modal');

// Create CSS renderers

const dimmerRenderer = css(dimmer);

const modalContainerRenderer = css(modalContainer);

const modalRenderer = css(modal);

// Return the center x, y of a bounding box

function findCenter({ top, left, height, width }) {

return {

x: left + (width / 2),

y: top + (height / 2)

};

}

/*

Generate a function that will take a progress value (0 - 1)

and use that to tween the modal from the source to the destination

bounding boxes

*/

const vRange = [0, 1];

function generateModalTweener(sourceBBox, destinationBBox) {

const sourceCenter = findCenter(sourceBBox);

const destinationCenter = findCenter(destinationBBox);

const toX = interpolate(vRange, [sourceCenter.x - destinationCenter.x, 0]);

const toY = interpolate(vRange, [sourceCenter.y - destinationCenter.y, 0]);

const toScaleX = interpolate(vRange, [sourceBBox.width / destinationBBox.width, 1]);

const toScaleY = interpolate(vRange, [sourceBBox.height / destinationBBox.height, 1]);

return (v) => modalRenderer.set({

opacity: v,

x: toX(v),

y: toY(v),

scaleX: toScaleX(v),

scaleY: toScaleY(v)

});

}

function openModal(e) {

if (e.target && e.target.classList.contains('modal-trigger')) {

trigger = e.target;

// Get bounding box of triggering element

const triggerBBox = trigger.getBoundingClientRect();

// Temporarily show modal container to measure modal

dimmerRenderer.set('display', 'block').render();

modalContainerRenderer.set('display', 'flex').render();

modalRenderer.set('opacity', 0).render();

// Get bounding box of final modal position

const modalBBox = modal.getBoundingClientRect();

// Get a function to tween the modal from the trigger

const modalTweener = generateModalTweener(triggerBBox, modalBBox);

// Fade in overlay

tween({

duration: 200,

onUpdate: (v) => dimmerRenderer.set('opacity', v)

}).start();

chain([

delay(75),

tween({

duration: 200,

ease: easing.easeOut,

onUpdate: modalTweener

})

]).start();

}

}

function closeComplete() {

isClosing = false;

dimmerRenderer.set('display', 'none').render();

modalContainerRenderer.set('display', 'none').render();

modalRenderer.set({

y: 0,

scaleX: 1,

scaleY: 1,

transformOrigin: '50% 50%'

});

}

function cancelModal(e) {

if (e.target && e.target.classList.contains('cancel-modal') && !isClosing) {

e.stopPropagation();

isClosing = true;

const triggerBBox = trigger.getBoundingClientRect();

const modalBBox = modal.getBoundingClientRect();

const modalTweener = generateModalTweener(triggerBBox, modalBBox);

parallel([

tween({

from: dimmerRenderer.get('opacity'),

to: 0,

onUpdate: (v) => dimmerRenderer.set('opacity', v)

}),

tween({

from: modalRenderer.get('opacity'),

to: 0,

duration: 250,

onUpdate: modalTweener,

onComplete: closeComplete

})

]).start();

}

}

function submitModal(e) {

if (isClosing) return;

e.stopPropagation();

isClosing = true;

const toScaleXIn = interpolate(vRange, [1, 1.2]);

const toScaleYIn = interpolate(vRange, [1, 0.8]);

const toScaleXOut = interpolate(vRange, [1.2, 0.5]);

const toScaleYOut = interpolate(vRange, [0.8, 2]);

chain([

tween({

onStart: () => modalRenderer.set('transform-origin', '50% 100%'),

duration: 200,

onUpdate: (v) => modalRenderer.set({

scaleX: toScaleXIn(v),

scaleY: toScaleYIn(v),

y: v * 100

})

}),

parallel([

tween({

from: dimmerRenderer.get('opacity'),

to: 0,

onUpdate: (v) => dimmerRenderer.set('opacity', v)

}),

tween({

onUpdate: (v) => modalRenderer.set({

opacity: 1 - v,

scaleX: toScaleXOut(v),

scaleY: toScaleYOut(v),

y: - 300 * easing.easeIn(v)

}),

duration: 200,

onComplete: closeComplete

})

])

]).start();

}

document.addEventListener('click', openModal);

document.addEventListener('click', cancelModal);

document.querySelector('.submit').addEventListener('click', submitModal);

 类似资料: