function animateText(group, ms, play, props, cv, id) { var starttime = p_keyframes.find((x) => x.id == id).start; ms -= starttime; var length = group._objects.length; var globaldelay = 0; for (var i = 0; i < length; i++) { var index = i; if (props.order == 'backward') { index = length - i - 1; } let left = group.item(index).defaultLeft; let top = group.item(index).defaultTop; let scaleX = group.item(index).defaultScaleX; let scaleY = group.item(index).defaultScaleY; var delay = i * duration; var duration = props.duration / length; var animation = { opacity: 0, top: top, left: left, scaleX: scaleX, scaleY: scaleY, }; if (props.typeAnim == 'letter') { delay = i * duration - 100; } else if (props.typeAnim == 'word') { if (group.item(index).text == ' ') { globaldelay += 500; } delay = globaldelay; } if (props.preset == 'typewriter') { delay = i * duration; duration = 20; } else if (props.preset == 'fade in') { } else if (props.preset == 'slide top') { animation.top += 20; } else if (props.preset == 'slide bottom') { animation.top -= 20; } else if (props.preset == 'slide left') { animation.left += 20; } else if (props.preset == 'slide right') { animation.left -= 20; } else if (props.preset == 'scale') { animation.scaleX = 0; animation.scaleY = 0; } else if (props.preset == 'shrink') { animation.scaleX = 1.5; animation.scaleY = 1.5; } if (delay < 0) { delay = 0; } if (duration < 20) { duration = 20; } var start = false; var instance = anime({ targets: animation, delay: delay, opacity: 1, left: left, top: top, scaleX: scaleX, scaleY: scaleY, duration: duration, easing: props.easing, autoplay: play, update: function () { if (start && play) { group.item(index).set({ opacity: animation.opacity, left: animation.left, top: animation.top, scaleX: animation.scaleX, scaleY: animation.scaleY, }); cv.renderAll(); } }, changeBegin: function () { start = true; }, }); instance.seek(ms); if (!play) { group.item(index).set({ opacity: animation.opacity, left: animation.left, top: animation.top, scaleX: animation.scaleX, scaleY: animation.scaleY, }); cv.renderAll(); } } } function setText(group, props, cv) { var length = group._objects.length; for (var i = 0; i < length; i++) { group.item(i).set({ fill: props.fill, fontFamily: props.fontFamily, }); cv.renderAll(); } } function renderText(string, props, x, y, cv, id, isnew, start) { var textOffset = 0; var group = []; function renderLetter(letter) { var text = new fabric.Text(letter, { left: textOffset, top: 0, fill: props.fill, fontFamily: props.fontFamily, opacity: 1, }); text.set({ defaultLeft: text.left, defaultTop: text.top, defaultScaleX: 1, defaultScaleY: 1, }); textOffset += text.get('width'); return text; } for (var i = 0; i < string.length; i++) { group.push(renderLetter(string.charAt(i))); } var result = new fabric.Group(group, { cursorWidth: 1, stroke: '#000', strokeUniform: true, paintFirst: 'stroke', strokeWidth: 0, originX: 'center', originY: 'center', left: x - artboard.left, top: y - artboard.top, cursorDuration: 1, cursorDelay: 250, assetType: 'animatedText', id: id, strokeDashArray: false, inGroup: false, }); if (isnew) { result.set({ notnew: true, starttime: start, }); } result.objectCaching = false; cv.add(result); cv.renderAll(); newLayer(result); result._objects.forEach(function (object, index) { result.item(index).set({ defaultLeft: result.item(index).defaultLeft - result.width / 2, defaultTop: result.item(index).defaultTop - result.height / 2, }); }); cv.setActiveObject(result); cv.bringToFront(result); return result.id; } class AnimatedText { constructor(text, props) { this.text = text; this.props = props; this.id = 'Text' + layer_count; } render(cv) { this.id = renderText( this.text, this.props, this.props.left, this.props.top, cv, this.id, false, 0 ); animateText( cv.getItemById(this.id), currenttime, false, this.props, cv, this.id ); } seek(ms, cv) { animateText( cv.getItemById(this.id), ms, false, this.props, cv, this.id ); } play(cv) { animateText( cv.getItemById(this.id), 0, true, this.props, cv, this.id ); } getObject(cv) { return cv.getItemById(this.id); } setProps(newprops, cv) { this.props = $.extend(this.props, newprops); setText(cv.getItemById(this.id), this.props, cv); } setProp(newprop) { $.extend(this.props, newprop); } reset(text, newprops, cv) { var obj = cv.getItemById(this.id); var left = obj.left; var top = obj.top; var scaleX = obj, scaleX; var scaleY = obj.scaleY; var angle = obj.angle; var start = p_keyframes.find((x) => x.id == this.id).start; deleteObject(obj, false); this.text = text; this.props = newprops; this.inst = renderText( text, this.props, left, top, cv, this.id, true, start ); cv.getItemById(this.id).set({ angle: angle, scaleX: scaleX, scaleY: scaleY, }); cv.renderAll(); animateText( cv.getItemById(this.id), currenttime, false, this.props, cv, this.id ); animate(currenttime, false); save(); } assignTo(id, text, props) { this.id = id; } }