swiper-next
Version:
Vue3 的 Swiper 组件
116 lines (115 loc) • 3.13 kB
JavaScript
import { upx2px } from "../shared/index.mjs";
function converPx(value) {
if (/^-?\d+[ur]px$/i.test(value)) {
return value.replace(/(^-?\d+)[ur]px$/i, (text, num) => {
return `${upx2px(parseFloat(num))}px`;
});
} else if (/^-?[\d\.]+$/.test(value)) {
return `${value}px`;
}
return value || "";
}
function converType(type) {
return type.replace(/[A-Z]/g, (text) => {
return `-${text.toLowerCase()}`;
}).replace("webkit", "-webkit");
}
function getStyle(action) {
const animateTypes1 = [
"matrix",
"matrix3d",
"scale",
"scale3d",
"rotate3d",
"skew",
"translate",
"translate3d"
];
const animateTypes2 = [
"scaleX",
"scaleY",
"scaleZ",
"rotate",
"rotateX",
"rotateY",
"rotateZ",
"skewX",
"skewY",
"translateX",
"translateY",
"translateZ"
];
const animateTypes3 = ["opacity", "background-color"];
const animateTypes4 = ["width", "height", "left", "right", "top", "bottom"];
const animates = action.animates;
const option = action.option;
const transition = option.transition;
const style = {};
const transform = [];
animates.forEach((animate) => {
let type = animate.type;
let args = [...animate.args];
if (animateTypes1.concat(animateTypes2).includes(type)) {
if (type.startsWith("rotate") || type.startsWith("skew")) {
args = args.map((value) => parseFloat(value) + "deg");
} else if (type.startsWith("translate")) {
args = args.map(converPx);
}
if (animateTypes2.indexOf(type) >= 0) {
args.length = 1;
}
transform.push(`${type}(${args.join(",")})`);
} else if (animateTypes3.concat(animateTypes4).includes(args[0])) {
type = args[0];
const value = args[1];
style[type] = animateTypes4.includes(type) ? converPx(value) : value;
}
});
style.transform = style.webkitTransform = transform.join(" ");
style.transition = style.webkitTransition = Object.keys(style).map(
(type) => `${converType(type)} ${transition.duration}ms ${transition.timingFunction} ${transition.delay}ms`
).join(",");
style.transformOrigin = style.webkitTransformOrigin = option.transformOrigin;
return style;
}
function startAnimation(context) {
const animation2 = context.animation;
if (!animation2 || !animation2.actions || !animation2.actions.length) {
return;
}
let index = 0;
const actions = animation2.actions;
const length = animation2.actions.length;
function animate() {
const action = actions[index];
const transition = action.option.transition;
const style = getStyle(action);
Object.keys(style).forEach((key) => {
context.$el.style[key] = style[key];
});
index += 1;
if (index < length) {
setTimeout(animate, transition.duration + transition.delay);
}
}
setTimeout(() => {
animate();
}, 0);
}
const animation = {
props: ["animation"],
watch: {
animation: {
deep: true,
handler() {
startAnimation(this);
}
}
},
mounted() {
startAnimation(this);
}
};
export {
animation as default
};