uni-transition.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. "use strict";
  2. const uni_modules_uniTransition_components_uniTransition_createAnimation = require("./createAnimation.js");
  3. const common_vendor = require("../../../../common/vendor.js");
  4. const _sfc_main = {
  5. name: "uniTransition",
  6. emits: ["click", "change"],
  7. props: {
  8. show: {
  9. type: Boolean,
  10. default: false
  11. },
  12. modeClass: {
  13. type: [Array, String],
  14. default() {
  15. return "fade";
  16. }
  17. },
  18. duration: {
  19. type: Number,
  20. default: 300
  21. },
  22. styles: {
  23. type: Object,
  24. default() {
  25. return {};
  26. }
  27. },
  28. customClass: {
  29. type: String,
  30. default: ""
  31. }
  32. },
  33. data() {
  34. return {
  35. isShow: false,
  36. transform: "",
  37. opacity: 1,
  38. animationData: {},
  39. durationTime: 300,
  40. config: {}
  41. };
  42. },
  43. watch: {
  44. show: {
  45. handler(newVal) {
  46. if (newVal) {
  47. this.open();
  48. } else {
  49. if (this.isShow) {
  50. this.close();
  51. }
  52. }
  53. },
  54. immediate: true
  55. }
  56. },
  57. computed: {
  58. // 生成样式数据
  59. stylesObject() {
  60. let styles = {
  61. ...this.styles,
  62. "transition-duration": this.duration / 1e3 + "s"
  63. };
  64. let transform = "";
  65. for (let i in styles) {
  66. let line = this.toLine(i);
  67. transform += line + ":" + styles[i] + ";";
  68. }
  69. return transform;
  70. },
  71. // 初始化动画条件
  72. transformStyles() {
  73. return "transform:" + this.transform + ";opacity:" + this.opacity + ";" + this.stylesObject;
  74. }
  75. },
  76. created() {
  77. this.config = {
  78. duration: this.duration,
  79. timingFunction: "ease",
  80. transformOrigin: "50% 50%",
  81. delay: 0
  82. };
  83. this.durationTime = this.duration;
  84. },
  85. methods: {
  86. /**
  87. * ref 触发 初始化动画
  88. */
  89. init(obj = {}) {
  90. if (obj.duration) {
  91. this.durationTime = obj.duration;
  92. }
  93. this.animation = uni_modules_uniTransition_components_uniTransition_createAnimation.createAnimation(Object.assign(this.config, obj), this);
  94. },
  95. /**
  96. * 点击组件触发回调
  97. */
  98. onClick() {
  99. this.$emit("click", {
  100. detail: this.isShow
  101. });
  102. },
  103. /**
  104. * ref 触发 动画分组
  105. * @param {Object} obj
  106. */
  107. step(obj, config = {}) {
  108. if (!this.animation)
  109. return;
  110. for (let i in obj) {
  111. try {
  112. if (typeof obj[i] === "object") {
  113. this.animation[i](...obj[i]);
  114. } else {
  115. this.animation[i](obj[i]);
  116. }
  117. } catch (e) {
  118. console.error(`方法 ${i} 不存在`);
  119. }
  120. }
  121. this.animation.step(config);
  122. return this;
  123. },
  124. /**
  125. * ref 触发 执行动画
  126. */
  127. run(fn) {
  128. if (!this.animation)
  129. return;
  130. this.animation.run(fn);
  131. },
  132. // 开始过度动画
  133. open() {
  134. clearTimeout(this.timer);
  135. this.transform = "";
  136. this.isShow = true;
  137. let { opacity, transform } = this.styleInit(false);
  138. if (typeof opacity !== "undefined") {
  139. this.opacity = opacity;
  140. }
  141. this.transform = transform;
  142. this.$nextTick(() => {
  143. this.timer = setTimeout(() => {
  144. this.animation = uni_modules_uniTransition_components_uniTransition_createAnimation.createAnimation(this.config, this);
  145. this.tranfromInit(false).step();
  146. this.animation.run();
  147. this.$emit("change", {
  148. detail: this.isShow
  149. });
  150. }, 20);
  151. });
  152. },
  153. // 关闭过度动画
  154. close(type) {
  155. if (!this.animation)
  156. return;
  157. this.tranfromInit(true).step().run(() => {
  158. this.isShow = false;
  159. this.animationData = null;
  160. this.animation = null;
  161. let { opacity, transform } = this.styleInit(false);
  162. this.opacity = opacity || 1;
  163. this.transform = transform;
  164. this.$emit("change", {
  165. detail: this.isShow
  166. });
  167. });
  168. },
  169. // 处理动画开始前的默认样式
  170. styleInit(type) {
  171. let styles = {
  172. transform: ""
  173. };
  174. let buildStyle = (type2, mode) => {
  175. if (mode === "fade") {
  176. styles.opacity = this.animationType(type2)[mode];
  177. } else {
  178. styles.transform += this.animationType(type2)[mode] + " ";
  179. }
  180. };
  181. if (typeof this.modeClass === "string") {
  182. buildStyle(type, this.modeClass);
  183. } else {
  184. this.modeClass.forEach((mode) => {
  185. buildStyle(type, mode);
  186. });
  187. }
  188. return styles;
  189. },
  190. // 处理内置组合动画
  191. tranfromInit(type) {
  192. let buildTranfrom = (type2, mode) => {
  193. let aniNum = null;
  194. if (mode === "fade") {
  195. aniNum = type2 ? 0 : 1;
  196. } else {
  197. aniNum = type2 ? "-100%" : "0";
  198. if (mode === "zoom-in") {
  199. aniNum = type2 ? 0.8 : 1;
  200. }
  201. if (mode === "zoom-out") {
  202. aniNum = type2 ? 1.2 : 1;
  203. }
  204. if (mode === "slide-right") {
  205. aniNum = type2 ? "100%" : "0";
  206. }
  207. if (mode === "slide-bottom") {
  208. aniNum = type2 ? "100%" : "0";
  209. }
  210. }
  211. this.animation[this.animationMode()[mode]](aniNum);
  212. };
  213. if (typeof this.modeClass === "string") {
  214. buildTranfrom(type, this.modeClass);
  215. } else {
  216. this.modeClass.forEach((mode) => {
  217. buildTranfrom(type, mode);
  218. });
  219. }
  220. return this.animation;
  221. },
  222. animationType(type) {
  223. return {
  224. fade: type ? 1 : 0,
  225. "slide-top": `translateY(${type ? "0" : "-100%"})`,
  226. "slide-right": `translateX(${type ? "0" : "100%"})`,
  227. "slide-bottom": `translateY(${type ? "0" : "100%"})`,
  228. "slide-left": `translateX(${type ? "0" : "-100%"})`,
  229. "zoom-in": `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
  230. "zoom-out": `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
  231. };
  232. },
  233. // 内置动画类型与实际动画对应字典
  234. animationMode() {
  235. return {
  236. fade: "opacity",
  237. "slide-top": "translateY",
  238. "slide-right": "translateX",
  239. "slide-bottom": "translateY",
  240. "slide-left": "translateX",
  241. "zoom-in": "scale",
  242. "zoom-out": "scale"
  243. };
  244. },
  245. // 驼峰转中横线
  246. toLine(name) {
  247. return name.replace(/([A-Z])/g, "-$1").toLowerCase();
  248. }
  249. }
  250. };
  251. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  252. return common_vendor.e({
  253. a: $data.isShow
  254. }, $data.isShow ? {
  255. b: $data.animationData,
  256. c: common_vendor.n($props.customClass),
  257. d: common_vendor.s($options.transformStyles),
  258. e: common_vendor.o((...args) => $options.onClick && $options.onClick(...args))
  259. } : {});
  260. }
  261. const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__file", "/Users/RuHu.Xu/Desktop/mall-newfeifan-zx-app/uni_modules/uni-transition/components/uni-transition/uni-transition.vue"]]);
  262. wx.createComponent(Component);