diff --git a/_css/button.css b/_css/button.css index d89cf6f..f56934e 100644 --- a/_css/button.css +++ b/_css/button.css @@ -62,7 +62,9 @@ img.button:hover { height: 24px !important; line-height: 24px !important; } - +li.leaf uiLink.md-18 div, li.leaf .uiButton.md-18, li.leaf .window h1 .uiButton { + width: 36px !important; +} .uiLink.md-36 div, .uiButton.md-36 { font-size: 36px !important; width: 36px !important; @@ -256,12 +258,12 @@ img.button:hover { margin: 0.25ex 5px; height: 0.9em; - width: 1px; - background: gray; - background: -webkit-linear-gradient(transparent, gray, transparent); /* For Safari 5.1 to 6.0 */ - background: -o-linear-gradient(transparent, gray, transparent); /* For Opera 11.1 to 12.0 */ - background: -moz-linear-gradient(transparent, gray, transparent); /* For Firefox 3.6 to 15 */ - background: linear-gradient(transparent, gray, transparent); /* Standard syntax */ + width: 1em; + /* background: gray; */ + /* background: -webkit-linear-gradient(transparent, gray, transparent); /* For Safari 5.1 to 6.0 */ + /* background: -o-linear-gradient(transparent, gray, transparent); /* For Opera 11.1 to 12.0 */ + /* background: -moz-linear-gradient(transparent, gray, transparent); /* For Firefox 3.6 to 15 */ + /* background: linear-gradient(transparent, gray, transparent); /* Standard syntax */ } diff --git a/_css/manual.css b/_css/manual.css index ffa6e9d..e6bccce 100644 --- a/_css/manual.css +++ b/_css/manual.css @@ -32,6 +32,9 @@ src: url('../_fonts/MaterialIcons/MaterialIcons-Regular.ttf') format('truetype'); } +*, articles > * { + transition : all 0.1s linear 0s; +} body { font-family: 'Open Sans', sans-serif; @@ -179,6 +182,7 @@ p > img.right { body nav { font-size: 90%; + display: none; } body nav ol { @@ -197,22 +201,42 @@ p { margin-bottom: 1.5em; } +div#menu_header{ + vertical-align: top; + background-color: green; + top: 0; + position: fixed; + color: white; + padding: .5em; + border-radius: 0 0 10px 0; + cursor: pointer; +} + #menu { - font-size: 90%; position: fixed; top: 0px; left: 0px; - border-right: 2em solid #008000; + border-right: .5em solid #008000; background-color: white; height: 100%; - + + z-index: 10000; + width: 0px; overflow: hidden; white-space: nowrap; } -#menu:hover { +#menu > ol > li { + font-size: 120%; +} + +#menu > ol > li > ol { + font-size: 70%; +} + +div#menu_header:hover + #menu, #menu:hover { width: auto; overflow-y: auto; padding: 0 1em; @@ -230,6 +254,8 @@ div.logo { div.logo img { border: none; + max-width: 400px; + width: 40%; display: inline-block; } diff --git a/_css/section.css b/_css/section.css index e4c5f89..9476f46 100644 --- a/_css/section.css +++ b/_css/section.css @@ -6,11 +6,12 @@ div.uiSection > div:first-child { position: absolute; width: 100%; height: 100%; + border-bottom: 1px solid lightgrey; } /* row 1 */ .section-top-row1, .section-top-row2 { - font-size: 24px; + font-size: 1em; background: white; } @@ -26,9 +27,10 @@ div.uiSection > div:first-child { margin-left: 4px; height: 100%; float: left; + font-size: 1.2em; } -.section-top-row1 .editor > *, .section-top-row2 div:first-child > * { +.section-top-row1 .editor > * { vertical-align: middle; } @@ -62,6 +64,7 @@ div.uiSection > div:first-child { color: lightgray; font-size: 0.85em; font-style: italic; + width: 10em; } .section-top-row2 .uiButton { diff --git a/_css/style.css b/_css/style.css index bb214bb..146808c 100644 --- a/_css/style.css +++ b/_css/style.css @@ -446,14 +446,16 @@ label.checkbox { .timeline { position: absolute; - width: 100%; + width: calc(100% - 10px); + margin-left: 5px; z-index: 200; - height: 1px; + height: 0; cursor: pointer; - border-top: 2px solid transparent; - border-bottom: 2px solid transparent; + border-top: 3px dotted blue; + border-bottom: 3px dotted blue; background-clip: content-box; + top : -5px; } .timeline:hover { @@ -468,7 +470,7 @@ label.checkbox { font-size: 75%; transform: translate(0, -100%); cursor: pointer; - color: gray; + color: blue; } .timeline .boundary:hover { @@ -477,12 +479,14 @@ label.checkbox { } -.timeline .left { - left: 0.5ex; +.timeline .left, .timeline { + left: 0ex; + top: -2px; } .timeline .right { - right: 0.5ex; + right: 0ex; + top: -2px; } .timeline .slider { @@ -491,8 +495,8 @@ label.checkbox { cursor: pointer; width: 9px; height: 9px; - background-color: white; - border: 1.5px solid #555; + background-color: lightblue; + border: 1.5px solid blue; border-radius: 50%; transform: translate(-50%, 0); diff --git a/_css/window.css b/_css/window.css index f3296cf..8c83e51 100644 --- a/_css/window.css +++ b/_css/window.css @@ -159,7 +159,19 @@ table.keyframes td:first-child { color: transparent; width: 0.5em !important; cursor: pointer; - border: 1px solid transparent; + border: 1px solid red; +} + +table.keyframes tr.selected td:first-child { + background-color: green; + background: repeating-linear-gradient( + 0deg, + white, + #00ff00 1px, + transparent 1px, + transparent 3px + ); + border-color: #00ff00; } table.keyframes td:first-child:hover { @@ -174,7 +186,6 @@ table.keyframes td:first-child:hover { border-color: black; } - table.gradients tr.selected { background-color: #eee; } diff --git a/anigenActual.js b/anigenActual.js index ca541a2..eaedb97 100644 --- a/anigenActual.js +++ b/anigenActual.js @@ -971,10 +971,50 @@ anigenActual.prototype.getNodeIcon = function(element) { case "animatetransform": case "animatecolor": if(validChildren) { - icon = "settings_applications"; + icon = "directions_walk" } else { - icon = "settings"; + icon = "directions_run" } + + switch(element.getAttribute('type')) + { + case 'translate': + icon2 = "trending_up"; + break; + + case 'rotate': + icon2 = "refresh"; + break; + + case 'scale': + icon2 = "zoom_out_map"; + break; + + case 'skewX': + icon2 = "swap_horiz"; + break; + + case 'skewY': + icon2 = "swap_vert"; + break; + + default: + if (element.getAttribute('attributeName') == undefined && element.getAttribute('attributeName') == null) + { + icon2 = ""; + } + else + { + icon2 = "text_format"; + } + break; + } + if (element.nodeName.toLowerCase() == "animatemotion") + { + icon2 = "swap_calls"; + } + + icon = icon + icon2; break; case "svg": case "g": @@ -988,11 +1028,11 @@ anigenActual.prototype.getNodeIcon = function(element) { name = element.getAttribute("inkscape:label")+'#'+name; } if(element.getAttribute("anigen:name")) { - icon = "folder_special"; + icon = "filter_none"; name = element.getAttribute("anigen:name")+'#'+name; } if(element.getAttribute("anigen:type") == "animationState") { - icon = "fingerprint"; + icon = "directions_walk"; } if(element.getAttribute("anigen:type") == "animationGroup") { icon = "settings_applications"; @@ -1018,15 +1058,15 @@ anigenActual.prototype.getNodeIcon = function(element) { if(validChildren) { icon = "star_border"; } else { - icon = "star"; + icon = "star_border"; } break; default: if(validChildren) { - icon = "label_outline"; + icon = "star_outline"; } else { - icon = "label"; + icon = "star_outline"; } if(element.getAttribute("anigen:type") == "animatedViewbox") { icon = "videocam"; diff --git a/gui/infoContext.js b/gui/infoContext.js index d82a421..fc1a19f 100644 --- a/gui/infoContext.js +++ b/gui/infoContext.js @@ -20,11 +20,12 @@ infoContext.prototype.seed = function() { this.buttons.rectTool = new uiButton('crop_din', 'anigenActual.setTool(5, true);', 'Rectangle (F4)', { 'state': anigenActual.tool == 5 ? 1 : 0, 'radio': true, 'toggle': true, 'class': 'floatLeft' }).shepherd; this.buttons.ellipseTool = new uiButton('panorama_fish_eye', 'anigenActual.setTool(6, true);', 'Ellipse (F5)', { 'state': anigenActual.tool == 5 ? 1 : 0, 'radio': true, 'toggle': true, 'class': 'floatLeft' }).shepherd; - this.buttons.animate = new uiButton('power_settings_new', 'popup.macroAnimateMenu(anigenManager.classes.context.buttons.animate.container);', 'Animate element...', { 'toggle': true, 'class': 'floatLeft turn-90' }).shepherd; - this.buttons.edit = new uiButton('reorder', 'overlay.macroEdit(svg.selected);', 'Edit attributes', { 'class': 'floatLeft' }).shepherd; - this.buttons.editTextContent = new uiButton('title', 'popup.macroEditTextContent(this.container);', 'Edit text content', { 'class': 'floatLeft' }).shepherd; - this.buttons.children = new uiButton('details', 'popup.macroChildren(anigenManager.classes.context.buttons.children.container, svg.selected);', 'Child nodes...', { 'toggle': true, 'class': 'floatLeft' }).shepherd; - this.buttons.parent = new uiButton('change_history', 'svg.select(svg.selected.getViableParent());', 'Select parent', { 'class': 'floatLeft' } ).shepherd; + this.buttons.animate = new uiButton('directions_run', 'popup.macroAnimateMenu(anigenManager.classes.context.buttons.animate.container);', 'Animate Node', { 'toggle': true, 'class': 'floatLeft' }).shepherd; + this.buttons.edit = new uiButton('reorder', 'overlay.macroEdit(svg.selected);', 'Edit Node attributes', { 'class': 'floatLeft' }).shepherd; + this.buttons.editTextContent = new uiButton('title', 'popup.macroEditTextContent(this.container);', 'Edit Node Text Content', { 'class': 'floatLeft' }).shepherd; + + this.buttons.children = new uiButton('device_hub', 'popup.macroChildren(anigenManager.classes.context.buttons.children.container, svg.selected);', 'Child Nodes Selector', { 'toggle': true, 'class': 'floatLeft' }).shepherd; + this.buttons.parent = new uiButton('change_history', 'svg.select(svg.selected.getViableParent());', 'Select Parent Node (Alt + ↑)', { 'class': 'floatLeft' } ).shepherd; this.buttons.keyframePrev = new uiButton('arrow_back', 'var trg = svg.selected.shepherd || svg.selected;if(typeof trg.getClosest === "function") { svg.gotoTime(trg.getClosest().previous.time); }', 'Jump to previous keyframe (1 / Ctrl+Left)', { 'class': 'floatLeft' }).shepherd; this.buttons.keyframeNext = new uiButton('arrow_forward', 'var trg = svg.selected.shepherd || svg.selected;if(typeof trg.getClosest === "function") { svg.gotoTime(trg.getClosest().next.time); }', 'Jump to next keyframe (3 / Ctrl+Right)', { 'class': 'floatLeft' }).shepherd; @@ -32,8 +33,8 @@ infoContext.prototype.seed = function() { this.buttons.layers = new uiButton('layers', 'anigenManager.classes.windowLayers.toggle();', 'Show layers (Ctrl+Shift+L)', { 'toggle': true }).shepherd; this.buttons.keyframes = new uiButton('hourglass_empty', 'anigenManager.classes.windowAnimation.toggle();', 'Show animation keyframes (Ctrl+Shift+K)', { 'toggle': true }).shepherd; this.buttons.colors = new uiButton('format_paint', 'anigenManager.classes.windowColors.toggle();', 'Show fill and stroke', { 'toggle': true }).shepherd; - this.buttons.log = new uiButton('toc', 'anigenManager.named.bottom.toggle();anigenManager.refresh();anigenActual.settings.set("bottom", !(anigenActual.settings.get("bottom")));', 'Show event log', { 'toggle': true, 'class': 'flip-h' }).shepherd; - this.buttons.tree = new uiButton('share', 'anigenManager.named.left.toggle();anigenManager.classes.rulerH.refresh();anigenManager.classes.rulerV.refresh();anigenActual.settings.set("tree", !(anigenActual.settings.get("tree")));', 'Show XML tree (Ctrl+Shift+X)', { 'toggle': true, 'class': 'turn-90' }).shepherd; + this.buttons.log = new uiButton('subtitles', 'anigenManager.named.bottom.toggle();anigenManager.refresh();anigenActual.settings.set("bottom", !(anigenActual.settings.get("bottom")));', 'Toggle Event Log', { 'toggle': true, 'class': '' }).shepherd; + this.buttons.tree = new uiButton('list', 'anigenManager.named.left.toggle();anigenManager.classes.rulerH.refresh();anigenManager.classes.rulerV.refresh();anigenActual.settings.set("tree", !(anigenActual.settings.get("tree")));', 'Show XML tree (Ctrl+Shift+X)', { 'toggle': true, 'class': '' }).shepherd; /* tool-sensitive nodes */ @@ -53,21 +54,19 @@ infoContext.prototype.seed = function() { this.toolButtons.group = {}; - this.toolButtons.group.rotateLeft = new uiButton('rotate_right', 'svg.rotate(svg.selected, { "angle": 90 }, false, true);', 'Rotate 90° clockwise', { 'class': 'floatLeft' }).shepherd; - this.toolButtons.group.rotateRight = new uiButton('rotate_left', 'svg.rotate(svg.selected, { "angle": -90 }, false, true);', 'Rotate 90° counterclockwise', { 'class': 'floatLeft' }).shepherd; - this.toolButtons.group.flipH = new uiButton('flip', 'svg.scale(svg.selected, { "scaleX": -1, "scaleY": 1}, false, true);', 'Flip horizontally', { 'class': 'floatLeft' }).shepherd; - this.toolButtons.group.flipV = new uiButton('flip', 'svg.scale(svg.selected, { "scaleX": 1, "scaleY": -1}, false, true);', 'Flip vertically', { 'class': 'floatLeft turn-90' }).shepherd; - - this.toolButtons.group.moveBot = new uiButton('vertical_align_bottom', 'svg.selected.moveBottom(true);window.dispatchEvent(new Event("treeSeed"));svg.select();', 'Lower element to the bottom (end)', { 'class': 'floatLeft' }).shepherd; - this.toolButtons.group.moveDown = new uiButton('arrow_downward', 'svg.selected.moveDown(true);window.dispatchEvent(new Event("treeSeed"));svg.select();', 'Lower element one step (page down)', { 'class': 'floatLeft' }).shepherd; - this.toolButtons.group.moveUp = new uiButton('arrow_upward', 'svg.selected.moveUp(true);window.dispatchEvent(new Event("treeSeed"));svg.select();', 'Raise element one step (page up)', { 'class': 'floatLeft' }).shepherd; - this.toolButtons.group.moveTop = new uiButton('vertical_align_top', 'svg.selected.moveTop(true);window.dispatchEvent(new Event("treeSeed"));svg.select();', 'Raise element to the top (home)', { 'class': 'floatLeft' }).shepherd; + this.toolButtons.group.moveBot = new uiButton('vertical_align_bottom', 'svg.selected.moveBottom(true);window.dispatchEvent(new Event("treeSeed"));svg.select();', 'Lower element to the bottom (End)', { 'class': 'floatLeft' }).shepherd; + this.toolButtons.group.moveDown = new uiButton('arrow_downward', 'svg.selected.moveDown(true);window.dispatchEvent(new Event("treeSeed"));svg.select();', 'Lower element one step (PageDown)', { 'class': 'floatLeft' }).shepherd; + this.toolButtons.group.moveUp = new uiButton('arrow_upward', 'svg.selected.moveUp(true);window.dispatchEvent(new Event("treeSeed"));svg.select();', 'Raise element one step (PageUp)', { 'class': 'floatLeft' }).shepherd; + this.toolButtons.group.moveTop = new uiButton('vertical_align_top', 'svg.selected.moveTop(true);window.dispatchEvent(new Event("treeSeed"));svg.select();', 'Raise element to the top (Home)', { 'class': 'floatLeft' }).shepherd; this.toolGroups[1].appendChild(new uiBreak('floatLeft')); - this.toolGroups[1].appendChild(this.toolButtons.group.rotateLeft.container); - this.toolGroups[1].appendChild(this.toolButtons.group.rotateRight.container); - this.toolGroups[1].appendChild(this.toolButtons.group.flipH.container); - this.toolGroups[1].appendChild(this.toolButtons.group.flipV.container); + this.toolGroups[1].appendChild(this.buttons.animate.container); + this.toolGroups[1].appendChild(this.buttons.edit.container); + this.toolGroups[1].appendChild(this.buttons.editTextContent.container); + + this.toolGroups[1].appendChild(new uiBreak('floatLeft')); + this.toolGroups[1].appendChild(this.buttons.children.container); + this.toolGroups[1].appendChild(this.buttons.parent.container); this.toolGroups[1].appendChild(new uiBreak('floatLeft')); this.toolGroups[1].appendChild(this.toolButtons.group.moveBot.container); @@ -117,16 +116,17 @@ infoContext.prototype.seed = function() { this.container.appendChild(this.buttons.pickerTool.container); - this.container.appendChild(new uiBreak('floatLeft')); - this.container.appendChild(this.buttons.animate.container); - this.container.appendChild(this.buttons.edit.container); - this.container.appendChild(this.buttons.editTextContent.container); - this.container.appendChild(this.buttons.children.container); - this.container.appendChild(this.buttons.parent.container); - this.container.appendChild(new uiBreak('floatLeft')); - this.container.appendChild(this.buttons.keyframePrev.container); - this.container.appendChild(this.buttons.keyframeNext.container); + this.toolButtons.group.rotateLeft = new uiButton('rotate_right', 'svg.rotate(svg.selected, { "angle": 90 }, false, true);', 'Rotate 90° clockwise', { 'class': 'floatLeft' }).shepherd; + this.toolButtons.group.rotateRight = new uiButton('rotate_left', 'svg.rotate(svg.selected, { "angle": -90 }, false, true);', 'Rotate 90° counterclockwise', { 'class': 'floatLeft' }).shepherd; + this.toolButtons.group.flipH = new uiButton('flip', 'svg.scale(svg.selected, { "scaleX": -1, "scaleY": 1}, false, true);', 'Flip horizontally', { 'class': 'floatLeft' }).shepherd; + this.toolButtons.group.flipV = new uiButton('flip', 'svg.scale(svg.selected, { "scaleX": 1, "scaleY": -1}, false, true);', 'Flip vertically', { 'class': 'floatLeft turn-90' }).shepherd; + this.container.appendChild(new uiBreak('floatLeft')); + this.container.appendChild(this.toolButtons.group.rotateLeft.container); + this.container.appendChild(this.toolButtons.group.rotateRight.container); + this.container.appendChild(this.toolButtons.group.flipH.container); + this.container.appendChild(this.toolButtons.group.flipV.container); + for(var i = 0; i < this.toolGroups.length; i++) { this.toolGroups[i].addClass('floatLeft'); this.toolGroups[i].style.display = 'none'; diff --git a/gui/infoEditor.js b/gui/infoEditor.js index 0c2e1ff..e227846 100644 --- a/gui/infoEditor.js +++ b/gui/infoEditor.js @@ -8,40 +8,102 @@ function infoEditor(timeline) { this.container = document.createElement("div"); this.container.addClass('editor'); - this.pauseButton = new uiButton( - [ 'pause', 'play_arrow' ], - [ 'svg.pauseToggle(true);', 'svg.pauseToggle(false);' ], - [ 'Unpause animations', 'Pause animations' ] + this.zoomIcon = new uiButton( + 'settings_overscan', + 'svg.zoom = 1; svg.refreshUI(true);', + 'Reset zoom' ); - this.pauseButton = this.pauseButton.shepherd; - this.container.appendChild(this.pauseButton.container); - - this.hideIcon = new uiButton( + this.zoomIcon = this.zoomIcon.shepherd; + this.container.appendChild(this.zoomIcon.container); + + this.zoomOutIcon = new uiButton( + 'zoom_out', + 'svg.zoom -= .5; svg.refreshUI(true);', + 'Zoom out (Ctrl + -)' + ); + this.zoomOutIcon = this.zoomOutIcon.shepherd; + this.container.appendChild(this.zoomOutIcon.container); + + this.zoomValue = document.createElement("span"); + this.container.appendChild(this.zoomValue); + + this.refreshZoom(); + + this.zoomInIcon = new uiButton( + 'zoom_in', + 'svg.zoom += .5; svg.refreshUI(true);', + 'Zoom in (Ctrl + +)' + ); + this.zoomInIcon = this.zoomInIcon.shepherd; + this.container.appendChild(this.zoomInIcon.container); + + this.spacing = document.createElement("span"); + this.spacing.style.cssText = "width : 4em;"; + this.container.appendChild(this.spacing); + + this.hideClockIcon = new uiButton( 'timer', 'anigenManager.classes.editor.clock.toggle();', 'Hide/show clock' ); - this.hideIcon = this.hideIcon.shepherd; - this.container.appendChild(this.hideIcon.container); - + this.hideClockIcon = this.hideClockIcon.shepherd; + this.container.appendChild(this.hideClockIcon.container); + this.clock = new clock(timeline); this.clock.display(); this.container.appendChild(this.clock.container); - - this.zoomIcon = new uiButton( - 'search', - 'svg.zoom = 1; svg.refreshUI(true);', - 'Reset zoom' + this.rewindButton = new uiButton( + [ 'restore'], + [ 'svg.gotoTime(anigenManager.classes.editor.clock.minTime || 0);'], + [ 'Rewind animations (Alt + Pause)'] ); - this.zoomIcon = this.zoomIcon.shepherd; - this.container.appendChild(this.zoomIcon.container); - - this.zoomValue = document.createElement("span"); - this.container.appendChild(this.zoomValue); - - this.refreshZoom(); - + this.rewindButton = this.rewindButton.shepherd; + this.container.appendChild(this.rewindButton.container); + + this.spacing = document.createElement("span"); + this.spacing.style.cssText = "width : 1em;"; + this.container.appendChild(this.spacing); + + this.keyframeBackButton = new uiButton( + [ 'arrow_back'], + [ 'var trg = svg.selected.shepherd || svg.selected;if(typeof trg.getClosest === "function") { svg.gotoTime(trg.getClosest().previous.time); }'], + [ 'Previous keyframe (Ctrl + ←)'] + ); + this.keyframeBackButton = this.keyframeBackButton.shepherd; + this.container.appendChild(this.keyframeBackButton.container); + + this.fastRewindButton = new uiButton( + [ 'fast_rewind'], + [ 'svg.seek(-0.1*1);'], + [ 'Seek Back (-)'] + ); + this.fastRewindButton = this.fastRewindButton.shepherd; + this.container.appendChild(this.fastRewindButton.container); + + this.pauseButton = new uiButton( + [ 'pause', 'play_arrow' ], + [ 'svg.pauseToggle(false);', 'svg.pauseToggle(true);' ], + [ 'Pause animations (Space)', 'Play animations (Space)' ] + ); + this.pauseButton = this.pauseButton.shepherd; + this.container.appendChild(this.pauseButton.container); + + this.fastForwardButton = new uiButton( + [ 'fast_forward'], + [ 'svg.seek(0.1*1);'], + [ 'Seek Forward (+)'] + ); + this.fastForwardButton = this.fastForwardButton.shepherd; + this.container.appendChild(this.fastForwardButton.container); + + this.keyframeForwardButton = new uiButton( + [ 'arrow_forward'], + [ 'var trg = svg.selected.shepherd || svg.selected;if(typeof trg.getClosest === "function") { svg.gotoTime(trg.getClosest().next.time); }'], + [ 'Next keyframe (Ctrl + →)'] + ); + this.keyframeForwardButton = this.keyframeForwardButton.shepherd; + this.container.appendChild(this.keyframeForwardButton.container); } infoEditor.prototype.refreshZoom = function() { diff --git a/gui/infoSelection.js b/gui/infoSelection.js index 438b966..874b137 100644 --- a/gui/infoSelection.js +++ b/gui/infoSelection.js @@ -28,6 +28,29 @@ infoSelection.prototype.refresh = function() { this.container.appendChild(this.elementNodeName); this.container.appendChild(this.elementId); + this.container.appendChild(this.info); + + var bVis = new uiButton( + [ 'visibility', 'visibility_off' ], + [ 'svg.selected.style.display="none";anigenManager.classes.windowLayers.refresh();', 'svg.selected.style.display=null;anigenManager.classes.windowLayers.refresh();' ], + [ 'Toggle element visibility', 0 ], + { 'state': (svg.selected.style.display == 'none' ? 1 : 0) } + ); + bVis.shepherd.stateIcons[1].style.color = 'gray'; + this.container.appendChild(bVis); + + + var bNote = new uiButton( + [ 'bookmark_border', 'bookmark' ], + [ 'svg.selected.setAttributeHistory({"anigen:note": svg.selected.getAttribute("anigen:note")=="true" ? null : "true"});', 0 ], + [ 'Flag element as a note - notes are not rendered', 'Remove note flag' ], + { 'state': (svg.selected.getAttribute('anigen:note') == 'true' ? 1 : 0) } + ); + if(svg.selected instanceof SVGSVGElement) { bNote.shepherd.disable(); } + this.container.appendChild(bNote); + + this.container.appendChild(this.elementNodeName); + this.container.appendChild(this.elementId); this.container.appendChild(this.info); this.elementNodeName.removeChildren(); @@ -58,7 +81,7 @@ infoSelection.prototype.refresh = function() { var groupId = svg.animationStates[element.getAttribute('anigen:group')][0].groupElement.getAttribute('id'); var bGroup = new uiButton( - 'folder_special', + 'filter_none', 'svg.select("'+groupId+'")', 'Select state group element' ); @@ -78,26 +101,6 @@ infoSelection.prototype.refresh = function() { } - var bVis = new uiButton( - [ 'visibility', 'visibility_off' ], - [ 'svg.selected.style.display="none";anigenManager.classes.windowLayers.refresh();', 'svg.selected.style.display=null;anigenManager.classes.windowLayers.refresh();' ], - [ 'Toggle element visibility', 0 ], - { 'state': (svg.selected.style.display == 'none' ? 1 : 0) } - ); - bVis.shepherd.stateIcons[1].style.color = 'gray'; - this.container.appendChild(bVis); - - - var bNote = new uiButton( - [ 'bookmark', 'bookmark_border' ], - [ 'svg.selected.setAttributeHistory({"anigen:note": svg.selected.getAttribute("anigen:note")=="true" ? null : "true"});', 0 ], - [ 'Flag element as a note - notes are not rendered', 'Remove note flag' ], - { 'state': (svg.selected.getAttribute('anigen:note') == 'true' ? 1 : 0) } - ); - if(svg.selected instanceof SVGSVGElement) { bNote.shepherd.disable(); } - this.container.appendChild(bNote); - - var linkList = element.getLinkList(); for(var i = 0; i < linkList.length; i++) { diff --git a/gui/overlay.js b/gui/overlay.js index 8d902b5..dae1184 100644 --- a/gui/overlay.js +++ b/gui/overlay.js @@ -196,7 +196,7 @@ overlay.prototype.macroOpen = function() { this.add(build.br()); if(typeof(Storage) !== "undefined" && localStorage.getItem("quicksaveFilename")) { - this.add(new uiLink('folder_open', 'svg.loadLocal();overlay.hide();', localStorage.getItem("quicksaveFilename"), { 'title': 'Load saved file' })); + this.add(new uiLink('local_florist', 'svg.loadLocal();overlay.hide();', localStorage.getItem("quicksaveFilename"), { 'title': 'Load saved file' })); this.add(new uiLink('delete', 'svg.removeLocal();overlay.macroOpen();', 'Delete', { 'title': 'Delete local file' })); this.add(build.br()); } diff --git a/gui/popup.js b/gui/popup.js index 3fde1fa..9c85043 100644 --- a/gui/popup.js +++ b/gui/popup.js @@ -431,10 +431,10 @@ popup.prototype.macroContextMenu = function(target) { } else { tArray.push([ "", "", "" ]); rAttributes.push({ 'class': 'hr' }); - tArray.push([ build.icon("fingerprint"), "To animation state...", "" ]); + tArray.push([ build.icon("directions_walk"), "To animation state...", "" ]); rAttributes.push({ 'onclick': 'event.stopPropagation();popup.hide();popup.macroToAnimationState(null, svg.selected);' }); } - tArray.push([ build.icon("power_settings_new", "turn-90"), "Create animated group...", "" ]); + tArray.push([ build.icon("filter_none", "turn-90"), "Add Animation Group to scene", "" ]); rAttributes.push({ 'onclick': 'event.stopPropagation();popup.hide();popup.macroNewAnimationGroup();' }); } @@ -576,7 +576,7 @@ popup.prototype.macroContextMenu = function(target) { } } else if(anim[i].shepherd) { if(anim[i].shepherd instanceof animationGroup) { - animIcon = build.icon("power_settings_new", "turn-90"); + animIcon = build.icon("filter_none", "turn-90"); if(anim[i].getAttribute('anigen:group')) { descr += " ("+anim[i].getAttribute('anigen:group')+")"; } @@ -773,7 +773,7 @@ popup.prototype.macroSetCurrentValue = function(target) { intensity.setAttribute('id', 'anigenIntensity'); intensity.style.display = 'inline-block'; - this.add(build.icon('fingerprint', 'md-24')); + this.add(build.icon('directions_walk', 'md-24')); this.add(stateSelect); this.add(build.icon('star_half', 'md-24')); @@ -1225,8 +1225,8 @@ popup.prototype.macroMenuObject = function(target) { tArray.push([ build.icon("crop_din"), "Group", "Ctrl+G" ]); tArray.push([ build.icon("crop_free"), "Ungroup", "Ctrl+U" ]); tArray.push([ "", "", "" ]); - tArray.push([ build.icon("fingerprint"), "Object to animation state...", "" ]); - tArray.push([ build.icon("power_settings_new", "turn-90"), "Create animated group...", "" ]); + tArray.push([ build.icon("directions_walk"), "Put state in Animation Group", "" ]); + tArray.push([ build.icon("filter_none", "turn-90"), "Add Animation Group to scene", "" ]); tArray.push([ build.icon("settings_applications"), "Manage animation states...", "" ]); if(!(svg.selected instanceof SVGSVGElement)) { @@ -1292,22 +1292,22 @@ popup.prototype.macroMenuAnimation = function(target) { tArray.push([ "", "", "" ]); if(svg.svgElement.animationsPaused()) { - tArray.push([ build.icon("fast_rewind"), "Seek back (100ms)", "-" ]); - tArray.push([ build.icon("fast_forward"), "Seek forward (100ms)", "+" ]); + tArray.push([ build.icon("fast_rewind"), "Timeline Seek back (100ms)", "-" ]); + tArray.push([ build.icon("fast_forward"), "Timeline Seek forward (100ms)", "+ and Numpad +" ]); } else { - tArray.push([ build.icon("fast_rewind"), "Seek back (1s)", "-" ]); - tArray.push([ build.icon("fast_forward"), "Seek forward (1s)", "+" ]); + tArray.push([ build.icon("fast_rewind"), "Timeline Seek back (1s)", "-" ]); + tArray.push([ build.icon("fast_forward"), "Timeline Seek forward (1s)", "+" ]); } - + tArray.push([ "", "", "" ]); - - tArray.push([ build.icon("loop"), "Set animation loop...", "" ]); - tArray.push([ build.icon("restore"), "Restart animations", "" ]); - + + tArray.push([ build.icon("loop"), "Set Timeline time looping", "" ]); + tArray.push([ build.icon("restore"), "Rewind Timeline", "Alt+Pause" ]); + if(svg.svgElement.animationsPaused()) { - tArray.push([ build.icon("play_arrow"), "Unpause animations", "" ]); + tArray.push([ build.icon("play_arrow"), "Play Timeline animations", "Space" ]); } else { - tArray.push([ build.icon("pause"), "Pause animations", "" ]); + tArray.push([ build.icon("pause"), "Pause animations", "Space" ]); } @@ -1355,11 +1355,13 @@ popup.prototype.macroMenuHelp = function(target) { tArray.push([ build.icon("import_contacts"), "Manual..." ]); tArray.push([ build.icon("call_split", 'turn-90'), "Versions..." ]); + tArray.push([ build.icon("subtitles"), "Toggle Event Log" ]); tArray.push([ "", "" ]); tArray.push([ build.icon("info_outline"), "About..." ]); rAttributes.push({ 'onclick': 'popup.hide();window.open("manual.html", "_blank");' }); rAttributes.push({ 'onclick': 'popup.hide();window.open("../../index.html?redirect=false", "_blank");' }); + rAttributes.push({ 'onclick': 'anigenManager.named.bottom.toggle();anigenManager.refresh();anigenActual.settings.set("bottom", !(anigenActual.settings.get("bottom")));' }); rAttributes.push({ 'class': 'hr' }); rAttributes.push({ 'onclick': 'popup.hide();overlay.macroAbout();' }); @@ -1525,11 +1527,11 @@ popup.prototype.macroToAnimationState = function(target, element) { )); } - this.add(build.icon('fingerprint')); + this.add(build.icon('directions_walk')); this.add(build.input('text', stateNameText, { 'title': 'State name', 'id': 'anigenStateName', 'onfocus': 'if(this.value == "'+stateNameText+'") { this.value = null; }' } )); - this.add(build.icon('folder_open')); + this.add(build.icon('filter_none')); var stateSelect = build.select(options, { 'title': 'Group', 'id': 'anigenGroupSelect', 'onchange': 'this.nextSibling.style.display = this.value == "" ? null : "none";' } ); var groupName = build.input('text', groupNameText, { 'title': 'New group name', 'id': 'anigenGroupName', 'onfocus': 'if(this.value == "'+groupNameText+'") { this.value = null; }' } ); diff --git a/gui/uiTimeline.js b/gui/uiTimeline.js index 28cae07..2856bc2 100644 --- a/gui/uiTimeline.js +++ b/gui/uiTimeline.js @@ -73,7 +73,7 @@ uiTimeline.prototype.refresh = function() { var pos; if(this.tFrom == this.tTo) { - pos = 0.5; + pos = 1; } else { pos = (currentTime-this.tFrom)/(this.tTo-this.tFrom); } diff --git a/manual.html b/manual.html index 46d9a12..4002707 100644 --- a/manual.html +++ b/manual.html @@ -1,14 +1,14 @@ - - - + + + @@ -16,13 +16,13 @@ aniGen User Manual - + - - - + + + - + @@ -31,181 +31,252 @@

Table of contents

- - - + + + + +

Introduction

-

This document serves as user manual for the aniGen editor, version 0.8.1. - The manual describes the interface, controls and files, provides a basic explanation of SVG animation, and a set of examples which can serve as basic tutorials.

-

This document may be incomplete, or partially out of date with current version. If you find discrepancies, please follow the bug reporting section.

- +

Welcome to the user manual for the aniGen SVG editor, version 0.8.1. + This manual describes how to animate and manipulate SVG files. This manual includes examples as well as a basic overview of SVG internal file format.

+

From a high level, SVG files are text files that can be loaded in web browsers and display graphics. These SVG images can be animated as well as have interactivity with browser users. For example, a SVG graphic might show a chart, that changes shape and color when you click on it. add graphic Also, SVG graphics can be zoomed in or made as large as you want, without losing resolution. In other words, SVG graphics aren't get grainy or pixelated. +
For more technical specificsabout SVG format, see the format's specification.

+

This document may be incomplete and/or partially out of date with the current version. If you find discrepancies, please follow the procedures in the bug reporting section.

+
-

About editor

-

AniGen is a browser-based SVG animation editor. It is designed to work in tandem with Inkscape, expanding its functionality - to allow the user to animate vector images, as well as export them. Transfer of files between the editors should work without loss of information.

-

AniGen is free software available as is. It is written and maintained by Ondřej 'Aibo' Benda, and covered by GPLv3 license. The editor is currently in testing phase. Please take a moment to encounter any bugs you encounter.

-

For more information about SVG format, see the format's specification.

+

About aniGen SVG Editor

+

aniGen is a browser-based SVG editor to modify your SVG files to provide animation and interactivity. aniGen is designed to work in tandem with the vector software, Inkscape, expanding its functionality + Transferring SVG files between these two software editors should work without loss of information.

+

aniGen is free software available as is. It is written and maintained by Ondřej 'Aibo' Benda, and covered by GPLv3 license. The editor is currently in testing phase. Please report any bugs you encounter.

- +

Compatibility

-

The editor is developed mainly on Google Chrome, and should also work reasonably well on Mozilla Firefox. - Compatibility with other browsers is not the editor's main objective. To use the editor, JavaScript needs to be enabled.

+

The editor is developed mainly for use with the Google Chrome browser, but works equally as well with other browsers, such as Mozilla Firefox. + JavaScript needs to be enabled for aniGen to function properly.

- +

Third-party libraries

-

AniGen uses the following third-party assets, as mentioned in the "about" section of the editor:

+

aniGen uses the following third-party assets, as mentioned in the "about" section of the editor:

- + +
+
+

Quick Start

+

+ to +

+
+
+

Files

+ +
+

Opening and Saving SVGs

+ File open dialogueaniGen only works with existing SVG files (preferably created with Inkscape). + When aniGen is first loaded, you can open a SVG file by either: + + +

+ File open dialogue with existing fileIf a file is stored in local browser storage (by selecting file→save or hitting ctrl+s), it will be available in the file open dialogue. The local file can be deleted by the button next to it.

+
+ +
+

Importing Images to Your SVG

+ Files can be imported by dragging them into the editor's canvas. Imported files include : + +

+ _Raster files (i.e. JPEG and PNG files) will be appended to the currently selected container object. + SVGs will be merged, i.e. all elements container in the root SVG element will be moved to the current SVG's root element, and the contents of defs + (clip paths, gradients, animation states etc.) will be moved to current defs.

+

Note: It's recommended to save file before importing.

+
+ +
+

Exporting Static PNG or SVG files

+

File export dialogueSVG can be exported as a series of PNGs or static SVGs archived in a ZIP. User can set: +

+

Static SVGs will create individual SVG files for each frame, stripped of all animations.

+

Default duration is set to the loop length specified by the user with animation→loop animation... dialogue, or is computed as the least common multiple of all animation durations.

+

If only one frame is exported, it's downloaded directly instead of in a ZIP.

+

Rendering in progressWhile rendering, the editor will be unavailable. Progress and estimated time to completion (HH:MM:SS) is shown. + Progress percentage is shown in the page title. + The rendering process can take significant time, which scales with the number of elements in the SVG. Furthermore, each PNG is stored in the computer's memory. It's recommended to export longer animations, + or animations with extremely large size, in smaller segments. Rendering process can be canceled (with slight delay).

+

Files being packed into a ZIPWhen all frames are rendered, they are packed into a ZIP, which then triggers the standard save dialogue of the browser. + This process takes some time, but comperatively little to the rendering process.

+

Note: While mostly working, exporting is still in its testing phases. Save your work before you export and please report any problems.

+

Note: High resolutions, high downsampling settings, and long export times can lead to browser running out of allocated memory. It's advised to save your work before exporting, and export larger animations in shorter intervals.

+
+ +
+ -
-

User interface

+

interface Overview

Overview of the aniGen editor's main window.

The main window of aniGen (shown above) consists of eight main sections:

The XML editor and windows are toggled by the icons on right side of toolbar.

- +

Main menu

The menu (top right corner) allows access to most of the editor's functions:

- +

Global information

The top left section shows the following (left to right):

- +

Selection information

Shows information about currently selected element:

Selection information of a layer.Selection information of a layer. Left to right: tag name (g for group), identifier ("layer1"), inkscape's group name ("mouth").

Selection information of an animated group.Selection information of an animated group. Left to right: tag name (g for group), identifier ("g4138"), group type ("animated group"), group name ("mouth-female-3q").

- +

Toolbar

- +

Canvas

The visual representation of SVG document. The page (area exported as animation) is specified by the gray border. Page size can be set in Inkscape. See also controls and tools.

- +

Keyframes and timing window

Keyframes windowKeyframes window shows the keyframes and timing of currently selected animation. @@ -214,18 +285,18 @@

Keyframes and timing window

Animations with the spline interpolation mode also show the respective splines between every pair of keyframes.

Clicking the percent or time value of each keyframe allows you to change it, within the 0% - 100% range, or boundaries given by the animation's duration respectively.

Keyframes can be selected by clicking the striped button on the left. To select multiple frames, hold ctrl. Holding shift will select all frames between the furthest already selected frame and the frame clicked.

-

Values can be changed with standard input fields. If multiple keyframes are selected, all of their values are changed when you change one. It's also possible to drag the keyframes to switch their values with one another, +

Values can be changed with standard input fields. If multiple keyframes are selected, all of their values are changed when you change one. It's also possible to drag the keyframes to switch their values with one another, or move them up and down with page up / page down. Selected keyframes can be duplicated with ctrl+d and deleted with delete.

Keyframes window - spline menuKeyframes window - spline editorSplines can be changed between various presets or a custom value can be given instead. If custom spline is selected, a button allows the user to edit it.

The editor shows spline as the red curve, defined by its two control points (handles). The rectangles shown depict a five second animation, the top rectangle showing linear progression, the bottom showing progression as set by the given spline. Input fields allow direct change the spline's numeric components, and change with the handles. Any changes are immediately applied to the animation. Selecting multiple keyframes changes the spline for all of them.

- - + +

Selected keyframes are affected by the context menu (right click). If none is selected, the clicked keyframe is affected, except the cases noted below.

- +

Fill and stroke window

Fill tab of Fill and Stroke window, showing gradientsManages fill and stroke of selected element. Both fill (the inner parts of an element) and stroke (element's outlines) can be set to one of the following: @@ -272,10 +343,10 @@

Fill and stroke window

  • Miter limit - the maximum length of a miter join wedge (if applicable), measured in pixels
  • -

    AniGen currently doesn't have UI elements for creating and editing gradients, other than doing so manually. Linked objects (e.g. gradients) can be selected with link the appropriate button.

    +

    aniGen currently doesn't have UI elements for creating and editing gradients, other than doing so manually. Linked objects (e.g. gradients) can be selected with link the appropriate button.

    Additionally, the sliders at the bottom part of the window allows the user to change the blur and opacity of the element, independent of fill and stroke.

    - +

    Layers window

    Layers windowThe window similar to its Inkscape's counterpart. It shows layer groups in the usual order (higher layers overlap lower ones). Nested layers are shown indented. @@ -300,7 +371,7 @@

    Layers window

  • deleteDelete layer
  • - +

    XML editor

    XML editor windowThe XML editor allows quick navigation through the SVG's elements. Branch elements (i.e. elements with children) @@ -313,33 +384,37 @@

    XML editor

  • settingsAnimations
  • settings_applicationsAnimated groups
  • linkUse elements (links)
  • -
  • labellabel_outlineVisual elements (e.g. circles, paths etc.) as well as other general elements.
  • -
  • folderfolder_openContainer elements - namely groups and root SVG element.
  • -
  • layersLayers
  • -
  • videocamCamera
  • -
  • starstar_outlineDefinitions - a defs element, hosting various elements, such as:
  • +
  • labelstar_outlineVisual elements (e.g. circles, paths etc.) as well as other general elements.
  • +
  • folderfolder_openContainer elements - namely groups and root SVG element.
  • +
  • layersLayers
  • +
  • videocamCamera
  • +
  • starstar_outlineDefinitions - a defs element, hosting various elements, such as:
  • - +

    Event log

    -

    Keeps information about actions made during editing, such as copying, pasting, deleting etc.

    +

    While using aniGen, a log can be displayed (at the bottom of the screen) detailing your interactions, as well as problems that aniGen ran into. To turn on/off the Event log interface, either:

    +
    - - + +

    Preview window

    Shows the animation's canvas as it will look when exported. Limited controls are available:

    - +

    Settings

    Settings dialogue @@ -364,61 +439,12 @@

    Settings

    - - -
    - -
    -

    Files

    - -
    -

    Opening and saving SVGs

    -

    File open dialogueAniGen only works with existing SVG files (preferably created with Inkscape). They can be opened by clicking the icon, or by dropping the file on it.

    -

    File open dialogue with existing fileIf a file is stored in local browser storage (by selecting file→save or hitting ctrl+s), it will be available in the file open dialogue. The local file can be deleted by the button next to it.

    - -
    - -
    -

    Importing

    -

    Files can be imported by dragging them into the editor's canvas. Imported files include SVGs, JPEGs and PNGs. Raster files (JPEGs and PNGs) will be appended to the currently selected container object. - SVGs will be merged, i.e. all elements container in the root SVG element will be moved to the current SVG's root element, and the contents of defs - (clip paths, gradients, animation states etc.) will be moved to current defs.

    -

    It's recommended to save file before importing.

    - -
    - -
    -

    Exporting

    -

    File export dialogueCurrent SVG can be exported as a series of PNGs or static SVGs archived in a ZIP. User can set: -

    -

    Static SVGs will create individual SVG files for each frame, stripped of all animations.

    -

    Default duration is set to the loop length specified by the user with animation→loop animation... dialogue, or is computed as the least common multiple of all animation durations.

    -

    If only one frame is exported, it's downloaded directly instead of in a ZIP.

    -

    Rendering in progressWhile rendering, the editor will be unavailable. Progress and estimated time to completion (HH:MM:SS) is shown. - Progress percentage is shown in the page title. - The rendering process can take significant time, which scales with the number of elements in the SVG. Furthermore, each PNG is stored in the computer's memory. It's recommended to export longer animations, - or animations with extremely large size, in smaller segments. Rendering process can be canceled (with slight delay).

    -

    Files being packed into a ZIPWhen all frames are rendered, they are packed into a ZIP, which then triggers the standard save dialogue of the browser. - This process takes some time, but comperatively little to the rendering process.

    -

    Note: While mostly working, exporting is still in its testing phases. Save your work before you export and please report any problems.

    -

    Note: High resolutions, high downsampling settings, and long export times can lead to browser running out of allocated memory. It's advised to save your work before exporting, and export larger animations in shorter intervals.

    -
    - + +
    -
    -

    Controls

    - +

    Interaction and Controls

    +

    Mouse

    Generally used for selecting elements by clicking in a manner similar to Inkscape. Specific tools may change the default behavior.

    @@ -426,7 +452,7 @@

    Mouse

    Middle button allows user to drag the canvas view.

    Scroll wheel moves view up and down. Shift + wheel moves view left and right. Ctrl + wheel zooms in and out. Alt + wheel seeks (moves time) forward and backward, ctrl mask increases the seek distance.

    - +

    Keyboard shortcuts

    @@ -436,73 +462,73 @@

    Keyboard shortcuts

    - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + @@ -510,211 +536,24 @@

    Keyboard shortcuts

    - +
    F3Select the zoom tool
    F5Refreshes the window (after confirmation)
    F7Select the picker tool
    Space/Pause/Ctrl + PPause / unpause animations
    Alt + PauseReset animations
    Space/Pause/Ctrl + PPause / Play animations
    Alt + PauseRewind animations
    Ctrl + ←/1Go to previous keyframe of selected animation
    Ctrl + →/3Go to next keyframe of selected animation
    Ctrl + ↓/2Go to the closest keyframe of currently selected animation
    +/ESeek forward (1s if animation is running, 100ms if animation is paused)
    Shift + +/Shift + ESeek forward (10s if animation is running, 1s if animation is paused)
    Alt + +/Alt + ESeek forward (100ms if animation is running, 10ms if animation is paused)
    -/QSeek back (1s if animation is running, 100ms if animation is paused)
    Alt + -/Alt + QSeek back (100ms if animation is running, 10ms if animation is paused)
    Shift + -/Shift + QSeek back (10s if animation is running, 1s if animation is paused)
    Ctrl + ASelect / unselect all keyframes (keyframe window only)
    W/Ctrl + RSet current value for selected animation
    EscapeHide popup / dialogue
    Ctrl + +Zoom in
    Ctrl + -Zoom out
    DeleteRemove currently selected element
    Ctrl + Y/Ctrl + Shift + ZRedo
    Ctrl + ZUndo
    Page UpRaise currently selected element
    Page DownLower currently selected element
    HomeRaise currently selected element to the top of its parent
    EndLower currently selected element to the bottom of its parent
    ///Move selected element
    Alt + ←/Shift + ASelect previous sibling of selected element
    Alt + →/Shift + DSelect next sibling of selected element
    Alt + ↑/Shift + WSelect parent of selected element
    Alt + ↓/Shift + SSelect first child of selected element
    Alt + ↑/Alt + WSelect closest animation parent of selected element
    Ctrl + Shift + EOpen Export dialogue
    Ctrl + Shift + KOpen / close the Keyframes and timing window
    Ctrl + Shift + LOpen / close the Layers window
    Ctrl + Shift + XOpen / close the XML editor window
    Ctrl + OOpen the open dialogue
    Ctrl + SSaves SVG into browser local storage
    Ctrl + Shift + SSave and download SVG
    Ctrl + CCopy selected element into clipboard
    Ctrl + XCut element and move it to clipboard
    Ctrl + VPaste element or animation timing (animation to animation)
    Ctrl + L/Alt + DCreates a <use> link element.
    Ctrl + GGroup selected element
    Ctrl + UUngroup selected element
    - +
    - -
    -

    Elements and the XML tree

    -

    An SVG is an XML format, meaning the file is composed of elements. In code, these usually appear as pairs of tags similar to this:

    - - <svg id="green"></svg> - -

    In this example, svg is the element's tag name, id is a name of an attribute (in this case an identifier), and green is this attribute's value. <svg> is the opening tag and </svg> is the closing tag.

    -

    An element can have various attributes. Some are shared betwen different types of elements, like id or transform, others are exclusive to certain type of element, like dur (animation duration).

    -

    Most elements can have children, that is, other elements between the opening and closing tags.

    - - <svg id="green">
    - <g id="group"></g>
    - </svg> -
    -

    In this case, the g element is a child of the svg element.

    -

    An SVG file will usually have single svg element as its root, and all other elements will be its children, or the children of its children (and so on). This is called "nesting" and creates a tree structure depicted in the XML editor.

    -

    All SVGs share these basic properties.

    - -
    -

    Attributes

    -

    As mentioned above, elements can have various attributes. For example:

    - - <rect
    - id="rectangle1"
    - x="10"
    - y="20"
    - width="50"
    - height="100"
    - fill="red"
    - >
    - </rect> -
    -

    The code above defines a rectangle (rect element). Its top left corner is denoted by the given x and y attributes, its width and height by attributes of the same name (all sizes default to pixels). - Furthermore, its fill color is set to "red", equal to the hexadecimal value of #ff0000.

    -

    Were one of the attributes changed, e.g.

    - - <rect
    - id="rectangle1"
    - x="50"
    - y="20"
    - width="50"
    - height="100"
    - fill="red"
    - >
    - </rect> -
    -

    The element's properties will change. In this case, the top left corner (along with the rest of the element) will move 40 pixels right (along the x axis).

    -

    All SVG animations work by changing an attribute (or in some cases, CSS styles) over time.

    - -

    Attributes of interest common to multiple types of elements:

    - - - - - - - - -
    Attribute nameDescriptionPossible values
    transformTransformation of given element, usually in the form of a 3x3 matrix (simplified as its first two rows, i.e. six numeric values). Basis of all transformation animations.matrix(a b c d e f), rotate(angle cx cy), translate(x y), scale(x y), skewX(angle), skewY(angle)
    idIdentifier, unique to the SVG file. Other elements can use this to connect to others, for example, in case of gradients.string
    styleCSS styles, providing a large number of various visual options - colors, opacity, stroke width and dashing are all handled by these.semicolon separated pairs of name:value
    displayWhether the element should or should not be displayed. Sometimes as part of CSS styles.usually none or inline (none meaning hidden)
    visibilityWhether the element should or should not be visible, similar to "display". Sometimes as part of CSS styles.usually hidden or visible
    opacityOpacity (non-transparency) of the given element. Carries over to all of its children.numeric value between 0 and 1 (1 meaning 100% opaque)
    +
    +

    Editing tools

    + +
    +

    Group selection

    +

    near_meBased on Inkscape's "Select and transform objects" tool.

    +
      +
    • Left click - selects the highest group in current selection. Omits layers. If no group can be selected, the graphical element is selected instead.
    • +
    • Right click - context menu
    • +
    • Double click - goes inside the given group. Can select animations if the clicked element has one.
    • +
    - -
    -

    Common elements

    -

    This section contains a list of elements common to most SVG files, links to their official documentation, as well as short list of attributes interesting for attribute animation.

    -
    -

    SVG element <svg>

    -

    See also W3C recommendation.

    -

    Usually the root element of an SVG document (although not exclusively). Amongst others, SVG has the following attributes of interest:

    -
      -
    • width and height, determining the size of the rendered canvas
    • -
    • viewBox (x y width height), defining the position and size of rendered rectangular area
    • -
    -

    For the purpose of keeping aniGen running, animation of SVG attributes is not advised.

    -
    - -
    -

    Group <g>

    -

    See also W3C recommendation.

    -

    A container element, meaning an element with no actual graphical representation - simply holds other elements.

    -
    - -
    -

    Definitions <defs>

    -

    See also W3C recommendation.

    -

    A special container element, usually placed directly in the root svg element. Holds definitions, which can be various other elements. These are not rendered, but can be linked to by other elements in the SVG file.

    -

    For example, defs element holds the information about all clip paths, masks and filters. In aniGen, animation states are also kept here.

    -
    - -
    -

    Rectangle <rect>

    -

    See also W3C recommendation.

    -

    One of several graphical elements. Attributes of note:

    - - - - - - - - -
    Attribute nameDescriptionPossible values
    xx-axis position of top left cornernumeric value or length
    yy-axis position of top left cornernumeric value or length
    widthwidthnumeric value or length
    heightheightnumeric value or length
    cxx-axis rounding of cornersnumeric value, percentage, or length
    cyy-axis rounding of cornersnumeric value, percentage, or length
    -
    - -
    -

    Circle <circ>

    -

    See also W3C recommendation.

    -

    Circle, a special case of an ellipse (with both radii being the same). Attributes of note:

    - - - - - -
    Attribute nameDescriptionPossible values
    cxx-axis position of centernumeric value, percentage, or length
    cyy-axis position of centernumeric value, percentage, or length
    rradiusnumeric value or length
    -
    - -
    -

    Ellipse <ellipse>

    -

    See also W3C recommendation.

    -

    Attributes of note:

    - - - - - - - -
    Attribute nameDescriptionPossible values
    cxx-axis position of centernumeric value, percentage, or length
    cyy-axis position of centernumeric value, percentage, or length
    rxx-axis radiusnumeric value or length
    ryy-axis radiusnumeric value or length
    ryy-axis radiusnumeric value or length
    -
    - -
    -

    Path <path>

    -

    See also W3C recommendation.

    -

    Bread and butter of most SVG vectors - a Bézier curve. Shape is defined by its d attribute (path data), a sequence of commands.

    -

    When animating a path, keep in mind that both d attributes must have the same number and types of commands. In inkscape, the simplest way to achieve this is to create one path, duplicate it and adjust each node to another position, then each of the paths for different animation keyframe.

    -
    - -
    -

    Links <use>

    -

    See also W3C recommendation.

    -

    A link to another element. If original element changes, the link changes with it.

    -

    You can create links with from menu edit→create link.

    -
    - -
    -

    Transformation animation <animateTransform>

    -

    See also W3C recommendation.

    -

    Groups of animations which change the transform attribute of their parent. Includes translation, rotation, scaling, and horizontal and vertical skewing.

    -

    Attributes of note:

    - - - - - - - - - - - - - -
    Attribute nameDescriptionPossible values
    beginList of begin times.semicolon separated list of time values
    durDuration of single pass of animationtime value
    repeatCount Number of repeats of animation per each begin.nonnegative numeric value or "indefinite"
    fillThe state of the animated object after the animation finishes - freeze denotes the last value should be kept, remove means the object returns to the original state.freeze or remove
    additiveWhether this animation adds to values already present in the parent or completely replace them.sum or replace
    accumulateCumulation of the animation with itself. If set to sum, the animation will add to its last value each time it is repeated (good for infinitely moving objects).none or sum
    calcModeInterpolation mode.linear, spline, discrete, or paced
    keyTimesSee keyframes.Semicolon separated list of ascending numeric values between 0 and 1
    keySplinesSee splines.Semicolon separated groups of four numeric values between 0 and 1
    typeSpecific type of this animation.translate, rotate, scale, skewX, or skewY
    valuesValues for each keyframe.Semicolon separated list of values (groups of numeric values)
    -
    - -
    -

    Motion animation <animateMotion>

    -

    See also W3C recommendation.

    -

    Animation along a path. Shares most attributes with transform animation (except type and values), with these expetions:

    - - - - -
    Attribute nameDescriptionPossible values
    keyPointsList of lengths along the path for each keyframe.semicolon separated list of numeric values between 0 and 1
    pathPath data of the given path.path data
    -
    - -
    -

    Attribute animation <animate>

    -

    See also W3C recommendation.

    -

    Generic animation of attribute. Can handle almost anything except transform (which has specific animations). Shares most attributes (except type) with transform animation.

    -

    Bread and butter of most complex animations - can do anything from changing a path's shape to element's opacity to the color of its stroke.

    -
    - -
    - -
    - -
    -

    Editing tools

    - -
    -

    Group selection

    -

    near_meBased on Inkscape's "Select and transform objects" tool.

    -
      -
    • Left click - selects the highest group in current selection. Omits layers. If no group can be selected, the graphical element is selected instead.
    • -
    • Right click - context menu
    • -
    • Double click - goes inside the given group. Can select animations if the clicked element has one.
    • -
    -
    - +

    Element selection

    editBased on Inkscape's "Edit path by nodes" tool. Directly selects graphical objects, disregarding groups they might be in, and allows their editing with nodes.

    @@ -724,7 +563,7 @@

    Element selection

  • Double click - selects the clicked element's animation, if any.
  • - +

    Zoom

    searchZooms in or out at the factor of square root of two.

    @@ -733,7 +572,7 @@

    Zoom

  • Right click - zoom out
  • - +

    Picker

    colorizeBased on Inkscape's "Picker" tool. When a graphical element is selected:

    @@ -748,10 +587,9 @@

    Picker

  • Shift + click - if clicked element has an animation, copies its timing.
  • Right-click context menu will also show additional options tied to the selected element and target.

    - +
    -

    Animation

    All types of SVG animations share some common properties. Each animation has set duration of one pass (with possible repetition), a set of begin times, and keyframes which describe the value at given times, denoted as percentages of the animation's duration.

    @@ -762,17 +600,17 @@

    Timing

    Duration

    All animations have a set duration. This describes how long a single run of the animation lasts. In aniGen, this value is in seconds.

    - +

    Beginnings

    -

    Any animation can have multiple begin times. At each time, the animation restarts, and if applicable, loops the given number of times. If an animation is set to begin again while it's still running, it will usually reset. AniGen uses values given in seconds of the SVG's time.

    +

    Any animation can have multiple begin times. At each time, the animation restarts, and if applicable, loops the given number of times. If an animation is set to begin again while it's still running, it will usually reset. aniGen uses values given in seconds of the SVG's time.

    - +

    Repetition

    An animation can repeat multiple time per each beginning. Repeat count of zero means the animation only runs once, higher values denote multiple repetitions. Furthermore, repetition can be set to "indefinite", meaning the animation will run forever (or until it's ended by external source).

    - +

    Interpolation modes

    The progress between every pair of values can be calculated in several ways:

    @@ -783,11 +621,11 @@

    Interpolation modes

  • Paced - animation slows down and speeds up to provide smooth progression between keyframes. Usually only applicable for motion through path - the animation element will slow down during sharp turns, slow down as it nears each keyframe position etc.
  • - +

    Splines

    A non-linear way of interpolation between keyframes. Splines are simple curves defined by two control points, each as its X and Y value between 0 and 1.

    -

    AniGen uses several spline presets, but also allows the user to set custom splines more suited to their needs.

    +

    aniGen uses several spline presets, but also allows the user to set custom splines more suited to their needs.

    The following examples show simple two-value animation. Top bar progresses according to a spline, bottom bar has linear progression. Spline's shape is depicted in red, its control points are shown as white circles.

    Spline animation 0 0 1 1 (linear)
    0 0 1 1 - linear progression
    @@ -799,10 +637,10 @@

    Splines

    Spline animation .25 .25 .75 1 (ease out, sharp)
    0.25 0.25 0.75 1 - sharp ease out
    Spline animation .75 1 .25 .75 (custom)
    0.75 1 0.25 0.75 - a custom spline.
    - +
    - +

    Keyframes

    Keyframes windowEach animation has a set of keyframes. Each is denoted by its time (given as percentage of a single animation run) and its value. If spline interpolation mode is selected, every frame (except the first one) will have a spline attached to it as well, describing how the animation progresses to this keyframe from the previous one.

    @@ -810,7 +648,7 @@

    Keyframes

    Keyframes can be manipulated through the keyframes and timing window. Motion and transformation animations also have a node-based interface shown on the canvas, and described in sections below.

    Keyframe window allows duplication and deletion of keyframes (with the minimal two keyframes - 0% and 100%). Keyframes can be moved by dragging, efectively switching values (and splines) while retaining timing.

    - +

    Other attributes

    Animations have several other attributes:

    @@ -818,11 +656,11 @@

    Other attributes

    Additive indicates whether animation should add to any previous value the affected element already has or not. For instance, an additive translation from 0 to 100 will move the element from its original position. For non-additive animation, if the element already has a transformation attribute, however, it will be completely replaced. It's recommended to set additive to "yes" for transformations and motion along a path. Attribute animations, in contrast, are usually better served by replacing the attribute completely.

    Cumulative attribute indicates the animation should add to its own value each time it runs. This means that with each repetition (or new begin), the last value is kept as initial, and new values are added to it. For instance, a cumulative translation from 0 to 100 will, in first run, move the object from 0 to 100. On second repetition, the object will move from 100 to 200, and so on. This is particularly useful for creating continuous movement which should go forever.

    - +

    Animation types

    There are, for most intents and purposes, three basic animation types in SVG. Transformations change the element's transform attribute, allowing for rotation, translation, scaling, and skewing. Motion along path is similar, and as name implies, moves the element along a given path. Attribute animation is the widest and most generic type of animation, which allows for the change of almost any remaining attribute of almost any SVG element.

    -

    Element can be animated with the menu animation option, or with the power_settings_new animate element toolbar button.

    +

    Element can be animated with the menu animation option, or with the filter_none animate element toolbar button.

    Multiple animations can be applied to the same object. Their behavior can be exclusive if not set to additive.

    Camera

    @@ -830,68 +668,68 @@

    Camera

    videocamAnimates the SVG's viewbox - the rectangular view, which ultimately gets rendered.

    Each keyframe is defined as a rectangle. By default, the aspect ratio stays the same as the original, but this can be changed manually. However, the view always gets rendered to the same size raster, which would lead to uneven stretching or shrinking of the picture.

    - +

    Translation

    Translation animation trending_upMovement along X and Y axis. Each keyframe is defined by two values indicating the element's position. The node interface allows the user to set each by hand. Holding ctrl while dragging a node will move it in straight line from previous node to current node's last position.

    While not as versatile as motion through path, multiple translation animations can be combined to achieve similar effect without the hassle connected to the path management.

    - +

    Motion through path

    Motion animation swap_callsHas the element travel along a given path. Optionally, the angle can be set (or set to auto or auto-reverse) this will turn the element as it travels along the path instead of simply translating it.

    The picker tool can be used to assign the animation's path. The animation values are distance as percentage along the path, allowing the animation to run back and forth, or in reverse.

    - +
    - +

    Rotation

    Rotation animation refreshTurning around a given origin. Keyframes hold angle (in degrees) and the X and Y position of the origin. The position of origin can change throughout the animation, allowing for fairly complex range of motion (albeit harder to master than simply turning along a single point). Node interface allows the user to move all origins with the same location, and all handles.

    For each origin, angle zero is given as the angle the line from the origin to the affected element. This can effectively combine rotation with translation within a single animation.

    - +

    Scaling

    Scaling animation zoom_out_mapChanging the element's size. Described by scale factor in X and Y axis (allows independent scaling). As SVG has no native support for scaling origin, aniGen provides a more-or-less functional workaround. It's recommended to group any element you intent to scale, and only apply the scaling animation to this group to avoid issues.

    - +

    Skewing

    Skewing animation swap_horizswap_vertSeparated into horizontal (X axis) and vertical (Y axis) skew animations. Each keyframe is defined by the skew angle, zero being the initial value.

    A workaround similar to that with scaling is employed for skewing, and similar care should be used when using this animation.

    - +

    Attribute animation

    Attribute animation text_formatChanges the selected attribute of the parent (except transform and several other attributes) through time. Each value indicates the new value. Several attributes (display, visibility, opacity) allow the user to select values from available presets.

    If keyframes are selected in the keyframes window, the picker tool can be used to pick values of other (clicked) elements with relative ease.

    - +
    - +

    Animated groups

    Object menu Context menu - AniGen expands the basic animation functionality by introducing animated groups.

    + aniGen expands the basic animation functionality by introducing animated groups.

    The user can select any element (including groups) and save it as an animation state with main menu or right-click context menu.

    States are grouped according to the number and order of elements, so that standard path animation is applicable between all of them. When created, animated group allows the user to set each state from the group as the value of given keyframes. This allows the user to quickly change one complex shape to another without the need to create and synchronize large number of attribute animations.

    Animation state

    -

    Animation state dialogueAnimation states are set by selecting an object, and chosing object→object to animation state from the main menu, or via right-click context menu.

    +

    Animation state dialogueAnimation states are set by selecting an object, and chosing object→Put state in Animation Group from the main menu, or via right-click context menu.

    Animation state dialogueWhen selected, the user will be able to pick a name for the given state, as well as the group. If no group exists, or no group shares the element model necessary, the user will have to pick the New group option and naming the group.

    - +

    Note: if a group is made into a state, its transformation is disregarded. This means one can duplicate a group, move it somewhere else, and tweak elements therein without fear of making the final animation travel the distance.

    - +

    Note: if all children of selected elements share the same element model, a batch option is provided. This allows the user to set all the child elements as individual states, sharing the same group. For example, if the selected element is a layer, which has a number of sub-layers, each with a single state, the batch option will create a group named after the parent layer, and popuplate it with states named after each individual sub-layer. This is experimental.

    - +

    Animated group

    @@ -904,7 +742,7 @@

    Animated group

    Tip: To "hold" a temporary value created with intensity slider, simply set the intensity of the following keyframe to zero.

    Another addition is the ability to select which attributes will be animated. By default, the d attribute (see paths) is animated, but more can be added as the users desires.

    - +

    State manager

    Animation state manager @@ -914,26 +752,220 @@

    State manager

    State groups can be hidden by clicking their name. Empty groups are deleted automatically.

    Additionally, new states can be created from existing ones as an interpolation (inbetween value), or extrapolation, similar to the use of intensity option in keyframe window.

    The new state is a combination of two previous states, and is added to the end of the group.

    - +
    - + - + +
    +

    Elements and the XML tree

    +

    An SVG is an XML format, meaning the file is composed of elements. In code, these usually appear as pairs of tags similar to this:

    + + <svg id="green"></svg> + +

    In this example, svg is the element's tag name, id is a name of an attribute (in this case an identifier), and green is this attribute's value. <svg> is the opening tag and </svg> is the closing tag.

    +

    An element can have various attributes. Some are shared betwen different types of elements, like id or transform, others are exclusive to certain type of element, like dur (animation duration).

    +

    Most elements can have children, that is, other elements between the opening and closing tags.

    + + <svg id="green">
    + <g id="group"></g>
    + </svg> +
    +

    In this case, the g element is a child of the svg element.

    +

    An SVG file will usually have single svg element as its root, and all other elements will be its children, or the children of its children (and so on). This is called "nesting" and creates a tree structure depicted in the XML editor.

    +

    All SVGs share these basic properties.

    + +
    +

    Attributes

    +

    As mentioned above, elements can have various attributes. For example:

    + + <rect
    + id="rectangle1"
    + x="10"
    + y="20"
    + width="50"
    + height="100"
    + fill="red"
    + >
    + </rect> +
    +

    The code above defines a rectangle (rect element). Its top left corner is denoted by the given x and y attributes, its width and height by attributes of the same name (all sizes default to pixels). + Furthermore, its fill color is set to "red", equal to the hexadecimal value of #ff0000.

    +

    Were one of the attributes changed, e.g.

    + + <rect
    + id="rectangle1"
    + x="50"
    + y="20"
    + width="50"
    + height="100"
    + fill="red"
    + >
    + </rect> +
    +

    The element's properties will change. In this case, the top left corner (along with the rest of the element) will move 40 pixels right (along the x axis).

    +

    All SVG animations work by changing an attribute (or in some cases, CSS styles) over time.

    + +

    Attributes of interest common to multiple types of elements:

    + + + + + + + + +
    Attribute nameDescriptionPossible values
    transformTransformation of given element, usually in the form of a 3x3 matrix (simplified as its first two rows, i.e. six numeric values). Basis of all transformation animations.matrix(a b c d e f), rotate(angle cx cy), translate(x y), scale(x y), skewX(angle), skewY(angle)
    idIdentifier, unique to the SVG file. Other elements can use this to connect to others, for example, in case of gradients.string
    styleCSS styles, providing a large number of various visual options - colors, opacity, stroke width and dashing are all handled by these.semicolon separated pairs of name:value
    displayWhether the element should or should not be displayed. Sometimes as part of CSS styles.usually none or inline (none meaning hidden)
    visibilityWhether the element should or should not be visible, similar to "display". Sometimes as part of CSS styles.usually hidden or visible
    opacityOpacity (non-transparency) of the given element. Carries over to all of its children.numeric value between 0 and 1 (1 meaning 100% opaque)
    +
    + +
    +

    Common elements

    +

    This section contains a list of elements common to most SVG files, links to their official documentation, as well as short list of attributes interesting for attribute animation.

    +
    +

    SVG element <svg>

    +

    See also W3C recommendation.

    +

    Usually the root element of an SVG document (although not exclusively). Amongst others, SVG has the following attributes of interest:

    +
      +
    • width and height, determining the size of the rendered canvas
    • +
    • viewBox (x y width height), defining the position and size of rendered rectangular area
    • +
    +

    For the purpose of keeping aniGen running, animation of SVG attributes is not advised.

    +
    + +
    +

    Group <g>

    +

    See also W3C recommendation.

    +

    A container element, meaning an element with no actual graphical representation - simply holds other elements.

    +
    + +
    +

    Definitions <defs>

    +

    See also W3C recommendation.

    +

    A special container element, usually placed directly in the root svg element. Holds definitions, which can be various other elements. These are not rendered, but can be linked to by other elements in the SVG file.

    +

    For example, defs element holds the information about all clip paths, masks and filters. In aniGen, animation states are also kept here.

    +
    + +
    +

    Rectangle <rect>

    +

    See also W3C recommendation.

    +

    One of several graphical elements. Attributes of note:

    + + + + + + + + +
    Attribute nameDescriptionPossible values
    xx-axis position of top left cornernumeric value or length
    yy-axis position of top left cornernumeric value or length
    widthwidthnumeric value or length
    heightheightnumeric value or length
    cxx-axis rounding of cornersnumeric value, percentage, or length
    cyy-axis rounding of cornersnumeric value, percentage, or length
    +
    + +
    +

    Circle <circ>

    +

    See also W3C recommendation.

    +

    Circle, a special case of an ellipse (with both radii being the same). Attributes of note:

    + + + + + +
    Attribute nameDescriptionPossible values
    cxx-axis position of centernumeric value, percentage, or length
    cyy-axis position of centernumeric value, percentage, or length
    rradiusnumeric value or length
    +
    + +
    +

    Ellipse <ellipse>

    +

    See also W3C recommendation.

    +

    Attributes of note:

    + + + + + + + +
    Attribute nameDescriptionPossible values
    cxx-axis position of centernumeric value, percentage, or length
    cyy-axis position of centernumeric value, percentage, or length
    rxx-axis radiusnumeric value or length
    ryy-axis radiusnumeric value or length
    ryy-axis radiusnumeric value or length
    +
    + +
    +

    Path <path>

    +

    See also W3C recommendation.

    +

    Bread and butter of most SVG vectors - a Bézier curve. Shape is defined by its d attribute (path data), a sequence of commands.

    +

    When animating a path, keep in mind that both d attributes must have the same number and types of commands. In inkscape, the simplest way to achieve this is to create one path, duplicate it and adjust each node to another position, then each of the paths for different animation keyframe.

    +
    + +
    +

    Links <use>

    +

    See also W3C recommendation.

    +

    A link to another element. If original element changes, the link changes with it.

    +

    You can create links with from menu edit→create link.

    +
    + +
    +

    Transformation animation <animateTransform>

    +

    See also W3C recommendation.

    +

    Groups of animations which change the transform attribute of their parent. Includes translation, rotation, scaling, and horizontal and vertical skewing.

    +

    Attributes of note:

    + + + + + + + + + + + + + +
    Attribute nameDescriptionPossible values
    beginList of begin times.semicolon separated list of time values
    durDuration of single pass of animationtime value
    repeatCount Number of repeats of animation per each begin.nonnegative numeric value or "indefinite"
    fillThe state of the animated object after the animation finishes - freeze denotes the last value should be kept, remove means the object returns to the original state.freeze or remove
    additiveWhether this animation adds to values already present in the parent or completely replace them.sum or replace
    accumulateCumulation of the animation with itself. If set to sum, the animation will add to its last value each time it is repeated (good for infinitely moving objects).none or sum
    calcModeInterpolation mode.linear, spline, discrete, or paced
    keyTimesSee keyframes.Semicolon separated list of ascending numeric values between 0 and 1
    keySplinesSee splines.Semicolon separated groups of four numeric values between 0 and 1
    typeSpecific type of this animation.translate, rotate, scale, skewX, or skewY
    valuesValues for each keyframe.Semicolon separated list of values (groups of numeric values)
    +
    + +
    +

    Motion animation <animateMotion>

    +

    See also W3C recommendation.

    +

    Animation along a path. Shares most attributes with transform animation (except type and values), with these expetions:

    + + + + +
    Attribute nameDescriptionPossible values
    keyPointsList of lengths along the path for each keyframe.semicolon separated list of numeric values between 0 and 1
    pathPath data of the given path.path data
    +
    + +
    +

    Attribute animation <animate>

    +

    See also W3C recommendation.

    +

    Generic animation of attribute. Can handle almost anything except transform (which has specific animations). Shares most attributes (except type) with transform animation.

    +

    Bread and butter of most complex animations - can do anything from changing a path's shape to element's opacity to the color of its stroke.

    +
    + +
    +
    +
    +

    Audio

    +

    + to be added +

    +

    Bug reporting

    -

    Please report any bugs encountered to bugs(at)anigen.org. The report should include following:

    +

    + Please report any bugs encountered via email to bugs(at)aniGen.org. aniGen is also hosted on GitHub at https://github.com/aibosan/anigen. If you are familiar with using GitHub, you can post bugs there as well. +

    +

    + Bug reporting should include following:

    - - - diff --git a/root.js b/root.js index e5e1179..8383e72 100644 --- a/root.js +++ b/root.js @@ -190,7 +190,7 @@ root.prototype.getZoomReadable = function() { return Math.round(this.zoom * 100) + "%"; } -// pauses/unpauses animations +// pauses/plays animations root.prototype.pauseToggle = function(unpause) { if(this.svgElement.animationsPaused() && (unpause == true || unpause == null)) { if(popup.closeOnSeek) { @@ -736,7 +736,7 @@ root.prototype.evaluateSetCurrentValue = function() { } if(!newValue.invalid && (!hasValue || closest.closest.index == null)) { - animation.addValue(newValue, closest.progress, newSpline, intensity); + animation.addValue(newValue, closest.progress, newSpline, intensity); } if(anigenManager.classes.windowAnimation.animation == animation) {