I am trying to rotate the svg as it translates along, but i cant make it rotate on its axis. Is there a way to make it rotate on its own axis ?
jsFiddle
js Code
var paper = Snap('#svg');
matrix = new Snap.Matrix().translate(630, -95);
var start_gear = paper.path("M51.7,29.5v-7.2h-5.2c-0.5-3.1-1.6-6-3.3-8.5l3.4-3.4l-5.1-5.1l-3.2,3.2c-2.6-2-5.6-3.4-8.8-4V0.3h-7.1v4.1 c-3.4,0.5-6.5,1.7-9.2,3.6l-2.8-2.8l-5.1,5.1L8,12.9c-2,2.7-3.3,5.8-3.8,9.2H0v7.1h4.2c0.6,3.4,2,6.6,4,9.2l-2.8,2.8l5.1,5.1 l2.9-2.9c2.6,1.7,5.6,2.9,8.9,3.4v5.3h7.2v-5.4c3.1-0.6,6-1.9,8.5-3.7l3.6,3.6l5.1-5.1l-3.7-3.7c1.7-2.5,2.9-5.3,3.5-8.3H51.7z M25.8,38.1c-6.6,0-12-5.4-12-12c0-6.6,5.4-12,12-12c6.6,0,12,5.4,12,12C37.8,32.8,32.4,38.1,25.8,38.1z").transform(matrix);
start_gear.attr({fill: "#e8434d"});
start_gear.animate({ transform: 't630, 240 r540,22,20' }, 3000, mina.bounce);
If you don't include your own center of rotation, Snap will use its calculated bounding box center to rotate around. So it's as simple as removing that.
start_gear.animate({ transform: 't630, 240 r540' }, 3000, mina.bounce);
jsfiddle
If you only want to rotate, AND the element already has a transform applied to it, you need to include the previous transform, so it doesn't get overwritten. To get the previous transform, it's simply element.transform(). So the full command would be...
start_gear.animate({ transform: start_gear.transform() + 'r540' }, 3000, mina.bounce);
jsfiddle
See this demo, I used TimelineMax.js lib. it is Super easy and helpful in animation !
HTML code :
<svg id="svg" width="80vw" height="60vh" viewBox="0 0 1300 250">
<path class="myPath" d="M51.7,29.5v-7.2h-5.2c-0.5-3.1-1.6-6-3.3-8.5l3.4-3.4l-5.1-5.1l-3.2,3.2c-2.6-2-5.6-3.4-8.8-4V0.3h-7.1v4.1 c-3.4,0.5-6.5,1.7-9.2,3.6l-2.8-2.8l-5.1,5.1L8,12.9c-2,2.7-3.3,5.8-3.8,9.2H0v7.1h4.2c0.6,3.4,2,6.6,4,9.2l-2.8,2.8l5.1,5.1 l2.9-2.9c2.6,1.7,5.6,2.9,8.9,3.4v5.3h7.2v-5.4c3.1-0.6,6-1.9,8.5-3.7l3.6,3.6l5.1-5.1l-3.7-3.7c1.7-2.5,2.9-5.3,3.5-8.3H51.7z M25.8,38.1c-6.6,0-12-5.4-12-12c0-6.6,5.4-12,12-12c6.6,0,12,5.4,12,12C37.8,32.8,32.4,38.1,25.8,38.1z"></path>
JS code:
/*
var paper = Snap('#svg');
matrix = new Snap.Matrix().translate(630, -95);
var start_gear = paper.path("M51.7,29.5v-7.2h-5.2c-0.5-3.1-1.6-6-3.3-8.5l3.4-3.4l-5.1-5.1l-3.2,3.2c-2.6-2-5.6-3.4-8.8-4V0.3h-7.1v4.1 c-3.4,0.5-6.5,1.7-9.2,3.6l-2.8-2.8l-5.1,5.1L8,12.9c-2,2.7-3.3,5.8-3.8,9.2H0v7.1h4.2c0.6,3.4,2,6.6,4,9.2l-2.8,2.8l5.1,5.1 l2.9-2.9c2.6,1.7,5.6,2.9,8.9,3.4v5.3h7.2v-5.4c3.1-0.6,6-1.9,8.5-3.7l3.6,3.6l5.1-5.1l-3.7-3.7c1.7-2.5,2.9-5.3,3.5-8.3H51.7z M25.8,38.1c-6.6,0-12-5.4-12-12c0-6.6,5.4-12,12-12c6.6,0,12,5.4,12,12C37.8,32.8,32.4,38.1,25.8,38.1z").transform(matrix);
start_gear.attr({fill: "#e8434d"});
start_gear.animate({ transform: 't630, 240 r540,22,20' }, 3000, mina.bounce); */
var tl = new TimelineMax();
// Settings ...
tl.set(".myPath", {
x: 630,
y: -95,
fill: "#e8434d",
transformOrigin: "center"
})
// Animatiion ...
tl.to(".myPath", 3 , {
//x : "+= 500",
y: "+= 400",
rotation: "630",
ease: Bounce.easeOut
});
I’m quite new with the GreenSock and I got myself in trouble...
I would like to modify GreenSock TimelineLite timing offset for reverse so that some delays get deleted (I think that they are called staggers).
Here is an example: http://jsfiddle.net/4bvnv1d5/
var red = $('.red');
var green = $('.green');
var blue = $('.blue');
var black = $('.black');
var tl = new TimelineLite({onReverseComplete:reverseCompleted});
$('#start').click(function(){
tl.to(red, 0.3, {ease: Power1.easeInOut, 'margin-left':'100px'});
tl.to(green, 0.3, {ease: Power1.easeInOut, 'margin-left':'100px'});
tl.to(blue, 0.3, {ease: Power1.easeInOut, 'margin-left':'100px'});
tl.to(black, 0.3, {ease: Power1.easeInOut, 'margin-left':'100px', onComplete:lastCompleted, onCompleteParams:[black]}, "+=4");
});
$('#reverse').click(function(){
tl.reverse();
});
function lastCompleted(target) {
console.log('lastCompleted');
}
function reverseCompleted(){
console.log('reverseCompleted');
tl.clear();
tl.restart();
}
On play there is a four second delay with the last box, but on the reverse I’d like to animations to play right after each other with no delays. There is function lastCompleted() which is triggered after the last tween gets run. How can I use that function to remove the delay between the black and blue box animations?
Thanks!
Take a look at this fiddle.
JavaScript:
var red = $('.red');
var green = $('.green');
var blue = $('.blue');
var black = $('.black');
var tl = new TimelineLite({
paused: true,
callbackScope: this,
onReverseComplete: onTlReverseComplete
});
tl.staggerTo([red, green, blue], 0.3, { marginLeft: 100, ease: Power1.easeInOut }, 0.3);
tl.addLabel('MyLabel');
tl.to(black, 0.3, { marginLeft: 100, ease: Power1.easeInOut, onReverseComplete: onBlackBoxReverseComplete, callbackScope: this }, '+=4');
$('#start').click(function () {
tl.play();
});
$('#reverse').click(function () {
tl.reverse();
});
function onBlackBoxReverseComplete() {
tl.reverse('MyLabel');
}
function onTlReverseComplete() {
tl.stop();
}
Quite a few things have changed from your code. Here is the list:
The tweens are added into the tl instance outside the scope of click handler of #start button. The click handler only .play()s the timeline forward.
.staggerTo() method is used instead of adding adding the 3 tweens one by one before the one for .black element.
Also, margin-left has been replaced by its JS equivalent marginLeft and since it accepts numbers and defaults to pixels, no need to pass the values as strings.
The tween for .black element has now a onReverseComplete callback.
Hope this helps. Let me know if you have any questions.
I am trying to swipe a container and it's children elements off the screen. However when I run the following code, the child element I swipe goes off the screen as opposed to both elements.
// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Titanium.UI.setBackgroundColor('#000');
//
// create base UI tab and root window
//
var win1 = Titanium.UI.createWindow({
title : 'Tab 1',
backgroundColor : '#fff'
});
var viewContainer = Titanium.UI.createImageView({
backgroundColor : 'white',
width : '100%',
height : '100%',
top : 0
});
var view = Titanium.UI.createImageView({
backgroundColor : 'green',
width : '100%',
height : '100%',
top : 0
});
var view1 = Titanium.UI.createView({
backgroundColor : 'red',
width : '100%',
height : 100,
bottom : 0
});
viewContainer.addEventListener('swipe', function(e) {
if (e.direction == "right") {
//TODO: add functionality here
} else if (e.direction == "left") {
var anim = Ti.UI.createAnimation({
left : -300,
duration : 200,
curve : Ti.UI.ANIMATION_CURVE_EASE_OUT
});
anim.addEventListener('start', function(_startanicallback) {
});
anim.addEventListener('complete', function(_anicallback) {
});
e.source.animate(anim);
}
});
viewContainer.add(view);
viewContainer.add(view1);
win1.add(viewContainer);
win1.open();
I have a :
ViewContainer - where the event listener is attached too.
Inside that , view and view1 both child elements.
Not sure why this is happening.
Cheers.
The reason for only one of the elements being swiped is this line :
e.source.animate(anim);
If you will replace it with viewContainer.animate(anim); the swipe will work as you want.
Hope it helps.
I am learning how to use Spin.js so that a loading indicator (the spinner) can be shown while the web page is loading.
I got it working but I am not sure whether I am calling the spin/stop in the proper page lifecycle. Is it possible to show the spinner before $(window).ready ?
<script type="text/javascript">
var spinner;
$(window).ready(function loadingAnimation() {
var opts = {
lines: 13, // The number of lines to draw
length: 7, // The length of each line
width: 4, // The line thickness
radius: 10, // The radius of the inner circle
corners: 1, // Corner roundness (0..1)
rotate: 0, // The rotation offset
color: '#000', // #rgb or #rrggbb
speed: 1, // Rounds per second
trail: 60, // Afterglow percentage
shadow: false, // Whether to render a shadow
hwaccel: false, // Whether to use hardware acceleration
className: 'spinner', // The CSS class to assign to the spinner
zIndex: 2e9, // The z-index (defaults to 2000000000)
top: 'auto', // Top position relative to parent in px
left: 'auto' // Left position relative to parent in px
};
var target = $("body")[0];
spinner = new Spinner(opts).spin(target);
});
window.onload = function() {
spinner.stop();
};
For the working example, please see http://sgratrace.appspot.com/industry.html
I created an object to control the spinning:
Rats.UI.LoadAnimation = {
"start" : function(){
var opts = {
lines : 13, // The number of lines to draw
length : 7, // The length of each line
width : 4, // The line thickness
radius : 10, // The radius of the inner circle
corners : 1, // Corner roundness (0..1)
rotate : 0, // The rotation offset
color : '#000', // #rgb or #rrggbb
speed : 1, // Rounds per second
trail : 60, // Afterglow percentage
shadow : false, // Whether to render a shadow
hwaccel : false, // Whether to use hardware acceleration
className : 'spinner', // The CSS class to assign to the spinner
zIndex : 2e9, // The z-index (defaults to 2000000000)
top : $(window).height()/2.5, // Manual positioning in viewport
left : "auto"
};
var target = $("body")[0];
return new Spinner(opts).spin(target);
},
"stop" : function(spinner){
spinner.stop();
}
};
When the DOM is loaded, I start spinning:
$(document).ready(function(){
// Once the DOM is loaded, start spinning
spinner = Rats.UI.LoadAnimation.start();
pageUI();
});
When the entire page is loaded, I stop spinning:
$(window).load(function(){
// Once the page is fully loaded, stop spinning
Rats.UI.LoadAnimation.stop(spinner);
});
What's the difference between window.onload vs $(document).ready()
See the full code on my github repo:
https://github.com/seahrh/sgratrace/blob/master/war/js/rats.js
https://github.com/seahrh/sgratrace/blob/master/war/index.html
I'm developing some page when I use Raphael liblary to draw some items.
my App
So my problem is in that when I'm moving to some rect it growing up but when my mouse is on text which is positioning on my rect, it loss his hover. You can see it on my app example.
var paper = new Raphael(document.getElementById('holder'), 500, object.length * 100);
drawLine(paper, aType.length, bType.length, cType.length, cellSize, padding);
process = function(i,label)
{
txt = paper.text(390,((i+1)* cellSize) - 10,label.devRepo)
.attr({ stroke: "none", opacity: 0, "font-size": 20});
var a = paper.rect(200, ((i+1)* cellSize) - 25, rectWidth, rectHeight)
.hover(function()
{
this.animate({ transform : "s2"}, 1000, "elastic");
this.prev.animate({opacity: 1}, 500, "elastic");
this.next.attr({"font-size" : 30});
},
function()
{
this.animate({ transform : "s1" }, 1000, "elastic");
this.prev.animate({opacity: 0}, 500);
this.next.attr({"font-size" : 15});
});
}
I have tried e.preventDefault(); on hover of this.next and some other solutions but it's doesn't work.
Any help would be appreciated.
Most people will suggest you place a transparent rectangle over the box and the labels and attach the hover functions to that instead. (If memory serves, you have to make the opacity 0.01 instead of 0 to prevent the object from losing its attached events.) This works fine, but I don't love this solution; it feels hacky and clutters the page with unnecessary objects.
Instead, I recommend this: Remove the second function from the hover, making it functionally a mouseover function only. Before you draw any of the rectangles and labels, make a rectangular "mat" the size of the paper. Then, attach the function that minimizes the label as a mouseover on the mat. In other words, you're changing the trigger from mousing out of the box to mousing over the area outside of it.
I left a tiny bit of opacity and color on the mat to be sure it's working. You can just change the color to your background color.
var mat = paper.rect(0, 0, paper.width, paper.height).attr({fill: "#F00", opacity: 0.1});
Now, you want to make a container for all the rectangles so you can loop through them to see which need to be minimized. I made an object called "rectangles" that contains the objects we're concerned with. Then:
mat.mouseover(function () {
for (var c = 0; c < rectangles.length; c += 1) {
//some measure to tell if rectangle is presently expanded
if (rectangles[c].next.attr("font-size")) {
rectangles[c].animate({
transform : "s1"
}, 1000, "elastic");
rectangles[c].prev.animate({opacity: 0}, 500);
rectangles[c].next.attr({"font-size" : 15});
}
}
});
Then I just removed the mouseout function from the individual rectangles.
jsBin
To be clear, this will have some downsides: If people run the mouse around really fast, they can expand several rectangles at the same time. This is remedied as soon as the mouse touches the mat. I think the functionality looks pretty nice. But the invisible mats is always an option.
I wrote a small extension to Raphael - called hoverInBounds - that resolves this limitation.
Demo: http://jsfiddle.net/amustill/Bh276/1
Raphael.el.hoverInBounds = function(inFunc, outFunc) {
var inBounds = false;
// Mouseover function. Only execute if `inBounds` is false.
this.mouseover(function() {
if (!inBounds) {
inBounds = true;
inFunc.call(this);
}
});
// Mouseout function
this.mouseout(function(e) {
var x = e.offsetX || e.clientX,
y = e.offsetY || e.clientY;
// Return `false` if we're still inside the element's bounds
if (this.isPointInside(x, y)) return false;
inBounds = false;
outFunc.call(this);
});
return this;
}