I'm trying to anime an svg image inside an object tag via anime.js
This is what i found on internet+mycode:
<object id="object1" type="image/svg+xml" data="./image.svg"><object>
<script>
window.onload=()=>{
var o = document.getElementById('object1');
var svg=o.contentDocument();
var element=svg.getElementById('circle');
anime({
targets: element,
translateY: [0, 260],
direction: 'alternate',
duration: 2000,
easing: 'linear',
loop: true
})
}</script>
SVG Code:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmnls:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="157.627px" height="925.421px" viewBox="0 0 157.627 925.421" enable-background="nee 0 0 157.627 925.421" xml:space="preserve">
<circle id="circle" fill="#FFFFFF" stroke="#000000" stroke-width="5" stroke-miterlimit="10" cx="81.355" cy="842.37" r="50"/>
</svg>
With the SVG inside the HTML file, all works fine, so isn't a problem of anime.js.
I am having problems with loading svg files with fabric.js version 2.3.5. It seems that you cannot import shapes without an outline. See example below. This used to work fine in fabric.js version 1.7.22, but fails work with version 2.0.0 and higher. Is this intentional or an issue (bug)? Or do I need to modify the javascript code (see below)?
svg with outline (import works with fabric 2.3.5)
<svg width="100px" height="100px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g>
<path stroke="none" fill="#808080" d="M120 80 L120 160 40 160 40 80 120 80"/>
<path fill="none" stroke="#ff0000" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" d="M120 80 L120 160 40 160 40 80 120 80"/>
</g>
</svg>
svg without outline (import works with fabric 1.7.22, but not with 2.0.0 and higher)
<svg width="100px" height="100px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g>
<path stroke="none" fill="#808080" d="M120 80 L120 160 40 160 40 80 120 80"/>
</g>
</svg>
Javascript:
var load_imgs=function() {
fabric.loadSVGFromURL('mySvg.svg', function (objects, options) {
var obj = fabric.util.groupSVGElements(objects, options);
var logo = new fabric.Group(obj.getObjects(), {
left:20,
top: 10,
originX: 'left',
originY: 'top'
});
logo.scaleToHeight(50);
canvas.add(logo);
});
}();
After some time, I accidently discovered that the groupSVGElements is no longer valid or needed. So a correct working code is:
var load_imgs=function() {
fabric.loadSVGFromURL('mySvg.svg', function (objects, options) {
var logo = new fabric.Group(objects, {
left:20,
top: 10,
originX: 'left',
originY: 'top'
});
logo.scaleToHeight(50);
canvas.add(logo);
});
}();
I'm trying to animate this line so it would start from top to bottom, and then turn right to draw itself, with Vivus.js. However, the graphic does not seem to animate and I can't figure out why..anyone has some experience with SVG draw animations perhaps? Here's the pen: https://codepen.io/anon/pen/mLzYyE
Code:
var animate = ["animate1"];
animate.forEach(function (svgId) {
return new Vivus(svgId, {
type: "async",
start: "autostart",
duration: 100
});
});
As I understand Vivus.js works only with path element. So in your case you should replace rect elements to path. I also changed type to oneByOne for sequenced animation. Here is a simplified example:
var animate = ["animate1"];
animate.forEach(function (svgId) {
return new Vivus(svgId, {
type: 'oneByOne',
start: "autostart",
duration: 100
});
});
svg {
height: 500px;
width: 200px;
}
path {
stroke-width: 3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vivus/0.4.3/vivus.min.js"></script>
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="animate1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 66.598 221.333" enable-background="new 0 0 66.598 221.333" xml:space="preserve">
<path stroke="red" d="M0 0 l 0 20"/>
<path stroke="red" d="M0 25 l 0 20"/>
<path stroke="red" d="M0 50 l 0 20"/>
<path stroke="red" d="M0 75 l 30 0"/>
</svg>
I just wanted to do a very simple tweenMax animation, where the height of the bar goes from "0" to "100%". Now my SVG looks like below:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 69 64" style="enable-background:new 0 0 69 64;" xml:space="preserve">
<style type="text/css">
.st0{fill:#712215;}
.st1{fill:none;stroke:#712215;stroke-miterlimit:10;}
</style>
<path id="XMLID_8_" class="st0" d="M23,47.4h-5.4c-0.6,0-1-0.5-1-1v-6.9c0-0.5,0.4-1,1-1H23c0.5,0,1,0.5,1,1v6.9
C24,47,23.5,47.4,23,47.4z"/>
<path id="XMLID_7_" class="st0" d="M31.9,47.4h-5.4c-0.5,0-1-0.5-1-1V32.9c0-0.5,0.5-1,1-1h5.4c0.6,0,1,0.5,1,1v13.5
C32.9,47,32.5,47.4,31.9,47.4z"/>
<path id="XMLID_6_" class="st0" d="M41.9,47.4h-5.4c-0.6,0-1-0.5-1-1V36c0-0.5,0.4-1,1-1h5.4c0.5,0,1,0.5,1,1v10.5
C42.9,47,42.5,47.4,41.9,47.4z"/>
<path id="XMLID_5_" class="st0" d="M51,47.4h-5.4c-0.5,0-1-0.5-1-1V30c0-0.5,0.5-1,1-1H51c0.6,0,1,0.5,1,1v16.4
C52,47,51.5,47.4,51,47.4z"/>
<polygon id="XMLID_4_" class="st0" points="16.6,35 18,36.4 29.6,25.6 38.9,33 49.3,21.9 47.3,20 38.9,29.5 29.2,21.8 15.9,34.5 "/>
<polygon id="XMLID_3_" class="st0" points="43.2,17.8 51.7,17.9 51.9,26 "/>
<rect id="XMLID_2_" x="2.5" y="11.6" class="st1" width="63.5" height="40.8"/>
</svg>
Fiddle here. Now I have the following JavaScript to animate the bars:
$(function () {
var tx = new TimelineMax();
TweenMax.fromTo($('path')[0] , 2 , { css : { height : 0 } } , { css : { height : '100px' } });
});
But the height animation doesn't seem to be working. What am I doing wrong?
The problem is that height isn't an attribute supported by the path element;
an easy fix would be using transform:scaleY :
TweenMax.fromTo($('path')[0], 2, {
css: {
transform: 'scaleY(0)'
// height: 0
}
}, {
css: {
transform: 'scaleY(1)'
//height: '100px'
}
});
fiddle
For a more customized solution you might look into changing the d attribute...
Usually I'd use clipPath and move the entire bar to top. See fiddle
<clipPath id="myClip">
<path d="M23,47.4h-5.4c-0.6,0-1-0.5-1-1v-6.9c0-0.5,0.4-1,1-1H23c0.5,0,1,0.5,1,1v6.9
C24,47,23.5,47.4,23,47.4z" />
</clipPath>
<g clip-path="url(#myClip)">
<g id="path0" transform="translate(0 10)">
<path id="XMLID_8_" class="st0" d="M23,47.4h-5.4c-0.6,0-1-0.5-1-1v-6.9c0-0.5,0.4-1,1-1H23c0.5,0,1,0.5,1,1v6.9
C24,47,23.5,47.4,23,47.4z" />
</g>
</g>
I'm using greensock to animate an svg clippath, and it works great with one clippath, and hardcoded variables. Now I'm needing to add more clippaths, and I need each one to animate independently. So I need to build some sort of function to detect which circle is being moused over/ moused out and then call the timeline, passing it the correct parameters (the clippath and overlay circle). I'm sure I could probably do that with 'this' but I'm still at the point where 'this' makes my brain melt. Here's the codepen I'm working on.
http://codepen.io/kathryncrawford/pen/JYvdzx
HTML
<svg class="svg-graphic" width="500" height="500" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs>
<clipPath id="clippath">
<circle id="clip1" cx="200" cy="200" r="2.5"/>
<circle id="clip2" cx="400" cy="200" r="3.2"/>
</clipPath>
</defs>
<image class="svg-image1" xlink:href="http://lorempixel.com/300/300/" width="300" height="300" x="80" y="80"/>
<circle id="circle1" fill="#CC66FF" cx="200" cy="200" r="30"/>
<image class="svg-image2" xlink:href="http://lorempixel.com/300/300/" width="300" height="300" x="380" y="80"/>
<circle id="circle2" fill="#CC66FF" cx="400" cy="200" r="30"/>
JS
var clip = document.getElementById("clip1");
var circles = document.getElementById("circle1");
circles.addEventListener("mouseenter", expand);
circles.addEventListener("mouseleave", contract);
var tl = new TimelineMax({paused: true});
tl.to(clip, 0.5, {
attr: {
r: 120
},
transformOrigin: "50% 50%",
ease: Power4.easeInOut
})
.to(circles, 0.5, {alpha:0, ease:Power4.easeInOut}, '-0.1');
function expand() {
tl.play();
}
function contract() {
tl.reverse();
}
All right, this is what I was able to create by forking your pen.
And here is what has changed:
In HTML, I have removed unique IDs set on each of the circle HTML elements present inside the clipPath HTML element i.e. clipPath's children. Instead, I have given all of these circle tags a clip class.
The other circle elements that are siblings of the said clipPath i.e. present on the same level as clipPath element, have been given a circle class.
And as for the image elements, I have done similar thing. Removed unique IDs from them and instead gave them a common svg-image class.
This is HTML done.
In HTML, since the unique IDs have been removed such as #circle1, #circle2, #svg-image1 and #svg-image2, I have removed them from CSS as well and instead applied exactly the same rules they had on the newly created classes i.e. .circle and .svg-image respectively.
In JavaScript, the clip and circle elements as well as the total number of clip elements are first stored in variables clips, circles and numClips respectively.
There is also an empty array of timelines created initially.
Then there is a loop being initiated which goes up till the length of numClips and which does two things:
createTimeline as the name suggests, is supposed to create a TimelineMax instance which looks similar to what you previously had i.e. it adds two tweens, one for animating the opacity on the current circle element (remember, we are inside a loop and we have a reference of current circle element by the use of circles[i]) and the other for animating r of the current clip element.
assignListeners is for listening to mouseenter and mouseleave events on each of the circle elements.
And finally, expand and collapse methods are for playing or reversing the current timeline instance. (again, we have the reference of the timeline that should be playing when hovered or out using timelines[i] reference).
HTML:
<svg class="svg-graphic" width="500" height="500" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs>
<clipPath id="clippath">
<circle class="clip" cx="200" cy="200" r="20" />
<circle class="clip" cx="400" cy="200" r="20" />
<circle class="clip" cx="600" cy="200" r="20" />
</clipPath>
</defs>
<image class="svg-image" xlink:href="http://lorempixel.com/300/300/" width="300" height="300" x="80" y="80" />
<circle class="circle" fill="#CC66FF" cx="200" cy="200" r="20" />
<image class="svg-image" xlink:href="http://lorempixel.com/300/300/" width="300" height="300" x="380" y="80" />
<circle class="circle" fill="#CC66FF" cx="400" cy="200" r="20" />
<image class="svg-image" xlink:href="http://lorempixel.com/300/300/" width="300" height="300" x="680" y="80" />
<circle class="circle" fill="#CC66FF" cx="600" cy="200" r="20" />
</svg>
CSS:
*{
box-sizing: border-box;
}
body{
margin: 0;
padding: 0
}
.circle{
position: absolute;
margin: 0;
z-index: 1;
clip-path: url("#clippath");
}
.svg-image {
z-index: 3;
clip-path: url(#clippath);
}
svg{
overflow: visible;
}
.svg-graphic {
position: absolute;
}
.imgContainer {
position: relative;
width: 800px;
height: 800px;
}
JavaScript:
var clips = document.getElementsByClassName('clip');
var circles = document.getElementsByClassName('circle');
var numClips = clips.length;
var timelines = [];
for (var i = 0; i < numClips; i += 1) {
createTimeline(i);
assignListeners(i);
}
function createTimeline(i) {
var timeline = new TimelineMax({ paused: true });
timeline.to(circles[i], 0.6, { opacity: 0, ease: Expo.easeInOut }, 0);
timeline.to(clips[i], 0.6, {
attr: { r: 120 },
transformOrigin: '50% 50%',
ease: Expo.easeInOut
}, 0.1);
timelines[i] = timeline;
}
function assignListeners(i) {
(function(i) {
circles[i].addEventListener('mouseenter', function(e) { expand(e, i); }, false);
circles[i].addEventListener('mouseleave', function(e) { contract(e, i); }, false);
}(i));
}
function expand(e, i) { timelines[i].play(); }
function contract(e, i) { timelines[i].reverse(); }
Hope this helps.