update
This commit is contained in:
		| @@ -6,7 +6,7 @@ | ||||
|  * @FilePath: \dooringx\packages\dooringx-lib\src\config\index.tsx | ||||
|  */ | ||||
| import React from 'react'; | ||||
| import { IBlockType, IStoreData } from '../core/store/storetype'; | ||||
| import { IBlockType, IMainStoreData, IStoreData } from '../core/store/storetype'; | ||||
| import { ComponentClass, FunctionComponent, ReactNode } from 'react'; | ||||
| import { ComponentItemFactory } from '../core/components/abstract'; | ||||
| import { marklineConfig } from '../core/markline/marklineConfig'; | ||||
| @@ -34,6 +34,7 @@ import { VerticalAlignMiddleOutlined } from '@ant-design/icons'; | ||||
| import { wrapperMoveState } from '../components/wrapperMove/event'; | ||||
| import { wrapperMoveState as iframeWrapperMoveState } from '../components/IframeWrapperMove/event'; | ||||
| import { TimeLineConfigType, TimeLineNeedleConfigType } from '../components/timeLine/timeline'; | ||||
| import { AnimateFactory } from '../core/AnimateFactory'; | ||||
| // 组件部分 | ||||
|  | ||||
| /** | ||||
| @@ -158,7 +159,7 @@ export interface InitConfig { | ||||
| 	containerIcon: ReactNode; | ||||
| } | ||||
|  | ||||
| export const defaultStore: IStoreData = { | ||||
| export const defaultStore: IMainStoreData = { | ||||
| 	container: { | ||||
| 		width: 375, | ||||
| 		height: 667, | ||||
| @@ -173,6 +174,7 @@ export const defaultStore: IStoreData = { | ||||
| 		title: 'dooring', | ||||
| 		bodyColor: 'rgba(255,255,255,1)', | ||||
| 		script: [], | ||||
| 		customAnimate: [], | ||||
| 	}, | ||||
| 	modalConfig: {}, | ||||
| }; | ||||
| @@ -337,6 +339,7 @@ export class UserConfig { | ||||
| 	public componentRegister = new ComponentRegister(); | ||||
| 	public formRegister = new FormComponentRegister(); | ||||
| 	public storeChanger = new StoreChanger(); | ||||
| 	public animateFactory = new AnimateFactory(); | ||||
| 	public componentCache = {}; | ||||
| 	public asyncComponentUrlMap = {} as AsyncCacheComponentType; | ||||
| 	public marklineConfig = marklineConfig; | ||||
|   | ||||
							
								
								
									
										178
									
								
								packages/dooringx-lib/src/core/AnimateFactory/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								packages/dooringx-lib/src/core/AnimateFactory/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| import UserConfig from '../../config'; | ||||
| import { CustomAnimateObj, IMainStoreData, IStoreData } from '../store/storetype'; | ||||
| import { deepCopy } from '../utils'; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  *  opacity: 100 | ||||
|     percent: 0 | ||||
|     positionX: 0 | ||||
|     positionY: 0 | ||||
|     rotate: 0 | ||||
|     scale: 100 | ||||
|  * @export 转换使用 | ||||
|  * @interface TransformItemObj | ||||
|  */ | ||||
| export interface TransformItemObj { | ||||
| 	opacity: number; | ||||
| 	percent: number; | ||||
| 	positionX: number | null; | ||||
| 	positionY: number | null; | ||||
| 	rotate: number; | ||||
| 	scale: number; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * | ||||
|  * @export 用户输入对象 | ||||
|  * @interface TransformItem | ||||
|  */ | ||||
| export interface TransformItem { | ||||
| 	displayName: string; | ||||
| 	animateName: string; | ||||
| 	keyframes: TransformItemObj[]; | ||||
| } | ||||
|  | ||||
| export class AnimateFactory { | ||||
| 	constructor(public customAnimateName: Array<CustomAnimateObj> = []) {} | ||||
|  | ||||
| 	getCustomAnimateName() { | ||||
| 		return this.customAnimateName; | ||||
| 	} | ||||
| 	getStyleSheets() { | ||||
| 		return document.styleSheets; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * 插入动画 | ||||
| 	 * @param {string} ruleText | ||||
| 	 * @param {string} keyframeName 动画名称 | ||||
| 	 * @memberof AnimateFactory | ||||
| 	 */ | ||||
| 	inserKeyframeAnimate(ruleText: string, keyframeName: string) { | ||||
| 		const sheets = this.getStyleSheets(); | ||||
| 		if (sheets.length === 0) { | ||||
| 			let style = document.createElement('style'); | ||||
| 			style.appendChild(document.createTextNode('')); | ||||
| 			document.head.appendChild(style); | ||||
| 		} | ||||
| 		const len = sheets.length; | ||||
| 		let ss: number | null = null; | ||||
| 		let st: number | null = null; | ||||
| 		for (let i = 0; i < len; i++) { | ||||
| 			for (let k = 0; k < sheets[i].cssRules.length; k++) { | ||||
| 				const rule = sheets[i].cssRules[k] as CSSKeyframesRule; | ||||
| 				const name = rule?.name; | ||||
| 				if (name && name === keyframeName) { | ||||
| 					// 删除该keyframe | ||||
| 					ss = i; | ||||
| 					st = k; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if (ss !== null && st !== null) { | ||||
| 			sheets[ss].deleteRule(st); | ||||
| 		} | ||||
| 		let sheet = sheets[ss ? ss : sheets.length - 1] as CSSStyleSheet; | ||||
| 		sheet.insertRule(ruleText, sheet.rules ? sheet.rules.length : sheet.cssRules.length); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * 配置时使用 | ||||
| 	 * @param {Array<CustomAnimateObj>} [customAnimateNameArr=[]] | ||||
| 	 * @memberof AnimateFactory | ||||
| 	 */ | ||||
| 	addCustomAnimate(customAnimateNameArr: Array<CustomAnimateObj> = []) { | ||||
| 		this.customAnimateName = [...this.customAnimateName, ...customAnimateNameArr]; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * 删除使用animateName 防止displayName重名 用完需要同步store | ||||
| 	 * @param {string} animateName | ||||
| 	 * @memberof AnimateFactory | ||||
| 	 */ | ||||
| 	deleteCustomAnimate(animateName: string) { | ||||
| 		this.customAnimateName = this.customAnimateName.filter((v) => v.animateName !== animateName); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * 从配置项插入动画 导入设置 | ||||
| 	 * @memberof AnimateFactory | ||||
| 	 */ | ||||
| 	fromArrInsertKeyFrame(customAnimateName: Array<CustomAnimateObj> = this.customAnimateName) { | ||||
| 		customAnimateName.forEach((v) => { | ||||
| 			this.inserKeyframeAnimate(v.keyframe, v.animateName); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * 将this.customAnimateName写入store | ||||
| 	 * @memberof AnimateFactory | ||||
| 	 */ | ||||
| 	syncToStore(config: UserConfig) { | ||||
| 		// 先判断global的位置 | ||||
| 		const store = config.getStore(); | ||||
| 		let data: IStoreData; | ||||
| 		const isEdit = config.getStoreChanger().isEdit(); | ||||
| 		if (isEdit) { | ||||
| 			const origin = config.getStoreChanger().getOrigin()!; | ||||
| 			data = origin.data[origin.current]; | ||||
| 		} else { | ||||
| 			data = store.getData(); | ||||
| 		} | ||||
| 		const copy: IMainStoreData = deepCopy(data); | ||||
| 		const originGlobal = copy.globalState as IMainStoreData['globalState']; | ||||
| 		originGlobal.customAnimate = [...this.customAnimateName]; | ||||
| 		if (isEdit) { | ||||
| 			config.getStoreChanger().updateOrigin(copy); | ||||
| 		} else { | ||||
| 			store.setData(copy); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * 将用户输入转换为新的动画 | ||||
| 	 * @param {TransformItem} item | ||||
| 	 * @memberof AnimateFactory | ||||
| 	 */ | ||||
| 	addUserInputIntoCustom(item: TransformItem, config: UserConfig) { | ||||
| 		// 先转换keyframe | ||||
| 		const keyframeItem = item.keyframes.map((v) => { | ||||
| 			if (v.positionX !== null && v.positionY !== null) { | ||||
| 				// 带入xy 否则不计算xy | ||||
| 				return `${v.percent}% { | ||||
|             transform:translate(${v.positionX}px, ${v.positionY}px) scale(${(v.scale / 100).toFixed( | ||||
| 					2 | ||||
| 				)}) rotate(${v.rotate}deg); | ||||
|          }`; | ||||
| 			} else { | ||||
| 				return `${v.percent}% { | ||||
|           transform: scale(${(v.scale / 100).toFixed(2)}) rotate(${v.rotate}deg); | ||||
|        }`; | ||||
| 			} | ||||
| 		}); | ||||
| 		const keyframe = `@keyframes ${item.animateName} { | ||||
|       ${keyframeItem.join(' ')} | ||||
|     }`; | ||||
| 		const customAnimateNameArr: CustomAnimateObj[] = [ | ||||
| 			{ | ||||
| 				displayName: item.displayName, | ||||
| 				keyframe, | ||||
| 				animateName: item.animateName, | ||||
| 			}, | ||||
| 		]; | ||||
| 		// 添加内置 | ||||
| 		this.addCustomAnimate(customAnimateNameArr); | ||||
| 		// 插入动画 | ||||
| 		this.inserKeyframeAnimate(keyframe, item.animateName); | ||||
| 		// 写入store | ||||
| 		this.syncToStore(config); | ||||
| 	} | ||||
| } | ||||
| @@ -1,82 +0,0 @@ | ||||
| export interface CustomAnimateObj { | ||||
| 	displayName: string; | ||||
| 	animateName: string; | ||||
| 	keyframe: string; | ||||
| } | ||||
|  | ||||
| export class DynamicAnimate { | ||||
| 	constructor(public customAnimateName: Array<CustomAnimateObj> = []) {} | ||||
|  | ||||
| 	getCustomAnimateName() { | ||||
| 		return this.customAnimateName; | ||||
| 	} | ||||
| 	getStyleSheets() { | ||||
| 		return document.styleSheets; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * 插入动画 | ||||
| 	 * @param {string} ruleText | ||||
| 	 * @param {string} keyframeName | ||||
| 	 * @memberof DynamicAnimate | ||||
| 	 */ | ||||
| 	inserKeyframeAnimate(ruleText: string, keyframeName: string) { | ||||
| 		const sheets = this.getStyleSheets(); | ||||
| 		if (sheets.length === 0) { | ||||
| 			let style = document.createElement('style'); | ||||
| 			style.appendChild(document.createTextNode('')); | ||||
| 			document.head.appendChild(style); | ||||
| 		} | ||||
| 		const len = sheets.length; | ||||
| 		let ss: number | null = null; | ||||
| 		let st: number | null = null; | ||||
| 		for (let i = 0; i < len; i++) { | ||||
| 			for (let k = 0; k < sheets[i].cssRules.length; k++) { | ||||
| 				const rule = sheets[i].cssRules[k] as CSSKeyframesRule; | ||||
| 				const name = rule?.name; | ||||
| 				if (name && name === keyframeName) { | ||||
| 					// 删除该keyframe | ||||
| 					ss = i; | ||||
| 					st = k; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if (ss !== null && st !== null) { | ||||
| 			sheets[ss].deleteRule(st); | ||||
| 		} | ||||
| 		let sheet = sheets[ss ? ss : sheets.length - 1] as CSSStyleSheet; | ||||
| 		sheet.insertRule(ruleText, sheet.rules ? sheet.rules.length : sheet.cssRules.length); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * 配置时使用 | ||||
| 	 * @param {Array<CustomAnimateObj>} [customAnimateName=[]] | ||||
| 	 * @memberof DynamicAnimate | ||||
| 	 */ | ||||
| 	addCustomAnimate(customAnimateName: Array<CustomAnimateObj> = []) { | ||||
| 		this.customAnimateName = [...this.customAnimateName, ...customAnimateName]; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * 删除使用animateName 防止displayName重名 | ||||
| 	 * @param {string} animateName | ||||
| 	 * @memberof DynamicAnimate | ||||
| 	 */ | ||||
| 	deleteCustomAnimate(animateName: string) { | ||||
| 		this.customAnimateName = this.customAnimateName.filter((v) => v.animateName !== animateName); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * | ||||
| 	 * 从配置项插入动画 导入设置 | ||||
| 	 * @memberof DynamicAnimate | ||||
| 	 */ | ||||
| 	fromArrInsertKeyFrame(customAnimateName: Array<CustomAnimateObj> = this.customAnimateName) { | ||||
| 		customAnimateName.forEach((v) => { | ||||
| 			this.inserKeyframeAnimate(v.keyframe, v.animateName); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| @@ -8,6 +8,15 @@ | ||||
|  | ||||
| import { EventCenterMapType } from '../eventCenter'; | ||||
|  | ||||
| export interface GlobalState { | ||||
| 	[key: string]: any; | ||||
| 	customAnimate: CustomAnimateObj[]; | ||||
| 	containerColor: string; | ||||
| 	title: string; | ||||
| 	bodyColor: string; | ||||
| 	script: string[]; | ||||
| } | ||||
|  | ||||
| export interface IStoreData { | ||||
| 	container: { | ||||
| 		width: number; | ||||
| @@ -19,6 +28,10 @@ export interface IStoreData { | ||||
| 	globalState: Record<string, any>; | ||||
| 	modalConfig: Record<string, any>; | ||||
| } | ||||
| export interface IMainStoreData extends IStoreData { | ||||
| 	globalState: GlobalState; | ||||
| } | ||||
|  | ||||
| export interface AnimateItem { | ||||
| 	uid: string; | ||||
| 	animationName: string; | ||||
| @@ -26,8 +39,12 @@ export interface AnimateItem { | ||||
| 	animationDelay: number; | ||||
| 	animationIterationCount: string; | ||||
| 	animationTimingFunction: string; | ||||
| 	isCustom?: boolean; | ||||
| 	customKeyFrame?: string; | ||||
| } | ||||
|  | ||||
| export interface CustomAnimateObj { | ||||
| 	displayName: string; | ||||
| 	animateName: string; | ||||
| 	keyframe: string; | ||||
| } | ||||
|  | ||||
| export interface IBlockType { | ||||
|   | ||||
| @@ -82,6 +82,12 @@ export class StoreChanger { | ||||
| 		return this.map[ORIGIN]; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 *  判断是否在编辑模式。 | ||||
| 	 *  一次也没进行编辑时,storeChanger中未存store,所以只能判断去获取。 | ||||
| 	 * @return {*} | ||||
| 	 * @memberof StoreChanger | ||||
| 	 */ | ||||
| 	isEdit() { | ||||
| 		if (storeChangerState.modalEditName !== '') { | ||||
| 			return true; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 hufeixiong
					hufeixiong