UNPKG

@cloudgpt/timeline-editor

Version:

Enhanced React timeline editor with advanced features including theme system, max duration controls, cursor customization, handle styling, and media support for video editing applications.

1,517 lines (1,504 loc) 111 kB
import React, { useRef, useEffect, cloneElement, useImperativeHandle, useState, useLayoutEffect, useMemo } from 'react'; import { AutoSizer, Grid, ScrollSync } from 'react-virtualized'; import { prefixNames } from 'framework-utils'; import interact from 'interactjs'; function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } /** * 事件派发器 */ var Emitter = /*#__PURE__*/function () { function Emitter(events) { _classCallCheck(this, Emitter); this.events = {}; this.events = events.handlers; } return _createClass(Emitter, [{ key: "on", value: function on(names, handler) { var _this = this; var events = names instanceof Array ? names : names.split(' '); events.forEach(function (name) { if (!_this.events[name]) { throw new Error("The event ".concat(name, " does not exist")); } _this.events[name].push(handler); }); return this; } }, { key: "trigger", value: function trigger(name, params) { if (!(name in this.events)) { throw new Error("The event ".concat(String(name), " cannot be triggered")); } return this.events[name].reduce(function (r, e) { return e(params) !== false && r; }, true); // return false if at least one event is false } }, { key: "bind", value: function bind(name) { if (this.events[name]) { throw new Error("The event ".concat(name, " is already bound")); } this.events[name] = []; } }, { key: "exist", value: function exist(name) { return Array.isArray(this.events[name]); } }, { key: "off", value: function off(name, handler) { if (this.events[name]) { var listener = this.events[name]; if (!handler) this.events[name] = [];else { var index = listener.indexOf(handler); if (index !== -1) listener.splice(index, 1); } } } }, { key: "offAll", value: function offAll() { this.events = Object.fromEntries(Object.keys(this.events).map(function (name) { return [name, []]; })); } }]); }(); var Events = /*#__PURE__*/_createClass(function Events() { var handlers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, Events); this.handlers = {}; this.handlers = _objectSpread2({ beforeSetTime: [], afterSetTime: [], setTimeByTick: [], beforeSetPlayRate: [], afterSetPlayRate: [], setActiveActionIds: [], play: [], paused: [], ended: [] }, handlers); }); var PLAYING = 'playing'; var PAUSED = 'paused'; /** * 时间轴播放器 * 可脱离编辑器单独运行 * @export * @class TimelineEngine * @extends {Emitter<EventTypes>} */ var TimelineEngine = /*#__PURE__*/function (_Emitter) { function TimelineEngine() { var _this; _classCallCheck(this, TimelineEngine); _this = _callSuper(this, TimelineEngine, [new Events()]); /** requestAnimationFrame timerId */ _this._timerId = void 0; /** 播放速率 */ _this._playRate = 1; /** 当前时间 */ _this._currentTime = 0; /** 播放状态 */ _this._playState = 'paused'; /** 时间帧pre数据 */ _this._prev = void 0; /** 动作效果map */ _this._effectMap = {}; /** 需要运行的动作map */ _this._actionMap = {}; /** 按动作开始时间正序排列后的动作id数组 */ _this._actionSortIds = []; /** 当前遍历到的action index */ _this._next = 0; /** 动作时间范围包含当前时间的actionId列表 */ _this._activeActionIds = []; return _this; } _inherits(TimelineEngine, _Emitter); return _createClass(TimelineEngine, [{ key: "isPlaying", get: /** 是否正在播放 */ function get() { return this._playState === 'playing'; } /** 是否暂停中 */ }, { key: "isPaused", get: function get() { return this._playState === 'paused'; } }, { key: "effects", set: function set(effects) { this._effectMap = effects; } }, { key: "data", set: function set(data) { if (this.isPlaying) this.pause(); this._dealData(data); this._dealClear(); this._dealEnter(this._currentTime); } /** * 设置播放速率 * @memberof TimelineEngine */ }, { key: "setPlayRate", value: function setPlayRate(rate) { if (rate <= 0) { console.error('Error: rate cannot be less than 0!'); return; } var result = this.trigger('beforeSetPlayRate', { rate: rate, engine: this }); if (!result) return false; this._playRate = rate; this.trigger('afterSetPlayRate', { rate: rate, engine: this }); return true; } /** * 获取播放速率 * @memberof TimelineEngine */ }, { key: "getPlayRate", value: function getPlayRate() { return this._playRate; } /** * 重新渲染当前时间 * @return {*} * @memberof TimelineEngine */ }, { key: "reRender", value: function reRender() { if (this.isPlaying) return; this._tickAction(this._currentTime); } /** * 设置播放时间 * @param {number} time * @param {boolean} [isTick] 是否是tick触发 * @memberof TimelineEngine */ }, { key: "setTime", value: function setTime(time, isTick) { // Ensure time is never negative time = Math.max(0, time); var result = isTick || this.trigger('beforeSetTime', { time: time, engine: this }); if (!result) return false; this._currentTime = time; this._next = 0; this._dealLeave(time); this._dealEnter(time); if (isTick) this.trigger('setTimeByTick', { time: time, engine: this });else this.trigger('afterSetTime', { time: time, engine: this }); return true; } /** * 获取当前时间 * @return {*} {number} * @memberof TimelineEngine */ }, { key: "getTime", value: function getTime() { return this._currentTime; } /** * 运行: 开始时间为当前time * @param param * @return {boolean} {boolean} */ }, { key: "play", value: function play(param) { var _this2 = this; var toTime = param.toTime, autoEnd = param.autoEnd; var currentTime = this.getTime(); /** 当前状体啊正在播放中 or 运行终止时间小于开始时间 直接返回*/ if (this.isPlaying || toTime && toTime <= currentTime) return false; // 设置运行状态 this._playState = PLAYING; // activeIds 运行 start this._startOrStop('start'); // 触发事件 this.trigger('play', { engine: this }); this._timerId = requestAnimationFrame(function (time) { _this2._prev = time; _this2._tick({ now: time, autoEnd: autoEnd, to: toTime }); }); return true; } /** * 暂停播放 * @memberof TimelineEngine */ }, { key: "pause", value: function pause() { if (this.isPlaying) { this._playState = PAUSED; // activeIds 运行 stop this._startOrStop('stop'); this.trigger('paused', { engine: this }); } cancelAnimationFrame(this._timerId); } /** 播放完成 */ }, { key: "_end", value: function _end() { this.pause(); this.trigger('ended', { engine: this }); } }, { key: "_startOrStop", value: function _startOrStop(type) { for (var i = 0; i < this._activeActionIds.length; i++) { var actionId = this._activeActionIds[i]; var action = this._actionMap[actionId]; var effect = this._effectMap[action === null || action === void 0 ? void 0 : action.effectId]; if (type === 'start') { var _effect$source; (effect === null || effect === void 0 ? void 0 : (_effect$source = effect.source) === null || _effect$source === void 0 ? void 0 : _effect$source.start) && effect.source.start({ action: action, effect: effect, engine: this, isPlaying: this.isPlaying, time: this.getTime() }); } else if (type === 'stop') { var _effect$source2; (effect === null || effect === void 0 ? void 0 : (_effect$source2 = effect.source) === null || _effect$source2 === void 0 ? void 0 : _effect$source2.stop) && effect.source.stop({ action: action, effect: effect, engine: this, isPlaying: this.isPlaying, time: this.getTime() }); } } } /** 每帧执行 */ }, { key: "_tick", value: function _tick(data) { var _this3 = this; if (this.isPaused) return; var now = data.now, autoEnd = data.autoEnd, to = data.to; // 计算当前时间 var currentTime = this.getTime() + Math.min(1000, now - this._prev) / 1000 * this._playRate; this._prev = now; // 设置当前时间 if (to && to <= currentTime) currentTime = to; this.setTime(currentTime, true); // 执行动作 this._tickAction(currentTime); // 自动停止情况下,判断是否所有动作执行完毕 if (!to && autoEnd && this._next >= this._actionSortIds.length && this._activeActionIds.length === 0) { this._end(); return; } // 判断是否终止 if (to && to <= currentTime) { this._end(); } if (this.isPaused) return; this._timerId = requestAnimationFrame(function (time) { _this3._tick({ now: time, autoEnd: autoEnd, to: to }); }); } /** tick运行actions */ }, { key: "_tickAction", value: function _tickAction(time) { this._dealEnter(time); this._dealLeave(time); // render var length = this._activeActionIds.length; for (var i = 0; i < length; i++) { var _effect$source3; var actionId = this._activeActionIds[i]; var action = this._actionMap[actionId]; var effect = this._effectMap[action.effectId]; if (effect && ((_effect$source3 = effect.source) === null || _effect$source3 === void 0 ? void 0 : _effect$source3.update)) { effect.source.update({ time: time, action: action, isPlaying: this.isPlaying, effect: effect, engine: this }); } } } /** 重置active数据 */ }, { key: "_dealClear", value: function _dealClear() { while (this._activeActionIds.length) { var _effect$source4; var actionId = this._activeActionIds.shift(); var action = this._actionMap[actionId]; var effect = this._effectMap[action === null || action === void 0 ? void 0 : action.effectId]; if (effect === null || effect === void 0 ? void 0 : (_effect$source4 = effect.source) === null || _effect$source4 === void 0 ? void 0 : _effect$source4.leave) { effect.source.leave({ action: action, effect: effect, engine: this, isPlaying: this.isPlaying, time: this.getTime() }); } } this._next = 0; } /** 处理action time enter */ }, { key: "_dealEnter", value: function _dealEnter(time) { // add to active while (this._actionSortIds[this._next]) { var actionId = this._actionSortIds[this._next]; var action = this._actionMap[actionId]; if (!action.disable) { // 判断动作开始时间是否到达 if (action.start > time) break; // 动作可以执行开始 if (action.end > time && !this._activeActionIds.includes(actionId)) { var _effect$source5; var effect = this._effectMap[action.effectId]; if (effect && ((_effect$source5 = effect.source) === null || _effect$source5 === void 0 ? void 0 : _effect$source5.enter)) { effect.source.enter({ action: action, effect: effect, isPlaying: this.isPlaying, time: time, engine: this }); } this._activeActionIds.push(actionId); } } this._next++; } } /** 处理action time leave */ }, { key: "_dealLeave", value: function _dealLeave(time) { var i = 0; while (this._activeActionIds[i]) { var actionId = this._activeActionIds[i]; var action = this._actionMap[actionId]; // 不在播放区域内 if (action.start > time || action.end < time) { var _effect$source6; var effect = this._effectMap[action.effectId]; if (effect && ((_effect$source6 = effect.source) === null || _effect$source6 === void 0 ? void 0 : _effect$source6.leave)) { effect.source.leave({ action: action, effect: effect, isPlaying: this.isPlaying, time: time, engine: this }); } this._activeActionIds.splice(i, 1); continue; } i++; } } /** 处理数据 */ }, { key: "_dealData", value: function _dealData(data) { var actions = []; data.map(function (row) { actions.push.apply(actions, _toConsumableArray(row.actions)); }); var sortActions = actions.sort(function (a, b) { return a.start - b.start; }); var actionMap = {}; var actionSortIds = []; sortActions.forEach(function (action) { actionSortIds.push(action.id); actionMap[action.id] = _objectSpread2({}, action); }); this._actionMap = actionMap; this._actionSortIds = actionSortIds; } }]); }(Emitter); var PREFIX = "timeline-editor"; /** 开始时光标所在时间 */ var START_CURSOR_TIME = 0; /** 默认刻度 */ var DEFAULT_SCALE = 1; /** 默认刻度分割数量 */ var DEFAULT_SCALE_SPLIT_COUNT = 10; /** 默认刻度显示宽度 */ var DEFAULT_SCALE_WIDTH = 160; /** 默认刻度左侧开始距离 */ var DEFAULT_START_LEFT = 20; /** 默认移动最小像素 */ var DEFAULT_MOVE_GRID = 1; /** 默认吸附像素 */ var DEFAULT_ADSORPTION_DISTANCE = 8; /** 默认动作行高度 */ var DEFAULT_ROW_HEIGHT = 32; /** 最小scale数量 */ var MIN_SCALE_COUNT = 20; /** 每次新增scale个数 */ var ADD_SCALE_COUNT = 5; var LogLevel; (function (LogLevel) { LogLevel[LogLevel["VERBOSE"] = 0] = "VERBOSE"; LogLevel[LogLevel["LOG"] = 1] = "LOG"; LogLevel[LogLevel["INFO"] = 2] = "INFO"; LogLevel[LogLevel["WARN"] = 3] = "WARN"; LogLevel[LogLevel["ERROR"] = 4] = "ERROR"; LogLevel[LogLevel["FATAL"] = 5] = "FATAL"; LogLevel[LogLevel["SILENT"] = Infinity] = "SILENT"; })(LogLevel || (LogLevel = {})); var LogLevels = { VERBOSE: LogLevel.VERBOSE, LOG: LogLevel.LOG, INFO: LogLevel.INFO, WARN: LogLevel.WARN, ERROR: LogLevel.ERROR, SILENT: LogLevel.SILENT }; function colorize(hex, x) { return "color:".concat(hex, ";font-size:").concat(x, "px;"); } var ConsoleLogger = /*#__PURE__*/function () { /** * ConsoleLogger * @param {string} prefix Logger prefix * @return {ConsoleLogger} */ function ConsoleLogger(prefix) { _classCallCheck(this, ConsoleLogger); this.Levels = LogLevels; this.level = LogLevel.LOG; this.prefix = ''; this.enabled = true; this.debugColor = colorize('#cccccc', 12); this.logColor = colorize('#bbbbbb', 12); this.infoColor = colorize('#2196f3', 12); this.warnColor = colorize('#ff00ff', 12); this.errorColor = colorize('#e91e63', 12); this.fatalColor = colorize('#9a0101', 13); this.setPrefix(prefix); this.level = ConsoleLogger.level; ConsoleLogger.instances.push(this); } return _createClass(ConsoleLogger, [{ key: "setPrefix", value: /** * set logger prefix * @param prefix */ function setPrefix(prefix) { this.prefix = prefix; } /** * enable logger with optional log level * @param level */ }, { key: "enable", value: function enable() { var level = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.level; this.level = level; this.enabled = true; } /** * disable logger */ }, { key: "disable", value: function disable() { this.enabled = false; } /** * Set log level * @param {LogLevel} level * @return {void} */ }, { key: "setLevel", value: function setLevel(level) { this.level = level; } /** * trace * @param title * @param args */ }, { key: "trace", value: function trace(title) { if (!this.enabled || this.level > LogLevel.VERBOSE) { return; } for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } if (ConsoleLogger.noColor) { var _console; (_console = console).trace.apply(_console, ["[".concat(this.prefix, "] ").concat(title)].concat(args)); } else { var _console2; (_console2 = console).trace.apply(_console2, ["%c[".concat(this.prefix, "] ").concat(title), this.debugColor].concat(args)); } } /** * debug * @param title * @param args */ }, { key: "debug", value: function debug(title) { if (!this.enabled || this.level > LogLevel.VERBOSE) { return; } for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } if (ConsoleLogger.noColor) { var _console3; (_console3 = console).debug.apply(_console3, ["[".concat(this.prefix, "] ").concat(title)].concat(args)); } else { var _console4; (_console4 = console).debug.apply(_console4, ["%c[".concat(this.prefix, "] ").concat(title), this.debugColor].concat(args)); } } /** * log * @param title * @param args */ }, { key: "log", value: function log(title) { if (!this.enabled || this.level > LogLevel.LOG) { return; } for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { args[_key3 - 1] = arguments[_key3]; } if (ConsoleLogger.noColor) { var _console5; (_console5 = console).log.apply(_console5, ["[".concat(this.prefix, "] ").concat(title)].concat(args)); } else { var _console6; (_console6 = console).log.apply(_console6, ["%c[".concat(this.prefix, "] ").concat(title), this.logColor].concat(args)); } } /** * info * @param title * @param args */ }, { key: "info", value: function info(title) { if (!this.enabled || this.level > LogLevel.INFO) { return; } for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { args[_key4 - 1] = arguments[_key4]; } if (ConsoleLogger.noColor) { var _console7; (_console7 = console).info.apply(_console7, ["[".concat(this.prefix, "] ").concat(title)].concat(args)); } else { var _console8; (_console8 = console).info.apply(_console8, ["%c[".concat(this.prefix, "] ").concat(title), this.infoColor].concat(args)); } } /** * warn * @param title * @param args */ }, { key: "warn", value: function warn(title) { if (!this.enabled || this.level > LogLevel.WARN) { return; } for (var _len5 = arguments.length, args = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { args[_key5 - 1] = arguments[_key5]; } if (ConsoleLogger.noColor) { var _console9; (_console9 = console).warn.apply(_console9, ["[".concat(this.prefix, "] ").concat(title)].concat(args)); } else { var _console0; (_console0 = console).warn.apply(_console0, ["%c[".concat(this.prefix, "] ").concat(title), this.warnColor].concat(args)); } } /** * error * @param title * @param args */ }, { key: "error", value: function error(title) { if (!this.enabled || this.level > LogLevel.ERROR) { return; } for (var _len6 = arguments.length, args = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) { args[_key6 - 1] = arguments[_key6]; } if (ConsoleLogger.noColor) { var _console1; (_console1 = console).error.apply(_console1, ["[".concat(this.prefix, "] ").concat(title)].concat(args)); } else { var _console10; (_console10 = console).error.apply(_console10, ["%c[".concat(this.prefix, "] ").concat(title), this.errorColor].concat(args)); } } /** * fatal error * @param title * @param args */ }, { key: "fatal", value: function fatal(title) { if (!this.enabled || this.level > LogLevel.FATAL) { return; } for (var _len7 = arguments.length, args = new Array(_len7 > 1 ? _len7 - 1 : 0), _key7 = 1; _key7 < _len7; _key7++) { args[_key7 - 1] = arguments[_key7]; } if (ConsoleLogger.noColor) { var _console11; (_console11 = console).error.apply(_console11, ["[".concat(this.prefix, "] ").concat(title)].concat(args)); } else { var _console12; (_console12 = console).error.apply(_console12, ["%c[".concat(this.prefix, "] ").concat(title), this.fatalColor].concat(args)); } } /** * start a group with label * @param label */ }, { key: "group", value: function group() { if (console.group) { var _console13; (_console13 = console).group.apply(_console13, arguments); } } /** * end a group */ }, { key: "groupEnd", value: function groupEnd() { if (console.groupEnd) { console.groupEnd(); } } /** * collapse log group * @param label */ }, { key: "groupCollapsed", value: function groupCollapsed() { if (console.groupCollapsed) { var _console14; (_console14 = console).groupCollapsed.apply(_console14, arguments); } } }], [{ key: "setLevel", value: function setLevel(level) { this.level = level; this.instances.forEach(function (logger) { return logger.setLevel(level); }); } }, { key: "enable", value: function enable(level) { if (level) { this.level = level; } this.instances.forEach(function (logger) { return logger.enable(); }); } }, { key: "disable", value: function disable() { this.instances.forEach(function (logger) { return logger.disable(); }); } }]); }(); ConsoleLogger.instances = []; ConsoleLogger.level = LogLevel.LOG; ConsoleLogger.Levels = LogLevels; ConsoleLogger.noColor = false; var logger = new ConsoleLogger('timeline'); function checkProps(props) { var _props$editorData = props.editorData, editorData = _props$editorData === void 0 ? [] : _props$editorData, _props$effects = props.effects, effects = _props$effects === void 0 ? {} : _props$effects, _props$scrollTop = props.scrollTop, scrollTop = _props$scrollTop === void 0 ? 0 : _props$scrollTop, _props$scale = props.scale, scale = _props$scale === void 0 ? DEFAULT_SCALE : _props$scale, _props$scaleSplitCoun = props.scaleSplitCount, scaleSplitCount = _props$scaleSplitCoun === void 0 ? DEFAULT_SCALE_SPLIT_COUNT : _props$scaleSplitCoun, _props$scaleWidth = props.scaleWidth, scaleWidth = _props$scaleWidth === void 0 ? DEFAULT_SCALE_WIDTH : _props$scaleWidth, _props$startLeft = props.startLeft, startLeft = _props$startLeft === void 0 ? DEFAULT_START_LEFT : _props$startLeft, _props$minScaleCount = props.minScaleCount, minScaleCount = _props$minScaleCount === void 0 ? MIN_SCALE_COUNT : _props$minScaleCount, _props$maxScaleCount = props.maxScaleCount, maxScaleCount = _props$maxScaleCount === void 0 ? Infinity : _props$maxScaleCount, maxDuration = props.maxDuration, _props$rowHeight = props.rowHeight, rowHeight = _props$rowHeight === void 0 ? DEFAULT_ROW_HEIGHT : _props$rowHeight, _props$rowGap = props.rowGap, rowGap = _props$rowGap === void 0 ? 0 : _props$rowGap, theme = props.theme, sizing = props.sizing, handles = props.handles, cursor = props.cursor, animations = props.animations, behavior = props.behavior; // Default configurations var defaultTheme = { backgroundColor: '#191b1d', foregroundColor: '#ffffff', gridColor: 'rgba(255, 255, 255, 0.08)', cursorColor: '#ff6b35', selectionColor: '#0078d4', rowBackgroundColor: 'transparent', rowBorderColor: 'rgba(255, 255, 255, 0.1)', actionBackgroundColor: '#2f3134', actionBorderColor: 'rgba(255, 255, 255, 0.2)', dragLineColor: '#ff6b35', scaleTextColor: '#ffffff', scaleBackgroundColor: '#242629' }; var defaultSizing = { actionBorderRadius: 4, actionBorderWidth: 1, handleWidth: 14, handleHeightRatio: 0.7, handleBorderRadius: 999, timeAreaHeight: 32, controlAreaWidth: 200 }; var defaultCursor = { cursorColor: '#ff6b35', cursorWidth: 2, cursorStyle: 'solid', cursorOpacity: 1, showCursorHead: true, cursorHeadColor: 'inherit', cursorHeadSize: 10, cursorShadow: 'none', cursorZIndex: 100 }; var defaultHandles = { handleBackground: 'linear-gradient(180deg, rgba(255,255,255,.25), rgba(255,255,255,.12))', handleBorderColor: 'rgba(255,255,255,.3)', handleHoverOpacity: 1, handleOpacity: 0.3, showHandles: true }; var defaultAnimations = { handleTransitionDuration: 120, handleTransitionEasing: 'ease-in-out', actionHoverScale: 1.02, actionHoverDuration: 150, cursorTransitionDuration: 120, enableAnimations: true }; var defaultBehavior = { dragSensitivity: 1, resizeSensitivity: 1, doubleClickAction: 'select', contextMenuBehavior: 'show', allowMultiSelection: false, selectionMode: 'single', dragBoundsBehavior: 'clamp' }; // Merge with defaults var mergedTheme = _objectSpread2(_objectSpread2({}, defaultTheme), theme); var mergedSizing = _objectSpread2(_objectSpread2({}, defaultSizing), sizing); var mergedHandles = _objectSpread2(_objectSpread2({}, defaultHandles), handles); var mergedCursor = _objectSpread2(_objectSpread2({}, defaultCursor), cursor); var mergedAnimations = _objectSpread2(_objectSpread2({}, defaultAnimations), animations); var mergedBehavior = _objectSpread2(_objectSpread2({}, defaultBehavior), behavior); if (scale <= 0) { logger.error('Error: scale must be greater than 0!'); scale = DEFAULT_SCALE; } if (scrollTop < 0) { logger.warn('Warning: scrollTop cannot be less than 0!'); scrollTop = 0; } if (scaleSplitCount <= 0) { logger.warn('Warning: scaleSplitCount cannot be less than 1!'); scaleSplitCount = 1; } if (scaleWidth <= 0) { logger.warn('Warning: scaleWidth must be greater than 0!'); scaleWidth = DEFAULT_SCALE_WIDTH; } if (startLeft < 0) { logger.warn('Warning: startLeft cannot be less than 0!'); startLeft = 0; } if (minScaleCount < 1) { logger.warn('Warning: minScaleCount must be greater than 1!'); minScaleCount = MIN_SCALE_COUNT; } minScaleCount = parseInt(minScaleCount + ''); if (maxScaleCount < minScaleCount) { logger.warn('Warning: maxScaleCount cannot be less than minScaleCount!'); maxScaleCount = minScaleCount; } maxScaleCount = maxScaleCount === Infinity ? Infinity : parseInt(maxScaleCount + ''); if (maxDuration !== undefined && maxDuration <= 0) { logger.warn('Warning: maxDuration must be greater than 0!'); maxDuration = undefined; } if (rowHeight <= 0) { logger.warn('Warning: rowHeight must be greater than 0!'); rowHeight = DEFAULT_ROW_HEIGHT; } if (rowGap < 0) { logger.warn('Warning: rowGap cannot be less than 0!'); rowGap = 0; } var temp = _objectSpread2({}, props); delete temp['style']; return _objectSpread2(_objectSpread2({}, temp), {}, { editorData: editorData, effects: effects, scrollTop: scrollTop, scale: scale, scaleSplitCount: scaleSplitCount, scaleWidth: scaleWidth, startLeft: startLeft, minScaleCount: minScaleCount, maxScaleCount: maxScaleCount, maxDuration: maxDuration, rowHeight: rowHeight, rowGap: rowGap, theme: mergedTheme, sizing: mergedSizing, handles: mergedHandles, cursor: mergedCursor, animations: mergedAnimations, behavior: mergedBehavior }); } /** 时间转像素 */ function parserTimeToPixel(data, param) { var startLeft = param.startLeft, scale = param.scale, scaleWidth = param.scaleWidth; return startLeft + data / scale * scaleWidth; } /** 像素转时间 */ function parserPixelToTime(data, param) { var startLeft = param.startLeft, scale = param.scale, scaleWidth = param.scaleWidth; return (data - startLeft) / scaleWidth * scale; } /** 位置 + 宽度 转 start + end */ function parserTransformToTime(data, param) { var left = data.left, width = data.width; var start = parserPixelToTime(left, param); var end = parserPixelToTime(left + width, param); return { start: start, end: end }; } /** start + end 转 位置 + 宽度 */ function parserTimeToTransform(data, param) { var start = data.start, end = data.end; var left = parserTimeToPixel(start, param); var width = parserTimeToPixel(end, param) - left; return { left: left, width: width }; } /** 根据数据获取刻度个数 */ function getScaleCountByRows(data, param) { var max = 0; data.forEach(function (row) { row.actions.forEach(function (action) { max = Math.max(max, action.end); }); }); var count = Math.ceil(max / param.scale); return count + ADD_SCALE_COUNT; } /** 根据时间获取目前刻度数 */ function getScaleCountByPixel(data, param) { var startLeft = param.startLeft, scaleWidth = param.scaleWidth; var count = Math.ceil((data - startLeft) / scaleWidth); return Math.max(count + ADD_SCALE_COUNT, param.scaleCount); } /** 获取动作全部时间的位置集合 */ function parserActionsToPositions(actions, param) { var positions = []; actions.forEach(function (item) { positions.push(parserTimeToPixel(item.start, param)); positions.push(parserTimeToPixel(item.end, param)); }); return positions; } function generateThemeStyles(config) { var theme = config.theme, sizing = config.sizing, handles = config.handles, cursor = config.cursor, animations = config.animations; return { // Theme colors '--timeline-bg': theme.backgroundColor, '--timeline-fg': theme.foregroundColor, '--timeline-grid': theme.gridColor, '--timeline-cursor': theme.cursorColor, '--timeline-selection': theme.selectionColor, '--timeline-row-bg': theme.rowBackgroundColor, '--timeline-row-border': theme.rowBorderColor, '--timeline-action-bg': theme.actionBackgroundColor, '--timeline-action-border': theme.actionBorderColor, '--timeline-drag-line': theme.dragLineColor, '--timeline-scale-text': theme.scaleTextColor, '--timeline-scale-bg': theme.scaleBackgroundColor, // Sizing '--timeline-action-radius': "".concat(sizing.actionBorderRadius, "px"), '--timeline-action-border-width': "".concat(sizing.actionBorderWidth, "px"), '--timeline-handle-width': "".concat(sizing.handleWidth, "px"), '--timeline-handle-height-ratio': sizing.handleHeightRatio, '--timeline-handle-radius': "".concat(sizing.handleBorderRadius, "px"), '--timeline-time-height': "".concat(sizing.timeAreaHeight, "px"), '--timeline-control-width': "".concat(sizing.controlAreaWidth, "px"), // Cursor styling '--timeline-cursor-color': cursor.cursorColor, '--timeline-cursor-width': "".concat(cursor.cursorWidth, "px"), '--timeline-cursor-style': cursor.cursorStyle, '--timeline-cursor-opacity': cursor.cursorOpacity, '--timeline-cursor-head-color': cursor.cursorHeadColor === 'inherit' ? cursor.cursorColor : cursor.cursorHeadColor, '--timeline-cursor-head-size': "".concat(cursor.cursorHeadSize, "px"), '--timeline-cursor-shadow': cursor.cursorShadow, '--timeline-cursor-z-index': cursor.cursorZIndex, '--timeline-cursor-head-display': cursor.showCursorHead ? 'block' : 'none', // Handle styling '--timeline-handle-bg': handles.handleBackground, '--timeline-handle-border': handles.handleBorderColor, '--timeline-handle-opacity': handles.handleOpacity, '--timeline-handle-hover-opacity': handles.handleHoverOpacity, '--timeline-handles-display': handles.showHandles ? 'block' : 'none', // Animations '--timeline-handle-transition': "".concat(animations.handleTransitionDuration, "ms ").concat(animations.handleTransitionEasing), '--timeline-action-hover-scale': animations.actionHoverScale, '--timeline-action-hover-duration': "".concat(animations.actionHoverDuration, "ms") // '--timeline-cursor-transition': `${animations.cursorTransitionDuration}ms ease-in-out`, }; } function applyThemeToElement(element, styles) { Object.entries(styles).forEach(function (_ref) { var _ref2 = _slicedToArray(_ref, 2), property = _ref2[0], value = _ref2[1]; element.style.setProperty(property, String(value)); }); } function prefix() { for (var _len = arguments.length, classNames = new Array(_len), _key = 0; _key < _len; _key++) { classNames[_key] = arguments[_key]; } return prefixNames.apply(void 0, ["".concat(PREFIX, "-")].concat(classNames)); } var DEFAULT_SPEED = 1; var MAX_SPEED = 3; var CRITICAL_SIZE = 10; function useAutoScroll(target) { var leftBoundRef = useRef(Number.MIN_SAFE_INTEGER); var rightBoundRef = useRef(Number.MAX_SAFE_INTEGER); var speed = useRef(DEFAULT_SPEED); var frame = useRef(); var initAutoScroll = function initAutoScroll() { if (target === null || target === void 0 ? void 0 : target.current) { var _target$current$getBo = target.current.getBoundingClientRect(), left = _target$current$getBo.left, width = _target$current$getBo.width; leftBoundRef.current = left; rightBoundRef.current = left + width; } }; var dealDragAutoScroll = function dealDragAutoScroll(e, deltaScroll) { // 超出 if (e.clientX >= rightBoundRef.current || e.clientX <= leftBoundRef.current) { cancelAnimationFrame(frame.current); var over = Math.abs(e.clientX >= rightBoundRef.current ? e.clientX - rightBoundRef.current : e.clientX - leftBoundRef.current); speed.current = Math.min(Number((over / CRITICAL_SIZE).toFixed(0)) * DEFAULT_SPEED, MAX_SPEED); var dir = e.clientX >= rightBoundRef.current ? 1 : -1; var delta = dir * speed.current; var _loop = function loop() { deltaScroll && deltaScroll(delta); frame.current = requestAnimationFrame(_loop); }; frame.current = requestAnimationFrame(_loop); return false; } else { cancelAnimationFrame(frame.current); } return true; }; var dealResizeAutoScroll = function dealResizeAutoScroll(e, dir, deltaScroll) { if (e.clientX >= rightBoundRef.current || e.clientX < leftBoundRef.current) { cancelAnimationFrame(frame.current); var over = Math.abs(e.clientX >= rightBoundRef.current ? e.clientX - rightBoundRef.current : e.clientX - leftBoundRef.current); speed.current = Math.min(Number((over / CRITICAL_SIZE).toFixed(0)) * DEFAULT_SPEED, MAX_SPEED); var direction = e.clientX >= rightBoundRef.current ? 1 : -1; var delta = direction * speed.current; var _loop2 = function loop() { deltaScroll && deltaScroll(delta); frame.current = requestAnimationFrame(_loop2); }; frame.current = requestAnimationFrame(_loop2); return false; } else { cancelAnimationFrame(frame.current); } return true; }; var stopAutoScroll = function stopAutoScroll() { leftBoundRef.current = Number.MIN_SAFE_INTEGER; rightBoundRef.current = Number.MAX_SAFE_INTEGER; speed.current = DEFAULT_SPEED; cancelAnimationFrame(frame.current); }; return { initAutoScroll: initAutoScroll, dealDragAutoScroll: dealDragAutoScroll, dealResizeAutoScroll: dealResizeAutoScroll, stopAutoScroll: stopAutoScroll }; } var InteractComp = function InteractComp(_ref) { var children = _ref.children, interactRef = _ref.interactRef, draggable = _ref.draggable, resizable = _ref.resizable, draggableOptions = _ref.draggableOptions, resizableOptions = _ref.resizableOptions; var nodeRef = useRef(); var interactable = useRef(); var draggableOptionsRef = useRef(); var resizableOptionsRef = useRef(); useEffect(function () { draggableOptionsRef.current = _objectSpread2({}, draggableOptions); resizableOptionsRef.current = _objectSpread2({}, resizableOptions); }, [draggableOptions, resizableOptions]); useEffect(function () { interactable.current && interactable.current.unset(); interactable.current = interact(nodeRef.current); interactRef.current = interactable.current; setInteractions(); }, [draggable, resizable]); var setInteractions = function setInteractions() { if (draggable) interactable.current.draggable(_objectSpread2(_objectSpread2({}, draggableOptionsRef.current), {}, { onstart: function onstart(e) { return draggableOptionsRef.current.onstart && draggableOptionsRef.current.onstart(e); }, onmove: function onmove(e) { return draggableOptionsRef.current.onmove && draggableOptionsRef.current.onmove(e); }, onend: function onend(e) { return draggableOptionsRef.current.onend && draggableOptionsRef.current.onend(e); } })); if (resizable) interactable.current.resizable(_objectSpread2(_objectSpread2({}, resizableOptionsRef.current), {}, { onstart: function onstart(e) { return resizableOptionsRef.current.onstart && resizableOptionsRef.current.onstart(e); }, onmove: function onmove(e) { return resizableOptionsRef.current.onmove && resizableOptionsRef.current.onmove(e); }, onend: function onend(e) { return resizableOptionsRef.current.onend && resizableOptionsRef.current.onend(e); } })); }; return /*#__PURE__*/cloneElement(children, { ref: nodeRef, draggable: false }); }; var RowDnd = /*#__PURE__*/React.forwardRef(function (_ref, ref) { var children = _ref.children, edges = _ref.edges, left = _ref.left, width = _ref.width, _ref$start = _ref.start, start = _ref$start === void 0 ? DEFAULT_START_LEFT : _ref$start, _ref$grid = _ref.grid, grid = _ref$grid === void 0 ? DEFAULT_MOVE_GRID : _ref$grid, _ref$bounds = _ref.bounds, bounds = _ref$bounds === void 0 ? { left: Number.MIN_SAFE_INTEGER, right: Number.MAX_SAFE_INTEGER } : _ref$bounds, _ref$enableResizing = _ref.enableResizing, enableResizing = _ref$enableResizing === void 0 ? true : _ref$enableResizing, _ref$enableDragging = _ref.enableDragging, enableDragging = _ref$enableDragging === void 0 ? true : _ref$enableDragging, _ref$adsorptionDistan = _ref.adsorptionDistance, adsorptionDistance = _ref$adsorptionDistan === void 0 ? DEFAULT_ADSORPTION_DISTANCE : _ref$adsorptionDistan, _ref$adsorptionPositi = _ref.adsorptionPositions, adsorptionPositions = _ref$adsorptionPositi === void 0 ? [] : _ref$adsorptionPositi, onResizeStart = _ref.onResizeStart, onResize = _ref.onResize, onResizeEnd = _ref.onResizeEnd, onDragStart = _ref.onDragStart, onDragEnd = _ref.onDragEnd, onDrag = _ref.onDrag, parentRef = _ref.parentRef, deltaScrollLeft = _ref.deltaScrollLeft; var interactable = useRef(); var deltaX = useRef(0); var isAdsorption = useRef(false); var _useAutoScroll = useAutoScroll(parentRef), initAutoScroll = _useAutoScroll.initAutoScroll, dealDragAutoScroll = _useAutoScroll.dealDragAutoScroll, dealResizeAutoScroll = _useAutoScroll.dealResizeAutoScroll, stopAutoScroll = _useAutoScroll.stopAutoScroll; useEffect(function () { return function () { interactable.current && interactable.current.unset(); }; }, []); //#region [rgba(100,120,156,0.08)] 赋值相关api useImperativeHandle(ref, function () { return { updateLeft: function updateLeft(left) { return handleUpdateLeft(left || 0, false); }, updateWidth: function updateWidth(width) { return handleUpdateWidth(width, false); }, getLeft: handleGetLeft, getWidth: handleGetWidth }; }); useEffect(function () { var target = interactable.current.target; handleUpdateWidth(typeof width === 'undefined' ? target.offsetWidth : width, false); }, [width]); useEffect(function () { handleUpdateLeft(left || 0, false); }, [left]); var handleUpdateLeft = function handleUpdateLeft(left) { var reset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; if (!interactable.current || !interactable.current.target) return; reset && (deltaX.current = 0); var target = interactable.current.target; target.style.left = "".concat(left, "px"); Object.assign(target.dataset, { left: left }); }; var handleUpdateWidth = function handleUpdateWidth(width) { var reset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; if (!interactable.current || !interactable.current.target) return; reset && (deltaX.current = 0); var target = interactable.current.target; target.style.width = "".concat(width, "px"); Object.assign(target.dataset, { width: width }); }; var handleGetLeft = function handleGetLeft() { var _target$dataset; var target = interactable.current.target; return parseFloat((target === null || target === void 0 ? void 0 : (_target$dataset = target.dataset) === null || _target$dataset === void 0 ? void 0 : _target$dataset.left) || '0'); }; var handleGetWidth = function handleGetWidth() { var _target$dataset2; var target = interactable.current.target; return parseFloat((target === null || target === void 0 ? void 0 : (_target$dataset2 = target.dataset) === null || _target$dataset2 === void 0 ? void 0 : _target$dataset2.width) || '0'); }; //#endregion //#region [rgba(188,188,120,0.05)] 回调api var handleMoveStart = function handleMoveStart(e) { deltaX.current = 0; isAdsorption.current = false; initAutoScroll(); onDragStart && onDragStart(); }; var move = function move(param) { var preLeft = param.preLeft, preWidth = param.preWidth, scrollDelta = param.scrollDelta; var distance = isAdsorption.current ? adsorptionDistance : grid; if (Math.abs(deltaX.current) >= distance) { var count = parseInt(deltaX.current / distance + ''); var curLeft = preLeft + count * distance; // 控制吸附 var adsorption = curLeft; var minDis = Number.MAX_SAFE_INTEGER; adsorptionPositions.forEach(function (item) { var dis = Math.abs(item - curLeft); if (dis < adsorptionDistance && dis < minDis) adsorption = item; var dis2 = Math.abs(item - (curLeft + preWidth)); if (dis2 < adsorptionDistance && dis2 < minDis) adsorption = item - preWidth; }); if (adsorption !== curLeft) { // 采用吸附数据 isAdsorption.current = true; curLeft = adsorption; } else { // 控制网格 if ((curLeft - start) % grid !== 0) { curLeft = start + grid * Math.round((curLeft - start) / grid); } isAdsorption.current = false; } deltaX.current = deltaX.current % distance; // 控制bounds if (curLeft < bounds.left) curLeft = bounds.left;else if (curLeft + preWidth > bounds.right) curLeft = bounds.right - preWidth; if (onDrag) { var ret = onDrag({ lastLeft: preLeft, left: curLeft, lastWidth: preWidth, width: preWidth }, scrollDelta); if (ret === false) return; } handle