I'm trying to animate my jquery dial and have the libraries loaded and all yet when I try to animate them after building the knob object, nothing happens. If I call both $('#dial') on both the animate and knob constructor it animates but doesn't ceil the value or give it a percent until I click it after its finished animating.
Here is what I have got
HTML
<input type="text" value="0" class="dial"/>
Javascript
var dial = $('.dial').knob({
value: 0,
width: 120,
height: 120,
min: 0,
max: 100,
stopper: true,
readOnly: true,//if true This will Set the Knob readonly cannot click
draw: function () {
$(this.i).val(this.cv + '%'); //Puts a percent after values
},
'format': function(v) {return v + '%'},
thickness: 0.1,
tickColorizeValues: true,
skin: 'tron'
});
dial.animate({//animate to data targetValue
value: 89
}, {
duration: 5000,
easing: 'swing',
step: function () {
var percent = Math.ceil(this.value) + '%';
$(this).val(Math.ceil(this.value) + '%').trigger('change');
// $(this).val($(this).val() + '%');
}
});
here my code maybe help you (included animation and style )
http://codepen.io/AdelDima/pen/ueKrI
I used GSAP animation library as there seemed to be a conflict with step and progress callbacks from the jquery animate.
Related
I have made a basic svg image resizing, rotating and dragging inside mask on fiddle. I'm getting trouble in rotate image from center after moving. How do I reset origin x,y after moving?
Please move the image first, then rotate it with slider.
Try here: https://jsfiddle.net/david7418/o497akje/6/
Transform attribute gets overwrited here. How do I get origin x,y and put into transform arguments?
//Slider rotate
$( "#slider_rotate" ).slider({
max: 360,
min: 0,
step:1,
value:0,
slide: function( event, ui ) {
var matrixObj = obj.transform().localMatrix.split()
console.log(matrixObj);
var t = new Snap.Matrix();
//Transform overwrite
t.add(obj.transform().localMatrix);
obj.transform('r'+ui.value+','+t);
}
});
Full code:
$(function() {
obj = Snap(".cat");
//Enable drag event
obj.drag();
var dimens = obj.node.getBoundingClientRect();
var orinDimens = dimens;
//Image max enlarge rate
var enlargeRate = 4;
var smax = dimens.width;
//Slider resize
$( "#slider_resize" ).slider({
max: smax*enlargeRate,
min: smax,
step:1,
value:dimens.width,
slide: function( event, ui ) {
w = ui.value * dimens.width / smax;
h = ui.value * dimens.height / smax;
obj.attr({
width: w,
height: h,
x: (dimens.width - w)/2,
y: (dimens.height - h)/2
});
}
});
//Slider rotate
$( "#slider_rotate" ).slider({
max: 360,
min: 0,
step:1,
value:0,
slide: function( event, ui ) {
obj.transform('r'+ui.value);
}
});
//Reset button
$('#reset').click(function(){
$("#slider_resize").slider('value',orinDimens.width);
$("#slider_rotate").slider('value',0);
var objMatrix = new Snap.Matrix();
objMatrix.translate(0,0);
objMatrix.rotate(0);
obj.transform(objMatrix);
obj.attr({width: orinDimens.width,x:0})
});
});
I would create one central place to update all the transforms. It flows a bit easier probably if you use a Snap plugin as well for ease of coding, so something like the following.
We will store the x,y,r,s variables in a data() method for the object.
Snap.plugin( function( Snap, Element, Paper, global ) {
Element.prototype.updateTransform = function() {
var newTransform = 't' + (this.data('xy').x) + ',' + (this.data('xy').y);
newTransform += 'r' + (this.data('r'))
newTransform += 's' + (this.data('s'))
this.transform( newTransform )
return this;
}
Element.prototype.init = function() {
return this.data('xy', {x:0,y:0})
.data('r',0)
.data('s',1)
}
});
Now we have an update method, we can call this, any time we change something on the screen, or want to initialise it or whatever.
So when we want to reset it all, we can call...
$('#reset').click(function(){
obj.init().updateTransform();
});
For the drag handler...(store the old position in oxy)
function dragStart (x,y) {
this.data('oxy', this.data('xy') );
}
function dragMove( dx,dy,x,y ) {
this.data('xy', { x: this.data('oxy').x + dx ,
y: this.data('oxy').y + dy })
.updateTransform();
}
And for the sliders, we just store the values, and call updateTransform()
$( "#slider_resize" ).slider({
max: 4,
min: 1,
step:0.1,
slide: function( event, ui ) {
obj.data('s', ui.value)
.updateTransform();
}
});
With it all tied together, it would look like...
jsfiddle
When clicked, I want a button to produce three child options, which then when tapped again should do retract and then disappear when behind the parent button. I hope this is clear from the code (note this is a nativescript application, hence the slightly strange css choices).
exports.fabTap = function (args) {
var google = page.getViewById("google");
var facebook = page.getViewById("facebook");
var amazon = page.getViewById("amazon");
if (clicked == false) {
google.style.visibility = "visible";
facebook.style.visibility = "visible";
amazon.style.visibility = "visible";
google.animate({
translate: { x: -55, y: -66 },
duration: 500,
curve: enums.AnimationCurve.cubicBezier(0.1, 0.1, 0.1, 1)
});
facebook.animate({
translate: { x: 0, y: -75 },
duration: 500,
curve: enums.AnimationCurve.cubicBezier(0.1, 0.1, 0.1, 1)
});
amazon.animate({
translate: { x: 55, y: -66 },
duration: 500,
curve: enums.AnimationCurve.cubicBezier(0.1, 0.1, 0.1, 1)
});
} else {
google.animate({
translate: { x: 0, y: 0 },
duration: 500,
curve: enums.AnimationCurve.cubicBezier(0.1, 0.1, 0.1, 1)
});
facebook.animate({
translate: { x: 0, y: 0 },
duration: 500,
curve: enums.AnimationCurve.cubicBezier(0.1, 0.1, 0.1, 1)
});
amazon.animate({
translate: { x: 0, y: 0 },
duration: 500,
curve: enums.AnimationCurve.cubicBezier(0.1, 0.1, 0.1, 1)
});
google.style.visibility = "collapse";
facebook.style.visibility = "collapse";
amazon.style.visibility = "collapse";
}
clicked = !clicked;
}
However, as you can see from the gif, on the return journey, the buttons just disappear before the return. What can I do to ensure this animates in sequence?
You're doing this:
google.style.visibility = "collapse";
facebook.style.visibility = "collapse";
amazon.style.visibility = "collapse";
immediately after starting the animations, not giving the animations time to run before you do it.
If you want to wait, either use a callback on the animations, or just delay 500ms.
I don't know what animation lib you're using, so I can't show an example of a callback waiting for all three to be done.
Here's the "just wait 500ms" version, though:
setTimeout(function() {
google.style.visibility = "collapse";
facebook.style.visibility = "collapse";
amazon.style.visibility = "collapse";
}, 500);
You could probably do this easily with transitions. Instead of using visibility, try using opacity to fade your buttons in and out. Or, you could add a transition end listener to your JS and only set visibility to collapse after the three tabs have moved back under the main button. I think your problem is trying to animate visibility.
I am looking to animate this progress bars, but I'm having a different behavior using jQuery animate() method. I want to animate the progress bars one by one with a 0.1s delay. I will need help with choosing the right animation, because now my animation is behaving downwards. I'd like to do it in the simplest way possible.
Here is what I have so far:
$('.vertical-bars .progress-fill span').each(function() {
var percent = $(this).html();
var pTop = 100 - (percent.slice(0, percent.length - 1)) + "%";
$(this).parent().css({
'height': percent,
'top': pTop
});
$(this).parent().animate({
height: "toggle"
}, {
duration: 900,
specialEasing: {
height: "swing"
}
});
});
I have prepared a JSFiddle with my progress bars HERE.
The right behavior is to fill the progress-bars upwards, like in THIS example.
You need to animate both the height and top of your bars, or you need to construct them such that they are pinned to the horizontal axis when you change the height. The second takes a little more thought, but the first, although not as elegant, is straight forward.
To animate top you can't use toggle (as it is animating to 100% and back, not to 0), so you will need to animate both the shrink and grow separately using done to trigger a second animation. Taking the same style as you used above:
$('.vertical-bars .progress-fill span').each(function () {
var percent = $(this).html();
var pTop = 100 - ( percent.slice(0, percent.length - 1) ) + "%";
$(this).parent().css({
'height': percent,
'top': pTop
});
var self=this;
$(this).parent().animate({
height: 0,
top: "100%"
}, {
duration: 900,
specialEasing: {
height: "swing",
top: "swing"
},
done:function(){
$(self).parent().animate({
height: percent,
top: pTop
}, {
duration: 900,
specialEasing: {
height: "swing",
top: "swing"
}
})
}
});
});
Of course you can also achieve the same thing using css animation. If I have time to figure it out I'll post an edit.
I don't know what height: "toggle" does but you basically want to set 0 height and 100% offset from top and then start animation that adjusts both styles.
The 100ms between animations is done simply by using setTimeout and incrementing the timeout.
https://jsfiddle.net/kss1su0b/1/
var elm = $(this).parent();
elm.css({
'top': '100%',
'height': 0
});
setTimeout(function() {
elm.animate({
'height': percent,
'top': pTop
}, {
duration: 900,
specialEasing: {
height: "swing"
},
});
}, animOffset);
animOffset += 100;
The simplest and most performing way to invert the animation direction is to align the bars at the bottom with css:
vertical-bars .progress-fill {
position: absolute;
bottom: 0;
}
Then you don't need to set the top any more with jQuery and set a delay:
$('.vertical-bars .progress-fill').each(function (index) {
var percentage = $(this).find('.percentage').html();
$(this).delay(index * 100).animate(
{
height: percentage
}, {
duration: 900,
done: function () {
$(this).find('span').show("normal");
}
}
);
});
jsfiddle
I'm trying to animate the backgroundPositionY of an <div> element. What I try to do is to animate it linearly. Every step should be in between a fixed range.
For example:
step1: backgroundPositionY: 0 (192*0)
step2: backgroundPositionY: 192 (192*1)
step3: backgroundPositionY: 384 (192*2)
... and so on
My current code looks like the following:
$curtains = $("#unshredder-curtains");
$curtains.data('backgroundPositionY', -3456);
$curtains.animate({
backgroundPositionY: 3648
}, {
duration: 2000,
easing: "linear",
step: function(now, fx) {
var newTop = Math.floor(now / 192) * 192;
$(fx.elem).css('backgroundPositionY', newTop+'px');
}
});
But that does nothing. It just animates the background as it usually does. The steps are just ignored.
Does anyone know how to do that special animation?
Thanks :)
I'd probably do something like:
var step = 192;
setInterval(function(){
$('#unshredder-curtains').css('backgroundPositionY', function(i, val){
var bgPosY = (parseInt(val) + step) + 'px';
$(this).html('New position: ' + bgPosY);
return bgPosY;
});
}, 100);
You can see it in action here: http://jsfiddle.net/pr7cc/
I use the Jquery Jcrop for cropping my images. Now I'm implementing a slider for resizing the image. I want the cropping and resizing to happend on the same page.
I do it like this:
$(document).ready(function() {
var img = $('#cropbox')[0]; // Get my img elem
var orgwidth, orgheight;
$("<img/>") // Make in memory copy of image to avoid css issues
.attr("src", $(img).attr("src"))
.load(function() {
orgwidth = this.width; // Note: $(this).width() will not
orgheight = this.height; // work for in memory images.
});
$('#cropbox').Jcrop({
onSelect: updateCoords
});
$("#imageslider").slider({
value: 100,
max: 100,
min: 1,
slide: function(event, ui) {
//$('ul#grid li').css('font-size',ui.value+"px");
resizeImage(orgwidth, orgheight);
}
});
});
And my simple resizeImage function:
function resizeImage(orgwidth, orgheight) {
var value = $('#imageslider').slider('option', 'value');
var width = orgwidth * (value / 100);
var height = orgheight * (value / 100);
$('#cropbox').width(width);
$('#cropbox').height(height);
$('#tester').val("org: "+orgwidth+" now: "+width);
}
The problem is that, as soon I turn on Jcrop I can't resize the image. How can I use both these functions at the same time?
I ended up destroying the jCrop while resizing and putting it back on after resize. Thanks anyway. Code:
function resizeImage(orgwidth, orgheight) {
jcrop_api.destroy();
var value = $('#imageslider').slider('option', 'value');
var width = orgwidth * (value / 100);
var height = orgheight * (value / 100);
$('#cropbox').width(width);
$('#cropbox').height(height);
$('#rw').val(width);
$('#rh').val(height);
initJcrop();
}
I had the same task to accomplish: resize the image with a slider where jCrop is applied. There are some more elements you have to resize also that jCrop created, not only the image. I ended up patching the jCrop plugin and here is the patch for latest jCrop-0.9.10.
Patch your jCrop. If you don't know how to apply the patch, just put the resizeImage function to line 1578 of jCrop (unimified version ofcourse):
--- /home/dr0bz/Desktop/jquery.Jcrop.js
+++ /home/dr0bz/workspace/profile_tuning/js/lib/jquery.Jcrop.js
## -1573,6 +1573,15 ##
ui: {
holder: $div,
selection: $sel
+ },
+
+ resizeImage: function(width, height) {
+ boundx = width;
+ boundy = height;
+ $([$img2, $img, $div, $trk]).each(function(index, element)
+ {
+ element.width(width).height(height);
+ });
}
};
Get the jCrop API:
var jCropApi;
$('#photo').Jcrop({}, function()
{
jCropApi = this;
});
Calc new height and width. If your are doing it with a slider, let the slider say return the new width of the image and you calculate new height with aspect ratio of the image:
var aspectRatio = width / height;
// newWidth returned by slider
var newHeight = Math.round(width / aspectRatio);
jCropApi.resizeImage(newWidth, newHeight);
There are some other points to keep an eye on. After each resize your should look that crop area is still in the viewport of the image. If you need i could post the complete source how i've done it for me: jCrop + jquery ui slider to resize the image.
Regards
What you can also do is make use of the setImage function of Jcrop, when the slider changes, call the setImage with the Jcrop api and set new width and height values like this:
var jcrop_api;
$('#cropbox').Jcrop({
onSelect: updateCoords
}, function() {
jcrop_api = this;
});
$("#imageslider").slider({
value: 100,
max: 100,
min: 1,
slide: function(event, ui) {
var value = $('#imageslider').slider('option', 'value');
var width = orgwidth * (value / 100);
var height = orgheight * (value / 100);
jcrop_api.setImage($(img).attr("src"), function() {
this.setOptions({
boxWidth: width,
boxHeight: height
});
});
$('#tester').val("org: "+orgwidth+" now: "+width);
}
});
What I am not sure about this technique is if it is the best solution because everytime you call the setImage function, jcrop creates a new Image object.
If what you want is that the resizing should be proportional, I don't think you need the slider (since it seems to be incompatible with jCrop). You could use jCrop and in the onChange event, ensure the proportionality (that is, implement the resizeImage function, modified).
That's what I think.
As an extension to Hermann Bier answer, i have added the jquery animation.
The resizing looks way better when it's animated :)
Implemented in Jcrop version: jquery.Jcrop.js v0.9.12
Locate the code:
ui: {
holder: $div,
selection: $sel
}
in jquery.Jcrop.js around line 1573
and replace it with:
ui: {
holder: $div,
selection: $sel
},
resizeImage: function(width, height) {
animationsTid = 500;
boundx = width;
boundy = height;
$($img2).animate({
width: width,
height: height,
}, { duration: animationsTid, queue: false });
$($img).animate({
width: width,
height: height,
}, { duration: animationsTid, queue: false });
$($div).animate({
width: width,
height: height,
}, { duration: animationsTid, queue: false });
$($trk).animate({
width: width,
height: height,
}, { duration: animationsTid, queue: false });
/*
//Old way of resizing, but without animation
$([$img2, $img, $div, $trk]).each(function(index, element){
element.width(width).height(height);
});
*/
}
Call to the function will animate the resize.
Feel free to delete the code between /* */ - I just kept it as an reference
Happy Coding :)