| | |
| | function resizeCanvas() { |
| | canvas.discardActiveObject(); |
| | canvas.setHeight($('#canvas-area').height()); |
| | canvas.setWidth($('#canvas-area').width()); |
| | artboard.set({ |
| | left: canvas.get('width') / 2 - artboard.get('width') / 2, |
| | top: canvas.get('height') / 2 - artboard.get('height') / 2, |
| | }); |
| | canvas.renderAll(); |
| | animate(false, currenttime); |
| | initLines(); |
| | } |
| | window.addEventListener('resize', resizeCanvas, false); |
| | resizeCanvas(); |
| |
|
| | |
| | function updateSelection(e) { |
| | if (e.target.type == 'activeSelection') { |
| | $('.layer-selected').removeClass('layer-selected'); |
| | canvas.getActiveObjects().forEach(function (object) { |
| | if ( |
| | $('.layer').length > 0 && |
| | $(".layer[data-object='" + object.get('id') + "']").length > 0 |
| | ) { |
| | $(".layer[data-object='" + object.get('id') + "']").addClass( |
| | 'layer-selected' |
| | ); |
| | if (e.e != undefined) { |
| | document |
| | .getElementsByClassName('layer-selected')[0] |
| | .scrollIntoView(); |
| | } |
| | } |
| | }); |
| | } else { |
| | if ( |
| | $('.layer').length > 0 && |
| | $(".layer[data-object='" + e.target.get('id') + "']").length > 0 |
| | ) { |
| | $('.layer-selected').removeClass('layer-selected'); |
| | $(".layer[data-object='" + e.target.get('id') + "']").addClass( |
| | 'layer-selected' |
| | ); |
| | if (e.e != undefined) { |
| | document |
| | .getElementsByClassName('layer-selected')[0] |
| | .scrollIntoView(); |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | function autoKeyframe(object, e, multi) { |
| | if (e.action == 'drag') { |
| | newKeyframe( |
| | 'left', |
| | object, |
| | currenttime, |
| | object.get('left'), |
| | true |
| | ); |
| | newKeyframe('top', object, currenttime, object.get('top'), true); |
| | } else if (e.action == 'scale') { |
| | newKeyframe( |
| | 'scaleX', |
| | object, |
| | currenttime, |
| | object.get('scaleX'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'scaleY', |
| | object, |
| | currenttime, |
| | object.get('scaleY'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'left', |
| | object, |
| | currenttime, |
| | object.get('left'), |
| | true |
| | ); |
| | newKeyframe('top', object, currenttime, object.get('top'), true); |
| | newKeyframe( |
| | 'width', |
| | object, |
| | currenttime, |
| | object.get('width'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'height', |
| | object, |
| | currenttime, |
| | object.get('height'), |
| | true |
| | ); |
| | } else if (e.action == 'rotate') { |
| | newKeyframe( |
| | 'angle', |
| | object, |
| | currenttime, |
| | object.get('angle'), |
| | true |
| | ); |
| | if (multi) { |
| | newKeyframe( |
| | 'scaleX', |
| | object, |
| | currenttime, |
| | object.get('scaleX'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'scaleY', |
| | object, |
| | currenttime, |
| | object.get('scaleY'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'width', |
| | object, |
| | currenttime, |
| | object.get('width'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'left', |
| | object, |
| | currenttime, |
| | object.get('left'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'top', |
| | object, |
| | currenttime, |
| | object.get('top'), |
| | true |
| | ); |
| | } |
| | } else if ( |
| | e.action == 'resizing' || |
| | e.action == 'scaleX' || |
| | e.action == 'scaleY' |
| | ) { |
| | newKeyframe( |
| | 'scaleX', |
| | object, |
| | currenttime, |
| | object.get('scaleX'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'scaleY', |
| | object, |
| | currenttime, |
| | object.get('scaleY'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'left', |
| | object, |
| | currenttime, |
| | object.get('left'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'width', |
| | object, |
| | currenttime, |
| | object.get('width'), |
| | true |
| | ); |
| | newKeyframe('top', object, currenttime, object.get('top'), true); |
| | newKeyframe( |
| | 'height', |
| | object, |
| | currenttime, |
| | object.get('height'), |
| | true |
| | ); |
| | } |
| | } |
| |
|
| | |
| | function reselect(selection) { |
| | tempselection = false; |
| | if (selection.type == 'activeSelection') { |
| | var objs = []; |
| | for (let so of selection._objects) { |
| | for (let obj of canvas.getObjects()) { |
| | if (obj.get('id') === so.get('id')) { |
| | objs.push(obj); |
| | break; |
| | } |
| | } |
| | } |
| | canvas.setActiveObject( |
| | new fabric.ActiveSelection(objs, { |
| | canvas: canvas, |
| | }) |
| | ); |
| | canvas.renderAll(); |
| | } else { |
| | if (selection.get('type') == 'group') { |
| | canvas.setActiveObject(canvas.getItemById(selection.get('id'))); |
| | } else { |
| | canvas.setActiveObject(selection); |
| | } |
| | canvas.renderAll(); |
| | } |
| | } |
| |
|
| | |
| | function group() { |
| | var objects = canvas.getActiveObjects(); |
| | var object_ids = []; |
| | var newgroup = new fabric.Group(); |
| | objects.forEach(function (object) { |
| | newgroup.addWithUpdate(object); |
| | object.set({ inGroup: true }); |
| | $(".layer[data-object='" + object.get('id') + "']").remove(); |
| | object_ids.push(object.get('id')); |
| | $('#' + object.get('id')).remove(); |
| | canvas.remove(object); |
| | }); |
| | |
| | newgroup.set({ |
| | id: 'Group' + layer_count, |
| | objectCaching: false, |
| | isGroup: true, |
| | color: '#F1890E', |
| | type: 'group', |
| | stroke: '#000', |
| | strokeUniform: true, |
| | strokeWidth: 0, |
| | paintFirst: 'stroke', |
| | absolutePositioned: true, |
| | inGroup: false, |
| | strokeDashArray: false, |
| | objectCaching: true, |
| | shadow: { |
| | color: 'black', |
| | offsetX: 0, |
| | offsetY: 0, |
| | blur: 0, |
| | opacity: 0, |
| | }, |
| | }); |
| | groups.push({ id: newgroup.get('id'), objects: object_ids }); |
| | canvas.renderAll(); |
| | newLayer(newgroup); |
| | canvas.setActiveObject(newgroup); |
| | keyframes.sort(function (a, b) { |
| | if (a.id.indexOf('Group') >= 0 && b.id.indexOf('Group') == -1) { |
| | return 1; |
| | } else if ( |
| | b.id.indexOf('Group') >= 0 && |
| | a.id.indexOf('Group') == -1 |
| | ) { |
| | return -1; |
| | } else { |
| | return 0; |
| | } |
| | }); |
| | save(); |
| | } |
| | $(document).on('click', '#group-objects', group); |
| |
|
| | |
| | function unGroup(group) { |
| | canvas.discardActiveObject(); |
| | canvas.renderAll(); |
| | tempgroup = group._objects; |
| | group._restoreObjectsState(); |
| | $(".layer[data-object='" + group.get('id') + "']").remove(); |
| | $('#' + group.get('id')).remove(); |
| | canvas.remove(group); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != group.get('id'); |
| | }); |
| | p_keyframes = $.grep(p_keyframes, function (e) { |
| | return e.id != group.get('id'); |
| | }); |
| | objects = $.grep(objects, function (e) { |
| | return e.id != group.get('id'); |
| | }); |
| | canvas.renderAll(); |
| | for (var i = 0; i < tempgroup.length; i++) { |
| | if (tempgroup[i].inGroup) { |
| | canvas.add(tempgroup[i]); |
| | renderLayer(tempgroup[i]); |
| | props.forEach(function (prop) { |
| | if ( |
| | prop != 'top' && |
| | prop != 'scaleY' && |
| | prop != 'width' && |
| | prop != 'height' && |
| | prop != 'shadow.offsetX' && |
| | prop != 'shadow.offsetY' && |
| | prop != 'shadow.opacity' && |
| | prop != 'shadow.blur' && |
| | prop != 'lineHeight' |
| | ) { |
| | renderProp(prop, tempgroup[i]); |
| | } |
| | }); |
| | const keyarr = $.grep(keyframes, function (e) { |
| | return e.id == tempgroup[i].id; |
| | }); |
| | keyarr.forEach(function (keyframe) { |
| | if ( |
| | keyframe.name != 'top' && |
| | keyframe.name != 'scaleY' && |
| | keyframe.name != 'width' && |
| | keyframe.name != 'height' && |
| | keyframe.name != 'shadow.offsetX' && |
| | keyframe.name != 'shadow.offsetY' && |
| | keyframe.name != 'shadow.opacity' && |
| | keyframe.name != 'shadow.blur' && |
| | keyframe.name != 'lineHeight' |
| | ) { |
| | renderKeyframe( |
| | canvas.getItemById(keyframe.id), |
| | keyframe.name, |
| | keyframe.t |
| | ); |
| | } |
| | }); |
| | } |
| | } |
| | canvas.renderAll(); |
| | save(); |
| | } |
| | $(document).on('click', '#ungroup-objects', function () { |
| | if (canvas.getActiveObject()) { |
| | unGroup(canvas.getActiveObject()); |
| | } |
| | }); |
| |
|
| | |
| | function reGroup(id) { |
| | var group = []; |
| | var objects = []; |
| | groups |
| | .find((x) => x.id == id) |
| | .objects.forEach(function (object) { |
| | objects.push(canvas.getItemById(object)); |
| | }); |
| | var activeselection = new fabric.ActiveSelection(objects); |
| | var newgroup = activeselection.toGroup(); |
| | newgroup.set({ |
| | id: id, |
| | objectCaching: false, |
| | }); |
| | canvas.add(newgroup); |
| | canvas.renderAll(); |
| | } |
| |
|
| | |
| | function updateRecordCanvas() { |
| | canvasrecord.setWidth(artboard.width); |
| | canvasrecord.setHeight(artboard.height); |
| | canvasrecord.width = artboard.width; |
| | canvasrecord.height = artboard.height; |
| | canvas.clipPath = null; |
| | objects.forEach(async function (object) { |
| | var obj = canvas.getItemById(object.id); |
| | if (obj.filters) { |
| | if (obj.filters.length > 0) { |
| | object.filters = []; |
| | obj.filters.forEach(function (filter) { |
| | if ( |
| | filter.type == 'BlackWhite' || |
| | filter.type == 'Invert' || |
| | filter.type == 'Sepia' || |
| | filter.type == 'Kodachrome' || |
| | filter.type == 'Polaroid' || |
| | filter.type == 'Technicolor' || |
| | filter.type == 'Brownie' || |
| | filter.type == 'Vintage' |
| | ) { |
| | object.filters.push({ type: filter.type }); |
| | } else if (filter.type == 'Brightness') { |
| | object.filters.push({ |
| | type: filter.type, |
| | value: filter.brightness, |
| | }); |
| | } else if (filter.type == 'Contrast') { |
| | object.filters.push({ |
| | type: filter.type, |
| | value: filter.contrast, |
| | }); |
| | } else if (filter.type == 'Vibrance') { |
| | object.filters.push({ |
| | type: filter.type, |
| | value: filter.vibrance, |
| | }); |
| | } else if (filter.type == 'Saturation') { |
| | object.filters.push({ |
| | type: filter.type, |
| | value: filter.saturation, |
| | }); |
| | } else if (filter.type == 'HueRotation') { |
| | object.filters.push({ |
| | type: filter.type, |
| | value: filter.rotation, |
| | }); |
| | } else if (filter.type == 'Blur') { |
| | object.filters.push({ |
| | type: filter.type, |
| | value: filter.blur, |
| | }); |
| | } else if (filter.type == 'Noise') { |
| | object.filters.push({ |
| | type: filter.type, |
| | value: filter.noise, |
| | }); |
| | } else if (filter.type == 'RemoveColor') { |
| | object.filters.push({ |
| | type: filter.type, |
| | distance: filter.distance, |
| | color: filter.color, |
| | }); |
| | } |
| | }); |
| | obj.filters = []; |
| | obj.applyFilters(); |
| | var backend = fabric.filterBackend; |
| | if (backend && backend.evictCachesForKey) { |
| | backend.evictCachesForKey(obj.cacheKey); |
| | backend.evictCachesForKey(obj.cacheKey + '_filtered'); |
| | } |
| | if ( |
| | obj.filters.length > 0 && |
| | obj.get('id').indexOf('Video') >= 0 |
| | ) { |
| | await obj.setElement(obj.saveElem); |
| | } |
| | } else { |
| | object.filters = []; |
| | } |
| | } else { |
| | object.filters = []; |
| | } |
| | }); |
| | const canvassave = canvas.toJSON([ |
| | 'volume', |
| | 'audioSrc', |
| | 'defaultLeft', |
| | 'defaultTop', |
| | 'defaultScaleX', |
| | 'defaultScaleY', |
| | 'notnew', |
| | 'starttime', |
| | 'top', |
| | 'left', |
| | 'width', |
| | 'height', |
| | 'scaleX', |
| | 'scaleY', |
| | 'flipX', |
| | 'flipY', |
| | 'originX', |
| | 'originY', |
| | 'transformMatrix', |
| | 'stroke', |
| | 'strokeWidth', |
| | 'strokeDashArray', |
| | 'strokeLineCap', |
| | 'strokeDashOffset', |
| | 'strokeLineJoin', |
| | 'strokeMiterLimit', |
| | 'angle', |
| | 'opacity', |
| | 'fill', |
| | 'globalCompositeOperation', |
| | 'shadow', |
| | 'clipTo', |
| | 'visible', |
| | 'backgroundColor', |
| | 'skewX', |
| | 'skewY', |
| | 'fillRule', |
| | 'paintFirst', |
| | 'clipPath', |
| | 'strokeUniform', |
| | 'rx', |
| | 'ry', |
| | 'selectable', |
| | 'hasControls', |
| | 'subTargetCheck', |
| | 'id', |
| | 'hoverCursor', |
| | 'defaultCursor', |
| | 'isEditing', |
| | 'source', |
| | 'assetType', |
| | 'duration', |
| | 'inGroup', |
| | ]); |
| | canvas.clipPath = artboard; |
| | canvasrecord.loadFromJSON(canvassave, function () { |
| | if (canvasrecord.getItemById('center_h')) { |
| | canvasrecord.remove(canvasrecord.getItemById('center_h')); |
| | canvasrecord.remove(canvasrecord.getItemById('center_v')); |
| | } |
| | if (canvasrecord.getItemById('line_h')) { |
| | canvasrecord.remove(canvasrecord.getItemById('line_h')); |
| | canvasrecord.remove(canvasrecord.getItemById('line_v')); |
| | } |
| | canvasrecord.renderAll(); |
| | canvasrecord.setWidth(artboard.width); |
| | canvasrecord.setHeight(artboard.height); |
| | canvasrecord.width = artboard.width; |
| | canvasrecord.height = artboard.height; |
| | canvasrecord.renderAll(); |
| | objects.forEach(function (object) { |
| | replaceSource( |
| | canvasrecord.getItemById(object.id), |
| | canvasrecord |
| | ); |
| | replaceSource(canvas.getItemById(object.id), canvas); |
| | }); |
| | }); |
| | } |
| |
|
| | |
| | function downloadRecording(chunks) { |
| | $('#download-real').html('Downloading...'); |
| | if ($('input[name=radio]:checked').val() == 'webm') { |
| | var url = URL.createObjectURL( |
| | new Blob(chunks, { |
| | type: 'video/webm', |
| | }) |
| | ); |
| | const a = document.createElement('a'); |
| | a.style.display = 'none'; |
| | a.href = url; |
| | a.download = name; |
| | document.body.appendChild(a); |
| | a.click(); |
| | recording = false; |
| | currenttime = 0; |
| | animate(false, 0); |
| | $('#seekbar').offset({ |
| | left: |
| | offset_left + |
| | $('#inner-timeline').offset().left + |
| | currenttime / timelinetime, |
| | }); |
| | canvas.renderAll(); |
| | resizeCanvas(); |
| | $('#download-real').html('Download'); |
| | $('#download-real').removeClass('downloading'); |
| | updateRecordCanvas(); |
| | } else if ($('input[name=radio]:checked').val() == 'mp4') { |
| | type = 'video/mp4'; |
| | } else { |
| | convertStreams(new Blob(chunks, { type: 'video/webm' }), 'gif'); |
| | } |
| | } |
| |
|
| | $('#download-real').on('click', record); |
| |
|
| | |
| | function save() { |
| | redo = []; |
| | redoarr = []; |
| | if (state) { |
| | undo.push(state); |
| | undoarr.push(statearr); |
| | } |
| | canvas.clipPath = null; |
| | state = canvas.toJSON([ |
| | 'volume', |
| | 'audioSrc', |
| | 'top', |
| | 'left', |
| | 'width', |
| | 'height', |
| | 'scaleX', |
| | 'scaleY', |
| | 'flipX', |
| | 'flipY', |
| | 'originX', |
| | 'originY', |
| | 'transformMatrix', |
| | 'stroke', |
| | 'strokeWidth', |
| | 'strokeDashArray', |
| | 'strokeLineCap', |
| | 'strokeDashOffset', |
| | 'strokeLineJoin', |
| | 'strokeMiterLimit', |
| | 'angle', |
| | 'opacity', |
| | 'fill', |
| | 'globalCompositeOperation', |
| | 'shadow', |
| | 'clipTo', |
| | 'visible', |
| | 'backgroundColor', |
| | 'skewX', |
| | 'skewY', |
| | 'fillRule', |
| | 'paintFirst', |
| | 'clipPath', |
| | 'strokeUniform', |
| | 'rx', |
| | 'ry', |
| | 'selectable', |
| | 'hasControls', |
| | 'subTargetCheck', |
| | 'id', |
| | 'hoverCursor', |
| | 'defaultCursor', |
| | 'isEditing', |
| | 'source', |
| | 'assetType', |
| | 'duration', |
| | 'inGroup', |
| | 'filters', |
| | ]); |
| | canvas.clipPath = artboard; |
| | statearr = { |
| | keyframes: JSON.parse(JSON.stringify(keyframes)), |
| | p_keyframes: JSON.parse(JSON.stringify(p_keyframes)), |
| | objects: JSON.parse(JSON.stringify(objects)), |
| | colormode: colormode, |
| | duration: duration, |
| | currenttime: currenttime, |
| | }; |
| | if (undo.length >= 1) { |
| | $('#undo').addClass('history-active'); |
| | } else { |
| | $('#undo').removeClass('history-active'); |
| | } |
| | if (redo.length >= 1) { |
| | $('#redo').addClass('history-active'); |
| | } else { |
| | $('#redo').removeClass('history-active'); |
| | } |
| |
|
| | updateRecordCanvas(); |
| | autoSave(); |
| | } |
| |
|
| | |
| | function copyObject() { |
| | if (clipboard) { |
| | if (cliptype == 'object') { |
| | if (clipboard.type == 'activeSelection') { |
| | clipboard._objects.forEach(function (clone) { |
| | clone.clone(function (cloned) { |
| | cloned.set({ |
| | id: 'Shape' + layer_count, |
| | }); |
| | canvas.add(cloned); |
| | canvas.renderAll(); |
| | newLayer(cloned); |
| | canvas.setActiveObject(cloned); |
| | }); |
| | }); |
| | } else { |
| | clipboard.clone(function (cloned) { |
| | cloned.set({ |
| | id: 'Shape' + layer_count, |
| | }); |
| | canvas.add(cloned); |
| | canvas.renderAll(); |
| | newLayer(cloned); |
| | canvas.setActiveObject(cloned); |
| | }); |
| | } |
| | save(); |
| | } else { |
| | copyKeyframes(); |
| | } |
| | } |
| | } |
| |
|
| | |
| | function replaceSource(object, canvas) { |
| | if (object == null) { |
| | return false; |
| | } |
| | if (object.get('type') != 'group') { |
| | if (object.type) { |
| | if (object.type == 'image') { |
| | if (object.get('id').indexOf('Video') >= 0) { |
| | var vidObj = document.createElement('video'); |
| | var vidSrc = document.createElement('source'); |
| | vidSrc.src = object.get('source'); |
| | vidObj.crossOrigin = 'anonymous'; |
| | vidObj.appendChild(vidSrc); |
| | vidObj.addEventListener('loadeddata', function () { |
| | vidObj.width = this.videoWidth; |
| | vidObj.height = this.videoHeight; |
| | vidObj.currentTime = 0; |
| | vidObj.muted = false; |
| | async function waitLoad() { |
| | if (vidObj.readyState >= 3) { |
| | object.setElement(vidObj); |
| | object.saveElem = vidObj; |
| | await canvas.renderAll(); |
| | await animate(false, currenttime); |
| | if ( |
| | objects.find((x) => x.id == object.get('id')) |
| | .filters |
| | ) { |
| | if ( |
| | objects.find((x) => x.id == object.get('id')) |
| | .filters.length > 0 |
| | ) { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .filters.forEach(function (filter) { |
| | if (filter.type == 'Sepia') { |
| | object.filters.push(new f.Sepia()); |
| | } else if (filter.type == 'Invert') { |
| | object.filters.push(new f.Invert()); |
| | } else if (filter.type == 'BlackWhite') { |
| | object.filters.push(new f.BlackWhite()); |
| | } else if (filter.type == 'Kodachrome') { |
| | object.filters.push(new f.Kodachrome()); |
| | } else if (filter.type == 'Polaroid') { |
| | object.filters.push(new f.Polaroid()); |
| | } else if (filter.type == 'Technicolor') { |
| | object.filters.push(new f.Technicolor()); |
| | } else if (filter.type == 'Vintage') { |
| | object.filters.push(new f.Vintage()); |
| | } else if (filter.type == 'Brownie') { |
| | object.filters.push(new f.Brownie()); |
| | } else if (filter.type == 'Brightness') { |
| | object.filters.push( |
| | new f.Brightness({ |
| | brightness: filter.value, |
| | }) |
| | ); |
| | } else if (filter.type == 'Contrast') { |
| | object.filters.push( |
| | new f.Contrast({ contrast: filter.value }) |
| | ); |
| | } else if (filter.type == 'Saturation') { |
| | object.filters.push( |
| | new f.Saturation({ |
| | saturation: filter.value, |
| | }) |
| | ); |
| | } else if (filter.type == 'Vibrance') { |
| | object.filters.push( |
| | new f.Vibrance({ vibrance: filter.value }) |
| | ); |
| | } else if (filter.type == 'HueRotation') { |
| | object.filters.push( |
| | new f.HueRotation({ |
| | rotation: filter.value, |
| | }) |
| | ); |
| | } else if (filter.type == 'Noise') { |
| | object.filters.push( |
| | new f.Noise({ noise: filter.value }) |
| | ); |
| | } else if (filter.type == 'Blur') { |
| | object.filters.push( |
| | new f.Blur({ blur: filter.value }) |
| | ); |
| | } else if (filter.type == 'RemoveColor') { |
| | object.filters.push( |
| | new f.RemoveColor({ |
| | distance: filter.distance, |
| | color: filter.color, |
| | }) |
| | ); |
| | } |
| | }); |
| | object.applyFilters(); |
| | canvas.renderAll(); |
| | } |
| | } |
| | } else { |
| | window.setTimeout(function () { |
| | waitLoad(); |
| | }, 100); |
| | } |
| | } |
| | window.setTimeout(function () { |
| | waitLoad(); |
| | }, 100); |
| | }); |
| | vidObj.currentTime = 0; |
| | } else { |
| | |
| | |
| | |
| | |
| | if (objects.find((x) => x.id == object.get('id')).filters) { |
| | if ( |
| | objects.find((x) => x.id == object.get('id')).filters |
| | .length > 0 |
| | ) { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .filters.forEach(function (filter) { |
| | if (filter.type == 'Sepia') { |
| | object.filters.push(new f.Sepia()); |
| | } else if (filter.type == 'Invert') { |
| | object.filters.push(new f.Invert()); |
| | } else if (filter.type == 'BlackWhite') { |
| | object.filters.push(new f.BlackWhite()); |
| | } else if (filter.type == 'Kodachrome') { |
| | object.filters.push(new f.Kodachrome()); |
| | } else if (filter.type == 'Polaroid') { |
| | object.filters.push(new f.Polaroid()); |
| | } else if (filter.type == 'Technicolor') { |
| | object.filters.push(new f.Technicolor()); |
| | } else if (filter.type == 'Vintage') { |
| | object.filters.push(new f.Vintage()); |
| | } else if (filter.type == 'Brownie') { |
| | object.filters.push(new f.Brownie()); |
| | } else if (filter.type == 'Brightness') { |
| | object.filters.push( |
| | new f.Brightness({ brightness: filter.value }) |
| | ); |
| | } else if (filter.type == 'Contrast') { |
| | object.filters.push( |
| | new f.Contrast({ contrast: filter.value }) |
| | ); |
| | } else if (filter.type == 'Saturation') { |
| | object.filters.push( |
| | new f.Saturation({ saturation: filter.value }) |
| | ); |
| | } else if (filter.type == 'Vibrance') { |
| | object.filters.push( |
| | new f.Vibrance({ vibrance: filter.value }) |
| | ); |
| | } else if (filter.type == 'HueRotation') { |
| | object.filters.push( |
| | new f.HueRotation({ rotation: filter.value }) |
| | ); |
| | } else if (filter.type == 'Noise') { |
| | object.filters.push( |
| | new f.Noise({ noise: filter.value }) |
| | ); |
| | } else if (filter.type == 'Blur') { |
| | object.filters.push( |
| | new f.Blur({ blur: filter.value }) |
| | ); |
| | } else if (filter.type == 'RemoveColor') { |
| | object.filters.push( |
| | new f.RemoveColor({ |
| | distance: filter.distance, |
| | color: filter.color, |
| | }) |
| | ); |
| | } |
| | }); |
| | object.applyFilters(); |
| | canvas.renderAll(); |
| | } else { |
| | object.filters = []; |
| | object.applyFilters(); |
| | canvas.renderAll(); |
| | } |
| | } |
| |
|
| | |
| | |
| | } |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | function undoRedo(newState, saveState, newArrState, saveArrState) { |
| | saveState.push(state); |
| | saveArrState.push(statearr); |
| | statearr = newArrState.pop(); |
| | state = newState.pop(); |
| | keyframes = statearr.keyframes; |
| | p_keyframes = statearr.p_keyframes; |
| | objects = statearr.objects; |
| | colormode = statearr.colormode; |
| | duration = statearr.duration; |
| | currenttime = statearr.currenttime; |
| | canvas.clipPath = null; |
| | canvas.loadFromJSON(state, function () { |
| | canvas.clipPath = artboard; |
| | canvas.getItemById('line_h').set({ opacity: 0 }); |
| | canvas.getItemById('line_v').set({ opacity: 0 }); |
| | canvas.renderAll(); |
| | $('.object-props').remove(); |
| | $('.layer').remove(); |
| | objects.forEach(function (object) { |
| | replaceSource(canvas.getItemById(object.id), canvas); |
| | renderLayer(canvas.getItemById(object.id)); |
| | props.forEach(function (prop) { |
| | if ( |
| | prop != 'top' && |
| | prop != 'scaleY' && |
| | prop != 'width' && |
| | prop != 'height' && |
| | prop != 'shadow.offsetX' && |
| | prop != 'shadow.offsetY' && |
| | prop != 'shadow.opacity' && |
| | prop != 'shadow.blur' && |
| | prop != 'lineHeight' |
| | ) { |
| | renderProp(prop, canvas.getItemById(object.id)); |
| | } |
| | }); |
| | }); |
| | keyframes.forEach(function (keyframe) { |
| | if ( |
| | keyframe.name != 'top' && |
| | keyframe.name != 'scaleY' && |
| | keyframe.name != 'width' && |
| | keyframe.name != 'height' && |
| | keyframe.name != 'shadow.offsetX' && |
| | keyframe.name != 'shadow.offsetY' && |
| | keyframe.name != 'shadow.opacity' && |
| | keyframe.name != 'shadow.blur' && |
| | keyframe.name != 'lineHeight' |
| | ) { |
| | renderKeyframe( |
| | canvas.getItemById(keyframe.id), |
| | keyframe.name, |
| | keyframe.t |
| | ); |
| | } |
| | }); |
| | animate(false, currenttime); |
| | }); |
| | if (undo.length >= 1) { |
| | $('#undo').addClass('history-active'); |
| | } else { |
| | $('#undo').removeClass('history-active'); |
| | } |
| | if (redo.length >= 1) { |
| | $('#redo').addClass('history-active'); |
| | } else { |
| | $('#redo').removeClass('history-active'); |
| | } |
| | } |
| |
|
| | |
| | $(document).on('click', '#undo', function () { |
| | if (undo.length >= 1) { |
| | undoRedo(undo, redo, undoarr, redoarr); |
| | } |
| | }); |
| | $(document).on('click', '#redo', function () { |
| | if (undo.length >= 1) { |
| | undoRedo(redo, undo, redoarr, undoarr); |
| | } |
| | }); |
| |
|
| | |
| | function keyframeChanges(object, type, id, selection) { |
| | if (object.get('type') == 'rect') { |
| | object.set({ |
| | rx: parseFloat($('#object-corners input').val()), |
| | ry: parseFloat($('#object-corners input').val()), |
| | }); |
| | } else if (object.get('type') == 'textbox') { |
| | object.set({ |
| | charSpacing: parseFloat($('#text-h input').val()) * 10, |
| | lineHeight: parseFloat($('#text-v input').val() / 100), |
| | }); |
| | canvas.renderAll(); |
| | } |
| | canvas.renderAll(); |
| | if (type && type == 'opacity') { |
| | newKeyframe( |
| | 'opacity', |
| | object, |
| | currenttime, |
| | object.get('opacity'), |
| | true |
| | ); |
| | } else if (type && type == 'opacity3') { |
| | newKeyframe( |
| | 'charSpacing', |
| | object, |
| | currenttime, |
| | object.get('charSpacing'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'lineHeight', |
| | object, |
| | currenttime, |
| | object.get('lineHeight'), |
| | true |
| | ); |
| | } else { |
| | if (id == 'object-x' || id == 'object-y') { |
| | newKeyframe( |
| | 'left', |
| | object, |
| | currenttime, |
| | object.get('left'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'top', |
| | object, |
| | currenttime, |
| | object.get('top'), |
| | true |
| | ); |
| | } else if (id == 'object-w' || id == 'object-h') { |
| | newKeyframe( |
| | 'scaleX', |
| | object, |
| | currenttime, |
| | object.get('scaleX'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'scaleY', |
| | object, |
| | currenttime, |
| | object.get('scaleY'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'width', |
| | object, |
| | currenttime, |
| | object.get('width'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'height', |
| | object, |
| | currenttime, |
| | object.get('width'), |
| | true |
| | ); |
| | if (selection) { |
| | newKeyframe( |
| | 'left', |
| | object, |
| | currenttime, |
| | object.get('left'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'top', |
| | object, |
| | currenttime, |
| | object.get('top'), |
| | true |
| | ); |
| | } |
| | } else if (id == 'object-r') { |
| | newKeyframe( |
| | 'angle', |
| | object, |
| | currenttime, |
| | object.get('angle'), |
| | true |
| | ); |
| | if (selection) { |
| | newKeyframe( |
| | 'left', |
| | object, |
| | currenttime, |
| | object.get('left'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'top', |
| | object, |
| | currenttime, |
| | object.get('top'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'scaleX', |
| | object, |
| | currenttime, |
| | object.get('scaleX'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'scaleY', |
| | object, |
| | currenttime, |
| | object.get('scaleY'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'width', |
| | object, |
| | currenttime, |
| | object.get('width'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'height', |
| | object, |
| | currenttime, |
| | object.get('width'), |
| | true |
| | ); |
| | } |
| | } else if (id == 'object-stroke') { |
| | newKeyframe( |
| | 'strokeWidth', |
| | object, |
| | currenttime, |
| | object.get('strokeWidth'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'stroke', |
| | object, |
| | currenttime, |
| | object.get('stroke'), |
| | true |
| | ); |
| | } else if ( |
| | id == 'object-shadow-x' || |
| | id == 'object-shadow-y' || |
| | id == 'object-blur' || |
| | id == 'object-color-stroke-opacity' |
| | ) { |
| | newKeyframe( |
| | 'shadow.color', |
| | object, |
| | currenttime, |
| | object.shadow.color, |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.opacity', |
| | object, |
| | currenttime, |
| | object.shadow.opacity, |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.offsetX', |
| | object, |
| | currenttime, |
| | object.shadow.offsetX, |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.offsetY', |
| | object, |
| | currenttime, |
| | object.shadow.offsetY, |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.blur', |
| | object, |
| | currenttime, |
| | object.shadow.blur, |
| | true |
| | ); |
| | } |
| | } |
| | save(); |
| | } |
| |
|
| | |
| | function play() { |
| | paused = false; |
| | animate(true, currenttime); |
| | $('#play-button').attr('src', 'assets/pause-button.svg'); |
| | } |
| |
|
| | |
| | function pause() { |
| | paused = true; |
| | $('#play-button').attr('src', 'assets/play-button.svg'); |
| | } |
| |
|
| | |
| | function setObjectValue(prop, object, value, inst) { |
| | if (object.get('type') != 'group') { |
| | if (object.group) { |
| | var group = object.group; |
| | tempgroup = group._objects; |
| | group._restoreObjectsState(); |
| | canvas.setActiveObject(group); |
| | inst.remove(canvas.getActiveObject()); |
| | canvas.discardActiveObject(); |
| | inst.renderAll(); |
| | for (var i = 0; i < tempgroup.length; i++) { |
| | inst.add(tempgroup[i]); |
| | } |
| | } |
| | } |
| | if (prop == 'left' && !recording) { |
| | object.set(prop, value + artboard.get('left')); |
| | } else if (prop == 'top' && !recording) { |
| | object.set(prop, value + artboard.get('top')); |
| | } else if (prop == 'shadow.blur') { |
| | object.shadow.blur = value; |
| | } else if (prop == 'shadow.color') { |
| | object.shadow.color = value; |
| | } else if (prop == 'shadow.offsetX') { |
| | object.shadow.offsetX = value; |
| | } else if (prop == 'shadow.offsetY') { |
| | object.shadow.offsetY = value; |
| | } else if (prop == 'shadow.blur') { |
| | object.shadow.blur = value; |
| | } else if (object.get('type') != 'group') { |
| | object.set(prop, value); |
| | } else if (prop != 'width') { |
| | object.set(prop, value); |
| | } |
| | inst.renderAll(); |
| | } |
| |
|
| | |
| | function lastKeyframe(keyframe, index) { |
| | var temparr = keyframes.slice(); |
| | temparr.sort(function (a, b) { |
| | return a.t - b.t; |
| | }); |
| | temparr.length = temparr.findIndex((x) => x === keyframe); |
| | temparr.reverse(); |
| | if (temparr.length == 0) { |
| | return false; |
| | } else { |
| | for (var i = 0; i < temparr.length; i++) { |
| | if ( |
| | temparr[i].id == keyframe.id && |
| | temparr[i].name == keyframe.name |
| | ) { |
| | return temparr[i]; |
| | break; |
| | } else if (i == temparr.length - 1) { |
| | return false; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | function checkAnyKeyframe(id, prop, inst) { |
| | const object = inst.getItemById(id); |
| | if (object.get('assetType') == 'audio') { |
| | return false; |
| | } |
| | if ( |
| | object.get('type') != 'textbox' && |
| | (prop == 'charSpacing' || prop == 'lineHeight') |
| | ) { |
| | return false; |
| | } |
| | if ( |
| | object.get('type') == 'group' && |
| | (prop == 'shadow.opacity' || |
| | prop == 'shadow.color' || |
| | prop == 'shadow.offsetX' || |
| | prop == 'shadow.offsetY' || |
| | prop == 'shadow.blur') |
| | ) { |
| | return false; |
| | } |
| | const keyarr2 = $.grep(keyframes, function (e) { |
| | return e.id == id && e.name == prop; |
| | }); |
| | if (keyarr2.length == 0) { |
| | const value = objects |
| | .find((x) => x.id == id) |
| | .defaults.find((x) => x.name == prop).value; |
| | setObjectValue(prop, object, value, inst); |
| | } |
| | } |
| |
|
| | |
| | function isDomElem(el) { |
| | return el instanceof HTMLElement || el[0] instanceof HTMLElement |
| | ? true |
| | : false; |
| | } |
| |
|
| | |
| | async function playVideos(time) { |
| | objects.forEach(async function (object) { |
| | var object = canvas.getItemById(object.id); |
| | if (object == null) { |
| | return false; |
| | } |
| | var inst = canvas; |
| | var start = false; |
| | if (recording) { |
| | object = canvasrecord.getItemById(object.id); |
| | inst = canvasrecord; |
| | } |
| | if ( |
| | object.get('id').indexOf('Video') >= 0 && |
| | p_keyframes.find((x) => x.id == object.id).trimstart + |
| | p_keyframes.find((x) => x.id == object.id).start <= |
| | time && |
| | p_keyframes.find((x) => x.id == object.id).end >= time |
| | ) { |
| | var tempfilters = object.filters; |
| | if (object.filters.length > 0) { |
| | object.filters = []; |
| | object.applyFilters(); |
| | var image = object; |
| | var backend = fabric.filterBackend; |
| | if (backend && backend.evictCachesForKey) { |
| | backend.evictCachesForKey(image.cacheKey); |
| | backend.evictCachesForKey(image.cacheKey + '_filtered'); |
| | } |
| | await object.setElement(object.saveElem); |
| | } |
| | object.set('visible', true); |
| | inst.renderAll(); |
| | if ($(object.getElement())[0].paused == true) { |
| | $(object.getElement())[0].currentTime = parseFloat( |
| | ( |
| | (time - |
| | p_keyframes.find((x) => x.id == object.id).start + |
| | p_keyframes.find((x) => x.id == object.id).trimstart) / |
| | 1000 |
| | ).toFixed(2) |
| | ); |
| | } |
| | if (!recording) { |
| | var animation = { |
| | value: 0, |
| | }; |
| | var instance = anime({ |
| | targets: animation, |
| | value: [currenttime, duration], |
| | delay: 0, |
| | duration: duration, |
| | easing: 'linear', |
| | autoplay: true, |
| | update: async function () { |
| | if (!paused && start) { |
| | if (object.filters.length > 0) { |
| | object.filters = []; |
| | object.applyFilters(); |
| | var image = object; |
| | var backend = fabric.filterBackend; |
| | if (backend && backend.evictCachesForKey) { |
| | backend.evictCachesForKey(image.cacheKey); |
| | backend.evictCachesForKey( |
| | image.cacheKey + '_filtered' |
| | ); |
| | } |
| | await object.setElement(object.saveElem); |
| | } |
| | if ($(object.getElement())[0].tagName == 'VIDEO') { |
| | $(object.getElement())[0].play(); |
| | } |
| | await inst.renderAll(); |
| | if (tempfilters.length > 0) { |
| | object.filters = tempfilters; |
| | object.applyFilters(); |
| | inst.renderAll(); |
| | } |
| | } else if (paused) { |
| | if ( |
| | isDomElem($(object.getElement())[0]) && |
| | $(object.getElement())[0].tagName == 'VIDEO' |
| | ) { |
| | $(object.getElement())[0].pause(); |
| | } |
| | animation.value = duration + 1; |
| | anime.remove(animation); |
| | } |
| | }, |
| | changeBegin: function () { |
| | start = true; |
| | }, |
| | }); |
| | if (paused) { |
| | $(object.getElement())[0].currentTime = parseFloat( |
| | ( |
| | (time - |
| | p_keyframes.find((x) => x.id == object.id).start + |
| | p_keyframes.find((x) => x.id == object.id) |
| | .trimstart) / |
| | 1000 |
| | ).toFixed(2) |
| | ); |
| | await inst.renderAll(); |
| | if (tempfilters.length > 0) { |
| | object.filters = tempfilters; |
| | object.applyFilters(); |
| | inst.renderAll(); |
| | } |
| | } |
| | } else { |
| | if ($(object.getElement())[0].paused == true) { |
| | $(object.getElement())[0].play(); |
| | inst.renderAll(); |
| | } |
| | } |
| | } else if (object.get('id').indexOf('Video') >= 0) { |
| | $(object.getElement())[0].pause(); |
| | object.set('visible', false); |
| | inst.renderAll(); |
| | } |
| | }); |
| | } |
| |
|
| | |
| | function playAudio(time) { |
| | objects.forEach(async function (object) { |
| | var start = false; |
| | var obj = canvas.getItemById(object.id); |
| | if (obj.get('assetType') == 'audio') { |
| | var flag = false; |
| | var animation = { |
| | value: 0, |
| | }; |
| | var instance = anime({ |
| | targets: animation, |
| | value: [currenttime, duration], |
| | delay: 0, |
| | duration: duration, |
| | easing: 'linear', |
| | autoplay: true, |
| | update: async function () { |
| | if (start && play && !paused) { |
| | if ( |
| | !flag && |
| | p_keyframes.find((x) => x.id == object.id).start <= |
| | currenttime && |
| | p_keyframes.find((x) => x.id == object.id).end >= |
| | currenttime |
| | ) { |
| | if (obj.get('src')) { |
| | obj.get('src').currentTime = |
| | (p_keyframes.find((x) => x.id == object.id) |
| | .trimstart - |
| | p_keyframes.find((x) => x.id == object.id).start + |
| | currenttime) / |
| | 1000; |
| | obj.get('src').volume = obj.get('volume'); |
| | obj.get('src').play(); |
| | flag = true; |
| | } else { |
| | var audio = new Audio(obj.get('audioSrc')); |
| | obj.set('src', audio); |
| | audio.volume = obj.get('volume'); |
| | audio.crossOrigin = 'anonymous'; |
| | audio.currentTime = |
| | (p_keyframes.find((x) => x.id == object.id) |
| | .trimstart - |
| | p_keyframes.find((x) => x.id == object.id).start + |
| | currenttime) / |
| | 1000; |
| | audio.play(); |
| | flag = true; |
| | } |
| | } else if ( |
| | p_keyframes.find((x) => x.id == object.id).start >= |
| | currenttime || |
| | p_keyframes.find((x) => x.id == object.id).end <= |
| | currenttime |
| | ) { |
| | if (obj.get('src')) { |
| | obj.get('src').pause(); |
| | } |
| | } |
| | } else if (paused) { |
| | if (obj.get('src')) { |
| | obj.get('src').pause(); |
| | anime.remove(animation); |
| | } |
| | } |
| | }, |
| | changeBegin: function () { |
| | start = true; |
| | }, |
| | }); |
| | } |
| | }); |
| | } |
| |
|
| | |
| | async function recordAnimate(time) { |
| | anime.speed = 1; |
| | |
| | var inst = canvasrecord; |
| | if (animatedtext.length > 0) { |
| | animatedtext.forEach(function (text) { |
| | text.seek(time, inst); |
| | inst.renderAll(); |
| | }); |
| | } |
| | keyframes.forEach(function (keyframe, index) { |
| | |
| | if (groups.find((x) => x.id == keyframe.id)) { |
| | if (!canvas.getItemById(keyframe.id)) { |
| | reGroup(keyframe.id); |
| | } |
| | const object = canvas.getItemById(keyframe.id); |
| | if ( |
| | currenttime < |
| | p_keyframes.find((x) => x.id == keyframe.id).trimstart + |
| | p_keyframes.find((x) => x.id == keyframe.id).start |
| | ) { |
| | object.set('visible', false); |
| | inst.renderAll(); |
| | } else if ( |
| | currenttime > |
| | p_keyframes.find((x) => x.id == keyframe.id).end || |
| | currenttime > duration |
| | ) { |
| | object.set('visible', false); |
| | inst.renderAll(); |
| | } else { |
| | object.set('visible', true); |
| | inst.renderAll(); |
| | } |
| | if ( |
| | currenttime >= |
| | p_keyframes.find((x) => x.id == keyframe.id).trimstart + |
| | p_keyframes.find((x) => x.id == keyframe.id).start |
| | ) { |
| | props.forEach(function (prop) { |
| | checkAnyKeyframe(keyframe.id, prop, inst); |
| | }); |
| | } |
| | } |
| |
|
| | |
| | function setValue(prop, object, value, inst) { |
| | if (object.get('type') != 'group') { |
| | if (object.group) { |
| | var group = object.group; |
| | tempgroup = group._objects; |
| | group._restoreObjectsState(); |
| | canvas.setActiveObject(group); |
| | inst.remove(canvas.getActiveObject()); |
| | canvas.discardActiveObject(); |
| | inst.renderAll(); |
| | for (var i = 0; i < tempgroup.length; i++) { |
| | inst.add(tempgroup[i]); |
| | } |
| | } |
| | } |
| | if (prop == 'left' && !recording) { |
| | object.set(prop, value + artboard.get('left')); |
| | } else if (prop == 'top' && !recording) { |
| | object.set(prop, value + artboard.get('top')); |
| | } else if (prop == 'shadow.blur') { |
| | object.shadow.blur = value; |
| | } else if (prop == 'shadow.color') { |
| | object.shadow.color = value; |
| | } else if (prop == 'shadow.offsetX') { |
| | object.shadow.offsetX = value; |
| | } else if (prop == 'shadow.offsetY') { |
| | object.shadow.offsetY = value; |
| | } else if (prop == 'shadow.blur') { |
| | object.shadow.blur = value; |
| | } else if (object.get('type') != 'group') { |
| | object.set(prop, value); |
| | } else if (prop != 'width') { |
| | object.set(prop, value); |
| | } |
| | inst.renderAll(); |
| | } |
| |
|
| | |
| | function nextKeyframe(keyframe, index) { |
| | var temparr = keyframes.slice(); |
| | temparr.sort(function (a, b) { |
| | return a.t - b.t; |
| | }); |
| | temparr.splice(0, temparr.findIndex((x) => x === keyframe) + 1); |
| | if (temparr.length == 0) { |
| | return false; |
| | } else { |
| | for (var i = 0; i < temparr.length; i++) { |
| | if ( |
| | temparr[i].id == keyframe.id && |
| | temparr[i].name == keyframe.name |
| | ) { |
| | return temparr[i]; |
| | break; |
| | } else if (i == temparr.length - 1) { |
| | return false; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | var object = canvasrecord.getItemById(keyframe.id); |
| | if ( |
| | keyframe.t >= time && |
| | currenttime >= |
| | p_keyframes.find((x) => x.id == keyframe.id).trimstart + |
| | p_keyframes.find((x) => x.id == keyframe.id).start |
| | ) { |
| | var delay = 0; |
| | var start = false; |
| | var lasttime, lastprop; |
| | |
| | var lastkey = lastKeyframe(keyframe, index); |
| | if (!lastkey) { |
| | lasttime = 0; |
| | lastprop = objects |
| | .find((x) => x.id == keyframe.id) |
| | .defaults.find((x) => x.name == keyframe.name).value; |
| | } else { |
| | lasttime = lastkey.t; |
| | lastprop = lastkey.value; |
| | } |
| | if (lastkey && lastkey.t >= time && !play) { |
| | return; |
| | } |
| |
|
| | |
| | var animation = { |
| | value: lastprop, |
| | }; |
| | var instance = anime({ |
| | targets: animation, |
| | delay: delay, |
| | value: keyframe.value, |
| | duration: keyframe.t - lasttime, |
| | easing: keyframe.easing, |
| | autoplay: false, |
| | update: function () { |
| | if (start && paused) { |
| | anime.remove(animation); |
| | } |
| | }, |
| | changeBegin: function () { |
| | start = true; |
| | }, |
| | }); |
| |
|
| | if (time - lasttime <= 0) { |
| | instance.seek(0); |
| | } else { |
| | instance.seek(time - lasttime); |
| | } |
| |
|
| | if ( |
| | parseFloat(lasttime) <= parseFloat(time) && |
| | parseFloat(keyframe.t) >= parseFloat(time) |
| | ) { |
| | setValue(keyframe.name, object, animation.value, inst); |
| | } |
| | } else if (keyframe.t < time && !nextKeyframe(keyframe, index)) { |
| | var prop = keyframe.name; |
| | if (prop == 'shadow.blur') { |
| | if (object.shadow.blur != keyframe.value) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } else if (prop == 'shadow.color') { |
| | if (object.shadow.color != keyframe.value) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } else if (prop == 'shadow.offsetX') { |
| | if (object.shadow.offsetX != keyframe.value) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } else if (prop == 'shadow.offsetY') { |
| | if (object.shadow.offsetY != keyframe.value) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } else { |
| | if (object.get(prop) != keyframe.value) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } |
| | } |
| | }); |
| |
|
| | objects.forEach(function (object) { |
| | if (object.id.indexOf('Group') == -1) { |
| | const object2 = canvas.getItemById(object.id); |
| | if ( |
| | currenttime < |
| | p_keyframes.find((x) => x.id == object.id).trimstart + |
| | p_keyframes.find((x) => x.id == object.id).start |
| | ) { |
| | object2.set('visible', false); |
| | } else if ( |
| | currenttime > |
| | p_keyframes.find((x) => x.id == object.id).end || |
| | currenttime > duration |
| | ) { |
| | object2.set('visible', false); |
| | } else { |
| | object2.set('visible', true); |
| | } |
| | if ( |
| | currenttime >= |
| | p_keyframes.find((x) => x.id == object.id).trimstart + |
| | p_keyframes.find((x) => x.id == object.id).start |
| | ) { |
| | props.forEach(function (prop) { |
| | checkAnyKeyframe(object.id, prop, inst); |
| | }); |
| | } |
| | } |
| | }); |
| | inst.renderAll(); |
| |
|
| | playVideos(time); |
| | |
| | } |
| |
|
| | |
| | async function animate(play, time) { |
| | anime.speed = speed; |
| | if (!draggingPanel) { |
| | var starttime = new Date(); |
| | var offset = time; |
| | var inst = canvas; |
| | keyframes.forEach(function (keyframe, index) { |
| | |
| | function nextKeyframe(keyframe, index) { |
| | var temparr = keyframes.slice(); |
| | temparr.sort(function (a, b) { |
| | return a.t - b.t; |
| | }); |
| | temparr.splice( |
| | 0, |
| | temparr.findIndex((x) => x === keyframe) + 1 |
| | ); |
| | if (temparr.length == 0) { |
| | return false; |
| | } else { |
| | for (var i = 0; i < temparr.length; i++) { |
| | if ( |
| | temparr[i].id == keyframe.id && |
| | temparr[i].name == keyframe.name |
| | ) { |
| | return temparr[i]; |
| | break; |
| | } else if (i == temparr.length - 1) { |
| | return false; |
| | } |
| | } |
| | } |
| | } |
| | |
| | if (groups.find((x) => x.id == keyframe.id)) { |
| | if (!canvas.getItemById(keyframe.id)) { |
| | reGroup(keyframe.id); |
| | } |
| | const object = canvas.getItemById(keyframe.id); |
| | if ( |
| | currenttime < |
| | p_keyframes.find((x) => x.id == keyframe.id).trimstart + |
| | p_keyframes.find((x) => x.id == keyframe.id).start |
| | ) { |
| | object.set('visible', false); |
| | inst.renderAll(); |
| | } else if ( |
| | currenttime > |
| | p_keyframes.find((x) => x.id == keyframe.id).end || |
| | currenttime > duration |
| | ) { |
| | object.set('visible', false); |
| | inst.renderAll(); |
| | } else { |
| | object.set('visible', true); |
| | inst.renderAll(); |
| | } |
| | if ( |
| | currenttime >= |
| | p_keyframes.find((x) => x.id == keyframe.id).trimstart + |
| | p_keyframes.find((x) => x.id == keyframe.id).start |
| | ) { |
| | props.forEach(function (prop) { |
| | checkAnyKeyframe(keyframe.id, prop, inst); |
| | }); |
| | } |
| | } |
| |
|
| | |
| | function setValue(prop, object, value, inst) { |
| | if (object.get('assetType') == 'audio' && play) { |
| | if (object.get('src')) { |
| | object.get('src').volume = value; |
| | object.set('volume', value); |
| | } |
| | return false; |
| | } |
| | if (object.get('type') != 'group') { |
| | if (object.group) { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | } |
| | } |
| | if (prop == 'left' && !recording) { |
| | object.set(prop, value + artboard.get('left')); |
| | } else if (prop == 'top' && !recording) { |
| | object.set(prop, value + artboard.get('top')); |
| | } else if (prop == 'shadow.blur') { |
| | object.shadow.blur = value; |
| | } else if (prop == 'shadow.color') { |
| | object.shadow.color = value; |
| | } else if (prop == 'shadow.offsetX') { |
| | object.shadow.offsetX = value; |
| | } else if (prop == 'shadow.offsetY') { |
| | object.shadow.offsetY = value; |
| | } else if (prop == 'shadow.blur') { |
| | object.shadow.blur = value; |
| | } else if (object.get('type') != 'group') { |
| | object.set(prop, value); |
| | } else if (prop != 'width') { |
| | object.set(prop, value); |
| | } |
| | inst.renderAll(); |
| | } |
| |
|
| | var object = canvas.getItemById(keyframe.id); |
| | if ( |
| | keyframe.t >= time && |
| | currenttime >= |
| | p_keyframes.find((x) => x.id == keyframe.id).trimstart + |
| | p_keyframes.find((x) => x.id == keyframe.id).start |
| | ) { |
| | var delay = 0; |
| | var start = false; |
| | var lasttime, lastprop; |
| | |
| | var lastkey = lastKeyframe(keyframe, index); |
| | if (!lastkey) { |
| | lasttime = 0; |
| | lastprop = objects |
| | .find((x) => x.id == keyframe.id) |
| | .defaults.find((x) => x.name == keyframe.name).value; |
| | } else { |
| | lasttime = lastkey.t; |
| | lastprop = lastkey.value; |
| | } |
| | if (lastkey && lastkey.t >= time && !play) { |
| | return; |
| | } |
| | |
| | if (play) { |
| | if (lasttime > currenttime) { |
| | delay = lasttime - time; |
| | } |
| | } |
| | |
| | var animation = { |
| | value: lastprop, |
| | }; |
| | var instance = anime({ |
| | targets: animation, |
| | delay: delay, |
| | value: keyframe.value, |
| | duration: keyframe.t - lasttime, |
| | easing: keyframe.easing, |
| | autoplay: false, |
| | update: function () { |
| | if (start && !paused) { |
| | if ( |
| | currenttime < |
| | p_keyframes.find((x) => x.id == keyframe.id) |
| | .trimstart + |
| | p_keyframes.find((x) => x.id == keyframe.id) |
| | .start || |
| | currenttime > |
| | p_keyframes.find((x) => x.id == keyframe.id).end || |
| | currenttime > duration |
| | ) { |
| | object.set('visible', false); |
| | inst.renderAll(); |
| | } else { |
| | setValue( |
| | keyframe.name, |
| | object, |
| | animation.value, |
| | inst |
| | ); |
| | object.set('visible', true); |
| | inst.renderAll(); |
| | } |
| | } else if (start && paused) { |
| | anime.remove(animation); |
| | } |
| | }, |
| | changeBegin: function () { |
| | start = true; |
| | }, |
| | }); |
| |
|
| | if (time - lasttime <= 0) { |
| | instance.seek(0); |
| | } else { |
| | instance.seek(time - lasttime); |
| | } |
| |
|
| | if (play) { |
| | instance.play(); |
| | } else if ( |
| | parseFloat(lasttime) <= parseFloat(time) && |
| | parseFloat(keyframe.t) >= parseFloat(time) |
| | ) { |
| | setValue(keyframe.name, object, animation.value, inst); |
| | } |
| | } else if ( |
| | keyframe.t < time && |
| | !nextKeyframe(keyframe, index) |
| | ) { |
| | var prop = keyframe.name; |
| | if (prop == 'left' && !recording) { |
| | if ( |
| | object.get('left') - artboard.get('left') != |
| | keyframe.value |
| | ) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } else if (prop == 'top' && !recording) { |
| | if ( |
| | object.get('top') - artboard.get('top') != |
| | keyframe.value |
| | ) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } else if (prop == 'shadow.blur') { |
| | if (object.shadow.blur != keyframe.value) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } else if (prop == 'shadow.color') { |
| | if (object.shadow.color != keyframe.value) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } else if (prop == 'shadow.offsetX') { |
| | if (object.shadow.offsetX != keyframe.value) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } else if (prop == 'shadow.offsetY') { |
| | if (object.shadow.offsetY != keyframe.value) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } else { |
| | if (object.get(prop) != keyframe.value) { |
| | setValue(keyframe.name, object, keyframe.value, inst); |
| | } |
| | } |
| | } |
| | }); |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | objects.forEach(function (object) { |
| | if (object.id.indexOf('Group') == -1) { |
| | const object2 = canvas.getItemById(object.id); |
| | if ( |
| | currenttime < |
| | p_keyframes.find((x) => x.id == object.id).trimstart + |
| | p_keyframes.find((x) => x.id == object.id).start |
| | ) { |
| | object2.set('visible', false); |
| | } else if ( |
| | currenttime > |
| | p_keyframes.find((x) => x.id == object.id).end || |
| | currenttime > duration |
| | ) { |
| | object2.set('visible', false); |
| | } else { |
| | object2.set('visible', true); |
| | } |
| | if ( |
| | currenttime >= |
| | p_keyframes.find((x) => x.id == object.id).trimstart + |
| | p_keyframes.find((x) => x.id == object.id).start |
| | ) { |
| | props.forEach(function (prop) { |
| | checkAnyKeyframe(object.id, prop, inst); |
| | }); |
| | } |
| | } |
| | var obj = canvas.getItemById(object.id); |
| | if (obj.type == 'lottie') { |
| | obj.goToSeconds(currenttime); |
| | inst.renderAll(); |
| | } |
| | }); |
| | inst.renderAll(); |
| |
|
| | if (animatedtext.length > 0) { |
| | animatedtext.forEach(function (text) { |
| | text.seek(currenttime, canvas); |
| | inst.renderAll(); |
| | }); |
| | } |
| |
|
| | playVideos(time); |
| | if (play) { |
| | playAudio(time); |
| | } |
| | if (play && !paused) { |
| | var animation = { |
| | value: 0, |
| | }; |
| | var main_instance = anime({ |
| | targets: animation, |
| | value: [currenttime, duration], |
| | duration: duration - currenttime, |
| | easing: 'linear', |
| | autoplay: true, |
| | update: function () { |
| | if (!paused) { |
| | currenttime = animation.value; |
| | if (animatedtext.length > 0) { |
| | animatedtext.forEach(function (text) { |
| | text.seek(currenttime, canvas); |
| | inst.renderAll(); |
| | }); |
| | } |
| | objects.forEach(function (object) { |
| | if (object.id.indexOf('Group') == -1) { |
| | const object2 = inst.getItemById(object.id); |
| | if ( |
| | currenttime < |
| | p_keyframes.find((x) => x.id == object.id) |
| | .trimstart + |
| | p_keyframes.find((x) => x.id == object.id).start |
| | ) { |
| | object2.set('visible', false); |
| | } else if ( |
| | currenttime > |
| | p_keyframes.find((x) => x.id == object.id).end || |
| | currenttime > duration |
| | ) { |
| | object2.set('visible', false); |
| | } else { |
| | object2.set('visible', true); |
| | } |
| | if ( |
| | currenttime >= |
| | p_keyframes.find((x) => x.id == object.id) |
| | .trimstart + |
| | p_keyframes.find((x) => x.id == object.id).start |
| | ) { |
| | props.forEach(function (prop) { |
| | checkAnyKeyframe(object.id, prop, inst); |
| | }); |
| | } |
| | } |
| | var obj = canvas.getItemById(object.id); |
| | if (obj.type == 'lottie') { |
| | obj.goToSeconds(currenttime); |
| | inst.renderAll(); |
| | } |
| | }); |
| | inst.renderAll(); |
| | if (!recording) { |
| | renderTime(); |
| | $('#seekbar').css({ |
| | left: currenttime / timelinetime + offset_left, |
| | }); |
| | } |
| | } else { |
| | pause(); |
| | animation.value = duration + 1; |
| | anime.remove(animation); |
| | } |
| | }, |
| | complete: function () { |
| | pause(); |
| | }, |
| | }); |
| | } else if (paused) { |
| | currenttime = time; |
| | } |
| | } |
| | } |
| |
|
| | |
| | function renderKeyframe(object, prop, time) { |
| | const color = objects.find((x) => x.id == object.id).color; |
| | if (prop == 'shadow.color') { |
| | if ( |
| | $('#' + object.get('id')) |
| | .find('.shadowcolor') |
| | .is(':visible') |
| | ) { |
| | time = |
| | time - |
| | parseFloat( |
| | p_keyframes.find((x) => x.id == object.get('id')).start |
| | ); |
| | } |
| | $('#' + object.get('id')) |
| | .find('.shadowcolor') |
| | .prepend( |
| | "<div class='keyframe' data-time='" + |
| | time + |
| | "' data-object='" + |
| | object.get('id') + |
| | "' data-property='" + |
| | prop + |
| | "'></div>" |
| | ); |
| | $('#' + object.get('id')) |
| | .find('.shadowcolor') |
| | .find("[data-time='" + time + "']") |
| | .css({ left: time / timelinetime, background: color }); |
| | } else { |
| | if ( |
| | $('#' + object.get('id')) |
| | .find('.' + prop) |
| | .is(':visible') |
| | ) { |
| | time = |
| | time - |
| | parseFloat( |
| | p_keyframes.find((x) => x.id == object.get('id')).start |
| | ); |
| | } |
| | $('#' + object.get('id')) |
| | .find('.' + prop) |
| | .prepend( |
| | "<div class='keyframe' data-time='" + |
| | time + |
| | "' data-object='" + |
| | object.get('id') + |
| | "' data-property='" + |
| | prop + |
| | "'></div>" |
| | ); |
| | $('#' + object.get('id')) |
| | .find('.' + prop) |
| | .find("[data-time='" + time + "']") |
| | .css({ left: time / timelinetime, background: color }); |
| | } |
| | } |
| |
|
| | |
| | function newKeyframe(property, object, time, value, render) { |
| | |
| | if ( |
| | $.inArray( |
| | property, |
| | objects.find((x) => x.id == object.get('id')).animate |
| | ) != -1 |
| | ) { |
| | const keyarr = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(time) && |
| | e.id == object.get('id') && |
| | e.name == property |
| | ); |
| | }); |
| | const keyarr2 = $.grep(keyframes, function (e) { |
| | return e.id == object.get('id') && e.name == property; |
| | }); |
| | if (keyarr2.length == 0) { |
| | if (property == 'left') { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == property).value = |
| | object.get(property) - artboard.get('left'); |
| | } else if (property == 'top') { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == property).value = |
| | object.get(property) - artboard.get('top'); |
| | } else { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == property).value = value; |
| | } |
| | } |
| | if (keyarr.length == 0) { |
| | if (property == 'left') { |
| | keyframes.push({ |
| | t: time, |
| | name: property, |
| | value: value - artboard.get('left'), |
| | id: object.get('id'), |
| | easing: 'linear', |
| | }); |
| | } else if (property == 'top') { |
| | keyframes.push({ |
| | t: time, |
| | name: property, |
| | value: value - artboard.get('top'), |
| | id: object.get('id'), |
| | easing: 'linear', |
| | }); |
| | } else { |
| | keyframes.push({ |
| | t: time, |
| | name: property, |
| | value: value, |
| | id: object.get('id'), |
| | easing: 'linear', |
| | }); |
| | } |
| | if ( |
| | render && |
| | property != 'top' && |
| | property != 'scaleY' && |
| | property != 'width' && |
| | property != 'height' && |
| | property != 'stroke' && |
| | property != 'shadow.opacity' && |
| | property != 'shadow.offsetX' && |
| | property != 'shadow.offsetY' && |
| | property != 'shadow.blur' && |
| | property != 'lineHeight' |
| | ) { |
| | renderKeyframe(object, property, time); |
| | } |
| | keyframes.sort(function (a, b) { |
| | if ( |
| | a.id.indexOf('Group') >= 0 && |
| | b.id.indexOf('Group') == -1 |
| | ) { |
| | return 1; |
| | } else if ( |
| | b.id.indexOf('Group') >= 0 && |
| | a.id.indexOf('Group') == -1 |
| | ) { |
| | return -1; |
| | } else { |
| | return 0; |
| | } |
| | }); |
| | } else if (render) { |
| | if ( |
| | property != 'top' && |
| | property != 'scaleY' && |
| | property != 'width' && |
| | property != 'height' && |
| | property != 'stroke' && |
| | property != 'shadow.opacity' && |
| | property != 'shadow.offsetX' && |
| | property != 'shadow.offsetY' && |
| | property != 'shadow.blur' && |
| | property != 'lineHeight' |
| | ) { |
| | updateKeyframe( |
| | $('#' + object.get('id')).find( |
| | ".keyframe[data-time='" + |
| | time + |
| | "'][data-property='" + |
| | property + |
| | "']" |
| | ), |
| | true |
| | ); |
| | } |
| | } |
| | } else { |
| | if (property == 'left') { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == property).value = |
| | object.get(property) - artboard.get('left'); |
| | } else if (property == 'top') { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == property).value = |
| | object.get(property) - artboard.get('top'); |
| | } else { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == property).value = value; |
| | } |
| | } |
| | } |
| |
|
| | |
| | function manualKeyframe() { |
| | var prop = $(this).parent().attr('data-property'); |
| | const object = canvas.getItemById( |
| | $(this).parent().parent().parent().attr('data-object') |
| | ); |
| | if (prop == 'position') { |
| | prop = 'left'; |
| | newKeyframe('top', object, currenttime, object.get('top'), true); |
| | } else if (prop == 'scale') { |
| | prop = 'scaleX'; |
| | newKeyframe( |
| | 'scaleY', |
| | object, |
| | currenttime, |
| | object.get('scaleY'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'width', |
| | object, |
| | currenttime, |
| | object.get('width'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'height', |
| | object, |
| | currenttime, |
| | object.get('height'), |
| | true |
| | ); |
| | } else if (prop == 'stroke') { |
| | prop = 'strokeWidth'; |
| | newKeyframe( |
| | 'stroke', |
| | object, |
| | currenttime, |
| | object.get('stroke'), |
| | true |
| | ); |
| | } else if (prop == 'shadow') { |
| | prop = 'shadow.color'; |
| | newKeyframe( |
| | 'shadow.opacity', |
| | object, |
| | currenttime, |
| | object.get('shadow.opacity'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.offsetX', |
| | object, |
| | currenttime, |
| | object.get('shadow.offsetX'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.offsetY', |
| | object, |
| | currenttime, |
| | object.get('shadow.offsetY'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.blur', |
| | object, |
| | currenttime, |
| | object.get('shadow.blur'), |
| | true |
| | ); |
| | } else if (prop == 'text') { |
| | prop = 'charSpacing'; |
| | newKeyframe( |
| | 'lineHeight', |
| | object, |
| | currenttime, |
| | object.get('lineHeight'), |
| | true |
| | ); |
| | } |
| | newKeyframe(prop, object, currenttime, object.get(prop), true); |
| | save(); |
| | } |
| | $(document).on('click', '.property-keyframe', manualKeyframe); |
| |
|
| | |
| | function toggleAnimate(e) { |
| | e.stopPropagation(); |
| | const object = canvas.getItemById( |
| | $(this).parent().parent().parent().attr('data-object') |
| | ); |
| | |
| | if ($(this).hasClass('frozen')) { |
| | $(this).removeClass('frozen'); |
| | $(this).attr('src', 'assets/freeze.svg'); |
| | objects.find((x) => x.id == object.get('id')).animate = []; |
| | |
| | } else { |
| | $(this).addClass('frozen'); |
| | $(this).attr('src', 'assets/frozen.svg'); |
| | objects.find((x) => x.id == object.get('id')).animate = []; |
| | if (object.get('assetType') == 'audio') { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push('volume'); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id'); |
| | }); |
| | $(".keyframe[data-object='" + object.get('id') + "']").remove(); |
| | $(this) |
| | .parent() |
| | .parent() |
| | .parent() |
| | .find('.freeze-prop') |
| | .removeClass('frozen'); |
| | newKeyframe('volume', object, 0, 0.5, true); |
| | } else { |
| | props.forEach(function (prop) { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push(prop); |
| | }); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id'); |
| | }); |
| | $(".keyframe[data-object='" + object.get('id') + "']").remove(); |
| | $(this) |
| | .parent() |
| | .parent() |
| | .parent() |
| | .find('.freeze-prop') |
| | .removeClass('frozen'); |
| |
|
| | props.forEach(function (prop) { |
| | if (prop == 'lineHeight' || prop == 'charSpacing') { |
| | if (object.get('type') == 'textbox') { |
| | newKeyframe(prop, object, 0, object.get(prop), true); |
| | } |
| | } else if ( |
| | prop == 'shadow.opacity' || |
| | prop == 'shadow.blur' || |
| | prop == 'shadow.offsetX' || |
| | prop == 'shadow.offsetY' || |
| | prop == 'shadow.color' |
| | ) { |
| | if (object.get('type') != 'group') { |
| | if (prop == 'shadow.color') { |
| | newKeyframe(prop, object, 0, object.shadow.color, true); |
| | } else if (prop == 'shadow.opacity') { |
| | newKeyframe( |
| | prop, |
| | object, |
| | 0, |
| | object.shadow.opacity, |
| | true |
| | ); |
| | } else if (prop == 'shadow.offsetX') { |
| | newKeyframe( |
| | prop, |
| | object, |
| | 0, |
| | object.shadow.offsetX, |
| | true |
| | ); |
| | } else if (prop == 'shadow.offsetY') { |
| | newKeyframe( |
| | prop, |
| | object, |
| | 0, |
| | object.shadow.offsetY, |
| | true |
| | ); |
| | } else if (prop == 'shadow.blur') { |
| | newKeyframe(prop, object, 0, object.shadow.blur, true); |
| | } |
| | } |
| | } else { |
| | newKeyframe(prop, object, 0, object.get(prop), true); |
| | } |
| | }); |
| | } |
| | } |
| | save(); |
| | } |
| | $(document).on('click', '.freeze', toggleAnimate); |
| |
|
| | function animateProp(prop, object) { |
| | objects.find((x) => x.id == object.get('id')).animate.push(prop); |
| |
|
| | |
| | if (prop == 'left') { |
| | objects.find((x) => x.id == object.get('id')).animate.push('top'); |
| | newKeyframe( |
| | 'left', |
| | object, |
| | currenttime, |
| | object.get('left'), |
| | true |
| | ); |
| | newKeyframe('top', object, currenttime, object.get('top'), true); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'left').value = |
| | object.get('left') - artboard.get('left'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'top').value = |
| | object.get('top') - artboard.get('top'); |
| | } else if (prop == 'scaleX') { |
| | newKeyframe( |
| | 'scaleY', |
| | object, |
| | currenttime, |
| | object.get('scaleY'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'width', |
| | object, |
| | currenttime, |
| | object.get('width'), |
| | true |
| | ); |
| | newKeyframe( |
| | 'height', |
| | object, |
| | currenttime, |
| | object.get('height'), |
| | true |
| | ); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push('scaleY'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push('width'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push('height'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'height').value = |
| | object.get('height'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'width').value = |
| | object.get('width'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'scaleY').value = |
| | object.get('scaleY'); |
| | } else if (prop == 'strokeWidth') { |
| | newKeyframe( |
| | 'stroke', |
| | object, |
| | currenttime, |
| | object.get('stroke'), |
| | true |
| | ); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'stroke').value = |
| | object.get('stroke'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push('stroke'); |
| | } else if (prop == 'shadow.color') { |
| | newKeyframe( |
| | 'shadow.color', |
| | object, |
| | currenttime, |
| | object.shadow.color, |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.opacity', |
| | object, |
| | currenttime, |
| | object.shadow.opacity, |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.offsetX', |
| | object, |
| | currenttime, |
| | object.shadow.offsetX, |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.offsetY', |
| | object, |
| | currenttime, |
| | object.shadow.offsetY, |
| | true |
| | ); |
| | newKeyframe( |
| | 'shadow.blur', |
| | object, |
| | currenttime, |
| | object.shadow.blur, |
| | true |
| | ); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'shadow.color').value = |
| | object.get('shadow.color'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'shadow.opacity').value = |
| | object.get('shadow.opacity'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'shadow.offsetX').value = |
| | object.get('shadow.offsetX'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'shadow.offsetY').value = |
| | object.get('shadow.offsetY'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'shadow.blur').value = |
| | object.get('shadow.blur'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push('shadow.opacity'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push('shadow.offsetX'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push('shadow.offsetY'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push('shadow.blur'); |
| | } else if (prop == 'charSpacing') { |
| | newKeyframe( |
| | 'lineHeight', |
| | object, |
| | currenttime, |
| | object.get('lineHeight'), |
| | true |
| | ); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'lineHeight').value = |
| | object.get('lineHeight'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .animate.push('lineHeight'); |
| | } |
| |
|
| | |
| | if (prop != 'left' && prop != 'shadow.color') { |
| | newKeyframe(prop, object, currenttime, object.get(prop), true); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == prop).value = object.get(prop); |
| | } |
| | } |
| |
|
| | function freezeProp(prop, object) { |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != prop; |
| | } |
| | ); |
| | |
| | if (prop == 'left') { |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != 'top'; |
| | } |
| | ); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != 'top'; |
| | }); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'left').value = |
| | object.get('left') - artboard.get('left'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'top').value = |
| | object.get('top') - artboard.get('top'); |
| | } else if (prop == 'scaleX') { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'height').value = |
| | object.get('height'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'width').value = |
| | object.get('width'); |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'scaleY').value = |
| | object.get('scaleY'); |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != 'scaleY'; |
| | } |
| | ); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != 'scaleY'; |
| | }); |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != 'width'; |
| | } |
| | ); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != 'width'; |
| | }); |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != 'height'; |
| | } |
| | ); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != 'height'; |
| | }); |
| | } else if (prop == 'strokeWidth') { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'stroke').value = |
| | object.get('stroke'); |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != 'stroke'; |
| | } |
| | ); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != 'stroke'; |
| | }); |
| | } else if (prop == 'shadow.color') { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'shadow.opacity').value = |
| | object.shadow.opacity; |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'shadow.offsetX').value = |
| | object.shadow.offsetX; |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'shadow.offsetY').value = |
| | object.shadow.offsetY; |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'shadow.blur').value = |
| | object.shadow.blur; |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != 'shadow.opacity'; |
| | }); |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != 'shadow.opacity'; |
| | } |
| | ); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != 'shadow.offsetX'; |
| | }); |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != 'shadow.offsetX'; |
| | } |
| | ); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != 'shadow.offsetY'; |
| | }); |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != 'shadow.offsetY'; |
| | } |
| | ); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != 'shadow.blur'; |
| | }); |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != 'shadow.blur'; |
| | } |
| | ); |
| | } else if (prop == 'charSpacing') { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == 'lineHeight').value = |
| | object.get('lineHeight'); |
| | objects.find((x) => x.id == object.get('id')).animate = $.grep( |
| | objects.find((x) => x.id == object.get('id')).animate, |
| | function (e) { |
| | return e != 'lineHeight'; |
| | } |
| | ); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != 'lineHeight'; |
| | }); |
| | } |
| |
|
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id') || e.name != prop; |
| | }); |
| |
|
| | |
| | if (prop != 'left' && prop != 'shadow.color') { |
| | objects |
| | .find((x) => x.id == object.get('id')) |
| | .defaults.find((x) => x.name == prop).value = object.get(prop); |
| | } |
| |
|
| | $( |
| | ".keyframe[data-object='" + |
| | object.get('id') + |
| | "'][data-property='" + |
| | prop + |
| | "']" |
| | ).remove(); |
| | } |
| |
|
| | |
| | function toggleAnimateProp(e) { |
| | e.stopPropagation(); |
| | var prop = $(this).parent().attr('data-property'); |
| | const object = canvas.getItemById( |
| | $(this).parent().parent().parent().attr('data-object') |
| | ); |
| | if (prop == 'position') { |
| | prop = 'left'; |
| | } else if (prop == 'scale') { |
| | prop = 'scaleX'; |
| | } else if (prop == 'stroke') { |
| | prop = 'strokeWidth'; |
| | } else if (prop == 'shadow') { |
| | prop = 'shadow.color'; |
| | } else if (prop == 'text') { |
| | prop = 'charSpacing'; |
| | } |
| |
|
| | |
| | if ( |
| | $(this) |
| | .parent() |
| | .parent() |
| | .parent() |
| | .find('.freeze') |
| | .hasClass('frozen') |
| | ) { |
| | objects.find((x) => x.id == object.get('id')).animate = []; |
| | $(this) |
| | .parent() |
| | .parent() |
| | .parent() |
| | .find('.freeze') |
| | .removeClass('frozen'); |
| |
|
| | |
| | var propmatch = [ |
| | prop, |
| | 'scaleY', |
| | 'width', |
| | 'height', |
| | 'top', |
| | 'stroke', |
| | 'shadow.opacity', |
| | 'shadow.offsetX', |
| | 'shadow.offsetY', |
| | 'shadow.blur', |
| | 'lineHeight', |
| | ]; |
| | props.forEach(function (p) { |
| | if ($.inArray(p, propmatch) == -1) { |
| | if ( |
| | (object.get('type') == 'textbox' && p == 'charSpacing') || |
| | p == 'lineHeight' |
| | ) { |
| | freezeProp(p, object); |
| | } else if (p != 'charSpacing' && p != 'lineHeight') { |
| | freezeProp(p, object); |
| | } |
| | } |
| | }); |
| | } |
| |
|
| | |
| | if ($(this).hasClass('frozen')) { |
| | $(this).removeClass('frozen'); |
| | $(this).attr('src', 'assets/freeze.svg'); |
| | freezeProp(prop, object); |
| | |
| | } else { |
| | $(this).addClass('frozen'); |
| | $(this).attr('src', 'assets/frozen.svg'); |
| | animateProp(prop, object); |
| | } |
| | save(); |
| | } |
| | $(document).on('click', '.freeze-prop', toggleAnimateProp); |
| |
|
| | |
| | function lockLayer(e) { |
| | e.stopPropagation(); |
| | const object = canvas.getItemById( |
| | $(this).parent().parent().parent().attr('data-object') |
| | ); |
| | if ($(this).hasClass('locked')) { |
| | $(this).removeClass('locked'); |
| | $(this).attr('src', 'assets/lock.svg'); |
| | object.selectable = true; |
| | $(this).parent().parent().parent().attr('draggable', true); |
| | } else { |
| | $(this).addClass('locked'); |
| | $(this).attr('src', 'assets/locked.svg'); |
| | object.selectable = false; |
| | if (canvas.getActiveObject() == object) { |
| | canvas.discardActiveObject(); |
| | canvas.renderAll(); |
| | } |
| | $(this).parent().parent().parent().attr('draggable', false); |
| | } |
| | save(); |
| | } |
| | $(document).on('click', '.lock', lockLayer); |
| |
|
| | |
| | function centerObject(object) { |
| | object.set('top', artboard.get('top') + artboard.get('height') / 2); |
| | object.set( |
| | 'left', |
| | artboard.get('left') + artboard.get('width') / 2 |
| | ); |
| | canvas.renderAll(); |
| | save(); |
| | } |
| |
|
| | |
| | function renderLayer(object, animate = false) { |
| | $('#nolayers').addClass('yaylayers'); |
| | const color = objects.find((x) => x.id == object.get('id')).color; |
| | var src = ''; |
| | var classlock = ''; |
| | var srclock = 'lock'; |
| | var freeze = 'freeze'; |
| | if (object.get('type') == 'textbox') { |
| | src = 'assets/text.svg'; |
| | } else if ( |
| | object.get('type') == 'rect' || |
| | object.get('type') == 'group' || |
| | object.get('type') == 'circle' || |
| | object.get('type') == 'path' |
| | ) { |
| | src = 'assets/star.svg'; |
| | if (object.get('assetType') == 'animatedText') { |
| | src = 'assets/text.svg'; |
| | } |
| | if (object.get('assetType') == 'audio') { |
| | src = 'assets/audio.svg'; |
| | } |
| | } else if (object.get('type') == 'image') { |
| | if ( |
| | object.get('assetType') && |
| | object.get('assetType') == 'video' |
| | ) { |
| | src = 'assets/video.svg'; |
| | } else { |
| | src = 'assets/image.svg'; |
| | } |
| | } else if (object.get('type') == 'lottie') { |
| | src = 'assets/zappy.svg'; |
| | } else if (object.get('assetType') == 'audio') { |
| | src = 'assets/audio.svg'; |
| | } |
| | if (object.selectable == false) { |
| | classlock = 'locked'; |
| | srclock = 'locked'; |
| | } |
| | if (animate != false) { |
| | freeze = 'frozen'; |
| | } |
| | const leftoffset = |
| | p_keyframes.find((x) => x.id == object.get('id')).trimstart / |
| | timelinetime; |
| | const width = |
| | (p_keyframes.find((x) => x.id == object.get('id')).end - |
| | p_keyframes.find((x) => x.id == object.get('id')).trimstart) / |
| | timelinetime; |
| | $('#inner-timeline').prepend( |
| | "<div class='object-props' id='" + |
| | object.get('id') + |
| | "' style='width:" + |
| | (p_keyframes.find((x) => x.id == object.get('id')).end - |
| | p_keyframes.find((x) => x.id == object.get('id')).start) / |
| | timelinetime + |
| | "px'><div class='row main-row'><div class='row-el' style='background-color:" + |
| | color + |
| | "'><div class='trim-row' style='left:" + |
| | leftoffset + |
| | 'px;width:' + |
| | width + |
| | "px'></div></div></div></div>" |
| | ); |
| | if (object.get('assetType') == 'audio') { |
| | object.setControlsVisibility({ |
| | mt: false, |
| | mb: false, |
| | ml: false, |
| | mr: false, |
| | }); |
| | $('#layer-inner-list').prepend( |
| | "<div class='layer' data-object='" + |
| | object.get('id') + |
| | "'><div class='layer-name'><img class='droparrow' src='assets/drop-arrow.svg' ><img class='layer-icon' src=" + |
| | src + |
| | "><input class='layer-custom-name' value='" + |
| | objects.find((x) => x.id == object.get('id')).label + |
| | "' readonly></span><div class='layer-options'><img class='" + |
| | freeze + |
| | "' src='assets/" + |
| | freeze + |
| | ".svg' title='Toggle animation'></div></div><div class='properties'></div></div>" |
| | ); |
| | } else { |
| | $('#layer-inner-list').prepend( |
| | "<div class='layer' data-object='" + |
| | object.get('id') + |
| | "'><div class='layer-name'><img class='droparrow' src='assets/drop-arrow.svg' ><img class='layer-icon' src=" + |
| | src + |
| | "><input class='layer-custom-name' value='" + |
| | objects.find((x) => x.id == object.get('id')).label + |
| | "' readonly></span><div class='layer-options'><img class='lock " + |
| | classlock + |
| | "' src='assets/" + |
| | srclock + |
| | ".svg' title='Lock layer'><img class='" + |
| | freeze + |
| | "' src='assets/" + |
| | freeze + |
| | ".svg' title='Toggle animation'></div></div><div class='properties'></div></div>" |
| | ); |
| | } |
| | $(".layer[data-object='" + object.get('id') + "']") |
| | .find('.properties') |
| | .toggle(); |
| | setTimelineZoom(timelinetime); |
| | sortable('#layer-inner-list', { |
| | placeholderClass: 'hovering', |
| | copy: true, |
| | customDragImage: (draggedElement, elementOffset, event) => { |
| | return { |
| | element: document.getElementById('nothing'), |
| | posX: event.pageX - elementOffset.left, |
| | posY: event.pageY - elementOffset.top, |
| | }; |
| | }, |
| | }); |
| | if (object.selectable == false) { |
| | $(".layer[data-object='" + object.get('id') + "']").attr( |
| | 'draggable', |
| | false |
| | ); |
| | } |
| | } |
| |
|
| | |
| | function renderProp(prop, object) { |
| | var classfreeze = ''; |
| | srcfreeze = 'freeze'; |
| | if ( |
| | $.inArray( |
| | prop, |
| | objects.find((x) => x.id == object.get('id')).animate |
| | ) != -1 |
| | ) { |
| | classfreeze = 'frozen'; |
| | srcfreeze = 'frozen'; |
| | } |
| | if (prop == 'shadow.color') { |
| | prop = 'shadowcolor'; |
| | } |
| | $('#' + object.get('id')).append( |
| | "<div class='row " + |
| | prop + |
| | " keyframe-row' data-object='" + |
| | object.get('id') + |
| | "'><div class='row-el'></div></div>" |
| | ); |
| | if (prop == 'left') { |
| | $(".layer[data-object='" + object.get('id') + "']") |
| | .find('.properties') |
| | .append( |
| | "<div class='property-name' data-property='position'><span class='property-keyframe' title='Create a new keyframe'></span>Position<img class='freeze-prop " + |
| | classfreeze + |
| | "' src='assets/" + |
| | srcfreeze + |
| | ".svg' title='Toggle animation'></div>" |
| | ); |
| | } else if (prop == 'scaleX') { |
| | $(".layer[data-object='" + object.get('id') + "']") |
| | .find('.properties') |
| | .append( |
| | "<div class='property-name' data-property='scale'><span class='property-keyframe' title='Create a new keyframe'></span>Scale<img class='freeze-prop " + |
| | classfreeze + |
| | "' src='assets/" + |
| | srcfreeze + |
| | ".svg' title='Toggle animation'></div>" |
| | ); |
| | } else if (prop == 'strokeWidth') { |
| | $(".layer[data-object='" + object.get('id') + "']") |
| | .find('.properties') |
| | .append( |
| | "<div class='property-name' data-property='stroke'><span class='property-keyframe' title='Create a new keyframe'></span>Stroke<img class='freeze-prop " + |
| | classfreeze + |
| | "' src='assets/" + |
| | srcfreeze + |
| | ".svg' title='Toggle animation'></div>" |
| | ); |
| | } else if (prop == 'shadowcolor') { |
| | $(".layer[data-object='" + object.get('id') + "']") |
| | .find('.properties') |
| | .append( |
| | "<div class='property-name' data-property='shadow'><span class='property-keyframe' title='Create a new keyframe'></span>Shadow<img class='freeze-prop " + |
| | classfreeze + |
| | "' src='assets/" + |
| | srcfreeze + |
| | ".svg' title='Toggle animation'></div>" |
| | ); |
| | } else if (prop == 'charSpacing') { |
| | $(".layer[data-object='" + object.get('id') + "']") |
| | .find('.properties') |
| | .append( |
| | "<div class='property-name' data-property='text'><span class='property-keyframe' title='Create a new keyframe'></span>Text<img class='freeze-prop " + |
| | classfreeze + |
| | "' src='assets/" + |
| | srcfreeze + |
| | ".svg' title='Toggle animation'></div>" |
| | ); |
| | } else { |
| | $(".layer[data-object='" + object.get('id') + "']") |
| | .find('.properties') |
| | .append( |
| | "<div class='property-name' data-property='" + |
| | prop + |
| | "'><span class='property-keyframe' title='Create a new keyframe'></span>" + |
| | prop + |
| | "<img class='freeze-prop " + |
| | classfreeze + |
| | "' src='assets/" + |
| | srcfreeze + |
| | ".svg' title='Toggle animation'></div>" |
| | ); |
| | } |
| | $('#' + object.get('id')) |
| | .find('.keyframe-row' + '.' + prop) |
| | .toggle(); |
| | } |
| |
|
| | |
| | function newLayer(object) { |
| | layer_count++; |
| | var color; |
| | if (object.get('type') == 'image') { |
| | if ( |
| | object.get('assetType') && |
| | object.get('assetType') == 'video' |
| | ) { |
| | color = '#106CF6'; |
| | } else { |
| | color = '#92F711'; |
| | } |
| | } else if (object.get('type') == 'textbox') { |
| | color = '#F7119B'; |
| | } else if ( |
| | object.get('type') == 'rect' || |
| | object.get('type') == 'group' || |
| | object.get('type') == 'circle' || |
| | object.get('type') == 'path' |
| | ) { |
| | color = '#9211F7'; |
| | if (object.get('assetType') == 'animatedText') { |
| | color = '#F7119B'; |
| | } else if (object.get('assetType') == 'audio') { |
| | color = '#11C0F7'; |
| | } |
| | } |
| | if ( |
| | (object.get('assetType') && object.get('assetType') == 'video') || |
| | object.get('type') == 'lottie' || |
| | object.get('assetType') == 'audio' |
| | ) { |
| | objects.push({ |
| | object: object, |
| | id: object.get('id'), |
| | label: object.get('id'), |
| | color: color, |
| | defaults: [], |
| | locked: [], |
| | mask: 'none', |
| | start: 0, |
| | end: object.get('duration'), |
| | }); |
| | if (object.get('duration') < duration) { |
| | p_keyframes.push({ |
| | start: currenttime, |
| | end: object.get('duration') + currenttime, |
| | trimstart: 0, |
| | trimend: object.get('duration') + currenttime, |
| | object: object, |
| | id: object.get('id'), |
| | }); |
| | } else { |
| | p_keyframes.push({ |
| | start: currenttime, |
| | end: duration - currenttime, |
| | trimstart: 0, |
| | trimend: duration - currenttime, |
| | object: object, |
| | id: object.get('id'), |
| | }); |
| | } |
| | } else { |
| | objects.push({ |
| | object: object, |
| | id: object.get('id'), |
| | label: object.get('id'), |
| | color: color, |
| | defaults: [], |
| | locked: [], |
| | mask: 'none', |
| | }); |
| | if (object.get('notnew')) { |
| | p_keyframes.push({ |
| | start: object.get('starttime'), |
| | end: duration - object.get('starttime'), |
| | trimstart: 0, |
| | trimend: duration - currenttime, |
| | object: object, |
| | id: object.get('id'), |
| | }); |
| | } else { |
| | p_keyframes.push({ |
| | start: currenttime, |
| | end: duration - currenttime, |
| | trimstart: 0, |
| | trimend: duration - currenttime, |
| | object: object, |
| | id: object.get('id'), |
| | }); |
| | } |
| | } |
| | renderLayer(object); |
| | if ( |
| | !object.get('assetType') || |
| | object.get('assetType') != 'audio' |
| | ) { |
| | props.forEach(function (prop) { |
| | if (prop == 'lineHeight' || prop == 'charSpacing') { |
| | if (object.get('type') == 'textbox') { |
| | if (prop != 'lineHeight') { |
| | renderProp(prop, object); |
| | } |
| | objects |
| | .find((x) => x.id == object.id) |
| | .defaults.push({ name: prop, value: object.get(prop) }); |
| | } |
| | } else if ( |
| | prop == 'shadow.opacity' || |
| | prop == 'shadow.blur' || |
| | prop == 'shadow.offsetX' || |
| | prop == 'shadow.offsetY' || |
| | prop == 'shadow.color' |
| | ) { |
| | if (object.get('type') != 'group') { |
| | if (prop == 'shadow.color') { |
| | renderProp(prop, object); |
| | objects |
| | .find((x) => x.id == object.id) |
| | .defaults.push({ |
| | name: prop, |
| | value: object.shadow.color, |
| | }); |
| | } else if (prop == 'shadow.blur') { |
| | objects |
| | .find((x) => x.id == object.id) |
| | .defaults.push({ |
| | name: prop, |
| | value: object.shadow.blur, |
| | }); |
| | } else if (prop == 'shadow.offsetX') { |
| | objects |
| | .find((x) => x.id == object.id) |
| | .defaults.push({ |
| | name: prop, |
| | value: object.shadow.offsetX, |
| | }); |
| | } else if (prop == 'shadow.offsetY') { |
| | objects |
| | .find((x) => x.id == object.id) |
| | .defaults.push({ |
| | name: prop, |
| | value: object.shadow.offsetY, |
| | }); |
| | } else if (prop == 'shadow.opacity') { |
| | objects |
| | .find((x) => x.id == object.id) |
| | .defaults.push({ |
| | name: prop, |
| | value: object.shadow.opacity, |
| | }); |
| | } |
| | } |
| | } else { |
| | if ( |
| | prop != 'top' && |
| | prop != 'scaleY' && |
| | prop != 'stroke' && |
| | prop != 'width' && |
| | prop != 'height' |
| | ) { |
| | renderProp(prop, object); |
| | } |
| | objects |
| | .find((x) => x.id == object.id) |
| | .defaults.push({ name: prop, value: object.get(prop) }); |
| | } |
| | }); |
| | } else { |
| | renderProp('volume', object); |
| | objects |
| | .find((x) => x.id == object.id) |
| | .defaults.push({ name: 'volume', value: 0 }); |
| | } |
| | $('.layer-selected').removeClass('layer-selected'); |
| | $(".layer[data-object='" + object.get('id') + "']").addClass( |
| | 'layer-selected' |
| | ); |
| | document |
| | .getElementsByClassName('layer-selected')[0] |
| | .scrollIntoView(); |
| | objects.find((x) => x.id == object.id).animate = []; |
| | animate(false, currenttime); |
| | save(); |
| | checkFilter(); |
| | } |
| |
|
| | |
| | function newSVG(svg, x, y, width, center) { |
| | var svggroup = []; |
| | fabric.loadSVGFromURL(svg, function (objects, options) { |
| | var newsvg = objects[0]; |
| | if (objects.length > 1) { |
| | newsvg = fabric.util.groupSVGElements(objects, options); |
| | } |
| | newsvg.set({ |
| | id: 'Shape' + layer_count, |
| | stroke: '#000', |
| | left: x, |
| | top: y, |
| | strokeWidth: 0, |
| | strokeUniform: true, |
| | originX: 'center', |
| | originY: 'center', |
| | strokeDashArray: false, |
| | absolutePositioned: true, |
| | paintFirst: 'stroke', |
| | objectCaching: true, |
| | sourcePath: svg, |
| | inGroup: false, |
| | shadow: { |
| | color: '#000', |
| | offsetX: 0, |
| | offsetY: 0, |
| | blur: 0, |
| | opacity: 0, |
| | }, |
| | }); |
| | newsvg.scaleToWidth(width); |
| | newsvg.set({ |
| | scaleX: parseFloat(newsvg.get('scaleX').toFixed(2)), |
| | scaleY: parseFloat(newsvg.get('scaleY').toFixed(2)), |
| | }); |
| | canvas.add(newsvg); |
| | newLayer(newsvg); |
| | canvas.setActiveObject(newsvg); |
| | canvas.bringToFront(newsvg); |
| | canvas.renderAll(); |
| | if (center) { |
| | newsvg.set( |
| | 'left', |
| | artboard.get('left') + artboard.get('width') / 2 |
| | ); |
| | newsvg.set( |
| | 'top', |
| | artboard.get('top') + artboard.get('height') / 2 |
| | ); |
| | canvas.renderAll(); |
| | } |
| | }); |
| | } |
| |
|
| | |
| | function newVideo(file, src, x, y, duration, center) { |
| | var newvid = new fabric.Image(file, { |
| | left: x, |
| | top: y, |
| | width: file.width, |
| | height: file.height, |
| | originX: 'center', |
| | originY: 'center', |
| | backgroundColor: 'rgba(255,255,255,0)', |
| | cursorWidth: 1, |
| | stroke: '#000', |
| | strokeUniform: true, |
| | paintFirst: 'stroke', |
| | strokeWidth: 0, |
| | cursorDuration: 1, |
| | cursorDelay: 250, |
| | source: src, |
| | duration: duration * 1000, |
| | assetType: 'video', |
| | id: 'Video' + layer_count, |
| | objectCaching: false, |
| | strokeDashArray: false, |
| | inGroup: false, |
| | shadow: { |
| | color: '#000', |
| | offsetX: 0, |
| | offsetY: 0, |
| | blur: 0, |
| | opacity: 0, |
| | }, |
| | }); |
| | files.push({ name: newvid.get('id'), file: src }); |
| | newvid.saveElem = newvid.getElement(); |
| | canvas.add(newvid); |
| | if (newvid.get('width') > artboard.get('width')) { |
| | newvid.scaleToWidth(artboard.get('width')); |
| | } |
| | newvid.scaleToWidth(150); |
| | canvas.renderAll(); |
| | if (window.duration < newvid.duration + currenttime) { |
| | window.duration = |
| | ((newvid.duration + currenttime) / 1000).toFixed(2) * 1000; |
| | } |
| | newLayer(newvid); |
| | canvas.setActiveObject(newvid); |
| | canvas.bringToFront(newvid); |
| | if (center) { |
| | newvid.set( |
| | 'left', |
| | artboard.get('left') + artboard.get('width') / 2 |
| | ); |
| | newvid.set( |
| | 'top', |
| | artboard.get('top') + artboard.get('height') / 2 |
| | ); |
| | canvas.renderAll(); |
| | } |
| | $('#load-video').removeClass('loading-active'); |
| | } |
| |
|
| | |
| | function loadVideo(src, x, y, center) { |
| | var vidObj = document.createElement('video'); |
| | var vidSrc = document.createElement('source'); |
| | vidSrc.src = src; |
| | vidObj.crossOrigin = 'anonymous'; |
| | vidObj.appendChild(vidSrc); |
| | vidObj.addEventListener('loadeddata', function () { |
| | vidObj.width = this.videoWidth; |
| | vidObj.height = this.videoHeight; |
| | vidObj.currentTime = 0; |
| | vidObj.muted = false; |
| | function waitLoad() { |
| | if (vidObj.readyState >= 3) { |
| | newVideo(vidObj, src, x, y, vidObj.duration, center); |
| | } else { |
| | window.setTimeout(function () { |
| | waitLoad(); |
| | }, 100); |
| | } |
| | } |
| | window.setTimeout(function () { |
| | waitLoad(); |
| | }, 100); |
| | }); |
| | vidObj.currentTime = 0; |
| | } |
| |
|
| | |
| | function checkCrop(obj) { |
| | if (obj.isContainedWithinObject(cropobj)) { |
| | croptop = obj.get('top'); |
| | cropleft = obj.get('left'); |
| | cropscalex = obj.get('scaleX'); |
| | cropscaley = obj.get('scaleY'); |
| | } else { |
| | obj.top = croptop; |
| | obj.left = cropleft; |
| | obj.scaleX = cropscalex; |
| | obj.scaleY = cropscaley; |
| | obj.setCoords(); |
| | obj.saveState(); |
| | } |
| | obj.set({ |
| | borderColor: '#51B9F9', |
| | }); |
| | canvas.renderAll(); |
| | crop(canvas.getItemById('cropped')); |
| | } |
| |
|
| | |
| | function crop(obj) { |
| | var crop = canvas.getItemById('crop'); |
| | cropobj.setCoords(); |
| | crop.setCoords(); |
| | var cleft = |
| | crop.get('left') - (crop.get('width') * crop.get('scaleX')) / 2; |
| | var ctop = |
| | crop.get('top') - (crop.get('height') * crop.get('scaleY')) / 2; |
| | var height = |
| | (crop.get('height') / cropobj.get('scaleY')) * crop.get('scaleY'); |
| | var width = |
| | (crop.get('width') / cropobj.get('scaleX')) * crop.get('scaleX'); |
| | var img_height = cropobj.get('height') * cropobj.get('scaleY'); |
| | var img_width = cropobj.get('width') * cropobj.get('scaleX'); |
| | var left = |
| | cleft - |
| | (cropobj.get('left') - |
| | (cropobj.get('width') * cropobj.get('scaleX')) / 2); |
| | var top = |
| | ctop - |
| | (cropobj.get('top') - |
| | (cropobj.get('height') * cropobj.get('scaleY')) / 2); |
| | if (left < 0 && top > 0) { |
| | obj |
| | .set({ cropY: top / cropobj.get('scaleY'), height: height }) |
| | .setCoords(); |
| | canvas.renderAll(); |
| | obj.set({ |
| | top: ctop + (obj.get('height') * obj.get('scaleY')) / 2, |
| | }); |
| | canvas.renderAll(); |
| | } else if (top < 0 && left > 0) { |
| | obj |
| | .set({ cropX: left / cropobj.get('scaleX'), width: width }) |
| | .setCoords(); |
| | canvas.renderAll(); |
| | obj.set({ |
| | left: cleft + (obj.get('width') * obj.get('scaleX')) / 2, |
| | }); |
| | canvas.renderAll(); |
| | } else if (top > 0 && left > 0) { |
| | obj |
| | .set({ |
| | cropX: left / cropobj.get('scaleX'), |
| | cropY: top / cropobj.get('scaleY'), |
| | height: height, |
| | width: width, |
| | }) |
| | .setCoords(); |
| | canvas.renderAll(); |
| | obj.set({ |
| | left: cleft + (obj.get('width') * obj.get('scaleX')) / 2, |
| | top: ctop + (obj.get('height') * obj.get('scaleY')) / 2, |
| | }); |
| | canvas.renderAll(); |
| | } |
| | if (obj.get('id') != 'cropped') { |
| | canvas.remove(crop); |
| | canvas.remove(canvas.getItemById('overlay')); |
| | canvas.remove(canvas.getItemById('cropped')); |
| | cropping = false; |
| | resetControls(); |
| | canvas.uniformScaling = true; |
| | canvas.renderAll(); |
| | newKeyframe('scaleX', obj, currenttime, obj.get('scaleX'), true); |
| | newKeyframe('scaleY', obj, currenttime, obj.get('scaleY'), true); |
| | newKeyframe('width', obj, currenttime, obj.get('width'), true); |
| | newKeyframe('height', obj, currenttime, obj.get('width'), true); |
| | newKeyframe('left', obj, currenttime, obj.get('left'), true); |
| | newKeyframe('top', obj, currenttime, obj.get('top'), true); |
| | $('#properties-overlay').removeClass('properties-disabled'); |
| | save(); |
| | } |
| | canvas.renderAll(); |
| | } |
| |
|
| | var tlcrop = new Image(); |
| | tlcrop.src = 'assets/tlcrop.svg'; |
| | var trcrop = new Image(); |
| | trcrop.src = 'assets/trcrop.svg'; |
| | var blcrop = new Image(); |
| | blcrop.src = 'assets/blcrop.svg'; |
| | var brcrop = new Image(); |
| | brcrop.src = 'assets/brcrop.svg'; |
| |
|
| | function overlay() { |
| | canvas.add( |
| | new fabric.Rect({ |
| | left: artboard.left, |
| | top: artboard.top, |
| | originX: 'left', |
| | originY: 'top', |
| | width: artboard.width, |
| | height: artboard.height, |
| | fill: 'rgba(0,0,0,0.5)', |
| | selectable: false, |
| | id: 'overlay', |
| | }) |
| | ); |
| | } |
| |
|
| | |
| | function cropImage(object) { |
| | if (!cropping) { |
| | $('#properties-overlay').addClass('properties-disabled'); |
| | cropping = true; |
| | cropobj = object; |
| | canvas.uniformScaling = false; |
| | cropobj.setCoords(); |
| | var left = |
| | cropobj.get('left') - |
| | (cropobj.get('width') * cropobj.get('scaleX')) / 2; |
| | var top = |
| | cropobj.get('top') - |
| | (cropobj.get('height') * cropobj.get('scaleY')) / 2; |
| | var cropx = cropobj.get('cropX'); |
| | var cropy = cropobj.get('cropY'); |
| | overlay(); |
| | var cropUI = new fabric.Rect({ |
| | left: object.get('left'), |
| | top: object.get('top'), |
| | width: object.get('width') * object.get('scaleX') - 5, |
| | height: object.get('height') * object.get('scaleY') - 5, |
| | originX: 'center', |
| | originY: 'center', |
| | id: 'crop', |
| | fill: 'rgba(0,0,0,0)', |
| | shadow: { |
| | color: 'black', |
| | offsetX: 0, |
| | offsetY: 0, |
| | blur: 0, |
| | opacity: 0, |
| | }, |
| | }); |
| | cropobj.clone(function (cloned) { |
| | cloned.set({ |
| | id: 'cropped', |
| | selectable: false, |
| | originX: 'center', |
| | originY: 'center', |
| | }); |
| | canvas.add(cloned); |
| | canvas.bringToFront(cloned); |
| | canvas.bringToFront(cropUI); |
| | canvas.renderAll(); |
| | cropobj = object; |
| | }); |
| | cropobj |
| | .set({ |
| | cropX: 0, |
| | cropY: 0, |
| | width: cropobj.get('ogWidth'), |
| | height: cropobj.get('ogHeight'), |
| | }) |
| | .setCoords(); |
| | canvas.renderAll(); |
| | cropobj.set({ |
| | left: |
| | left + |
| | (cropobj.get('width') * cropobj.get('scaleX')) / 2 - |
| | cropx * cropobj.get('scaleX'), |
| | top: |
| | top + |
| | (cropobj.get('height') * cropobj.get('scaleY')) / 2 - |
| | cropy * cropobj.get('scaleY'), |
| | }); |
| | cropUI.setControlsVisibility({ |
| | mt: false, |
| | mb: false, |
| | mr: false, |
| | ml: false, |
| | mtr: false, |
| | }); |
| | cropUI.controls.tl = new fabric.Control({ |
| | x: -0.5, |
| | y: -0.5, |
| | offsetX: 3, |
| | offsetY: 3, |
| | cursorStyleHandler: |
| | fabric.controlsUtils.scaleCursorStyleHandler, |
| | actionHandler: fabric.controlsUtils.scalingEqually, |
| | render: function (ctx, left, top, styleOverride, fabricObject) { |
| | const wsize = 27; |
| | const hsize = 27; |
| | ctx.save(); |
| | ctx.translate(left, top); |
| | ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle)); |
| | ctx.drawImage(tlcrop, -wsize / 2, -hsize / 2, wsize, hsize); |
| | ctx.restore(); |
| | }, |
| | }); |
| | cropUI.controls.tr = new fabric.Control({ |
| | x: 0.5, |
| | y: -0.5, |
| | offsetX: -3, |
| | offsetY: 3, |
| | cursorStyleHandler: |
| | fabric.controlsUtils.scaleCursorStyleHandler, |
| | actionHandler: fabric.controlsUtils.scalingEqually, |
| | render: function (ctx, left, top, styleOverride, fabricObject) { |
| | const wsize = 27; |
| | const hsize = 27; |
| | ctx.save(); |
| | ctx.translate(left, top); |
| | ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle)); |
| | ctx.drawImage(trcrop, -wsize / 2, -hsize / 2, wsize, hsize); |
| | ctx.restore(); |
| | }, |
| | }); |
| | cropUI.controls.bl = new fabric.Control({ |
| | x: -0.5, |
| | y: 0.5, |
| | offsetX: 3, |
| | offsetY: -3, |
| | cursorStyleHandler: |
| | fabric.controlsUtils.scaleCursorStyleHandler, |
| | actionHandler: fabric.controlsUtils.scalingEqually, |
| | render: function (ctx, left, top, styleOverride, fabricObject) { |
| | const wsize = 27; |
| | const hsize = 27; |
| | ctx.save(); |
| | ctx.translate(left, top); |
| | ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle)); |
| | ctx.drawImage(blcrop, -wsize / 2, -hsize / 2, wsize, hsize); |
| | ctx.restore(); |
| | }, |
| | }); |
| | cropUI.controls.br = new fabric.Control({ |
| | x: 0.5, |
| | y: 0.5, |
| | offsetX: -3, |
| | offsetY: -3, |
| | cursorStyleHandler: |
| | fabric.controlsUtils.scaleCursorStyleHandler, |
| | actionHandler: fabric.controlsUtils.scalingEqually, |
| | render: function (ctx, left, top, styleOverride, fabricObject) { |
| | const wsize = 27; |
| | const hsize = 27; |
| | ctx.save(); |
| | ctx.translate(left, top); |
| | ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle)); |
| | ctx.drawImage(brcrop, -wsize / 2, -hsize / 2, wsize, hsize); |
| | ctx.restore(); |
| | }, |
| | }); |
| | canvas.add(cropUI); |
| | canvas.setActiveObject(cropUI); |
| | canvas.renderAll(); |
| | cropleft = cropUI.get('left'); |
| | croptop = cropUI.get('top'); |
| | cropscalex = cropUI.get('scaleX') - 0.03; |
| | cropscaley = cropUI.get('scaleY') - 0.03; |
| | } |
| | } |
| | $(document).on('click', '#crop-image', function () { |
| | if (canvas.getActiveObject()) { |
| | cropImage(canvas.getActiveObject()); |
| | } |
| | }); |
| |
|
| | |
| | function newImage(file, x, y, width, center) { |
| | var newimg = new fabric.Image(file, { |
| | left: x, |
| | top: y, |
| | originX: 'center', |
| | originY: 'center', |
| | stroke: '#000', |
| | strokeUniform: true, |
| | strokeWidth: 0, |
| | paintFirst: 'stroke', |
| | absolutePositioned: true, |
| | id: 'Image' + layer_count, |
| | inGroup: false, |
| | strokeDashArray: false, |
| | objectCaching: true, |
| | shadow: { |
| | color: 'black', |
| | offsetX: 0, |
| | offsetY: 0, |
| | blur: 0, |
| | opacity: 0, |
| | }, |
| | }); |
| | files.push({ name: newimg.get('id'), file: file.src }); |
| | canvas.add(newimg); |
| | newimg.scaleToWidth(width); |
| | newimg.set({ |
| | scaleX: parseFloat(newimg.get('scaleX').toFixed(2)), |
| | scaleY: parseFloat(newimg.get('scaleY').toFixed(2)), |
| | ogWidth: newimg.get('width'), |
| | ogHeight: newimg.get('height'), |
| | }); |
| | canvas.bringToFront(newimg); |
| | canvas.renderAll(); |
| | newLayer(newimg); |
| | canvas.setActiveObject(newimg); |
| | if (center) { |
| | newimg.set( |
| | 'left', |
| | artboard.get('left') + artboard.get('width') / 2 |
| | ); |
| | newimg.set( |
| | 'top', |
| | artboard.get('top') + artboard.get('height') / 2 |
| | ); |
| | canvas.renderAll(); |
| | } |
| | $('#load-image').removeClass('loading-active'); |
| | } |
| |
|
| | function loadImage(src, x, y, width, center) { |
| | var image = new Image(); |
| | image.onload = function (img) { |
| | newImage(image, x, y, width, center); |
| | }; |
| | image.src = src; |
| | } |
| |
|
| | function createVideoThumbnail(file, max, seekTo = 0.0, isURL) { |
| | return new Promise((resolve, reject) => { |
| | const videoPlayer = document.createElement('video'); |
| | if (isURL) { |
| | videoPlayer.setAttribute('src', file); |
| | } else { |
| | videoPlayer.setAttribute('src', URL.createObjectURL(file)); |
| | } |
| | videoPlayer.setAttribute('crossorigin', 'anonymous'); |
| | videoPlayer.load(); |
| | videoPlayer.addEventListener('error', (ex) => { |
| | reject('error when loading video file', ex); |
| | }); |
| | videoPlayer.addEventListener('loadedmetadata', () => { |
| | if (videoPlayer.duration < seekTo) { |
| | reject('video is too short.'); |
| | return; |
| | } |
| | setTimeout(() => { |
| | videoPlayer.currentTime = seekTo; |
| | }, 200); |
| | videoPlayer.addEventListener('seeked', () => { |
| | var oc = document.createElement('canvas'); |
| | var octx = oc.getContext('2d'); |
| | oc.width = videoPlayer.videoWidth; |
| | oc.height = videoPlayer.videoheight; |
| | octx.drawImage(videoPlayer, 0, 0); |
| | if (videoPlayer.videoWidth > videoPlayer.videoHeight) { |
| | oc.height = |
| | (videoPlayer.videoHeight / videoPlayer.videoWidth) * max; |
| | oc.width = max; |
| | } else { |
| | oc.width = |
| | (videoPlayer.videoWidth / videoPlayer.videoHeight) * max; |
| | oc.height = max; |
| | } |
| | octx.drawImage(oc, 0, 0, oc.width, oc.height); |
| | octx.drawImage(videoPlayer, 0, 0, oc.width, oc.height); |
| | resolve(oc.toDataURL()); |
| | }); |
| | }); |
| | }); |
| | } |
| |
|
| | function createThumbnail(file, max) { |
| | return new Promise(function (resolve, reject) { |
| | var reader = new FileReader(); |
| | reader.onload = function (event) { |
| | var img = new Image(); |
| | img.onload = function () { |
| | if (img.width > max) { |
| | var oc = document.createElement('canvas'); |
| | var octx = oc.getContext('2d'); |
| | oc.width = img.width; |
| | oc.height = img.height; |
| | octx.drawImage(img, 0, 0); |
| | if (img.width > img.height) { |
| | oc.height = (img.height / img.width) * max; |
| | oc.width = max; |
| | } else { |
| | oc.width = (img.width / img.height) * max; |
| | oc.height = max; |
| | } |
| | octx.drawImage(oc, 0, 0, oc.width, oc.height); |
| | octx.drawImage(img, 0, 0, oc.width, oc.height); |
| | resolve(oc.toDataURL()); |
| | } else { |
| | resolve(img.src); |
| | } |
| | }; |
| | img.src = event.target.result; |
| | }; |
| | reader.readAsDataURL(file); |
| | }); |
| | } |
| |
|
| | function dataURItoBlob(dataURI) { |
| | var byteString = atob(dataURI.split(',')[1]); |
| | var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; |
| | var ab = new ArrayBuffer(byteString.length); |
| | var ia = new Uint8Array(ab); |
| | for (var i = 0; i < byteString.length; i++) { |
| | ia[i] = byteString.charCodeAt(i); |
| | } |
| | var blob = new Blob([ab], { type: mimeString }); |
| | return blob; |
| | } |
| |
|
| | async function uploadFromURL() { |
| | var url = $('#upload-link-input').val(); |
| | let file = await fetch(url).then((r) => r.blob()); |
| | if (file.type.split('/')[0] === 'image') { |
| | $('#upload-link-input').val(''); |
| | $('.upload-show').removeClass('upload-show'); |
| | createThumbnail(file, 250).then(function (data) { |
| | saveFile( |
| | dataURItoBlob(data), |
| | file, |
| | file.type.split('/')[0], |
| | 'temp', |
| | false, |
| | false |
| | ); |
| | }); |
| | } else if (file.type.split('/')[0] === 'video') { |
| | $('.upload-show').removeClass('upload-show'); |
| | createVideoThumbnail(file, 250, 0, false).then(function (data) { |
| | saveFile( |
| | dataURItoBlob(data), |
| | file, |
| | file.type.split('/')[0], |
| | 'temp', |
| | false, |
| | false |
| | ); |
| | }); |
| | $('#upload-link-input').val(''); |
| | } else { |
| | alert('File type not accepted'); |
| | } |
| | } |
| | $(document).on('click', '#upload-link-add', uploadFromURL); |
| |
|
| | function handleUpload(custom = false) { |
| | var files2; |
| | if (custom == false) { |
| | files2 = $('#filepick').get(0).files; |
| | } else { |
| | files2 = custom.originalEvent.dataTransfer.files; |
| | } |
| | if (files2) { |
| | Array.from(files2).forEach((file) => { |
| | uploading = true; |
| | if (file.size / 1024 / 1024 <= 10) { |
| | $('#upload-button').html( |
| | "<img src='assets/upload.svg'> Uploading..." |
| | ); |
| | $('#upload-button').addClass('uploading'); |
| | if (file['type'].split('/')[0] === 'image') { |
| | $('.upload-show').removeClass('upload-show'); |
| | createThumbnail(file, 250).then(function (data) { |
| | saveFile( |
| | dataURItoBlob(data), |
| | file, |
| | file['type'].split('/')[0], |
| | 'temp', |
| | false, |
| | false |
| | ); |
| | }); |
| | } else if (file['type'].split('/')[0] === 'video') { |
| | $('.upload-show').removeClass('upload-show'); |
| | createVideoThumbnail(file, 250, 0, false).then(function ( |
| | data |
| | ) { |
| | saveFile( |
| | dataURItoBlob(data), |
| | file, |
| | file['type'].split('/')[0], |
| | 'temp', |
| | false, |
| | false |
| | ); |
| | }); |
| | } else { |
| | alert('File type not accepted'); |
| | } |
| | } else { |
| | alert('File is too big'); |
| | } |
| | }); |
| | if (files2.length == 1) { |
| | if (files2[0]['type'].split('/')[0] === 'image') { |
| | $('.upload-tab-active').removeClass('upload-tab-active'); |
| | $('#images-tab').addClass('upload-tab-active'); |
| | } else if (files2[0]['type'].split('/')[0] === 'video') { |
| | $('.upload-tab-active').removeClass('upload-tab-active'); |
| | $('#videos-tab').addClass('upload-tab-active'); |
| | } else if (files2[0]['type'].split('/')[0] === 'audio') { |
| | $('.upload-tab-active').removeClass('upload-tab-active'); |
| | $('#audio-tab').addClass('upload-tab-active'); |
| | } |
| | } |
| | } |
| | } |
| | $(document).on('change', '#filepick', function () { |
| | handleUpload(false); |
| | }); |
| |
|
| | |
| | function audioUpload() { |
| | const files = $('#filepick2').get(0).files; |
| | if (files) { |
| | if (files.length == 1) { |
| | if (files[0]['type'].split('/')[0] === 'audio') { |
| | if (files[0].size / 1024 / 1024 <= 10) { |
| | $('#audio-upload-button').html('Uploading...'); |
| | $('#audio-upload-button').addClass('uploading'); |
| | saveAudio(files[0]); |
| | } else { |
| | alert('File is too big'); |
| | } |
| | } else { |
| | alert('Wrong file type'); |
| | } |
| | } |
| | } |
| | } |
| | $(document).on('change', '#filepick2', audioUpload); |
| |
|
| | |
| | function newRectangle(color) { |
| | var newrect = new fabric.Rect({ |
| | left: 0, |
| | top: 0, |
| | originX: 'center', |
| | originY: 'center', |
| | width: 200, |
| | height: 200, |
| | stroke: '#000', |
| | strokeWidth: 0, |
| | strokeUniform: true, |
| | backgroundColor: 'rgba(255,255,255,0)', |
| | rx: 0, |
| | ry: 0, |
| | fill: color, |
| | cursorWidth: 1, |
| | cursorDuration: 1, |
| | paintFirst: 'stroke', |
| | cursorDelay: 250, |
| | strokeDashArray: false, |
| | inGroup: false, |
| | id: 'Shape' + layer_count, |
| | shadow: { |
| | color: '#000', |
| | offsetX: 0, |
| | offsetY: 0, |
| | blur: 0, |
| | opacity: 0, |
| | }, |
| | }); |
| | canvas.add(newrect); |
| | newLayer(newrect); |
| | canvas.setActiveObject(newrect); |
| | canvas.bringToFront(newrect); |
| | canvas.renderAll(); |
| | } |
| |
|
| | |
| | function formatText() { |
| | var isselected = false; |
| | if (!canvas.getActiveObject().isEditing) { |
| | canvas.getActiveObject().enterEditing(); |
| | canvas.getActiveObject().selectAll(); |
| | isselected = true; |
| | } |
| | if ($(this).hasClass('format-text-active')) { |
| | if ($(this).attr('id') == 'format-bold') { |
| | $(this).find('img').attr('src', 'assets/bold.svg'); |
| | canvas |
| | .getActiveObject() |
| | .setSelectionStyles({ fontWeight: 'normal' }); |
| | } else if ($(this).attr('id') == 'format-italic') { |
| | $(this).find('img').attr('src', 'assets/italic.svg'); |
| | canvas |
| | .getActiveObject() |
| | .setSelectionStyles({ fontStyle: 'normal' }); |
| | } else if ($(this).attr('id') == 'format-underline') { |
| | $(this).find('img').attr('src', 'assets/underline.svg'); |
| | canvas |
| | .getActiveObject() |
| | .setSelectionStyles({ underline: false }); |
| | } else { |
| | $(this).find('img').attr('src', 'assets/strike.svg'); |
| | canvas |
| | .getActiveObject() |
| | .setSelectionStyles({ linethrough: false }); |
| | } |
| | $(this).removeClass('format-text-active'); |
| | } else { |
| | $(this).addClass('format-text-active'); |
| | if ($(this).attr('id') == 'format-bold') { |
| | $(this).find('img').attr('src', 'assets/bold-active.svg'); |
| | canvas |
| | .getActiveObject() |
| | .setSelectionStyles({ fontWeight: 'bold' }); |
| | } else if ($(this).attr('id') == 'format-italic') { |
| | $(this).find('img').attr('src', 'assets/italic-active.svg'); |
| | canvas |
| | .getActiveObject() |
| | .setSelectionStyles({ fontStyle: 'italic' }); |
| | } else if ($(this).attr('id') == 'format-underline') { |
| | $(this).find('img').attr('src', 'assets/underline-active.svg'); |
| | canvas |
| | .getActiveObject() |
| | .setSelectionStyles({ underline: true }); |
| | } else { |
| | $(this).find('img').attr('src', 'assets/strike-active.svg'); |
| | canvas |
| | .getActiveObject() |
| | .setSelectionStyles({ linethrough: true }); |
| | } |
| | } |
| | if (isselected) { |
| | canvas.getActiveObject().exitEditing(); |
| | } |
| | canvas.renderAll(); |
| | save(); |
| | } |
| | $(document).on('click', '.format-text', formatText); |
| |
|
| | |
| | function lineJoin() { |
| | if ($('.line-join-active').attr('id') == 'miter') { |
| | $('.line-join-active') |
| | .find('img') |
| | .attr('src', 'assets/miter.svg'); |
| | } else if ($('.line-join-active').attr('id') == 'bevel') { |
| | $('.line-join-active') |
| | .find('img') |
| | .attr('src', 'assets/bevel.svg'); |
| | } else if ($('.line-join-active').attr('id') == 'round') { |
| | $('.line-join-active') |
| | .find('img') |
| | .attr('src', 'assets/round.svg'); |
| | } else if ($('.line-join-active').attr('id') == 'small-dash') { |
| | $('.line-join-active') |
| | .find('img') |
| | .attr('src', 'assets/dash2.svg'); |
| | } |
| | $('.line-join-active').removeClass('line-join-active'); |
| | $(this).addClass('line-join-active'); |
| | if ($(this).attr('id') == 'miter') { |
| | $(this).find('img').attr('src', 'assets/miter-active.svg'); |
| | canvas |
| | .getActiveObject() |
| | .set({ strokeWidth: 0, strokeDashArray: false }); |
| | canvas.renderAll(); |
| | updatePanelValues(); |
| | } else if ($(this).attr('id') == 'bevel') { |
| | $(this).find('img').attr('src', 'assets/bevel-active.svg'); |
| | canvas.getActiveObject().set({ strokeDashArray: false }); |
| | if (canvas.getActiveObject().get('strokeWidth') == 0) { |
| | canvas.getActiveObject().set({ strokeWidth: 1 }); |
| | canvas.renderAll(); |
| | updatePanelValues(); |
| | } |
| | } else if ($(this).attr('id') == 'round') { |
| | $(this).find('img').attr('src', 'assets/round-active.svg'); |
| | canvas.getActiveObject().set({ strokeDashArray: [10, 5] }); |
| | if (canvas.getActiveObject().get('strokeWidth') == 0) { |
| | canvas.getActiveObject().set({ strokeWidth: 1 }); |
| | canvas.renderAll(); |
| | updatePanelValues(); |
| | } |
| | } else { |
| | $(this).find('img').attr('src', 'assets/dash2-active.svg'); |
| | canvas.getActiveObject().set({ strokeDashArray: [3, 3] }); |
| | if (canvas.getActiveObject().get('strokeWidth') == 0) { |
| | canvas.getActiveObject().set({ strokeWidth: 1 }); |
| | canvas.renderAll(); |
| | updatePanelValues(); |
| | } |
| | } |
| | canvas.renderAll(); |
| | save(); |
| | } |
| | $(document).on('click', '.line-join', lineJoin); |
| |
|
| | |
| | function alignText() { |
| | var textalign; |
| | if ($('.align-text-active').attr('id') == 'align-text-left') { |
| | $('.align-text-active') |
| | .find('img') |
| | .attr('src', 'assets/align-text-left.svg'); |
| | } else if ( |
| | $('.align-text-active').attr('id') == 'align-text-center' |
| | ) { |
| | $('.align-text-active') |
| | .find('img') |
| | .attr('src', 'assets/align-text-center.svg'); |
| | } else if ( |
| | $('.align-text-active').attr('id') == 'align-text-right' |
| | ) { |
| | $('.align-text-active') |
| | .find('img') |
| | .attr('src', 'assets/align-text-right.svg'); |
| | } else { |
| | $('.align-text-active') |
| | .find('img') |
| | .attr('src', 'assets/align-text-justify.svg'); |
| | } |
| | $('.align-text-active').removeClass('align-text-active'); |
| | $(this).addClass('align-text-active'); |
| | if ($(this).attr('id') == 'align-text-left') { |
| | textalign = 'left'; |
| | $(this) |
| | .find('img') |
| | .attr('src', 'assets/align-text-left-active.svg'); |
| | } else if ($(this).attr('id') == 'align-text-center') { |
| | textalign = 'center'; |
| | $(this) |
| | .find('img') |
| | .attr('src', 'assets/align-text-center-active.svg'); |
| | } else if ($(this).attr('id') == 'align-text-right') { |
| | textalign = 'right'; |
| | $(this) |
| | .find('img') |
| | .attr('src', 'assets/align-text-right-active.svg'); |
| | } else { |
| | textalign = 'justify'; |
| | $(this) |
| | .find('img') |
| | .attr('src', 'assets/align-text-justify-active.svg'); |
| | } |
| | canvas.getActiveObject().set({ textAlign: textalign }); |
| | canvas.renderAll(); |
| | save(); |
| | } |
| | $(document).on('click', '.align-text', alignText); |
| |
|
| | |
| | function changeFont() { |
| | var font = $('#font-picker').val(); |
| | if (canvas.getActiveObject().get('assetType')) { |
| | WebFont.load({ |
| | google: { |
| | families: [font], |
| | }, |
| | active: () => { |
| | var object = canvas.getActiveObject(); |
| | animatedtext |
| | .find((x) => x.id == object.id) |
| | .reset( |
| | animatedtext.find((x) => x.id == object.id).text, |
| | $.extend( |
| | animatedtext.find((x) => x.id == object.id).props, |
| | { fontFamily: font } |
| | ), |
| | canvas |
| | ); |
| | save(); |
| | }, |
| | }); |
| | save(); |
| | } else { |
| | WebFont.load({ |
| | google: { |
| | families: [font], |
| | }, |
| | active: () => { |
| | canvas.getActiveObject().set('fontFamily', font); |
| | canvas.renderAll(); |
| | save(); |
| | }, |
| | }); |
| | } |
| | } |
| | $(document).on('change', '#font-picker', changeFont); |
| |
|
| | |
| | function calculateTextWidth(text, font) { |
| | var ctx = canvas.getContext('2d'); |
| | ctx.font = font; |
| | return ctx.measureText(text).width + 10; |
| | } |
| |
|
| | |
| | function newAudioLayer(src) { |
| | var audio = new Audio(src); |
| | audio.crossOrigin = 'anonymous'; |
| | audio.addEventListener('loadeddata', () => { |
| | var nullobject = new fabric.Rect({ |
| | id: 'Audio' + layer_count, |
| | width: 10, |
| | height: 10, |
| | audioSrc: src, |
| | duration: audio.duration * 1000, |
| | opacity: 0, |
| | selectable: false, |
| | volume: 0.5, |
| | assetType: 'audio', |
| | shadow: { |
| | color: '#000', |
| | offsetX: 0, |
| | offsetY: 0, |
| | blur: 0, |
| | opacity: 0, |
| | }, |
| | }); |
| | canvas.add(nullobject); |
| | newLayer(nullobject); |
| | }); |
| | } |
| |
|
| | |
| | function newTextbox( |
| | fontsize, |
| | fontweight, |
| | text, |
| | x, |
| | y, |
| | width, |
| | center, |
| | font |
| | ) { |
| | var newtext = new fabric.Textbox(text, { |
| | left: x, |
| | top: y, |
| | originX: 'center', |
| | originY: 'center', |
| | fontFamily: 'Inter', |
| | fill: '#000', |
| | fontSize: fontsize, |
| | fontWeight: fontweight, |
| | textAlign: 'center', |
| | cursorWidth: 1, |
| | stroke: '#000', |
| | strokeWidth: 0, |
| | cursorDuration: 1, |
| | paintFirst: 'stroke', |
| | objectCaching: false, |
| | absolutePositioned: true, |
| | strokeUniform: true, |
| | inGroup: false, |
| | cursorDelay: 250, |
| | strokeDashArray: false, |
| | width: calculateTextWidth( |
| | text, |
| | fontweight + ' ' + fontsize + 'px Inter' |
| | ), |
| | id: 'Text' + layer_count, |
| | shadow: { |
| | color: '#000', |
| | offsetX: 0, |
| | offsetY: 0, |
| | blur: 0, |
| | opacity: 0, |
| | }, |
| | }); |
| | newtext.setControlsVisibility({ |
| | mt: false, |
| | mb: false, |
| | }); |
| | canvas.add(newtext); |
| | newLayer(newtext); |
| | canvas.setActiveObject(newtext); |
| | canvas.bringToFront(newtext); |
| | newtext.enterEditing(); |
| | newtext.selectAll(); |
| | canvas.renderAll(); |
| | if (center) { |
| | newtext.set( |
| | 'left', |
| | artboard.get('left') + artboard.get('width') / 2 |
| | ); |
| | newtext.set( |
| | 'top', |
| | artboard.get('top') + artboard.get('height') / 2 |
| | ); |
| | canvas.renderAll(); |
| | } |
| | canvas.getActiveObject().set('fontFamily', font); |
| | canvas.renderAll(); |
| | } |
| |
|
| | function deleteObject(object, def = true) { |
| | if (object.get('assetType') == 'animatedText' && def) { |
| | animatedtext = $.grep(animatedtext, function (a) { |
| | return a.id != object.id; |
| | }); |
| | } |
| | if (object.type == 'image') { |
| | var temp = files.find((x) => x.name == object.get('id')); |
| | files = $.grep(files, function (a) { |
| | return a != temp.name; |
| | }); |
| | } |
| | $(".layer[data-object='" + object.get('id') + "']").remove(); |
| | $('#' + object.get('id')).remove(); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return e.id != object.get('id'); |
| | }); |
| | p_keyframes = $.grep(p_keyframes, function (e) { |
| | return e.id != object.get('id'); |
| | }); |
| | objects = $.grep(objects, function (e) { |
| | return e.id != object.get('id'); |
| | }); |
| | canvas.remove(object); |
| | canvas.renderAll(); |
| | canvas.discardActiveObject(); |
| | save(); |
| | if (objects.length == 0) { |
| | $('#nolayers').removeClass('yaylayers'); |
| | } |
| | } |
| |
|
| | |
| | function deleteSelection() { |
| | if ( |
| | canvas.getActiveObject() && |
| | !canvas.getActiveObject().isEditing |
| | ) { |
| | const selection = canvas.getActiveObject(); |
| | if (selection.type == 'activeSelection') { |
| | canvas.discardActiveObject(); |
| | selection._objects.forEach(function (object) { |
| | deleteObject(object); |
| | }); |
| | } else { |
| | deleteObject(canvas.getActiveObject()); |
| | } |
| | } |
| | } |
| |
|
| | |
| | function toggleLayer() { |
| | const layerid = $(this).parent().parent().attr('data-object'); |
| | $(this).parent().parent().find('.properties').toggle(); |
| | $(this).parent().parent().find('.droparrow').toggleClass('layeron'); |
| | $(".keyframe-row[data-object='" + layerid + "']").toggle(); |
| | setTimelineZoom(timelinetime); |
| | } |
| | $(document).on('click', '.droparrow', toggleLayer); |
| |
|
| | |
| | function selectLayer(e) { |
| | if (!$(e.target).hasClass('droparrow')) { |
| | const layerid = $(this).parent().attr('data-object'); |
| | $('.layer-selected').removeClass('layer-selected'); |
| | $(this).parent().addClass('layer-selected'); |
| | canvas.setActiveObject(canvas.getItemById(layerid)); |
| | } |
| | } |
| | $(document).on('click', '.layer-name', selectLayer); |
| |
|
| | |
| | function setDuration(length) { |
| | $('#inner-timeline').css('width', length / timelinetime + 50); |
| | $('#inner-seekarea').css('width', length / timelinetime + 50); |
| | duration = length; |
| | var minutes = Math.floor(duration / 1000 / 60); |
| | var seconds = (duration / 1000 - minutes * 60).toFixed(2); |
| | $('#total-time input').val( |
| | ('0' + minutes).slice(-2) + |
| | ':' + |
| | ('0' + Math.floor(seconds)).slice(-2) + |
| | ':' + |
| | ('0' + Math.floor((seconds % 1) * 100)).slice(-2) |
| | ); |
| | $('.object-props').each(function () { |
| | $(this).css( |
| | 'width', |
| | duration / timelinetime - |
| | p_keyframes.find((x) => x.id == $(this).attr('id')).start / |
| | timelinetime + |
| | 'px' |
| | ); |
| | p_keyframes.find((x) => x.id == $(this).attr('id')).end = |
| | duration; |
| | if ( |
| | p_keyframes.find((x) => x.id == $(this).attr('id')).trimend > |
| | p_keyframes.find((x) => x.id == $(this).attr('id')).end |
| | ) { |
| | p_keyframes.find((x) => x.id == $(this).attr('id')).trimend = |
| | duration; |
| | $(this) |
| | .find('.trim-row') |
| | .css( |
| | 'width', |
| | duration / timelinetime - |
| | p_keyframes.find((x) => x.id == $(this).attr('id')) |
| | .trimstart / |
| | timelinetime + |
| | 'px' |
| | ); |
| | } |
| | }); |
| | setTimelineZoom(timelinetime); |
| | save(); |
| | } |
| |
|
| | |
| | function renderTimeMarkers() { |
| | var renderoffset = 1000 / timelinetime - 20; |
| | var timenumber = 0; |
| | var modulo = 1; |
| | if (timelinetime > 18) { |
| | modulo = 5; |
| | } else if (timelinetime > 12) { |
| | modulo = 2; |
| | } |
| | $('#time-numbers').html(''); |
| | $('#time-numbers').append( |
| | "<div class='time-number' style='margin-left:" + |
| | offset_left + |
| | "px'>" + |
| | timenumber + |
| | 's<span></span></div>' |
| | ); |
| | timenumber++; |
| | while (timenumber * 1000 <= duration) { |
| | $('#time-numbers').append( |
| | "<div class='time-number' style='margin-left:" + |
| | renderoffset + |
| | "px'>" + |
| | timenumber + |
| | 's<span></span></div>' |
| | ); |
| | if (timenumber % modulo != 0) { |
| | $('.time-number:last-child()').css('opacity', '0'); |
| | } |
| | timenumber++; |
| | } |
| | } |
| |
|
| | |
| | function setTimelineZoom(time) { |
| | $('.object-props').each(function () { |
| | $(this).offset({ |
| | left: |
| | p_keyframes.find((x) => x.id == $(this).attr('id')).start / |
| | time + |
| | $('#inner-timeline').offset().left + |
| | offset_left, |
| | }); |
| | $(this).css({ width: ($(this).width() * timelinetime) / time }); |
| | $(this) |
| | .find('.trim-row') |
| | .css({ |
| | left: |
| | p_keyframes.find((x) => x.id == $(this).attr('id')) |
| | .trimstart / time, |
| | }); |
| | $(this) |
| | .find('.trim-row') |
| | .css({ |
| | width: |
| | ($(this).find('.trim-row').width() * timelinetime) / time, |
| | }); |
| | }); |
| | timelinetime = time; |
| | $('.keyframe').each(function () { |
| | $(this).offset({ |
| | left: |
| | $(this).attr('data-time') / timelinetime + |
| | $('#inner-timeline').offset().left + |
| | offset_left, |
| | }); |
| | }); |
| | $('#seekbar').offset({ |
| | left: |
| | $('#inner-timeline').offset().left + |
| | currenttime / timelinetime + |
| | offset_left, |
| | }); |
| | $('#inner-timeline').css({ width: duration / timelinetime + 50 }); |
| | $('#inner-seekarea').css({ |
| | minWidth: duration / timelinetime + 50, |
| | }); |
| | renderTimeMarkers(); |
| | } |
| | $(document).on('input', '#timeline-zoom', function () { |
| | setTimelineZoom($('#timeline-zoom').val()); |
| | }); |
| |
|
| | function removeKeyframe() { |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != selectedkeyframe.attr('data-property') |
| | ); |
| | }); |
| | if (selectedkeyframe.attr('data-property') == 'left') { |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != 'top' |
| | ); |
| | }); |
| | } else if (selectedkeyframe.attr('data-property') == 'scaleX') { |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != 'scaleY' |
| | ); |
| | }); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != 'width' |
| | ); |
| | }); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != 'height' |
| | ); |
| | }); |
| | } else if ( |
| | selectedkeyframe.attr('data-property') == 'strokeWidth' |
| | ) { |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != 'stroke' |
| | ); |
| | }); |
| | } else if ( |
| | selectedkeyframe.attr('data-property') == 'shadow.color' |
| | ) { |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != 'shadow.blur' |
| | ); |
| | }); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != 'shadow.offsetX' |
| | ); |
| | }); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != 'shadow.offsetY' |
| | ); |
| | }); |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != 'shadow.opacity' |
| | ); |
| | }); |
| | } else if ( |
| | selectedkeyframe.attr('data-property') == 'charSpacing' |
| | ) { |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != selectedkeyframe.attr('data-time') || |
| | e.id != selectedkeyframe.attr('data-object') || |
| | e.name != 'lineHeight' |
| | ); |
| | }); |
| | } |
| | selectedkeyframe.remove(); |
| | $('#keyframe-properties').removeClass('show-properties'); |
| | } |
| |
|
| | |
| | function deleteKeyframe() { |
| | if (shiftkeys.length > 0) { |
| | shiftkeys.forEach(function (key) { |
| | selectedkeyframe = $(key.keyframe); |
| | removeKeyframe(); |
| | }); |
| | shiftkeys = []; |
| | } else { |
| | removeKeyframe(); |
| | } |
| | animate(false, currenttime); |
| | save(); |
| | } |
| | $(document).on('click', '#delete-keyframe', deleteKeyframe); |
| |
|
| | |
| | function copyKeyframes() { |
| | clipboard.sort(function (a, b) { |
| | return a.t - b.t; |
| | }); |
| | var inittime = clipboard[0].t; |
| | clipboard.forEach(function (keyframe) { |
| | var newtime = keyframe.t - inittime + currenttime; |
| | newKeyframe( |
| | keyframe.name, |
| | canvas.getItemById(keyframe.id), |
| | newtime, |
| | keyframe.value, |
| | true |
| | ); |
| | var keyprop = keyframe.name; |
| | if (keyprop == 'left') { |
| | const keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == keyframe.t && e.id == keyframe.id && e.name == 'top' |
| | ); |
| | }); |
| | newKeyframe( |
| | 'top', |
| | canvas.getItemById(keyframe.id), |
| | newtime, |
| | keyarr2[0].value, |
| | true |
| | ); |
| | } else if (keyprop == 'scaleX') { |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == keyframe.t && |
| | e.id == keyframe.id && |
| | e.name == 'scaleY' |
| | ); |
| | }); |
| | newKeyframe( |
| | 'scaleY', |
| | canvas.getItemById(keyframe.id), |
| | newtime, |
| | keyarr2[0].value, |
| | true |
| | ); |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == keyframe.t && |
| | e.id == keyframe.id && |
| | e.name == 'width' |
| | ); |
| | }); |
| | if (keyarr2.length > 0) { |
| | newKeyframe( |
| | 'width', |
| | canvas.getItemById(keyframe.id), |
| | newtime, |
| | keyarr2[0].value, |
| | true |
| | ); |
| | } |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == keyframe.t && |
| | e.id == keyframe.id && |
| | e.name == 'height' |
| | ); |
| | }); |
| | if (keyarr2.length > 0) { |
| | newKeyframe( |
| | 'height', |
| | canvas.getItemById(keyframe.id), |
| | newtime, |
| | keyarr2[0].value, |
| | true |
| | ); |
| | } |
| | } else if (keyprop == 'strokeWidth') { |
| | const keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == keyframe.t && |
| | e.id == keyframe.id && |
| | e.name == 'stroke' |
| | ); |
| | }); |
| | newKeyframe( |
| | 'stroke', |
| | canvas.getItemById(keyframe.id), |
| | newtime, |
| | keyarr2[0].value, |
| | true |
| | ); |
| | } else if (keyprop == 'charSpacing') { |
| | const keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == keyframe.t && |
| | e.id == keyframe.id && |
| | e.name == 'lineHeight' |
| | ); |
| | }); |
| | newKeyframe( |
| | 'lineHeight', |
| | canvas.getItemByid(keyframe.id), |
| | newtime, |
| | keyarr2[0].value, |
| | true |
| | ); |
| | } else if (keyprop == 'shadow.color') { |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == keyframe.t && |
| | e.id == keyframe.id && |
| | e.name == 'shadow.opacity' |
| | ); |
| | }); |
| | newKeyframe( |
| | 'shadow.opacity', |
| | canvas.getItemById(keyframe.id), |
| | newtime, |
| | keyarr2[0].value, |
| | true |
| | ); |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == keyframe.t && |
| | e.id == keyframe.id && |
| | e.name == 'shadow.offsetX' |
| | ); |
| | }); |
| | newKeyframe( |
| | 'shadow.offsetX', |
| | canvas.getItemById(keyframe.id), |
| | newtime, |
| | keyarr2[0].value, |
| | true |
| | ); |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == keyframe.t && |
| | e.id == keyframe.id && |
| | e.name == 'shadow.offsetY' |
| | ); |
| | }); |
| |
|
| | newKeyframe( |
| | 'shadow.offsetY', |
| | canvas.getItemById(keyframe.id), |
| | newtime, |
| | keyarr2[0].value, |
| | true |
| | ); |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == keyframe.t && |
| | e.id == keyframe.id && |
| | e.name == 'shadow.blur' |
| | ); |
| | }); |
| | newKeyframe( |
| | 'shadow.blur', |
| | canvas.getItemById(keyframe.id), |
| | newtime, |
| | keyarr2[0].value, |
| | true |
| | ); |
| | } |
| | save(); |
| | }); |
| | } |
| |
|
| | |
| | function updateKeyframe(drag, newval, offset) { |
| | var time = parseFloat( |
| | (drag.position().left * timelinetime).toFixed(1) |
| | ); |
| | const keyprop = drag.attr('data-property'); |
| | const keytime = drag.attr('data-time'); |
| | const keyarr = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == keyprop |
| | ); |
| | }); |
| | const keyobj = canvas.getItemById(keyarr[0].id); |
| | time = |
| | parseFloat( |
| | p_keyframes.find((x) => x.id == keyobj.get('id')).start |
| | ) + time; |
| | if (newval) { |
| | time = currenttime; |
| | } |
| | var keyval = keyarr[0].value; |
| | if (newval) { |
| | if (keyprop == 'shadow.color') { |
| | keyval = keyobj.shadow.color; |
| | } else if (keyprop == 'volume') { |
| | keyval = parseFloat($('#object-volume input').val() / 200); |
| | } else { |
| | keyval = keyobj.get(keyprop); |
| | } |
| | } else if (keyprop == 'left') { |
| | keyval = keyval + artboard.get('left'); |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != keyprop |
| | ); |
| | }); |
| | newKeyframe(keyprop, keyobj, time, keyval, false); |
| | if (keyprop == 'left') { |
| | const keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == 'top' |
| | ); |
| | }); |
| | var keyval2 = keyarr2[0].value + artboard.get('top'); |
| | if (newval) { |
| | keyval2 = canvas.getItemById(keyarr2[0].id).get('top'); |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != 'top' |
| | ); |
| | }); |
| | newKeyframe('top', keyobj, time, keyval2, false); |
| | } else if (keyprop == 'scaleX') { |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == 'scaleY' |
| | ); |
| | }); |
| | var keyval2 = keyarr2[0].value; |
| | if (newval) { |
| | keyval2 = canvas.getItemById(keyarr2[0].id).get('scaleY'); |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != 'scaleY' |
| | ); |
| | }); |
| | newKeyframe('scaleY', keyobj, time, keyval2, false); |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == 'width' |
| | ); |
| | }); |
| | if (keyarr2.length > 0) { |
| | var keyval2 = keyarr2[0].value; |
| | if (newval) { |
| | keyval2 = canvas.getItemById(keyarr2[0].id).get('width'); |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != 'width' |
| | ); |
| | }); |
| | newKeyframe('width', keyobj, time, keyval2, false); |
| | } |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == 'height' |
| | ); |
| | }); |
| | if (keyarr2.length > 0) { |
| | var keyval2 = keyarr2[0].value; |
| | if (newval) { |
| | keyval2 = canvas.getItemById(keyarr2[0].id).get('height'); |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != 'height' |
| | ); |
| | }); |
| | newKeyframe('height', keyobj, time, keyval2, false); |
| | } |
| | } else if (keyprop == 'strokeWidth') { |
| | const keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == 'stroke' |
| | ); |
| | }); |
| | var keyval2 = keyarr2[0].value; |
| | if (newval) { |
| | keyval2 = canvas.getItemById(keyarr2[0].id).get('stroke'); |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != 'stroke' |
| | ); |
| | }); |
| | newKeyframe('stroke', keyobj, time, keyval2, false); |
| | } else if (keyprop == 'charSpacing') { |
| | const keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == 'lineHeight' |
| | ); |
| | }); |
| | var keyval2 = keyarr2[0].value; |
| | if (newval) { |
| | keyval2 = canvas.getItemById(keyarr2[0].id).get('lineHeight'); |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != 'lineHeight' |
| | ); |
| | }); |
| | newKeyframe('lineHeight', keyobj, time, keyval2, false); |
| | } else if (keyprop == 'shadow.color') { |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == 'shadow.opacity' |
| | ); |
| | }); |
| | var keyval2 = keyarr2[0].value; |
| | if (newval) { |
| | keyval2 = canvas.getItemById(keyarr2[0].id).shadow.opacity; |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != 'shadow.opacity' |
| | ); |
| | }); |
| | newKeyframe('shadow.opacity', keyobj, time, keyval2, false); |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == 'shadow.offsetX' |
| | ); |
| | }); |
| | var keyval2 = keyarr2[0].value; |
| | if (newval) { |
| | keyval2 = canvas.getItemById(keyarr2[0].id).shadow.offsetX; |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != 'shadow.offsetX' |
| | ); |
| | }); |
| | newKeyframe('shadow.offsetX', keyobj, time, keyval2, false); |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == 'shadow.offsetY' |
| | ); |
| | }); |
| | var keyval2 = keyarr2[0].value; |
| | if (newval) { |
| | keyval2 = canvas.getItemById(keyarr2[0].id).shadow.offsetY; |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != 'shadow.offsetY' |
| | ); |
| | }); |
| | newKeyframe('shadow.offsetY', keyobj, time, keyval2, false); |
| | var keyarr2 = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t == parseFloat(keytime) && |
| | e.id == drag.attr('data-object') && |
| | e.name == 'shadow.blur' |
| | ); |
| | }); |
| | var keyval2 = keyarr2[0].value; |
| | if (newval) { |
| | keyval2 = canvas.getItemById(keyarr2[0].id).shadow.blur; |
| | } |
| | keyframes = $.grep(keyframes, function (e) { |
| | return ( |
| | e.t != parseFloat(keytime) || |
| | e.id != drag.attr('data-object') || |
| | e.name != 'shadow.blur' |
| | ); |
| | }); |
| | newKeyframe('shadow.blur', keyobj, time, keyval2, false); |
| | } |
| | if (offset) { |
| | drag.attr('data-time', time); |
| | } else { |
| | drag.attr( |
| | 'data-time', |
| | time + p_keyframes.find((x) => x.id == keyarr[0].id).start |
| | ); |
| | } |
| | keyframes.sort(function (a, b) { |
| | if (a.id.indexOf('Group') >= 0 && b.id.indexOf('Group') == -1) { |
| | return 1; |
| | } else if ( |
| | b.id.indexOf('Group') >= 0 && |
| | a.id.indexOf('Group') == -1 |
| | ) { |
| | return -1; |
| | } else { |
| | return 0; |
| | } |
| | }); |
| | } |
| |
|
| | function keyframeSnap(drag) { |
| | if (shiftkeys.length == 0) { |
| | if ( |
| | drag.offset().left > $('#seekbar').offset().left - 5 && |
| | drag.offset().left < $('#seekbar').offset().left + 5 |
| | ) { |
| | drag.offset({ left: $('#seekbar').offset().left }); |
| | $('#line-snap').offset({ |
| | left: $('#seekbar').offset().left, |
| | top: drag.parent().parent().offset().top, |
| | }); |
| | $('#line-snap').css({ |
| | height: drag.parent().parent().height(), |
| | }); |
| | $('#line-snap').addClass('line-active'); |
| | } else { |
| | drag |
| | .parent() |
| | .parent() |
| | .find('.keyframe') |
| | .each(function (index) { |
| | if (!drag.is($(this))) { |
| | if ( |
| | drag.offset().left > $(this).offset().left - 5 && |
| | drag.offset().left < $(this).offset().left + 5 |
| | ) { |
| | drag.offset({ left: $(this).offset().left }); |
| | $('#line-snap').offset({ |
| | left: $(this).offset().left, |
| | top: drag.parent().parent().offset().top, |
| | }); |
| | $('#line-snap').css({ |
| | height: drag.parent().parent().height(), |
| | }); |
| | $('#line-snap').addClass('line-active'); |
| | return false; |
| | } |
| | } |
| | if (index == $('.keyframe').length - 1) { |
| | $('#line-snap').removeClass('line-active'); |
| | } |
| | }); |
| | } |
| | } |
| | } |
| |
|
| | |
| | function dragKeyframe(e) { |
| | if (e.which == 3) { |
| | return false; |
| | } |
| | e.stopPropagation(); |
| | e.preventDefault(); |
| | var inst = this; |
| | var drag = $(this); |
| | var pageX = e.pageX; |
| | var offset = $(this).offset(); |
| | var move = false; |
| | if (e.shiftKey) { |
| | if (!$(this).hasClass('keyframe-selected')) { |
| | shiftkeys.push({ |
| | keyframe: this, |
| | offset: $(this).offset().left, |
| | }); |
| | $(this).addClass('keyframe-selected'); |
| | } else { |
| | shiftkeys = $.grep(shiftkeys, function (e) { |
| | return e.keyframe != this; |
| | }); |
| | $(this).removeClass('keyframe-selected'); |
| | } |
| | } |
| | if (shiftkeys.length > 0) { |
| | shiftkeys.forEach(function (key) { |
| | key.offset = $(key.keyframe).offset().left; |
| | }); |
| | } |
| | function draggingKeyframe(e) { |
| | move = true; |
| | var left = offset.left + (e.pageX - pageX); |
| | if (shiftkeys.length == 0) { |
| | if (left > $('#timearea').offset().left + offset_left) { |
| | drag.offset({ left: left }); |
| | } else { |
| | drag.offset({ |
| | left: $('#timearea').offset().left + offset_left, |
| | }); |
| | } |
| | keyframeSnap(drag); |
| | } else { |
| | shiftkeys.forEach(function (key) { |
| | if (key.keyframe != inst) { |
| | $(key.keyframe).offset({ |
| | left: key.offset + (e.pageX - pageX), |
| | }); |
| | keyframeSnap($(key.keyframe)); |
| | } else { |
| | drag.offset({ left: left }); |
| | keyframeSnap(drag); |
| | } |
| | }); |
| | } |
| | } |
| | function releasedKeyframe(e) { |
| | $('body') |
| | .off('mousemove', draggingKeyframe) |
| | .off('mouseup', releasedKeyframe); |
| | $('#line-snap').removeClass('line-active'); |
| | if (move) { |
| | if (shiftkeys.length == 0) { |
| | |
| | var time = parseFloat( |
| | (drag.position().left * timelinetime).toFixed(1) |
| | ); |
| | if (time % 16.666 != 0) { |
| | drag.offset({ |
| | left: |
| | (Math.ceil(time / 16.666) * 16.666) / timelinetime + |
| | drag.parent().offset().left, |
| | }); |
| | updateKeyframe(drag, false); |
| | } else { |
| | updateKeyframe(drag, false); |
| | } |
| | } else { |
| | shiftkeys.forEach(function (key) { |
| | |
| | var time = parseFloat( |
| | ($(key.keyframe).position().left * timelinetime).toFixed( |
| | 1 |
| | ) |
| | ); |
| | if (time % 16.666 != 0) { |
| | $(key.keyframe).offset({ |
| | left: |
| | (Math.ceil(time / 16.666) * 16.666) / timelinetime + |
| | $(key.keyframe).parent().offset().left, |
| | }); |
| | updateKeyframe($(key.keyframe), false); |
| | } else { |
| | updateKeyframe($(key.keyframe), false); |
| | } |
| | }); |
| | } |
| | } else if (!e.shiftDown) { |
| | keyframeProperties(inst); |
| | } |
| | move = false; |
| | $('.line-active').removeClass('line-active'); |
| | save(); |
| | } |
| | $('body') |
| | .on('mouseup', releasedKeyframe) |
| | .on('mousemove', draggingKeyframe); |
| | } |
| | $(document).on('mousedown', '.keyframe', dragKeyframe); |
| |
|
| | |
| | function renderTime() { |
| | var minutes = Math.floor(currenttime / 1000 / 60); |
| | var seconds = (currenttime / 1000 - minutes * 60).toFixed(2); |
| | $('#current-time input').val( |
| | ('0' + minutes).slice(-2) + |
| | ':' + |
| | ('0' + Math.floor(seconds)).slice(-2) + |
| | ':' + |
| | ('0' + Math.floor((seconds % 1) * 100)).slice(-2) |
| | ); |
| | } |
| |
|
| | |
| | function updateTime(drag, check) { |
| | if ($('#timeline').scrollLeft() > offset_left) { |
| | currenttime = parseFloat( |
| | ( |
| | (drag.position().left + |
| | $('#timeline').scrollLeft() - |
| | offset_left) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | } else { |
| | currenttime = parseFloat( |
| | ( |
| | (drag.position().left + |
| | $('#timeline').scrollLeft() - |
| | offset_left) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | } |
| | |
| | if (currenttime % 16.666 != 0 && !check) { |
| | currenttime = Math.ceil(currenttime / 16.666) * 16.666; |
| | } |
| | renderTime(); |
| | pause(); |
| | animate(false, currenttime); |
| | } |
| |
|
| | |
| | function dragSeekBar(e) { |
| | if (e.which == 3) { |
| | return false; |
| | } |
| | var drag = $(this); |
| | var pageX = e.pageX; |
| | var offset = $(this).offset(); |
| | tempselection = canvas.getActiveObject(); |
| | canvas.discardActiveObject(); |
| | function dragging(e) { |
| | paused = true; |
| | var left = offset.left + (e.pageX - pageX); |
| | if ( |
| | left > $('#timearea').offset().left + offset_left && |
| | left - $('#timearea').offset().left < |
| | duration / timelinetime + offset_left |
| | ) { |
| | drag.offset({ left: left }); |
| | } else if (left < $('#timearea').offset().left + offset_left) { |
| | drag.offset({ |
| | left: offset_left + $('#timearea').offset().left, |
| | }); |
| | } |
| | if ($('#timeline').scrollLeft() > offset_left) { |
| | currenttime = parseFloat( |
| | ( |
| | (drag.position().left + |
| | $('#timeline').scrollLeft() - |
| | offset_left) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | } else { |
| | currenttime = parseFloat( |
| | ( |
| | (drag.position().left + |
| | $('#timeline').scrollLeft() - |
| | offset_left) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | } |
| | animate(false, currenttime); |
| | seeking = true; |
| | renderTime(); |
| | } |
| | function released(e) { |
| | $('body').off('mousemove', dragging).off('mouseup', released); |
| | updateTime(drag, false); |
| | seeking = false; |
| | if (tempselection && tempselection.type != 'activeSelection') { |
| | reselect(tempselection); |
| | } |
| | updatePanelValues(); |
| | } |
| | $('body').on('mouseup', released).on('mousemove', dragging); |
| | } |
| | $(document).on('mousedown', '#seekbar', dragSeekBar); |
| |
|
| | |
| | function dragObjectProps(e) { |
| | if (e.which == 3) { |
| | return false; |
| | } |
| | var drag = $(this).parent(); |
| | var drag2 = $(this).find('.trim-row'); |
| | var target = e.target; |
| | var pageX = e.pageX; |
| | var offset = drag.offset(); |
| | var offset2 = drag2.offset(); |
| | var initwidth = drag2.width(); |
| | var initpos = drag2.position().left; |
| | var opened = false; |
| | var trim = 'no'; |
| | |
| | if (e.metaKey) { |
| | if (e.shiftKey) { |
| | if (drag2.position().left + e.pageX >= 0) { |
| | drag2.offset({ |
| | left: |
| | hovertime / timelinetime - |
| | p_keyframes.find((x) => x.id == drag.attr('id')) |
| | .trimstart / |
| | timelinetime + |
| | offset2.left, |
| | }); |
| | const leftval = parseFloat( |
| | (drag2.position().left * timelinetime).toFixed(1) |
| | ); |
| | p_keyframes.find((x) => x.id == drag.attr('id')).trimstart = |
| | leftval; |
| | drag2.css({ |
| | width: |
| | (p_keyframes.find((x) => x.id == drag.attr('id')) |
| | .trimend - |
| | p_keyframes.find((x) => x.id == drag.attr('id')) |
| | .trimstart) / |
| | timelinetime, |
| | }); |
| | return false; |
| | } |
| | } else { |
| | if ( |
| | hovertime + |
| | p_keyframes.find((x) => x.id == drag.attr('id')).start < |
| | duration |
| | ) { |
| | drag2.css({ |
| | width: |
| | hovertime / timelinetime - |
| | p_keyframes.find((x) => x.id == drag.attr('id')) |
| | .trimstart / |
| | timelinetime, |
| | }); |
| | save(); |
| | p_keyframes.find((x) => x.id == drag.attr('id')).end = |
| | hovertime; |
| | p_keyframes.find((x) => x.id == drag.attr('id')).trimend = |
| | hovertime; |
| | } |
| | return false; |
| | } |
| | } |
| | if (pageX - $(this).find('.trim-row').offset().left < 7) { |
| | trim = 'left'; |
| | } else if ( |
| | pageX - $(this).find('.trim-row').offset().left > |
| | $(this).find('.trim-row').width() - 7 |
| | ) { |
| | trim = 'right'; |
| | } |
| | function dragging(e) { |
| | if (trim == 'no') { |
| | var left = offset.left + (e.pageX - pageX); |
| | if ( |
| | left > |
| | $('#timearea').offset().left + |
| | offset_left - |
| | $('#timeline').scrollLeft() |
| | ) { |
| | drag.offset({ left: left }); |
| | } else if ( |
| | left + $('#timeline').scrollLeft() < |
| | $('#timearea').offset().left + offset_left |
| | ) { |
| | drag.css({ left: offset_left }); |
| | } |
| | p_keyframes.find((x) => x.id == drag.attr('id')).start = |
| | parseFloat( |
| | ( |
| | (drag.position().left - |
| | offset_left + |
| | $('#timeline').scrollLeft()) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | p_keyframes.find((x) => x.id == drag.attr('id')).end = |
| | parseFloat( |
| | ( |
| | (drag.position().left + |
| | drag.width() - |
| | offset_left + |
| | $('#timeline').scrollLeft()) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | if ( |
| | $(".keyframe-row[data-object='" + drag.attr('id') + "']").is( |
| | ':hidden' |
| | ) |
| | ) { |
| | opened = true; |
| | $(".layer[data-object='" + drag.attr('id') + "']") |
| | .find('.properties') |
| | .toggle(); |
| | $(".layer[data-object='" + drag.attr('id') + "']") |
| | .find('.properties') |
| | .toggleClass('layeron'); |
| | $( |
| | ".keyframe-row[data-object='" + drag.attr('id') + "']" |
| | ).toggle(); |
| | setTimelineZoom(timelinetime); |
| | } |
| | drag.find('.keyframe').each(function () { |
| | updateKeyframe($(this), false, true); |
| | }); |
| | animate(false, currenttime); |
| | } else if (trim == 'left') { |
| | if (drag2.position().left + (e.pageX - pageX) >= 0) { |
| | drag2.offset({ |
| | left: offset2.left + (e.pageX - pageX), |
| | }); |
| | drag2.css({ |
| | width: initwidth - (-initpos + drag2.position().left), |
| | }); |
| | const leftval = parseFloat( |
| | (drag2.position().left * timelinetime).toFixed(1) |
| | ); |
| | p_keyframes.find((x) => x.id == drag.attr('id')).trimstart = |
| | leftval; |
| | } |
| | } else if (trim == 'right') { |
| | if (initwidth + (e.pageX - pageX) < duration / timelinetime) { |
| | drag2.css({ |
| | width: initwidth + (e.pageX - pageX), |
| | }); |
| | } else { |
| | drag2.css({ |
| | width: |
| | duration / timelinetime - |
| | drag.position().left - |
| | $('#timeline').scrollLeft() + |
| | offset_left, |
| | }); |
| | } |
| | const rightval = parseFloat( |
| | ( |
| | (drag2.position().left + drag2.width()) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | p_keyframes.find((x) => x.id == drag.attr('id')).end = rightval; |
| | p_keyframes.find((x) => x.id == drag.attr('id')).trimend = |
| | rightval; |
| | } |
| | } |
| | function released(e) { |
| | $('body').off('mousemove', dragging).off('mouseup', released); |
| | if (opened) { |
| | $(".layer[data-object='" + drag.attr('id') + "']") |
| | .find('.properties') |
| | .toggle(); |
| | $(".layer[data-object='" + drag.attr('id') + "']") |
| | .find('.properties') |
| | .toggleClass('layeron'); |
| | $( |
| | ".keyframe-row[data-object='" + drag.attr('id') + "']" |
| | ).toggle(); |
| | setTimelineZoom(timelinetime); |
| | } |
| | animate(false, currenttime); |
| | save(); |
| | } |
| | $('body').on('mouseup', released).on('mousemove', dragging); |
| | } |
| | $(document).on('mousedown', '.main-row', dragObjectProps); |
| |
|
| | function resetHeight() { |
| | var top = $(window).height() - oldtimelinepos - 92; |
| | if ($('#upload-tool').hasClass('tool-active')) { |
| | $('#browser').css('top', '150px'); |
| | $('#browser').css( |
| | 'height', |
| | 'calc(100% - ' + (top + 97 + 150) + 'px)' |
| | ); |
| | } else { |
| | $('#browser').css('top', '110px'); |
| | $('#browser').css( |
| | 'height', |
| | 'calc(100% - ' + (top + 97 + 100) + 'px)' |
| | ); |
| | } |
| | $('#timearea').css('height', top); |
| | $('#layer-list').css('height', top); |
| | $('#toolbar').css('height', 'calc(100% - ' + (top + 97) + 'px)'); |
| | $('#canvas-area').css( |
| | 'height', |
| | 'calc(100% - ' + (top + 97) + 'px)' |
| | ); |
| | $('#properties').css('height', 'calc(100% - ' + (top + 97) + 'px)'); |
| | $('#timeline-handle').css('bottom', top + 95); |
| | resizeCanvas(); |
| | } |
| |
|
| | |
| | function dragTimeline(e) { |
| | const disableselect = (e) => { |
| | return false |
| | } |
| | document.onselectstart = disableselect |
| | document.onmousedown = disableselect |
| | |
| | oldtimelinepos = e.pageY; |
| | if (e.which == 3) { |
| | return false; |
| | } |
| | function draggingKeyframe(e) { |
| | oldtimelinepos = e.pageY; |
| | resetHeight(e); |
| | } |
| | function releasedKeyframe(e) { |
| | $('body') |
| | .off('mousemove', draggingKeyframe) |
| | .off('mouseup', releasedKeyframe); |
| | } |
| | $('body') |
| | .on('mouseup', releasedKeyframe) |
| | .on('mousemove', draggingKeyframe); |
| | } |
| |
|
| | $(document).on('mousedown', '#timeline-handle', dragTimeline); |
| |
|
| | oldtimelinepos = $(window).height() - 92 - $('#timearea').height(); |
| |
|
| | |
| | function syncScroll(el1, el2) { |
| | var $el1 = $(el1); |
| | var $el2 = $(el2); |
| | var forcedScroll = false; |
| | $el1.scroll(function () { |
| | performScroll($el1, $el2); |
| | }); |
| | $el2.scroll(function () { |
| | performScroll($el2, $el1); |
| | }); |
| |
|
| | function performScroll($scrolled, $toScroll) { |
| | if (forcedScroll) return (forcedScroll = false); |
| | var percent = |
| | ($scrolled.scrollTop() / |
| | ($scrolled[0].scrollHeight - $scrolled.outerHeight())) * |
| | 100; |
| | setScrollTopFromPercent($toScroll, percent); |
| | } |
| |
|
| | function setScrollTopFromPercent($el, percent) { |
| | var scrollTopPos = |
| | (percent / 100) * ($el[0].scrollHeight - $el.outerHeight()); |
| | forcedScroll = true; |
| | $el.scrollTop(scrollTopPos); |
| | } |
| | } |
| |
|
| | |
| | function syncScrollHoz(el1, el2) { |
| | var $el1 = $(el1); |
| | var $el2 = $(el2); |
| | var forcedScroll = false; |
| | $el1.scroll(function () { |
| | performScroll($el1, $el2); |
| | }); |
| | $el2.scroll(function () { |
| | performScroll($el2, $el1); |
| | }); |
| |
|
| | function performScroll($scrolled, $toScroll) { |
| | if (forcedScroll) return (forcedScroll = false); |
| | var percent = |
| | ($scrolled.scrollLeft() / $scrolled.outerWidth()) * 100; |
| | setScrollLeftFromPercent($toScroll, percent); |
| | } |
| |
|
| | function setScrollLeftFromPercent($el, percent) { |
| | var scrollLeftPos = (percent / 100) * $el.outerWidth(); |
| | forcedScroll = true; |
| | $el.scrollLeft(scrollLeftPos); |
| | } |
| | } |
| |
|
| | |
| | function keyframeProperties(inst) { |
| | if (!shiftdown) { |
| | selectedkeyframe = $(inst); |
| | const popup = $('#keyframe-properties'); |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == selectedkeyframe.attr('data-property') |
| | ); |
| | }); |
| | $('#easing select').val(keyarr[0].easing); |
| | $('#easing select').niceSelect('update'); |
| | popup.css({ |
| | left: $(inst).offset().left - popup.width() / 2, |
| | top: $(inst).offset().top - popup.height() - 20, |
| | }); |
| | popup.addClass('show-properties'); |
| | $(inst).addClass('keyframe-selected'); |
| | } |
| | } |
| |
|
| | |
| | function applyEasing() { |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == selectedkeyframe.attr('data-property') |
| | ); |
| | }); |
| | keyarr[0].easing = $(this).attr('data-value'); |
| | if (selectedkeyframe.attr('data-property') == 'left') { |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == 'top' |
| | ); |
| | }); |
| | keyarr[0].easing = $('#easing select').val(); |
| | } else if (selectedkeyframe.attr('data-property') == 'scaleX') { |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == 'scaleY' |
| | ); |
| | }); |
| | keyarr[0].easing = $('#easing select').val(); |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == 'width' |
| | ); |
| | }); |
| | keyarr[0].easing = $('#easing select').val(); |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == 'height' |
| | ); |
| | }); |
| | keyarr[0].easing = $('#easing select').val(); |
| | } else if ( |
| | selectedkeyframe.attr('data-property') == 'strokeWidth' |
| | ) { |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == 'stroke' |
| | ); |
| | }); |
| | keyarr[0].easing = $('#easing select').val(); |
| | } else if ( |
| | selectedkeyframe.attr('data-property') == 'shadow.color' |
| | ) { |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == 'shadow.opacity' |
| | ); |
| | }); |
| | keyarr[0].easing = $('#easing select').val(); |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == 'shadow.offsetX' |
| | ); |
| | }); |
| | keyarr[0].easing = $('#easing select').val(); |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == 'shadow.offsetY' |
| | ); |
| | }); |
| | keyarr[0].easing = $('#easing select').val(); |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == 'shadow.blur' |
| | ); |
| | }); |
| | keyarr[0].easing = $('#easing select').val(); |
| | } else if ( |
| | selectedkeyframe.attr('data-property') == 'charSpacing' |
| | ) { |
| | var keyarr = keyframes.filter(function (e) { |
| | return ( |
| | e.t == selectedkeyframe.attr('data-time') && |
| | e.id == selectedkeyframe.attr('data-object') && |
| | e.name == 'lineHeight' |
| | ); |
| | }); |
| | keyarr[0].easing = $('#easing select').val(); |
| | } |
| | $('#keyframe-properties').removeClass('show-properties'); |
| | selectedkeyframe.removeClass('keyframe-selected'); |
| | save(); |
| | } |
| | $(document).on('mouseup', '#easing li', applyEasing); |
| |
|
| | |
| | function seekTo(e) { |
| | if ($(e.target).hasClass('keyframe')) { |
| | return false; |
| | } |
| | paused = true; |
| | if ($('#seekarea').scrollLeft() > offset_left) { |
| | currenttime = parseFloat( |
| | ( |
| | (e.pageX + |
| | $('#seekarea').scrollLeft() - |
| | $('#timearea').offset().left - |
| | offset_left) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | } else { |
| | currenttime = parseFloat( |
| | ( |
| | (e.pageX + |
| | $('#seekarea').scrollLeft() - |
| | $('#timearea').offset().left - |
| | offset_left) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | } |
| | if (currenttime < 0) { |
| | currenttime = 0; |
| | } |
| | |
| | if (currenttime % 16.666 != 0) { |
| | currenttime = Math.ceil(currenttime / 16.666) * 16.666; |
| | } |
| | renderTime(); |
| | $('#seekbar').offset({ |
| | left: |
| | offset_left + |
| | $('#inner-timeline').offset().left + |
| | currenttime / timelinetime, |
| | }); |
| | animate(false, currenttime); |
| | updatePanelValues(); |
| | } |
| | $(document).on('click', '#seekevents', seekTo); |
| | $(document).on('click', '#timearea', seekTo); |
| |
|
| | function hideSeekbar() { |
| | $('#seek-hover').css({ opacity: 0 }); |
| | } |
| | function followCursor(e) { |
| | $('#seek-hover').css({ opacity: 0.3 }); |
| | if ($('#seekarea').scrollLeft() > offset_left) { |
| | hovertime = parseFloat( |
| | ( |
| | (e.pageX + |
| | $('#seekarea').scrollLeft() - |
| | $('#timearea').offset().left - |
| | offset_left) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | } else { |
| | hovertime = parseFloat( |
| | ( |
| | (e.pageX + |
| | $('#seekarea').scrollLeft() - |
| | $('#timearea').offset().left - |
| | offset_left) * |
| | timelinetime |
| | ).toFixed(1) |
| | ); |
| | } |
| | if (e.pageX >= offset_left + $('#inner-timeline').offset().left) { |
| | $('#seek-hover').offset({ left: e.pageX }); |
| | } |
| | } |
| | $(document).on('mousemove', '#timearea', followCursor); |
| | $(document).on('mousemove', '#seekevents', followCursor); |
| | $(document).on('mousemove', '#toolbar', hideSeekbar); |
| | $(document).on('mousemove', '#canvas-area', hideSeekbar); |
| | $(document).on('mousemove', '#browser', hideSeekbar); |
| | $(document).on('mousemove', '#properties', hideSeekbar); |
| | $(document).on('mousemove', '#controls', hideSeekbar); |
| |
|
| | function orderLayers() { |
| | $('.layer').each(function (index) { |
| | const object = canvas.getItemById($(this).attr('data-object')); |
| | canvas.sendToBack(object); |
| | canvas.renderAll(); |
| | objects.splice( |
| | $('.layer').length - index - 1, |
| | 0, |
| | objects.splice( |
| | objects.findIndex((x) => x.id == object.get('id')), |
| | 1 |
| | )[0] |
| | ); |
| | }); |
| | save(); |
| | } |
| |
|
| | function handTool() { |
| | if ($(this).hasClass('hand-active')) { |
| | $(this).removeClass('hand-active'); |
| | $(this).find('img').attr('src', 'assets/hand-tool.svg'); |
| | handtool = false; |
| | canvas.defaultCursor = 'default'; |
| | canvas.renderAll(); |
| | } else { |
| | $(this).addClass('hand-active'); |
| | $(this).find('img').attr('src', 'assets/hand-tool-active.svg'); |
| | handtool = true; |
| | canvas.defaultCursor = 'grab'; |
| | canvas.renderAll(); |
| | } |
| | } |
| | $(document).on('click', '#hand-tool', handTool); |
| | |
| | setDuration(10000); |
| | checkDB(); |
| |
|