I want to change this jsfiddle jsfiddle. It uses jQueryCountDown (http://plugins.jquery.com/countdown360/)
It currently rotates an outer ring, by one increment every second, but this shows as an anti-clockwise rotation of the ring as it counts downs.
I want the countdown to still rotate each second, but the direction of the outer ring rotation should be clockwise (currently the ring rotates anti-clockwise). Please see the example:
Example code:
var countdown = $("#countdown").countdown360({
radius: 60,
seconds: 20,
label: ['sec', 'secs'],
fontColor: '#FFFFFF',
autostart: false,
onComplete: function () {
console.log('done');
}
});
countdown.start();
$('#countdown').click(function() {
countdown.extendTimer(2);
});
That plugin is hard-coded to rotate anti-clockwise. I updated the original plugin so that it now has an option to have clockwise: true.
The new demo looks like this:
This example has one running clockwise and the second running normally (anti-clockwise):
JSFiddle: http://jsfiddle.net/TrueBlueAussie/gs3WY/246/
In the defaults I added clockwise:
defaults = {
...[snip]...
clockwise: false
};
In the start method I made it conditionally draw the "stroke" (the outer ring):
start: function () {
...[snip]...
this._drawCountdownShape(Math.PI * 3.5, !this.settings.clockwise);
...[snip]...
},
and in the _draw method I added a conditional calculation of the angle. Also when the timer ends, it conditionally draws the outer ring again based on the clockwise flag (previously it always redrew the entire outer ring before rendering the changes):
_draw: function () {
var secondsElapsed = Math.round((new Date().getTime() - this.startedAt.getTime()) / 1000);
if (this.settings.clockwise) {
var endAngle = (((Math.PI * 2) / this.settings.seconds) * secondsElapsed) - (Math.PI * .5);
} else {
var endAngle = (Math.PI * 3.5) - (((Math.PI * 2) / this.settings.seconds) * secondsElapsed);
}
this._clearRect();
if (secondsElapsed < this.settings.seconds) {
this._drawCountdownShape(Math.PI * 3.5, false);
this._drawCountdownShape(endAngle, true);
this._drawCountdownLabel(secondsElapsed);
} else {
this._drawCountdownShape(Math.PI * 3.5, this.settings.clockwise);
this._drawCountdownLabel(this.settings.seconds);
this.stop();
this.settings.onComplete();
}
}
You simply add a clockwise: true when you create the countdown:
var countdown = $("#countdown").countdown360({
radius: 60,
seconds: 20,
label: ['sec', 'secs'],
fontColor: '#FFFFFF',
autostart: false,
clockwise: true, // <<<<< Added this
onComplete: function () {
console.log('done');
}
});
Related
In JSXGraph I graph a plate (polygon) with 4 forces (arrows) acting on it. I intend to use the code for a variable number of forces (that's why it is more general than necessary for just 4 forces).
Force components can be shown and hidden. When a force arrow (not passing through the pivot point) is dragged, the "drag" event triggers an animation:
1st: showing the force and its arm, waiting for 2s
2nd: rotate the polygon in the direction of the force component (either clockwise or anti-clockwise).
Problem 1: The animation is slow and rough. I tried to use "suspendUpdate" and "unsuspendUpdate", but it made things even worse. Probably, I did not use it at the right place.
Problem 2: (probably related) I did not find a good way to clone the polygon for the animation. Or would it be best to store its coordinates? But if so, how would I reset the polygon (plus force arrow) to its original position after the rotation/animation?
My complete code is here: https://jsfiddle.net/bujowi/j1etgLsp/3/
You find the function called for the animation from line 244 onwards:
function animateRotation(x1, y1, x2, y2, sign)
Any comments and suggestions for improvements are welcome.
In the jsfiddle the animation appears to be rough since the the drag event is fired multiple times. Therefore, the animation runs in parallel multiple times. In the code below this is prevented by the flag is_animated. If true no new animation can be started.
A minor, more JSXGraph-ish issue is that the transformation is added to the JSXGraph elements in every step of the animation in setInterval. This may produce strange effects. It is much more clean to bind the transformation once to an element, but make the transformation dynamic, e.g. dependent on an angle variable:
var angle = 0.03;
let tRot = b1.create('transform', [function() { return sign * angle; }, pivot], { type: 'rotate' });
Additionally, this would make it possible to rotate the polygon back to the zero angle at the end of the animation. So, in setInterval only the angle variable is increased and the board is updated:
let idInterval = setInterval(function() {
angle += 0.03;
b1.update();
// ...
}, refreshTime);
Here is the complete new animation code (without rotating back at the end):
function animateRotation(x1, y1, x2, y2, sign) {
if (this.is_animated) {
return;
}
this.is_animated = true;
// Force arrow and arm (distance from pivot)
let Rot1 = b1.create('point', [x1, y1], { visible: false })
let Rot2 = b1.create('point', [x2, y2], { visible: false })
let rotArrow = b1.create('arrow', [Rot1, Rot2], { strokeColor: '#000', strokeWidth: 3, visible: true })
// Polygon
let PolyCopy = []
for (i = 0; i < poly_coord.length; i++) {
PolyCopy.push(b1.create('point', [poly_coord[i][0], poly_coord[i][1]], at))
}
let polyCopy = b1.create('polygon', PolyCopy, { strokeColor: myBlue, fillColor: myBlue })
// Hide all other force arrows
showAllElements(false)
// Show line of action and distance from pivot for 1s
let lineOfAction = b1.create('line', [[x1, y1], [x2, y2]], { strokeColor: '#000', strokeWidth: 2, dash: 1 })
let perpLine = b1.create('perpendicular', [lineOfAction, Pivot], { withLabel: false, visible: false })
let isecP = b1.create('intersection', [perpLine, lineOfAction, 0], { withLabel: false, visible: false })
let dist = b1.create('segment', [Pivot, isecP], { strokeColor: '#000', strokeWidth: 4 })
var that = this; // make "this" available in the interval function
// This is the animation: rotating the polygon for how many 'frames', refreshTime in ms
setTimeout(function() {
b1.removeObject(lineOfAction)
b1.removeObject(perpLine)
b1.removeObject(isecP)
b1.removeObject(dist)
var angle = 0.03;
let tRot = b1.create('transform', [function() { return sign * angle; }, pivot], { type: 'rotate' });
tRot.bindTo(PolyCopy);
tRot.bindTo([Rot1, Rot2]);
let frames = 0;
const refreshTime = 50;
let idInterval = setInterval(function() {
angle += 0.03;
b1.update();
if (frames++ > 20) {
that.is_animated = false;
b1.removeObject(polyCopy);
b1.removeObject(rotArrow);
showAllElements(true);
clearInterval(idInterval);
}
}, refreshTime)
}, 1000); // time for showing the line of action and distance
}
See it live at https://jsfiddle.net/fbdzx0ht/3/
Best wishes,
Alfred
I am utilizing FabricJs it is a javascript canvas library to make a small application where you can create shapes and animation between different objects.
To Run it You can follow the following steps.
Click new animation
Click Rectangle
Click Add Child button (This allows you to link objects)
Click Circle or Rectangle
If you follow the steps above you will see that you can create 2 shapes and animation between the two displayed by a small circle going back and forth.
I was wondering if it is possible to create similar animation that goes either left to right or right to left only once. I would really appreciate if someone can guide me.
Here is my FIDDLE
Here is the code for the animation
var animateBallBetweenObjects = function (obj1, obj2) {
// Add the "ball"
var circle = new fabric.Circle({
radius: 10,
fill: 'blue',
left: obj1.getCenterPoint().x,
top: obj1.getCenterPoint().y,
originX: 'center',
originY: 'middle',
selectable: false
});
canvas.add(circle);
var period = 1000;
var amplitude = 0;
var angle = 0;
var prevTime = Date.now();
var loop = function () {
// Calculate the new amplitude
var now = Date.now();
var elapsed = now - prevTime;
prevTime = now;
angle += Math.PI * (elapsed / (period * 0.5));
amplitude = 0.5 * (Math.sin(angle - (0.5 * Math.PI)) + 1);
// Set the new position
var obj1Center = obj1.getCenterPoint();
var obj2Center = obj2.getCenterPoint();
circle.setLeft(obj1Center.x + (amplitude * (obj2Center.x - obj1Center.x)));
circle.setTop(obj1Center.y + (amplitude * (obj2Center.y - obj1Center.y)));
canvas.renderAll();
requestAnimationFrame(loop);
}
// Animate as fast as possible
requestAnimationFrame(loop);
};
You can try yo use fabric built in animation:
http://jsfiddle.net/asturur/s6ju2858/2/
I did not replicate your loop function, that requires extra work, but fabricJS gives you the ability to define an animation for a property ( in our case left and top ) with a start and end value.
var animateBallBetweenObjects = function (obj1, obj2) {
var completedLeft, completedTop;
// obj1, obj2 are predefined.
var c1 = obj1.getCenterPoint();
var c2 = obj2.getCenterPoint();
var circle = new fabric.Circle({
radius: 10,
fill: 'blue',
left: c1.x,
top: c1.y,
originX: 'center',
originY: 'center',
selectable: false
});
canvas.add(circle);
circle.animate('left', c2.x, {
onChange: canvas.renderAll.bind(canvas),
startValue: c1.x,
endValue: c2.x,
onComplete: function() {
completedLeft = true;
completedTop && canvas.remove(circle);
},
easing: fabric.util.ease['easeInQuad']
}).animate('top', c2.y, {
startValue: c1.y,
endValue: c2.y,
onChange: canvas.renderAll.bind(canvas),
onComplete: function() {
completedTop = true;
completedLeft && canvas.remove(circle);
},
easing: fabric.util.ease['easeInQuad']
});
};
Updated fiddle with ball removal at the end of animation.
I'm learning the phaser framework for games right now: http://phaser.io
This is example demonstrates multiple sprites coming in from the left hand side of the screen. I'm just trying to figure out how to get them to come in from the right. There's something I'm missing.
The working example can be seen here: http://examples.phaser.io/_site/view_full.html?d=sprites&f=add+several+sprites.js&t=add%20several%20sprites
code:
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload:preload, create: create, update: update });
var timer = 0;
var total = 0;
function preload() {
// 37x45 is the size of each frame
// There are 18 frames in the PNG - you can leave this value blank if the frames fill up the entire PNG, but in this case there are some
// blank frames at the end, so we tell the loader how many to load
game.load.spritesheet('mummy', 'assets/sprites/metalslug_mummy37x45.png', 37, 45, 18);
}
function create() {
releaseMummy();
}
function releaseMummy() {
var mummy = game.add.sprite(-(Math.random() * 800), game.world.randomY, 'mummy');
mummy.scale.setTo(2, 2);
// If you prefer to work in degrees rather than radians then you can use Phaser.Sprite.angle
// otherwise use Phaser.Sprite.rotation
mummy.angle = game.rnd.angle();
mummy.animations.add('walk');
mummy.animations.play('walk', 20, true);
game.add.tween(mummy).to({ x: game.width + (1600 + mummy.x) }, 20000, Phaser.Easing.Linear.None, true);
total++;
timer = game.time.now + 100;
}
function update() {
if (total < 200 && game.time.now > timer)
{
releaseMummy();
}
}
you could set sprite position far to the right after the game bounds.
var mummy = game.add.sprite(800 + (Math.random() * 800), game.world.randomY, 'mummy');
and tween far to the left after the game bounds.
game.add.tween(mummy).to({ x: -(1600 + mummy.x) }, 20000, Phaser.Easing.Linear.None, true);
FIDDLE DEMO
I can't figure out how to get the current rotation angle of an arch in jCanvas. layer.rotate only seems to provide me with the original setting of rotate, when I'd really like to change its behavior when it hits a certain angle.
I have an example setup on jsfiddle to demonstrate the problem.
Any insight would be appreciated.
are you looking for this value $('#rot').val()
while (i < 1000) {
setTimeout(function() { rotate() }, 1000);
alert( $('#rot').val());
i += 1;
}
The animateLayer() and animateLayerGroup() methods support the same alternate syntax as jQuery's animate() method, which allows for a step callback:
// Cache canvas element
var $canvas = $("canvas");
// Draw and animate
$canvas.drawArc({
layer: true,
name: 'arcy',
fillStyle: "#000",
x: 100, y: 100,
radius: 50,
start: 135, end: 45
});
$canvas.animateLayer('arcy', {
rotate: 360
}, {
// Use the step callback to run a function on every frame
step: function(now, fx, layer) {
console.log(layer.rotate);
}
});
I have t his effect on this website
http://www.immersive-garden.com/
there's this point of light sparking, on hover you get the background, I want something similar without using flash
this is the script I'm using right now
/*
Particle Emitter JavaScript Library
Version 0.3
by Erik Friend
Creates a circular particle emitter of specified radius centered and offset at specified screen location. Particles appear outside of emitter and travel outward at specified velocity while fading until disappearing in specified decay time. Particle size is specified in pixels. Particles reduce in size toward 1px as they decay. A custom image(s) may be used to represent particles. Multiple images will be cycled randomly to create a mix of particle types.
example:
var emitter = new particle_emitter({
image: ['resources/particle.white.gif', 'resources/particle.black.gif'],
center: ['50%', '50%'], offset: [0, 0], radius: 0,
size: 6, velocity: 40, decay: 1000, rate: 10
}).start();
*/
particle_emitter = function (opts) {
// DEFAULT VALUES
var defaults = {
center: ['50%', '50%'], // center of emitter (x / y coordinates)
offset: [0, 0], // offset emitter relative to center
radius: 0, // radius of emitter circle
image: 'particle.gif', // image or array of images to use as particles
size: 1, // particle diameter in pixels
velocity: 10, // particle speed in pixels per second
decay: 500, // evaporation rate in milliseconds
rate: 10 // emission rate in particles per second
};
// PASSED PARAMETER VALUES
var _options = $.extend({}, defaults, opts);
// CONSTRUCTOR
var _timer, _margin, _distance, _interval, _is_chrome = false;
(function () {
// Detect Google Chrome to avoid alpha transparency clipping bug when adjusting opacity
if (navigator.userAgent.indexOf('Chrome') >= 0) _is_chrome = true;
// Convert particle size into emitter surface margin (particles appear outside of emitter)
_margin = _options.size / 2;
// Convert emission velocity into distance traveled
_distance = _options.velocity * (_options.decay / 1000);
// Convert emission rate into callback interval
_interval = 1000 / _options.rate;
})();
// PRIVATE METHODS
var _sparkle = function () {
// Pick a random angle and convert to radians
var rads = (Math.random() * 360) * (Math.PI / 180);
// Starting coordinates
var sx = parseInt((Math.cos(rads) * (_options.radius + _margin)) + _options.offset[0] - _margin);
var sy = parseInt((Math.sin(rads) * (_options.radius + _margin)) + _options.offset[1] - _margin);
// Ending Coordinates
var ex = parseInt((Math.cos(rads) * (_options.radius + _distance + _margin + 0.5)) + _options.offset[0] - 0.5);
var ey = parseInt((Math.sin(rads) * (_options.radius + _distance + _margin + 0.5)) + _options.offset[1] - 0.5);
// Pick from available particle images
var image;
if (typeof(_options.image) == 'object') image = _options.image[Math.floor(Math.random() * _options.image.length)];
else image = _options.image;
// Attach sparkle to page, then animate movement and evaporation
var s = $('<img>')
.attr('src', image)
.css({
zIndex: 10,
position: 'absolute',
width: _options.size + 'px',
height: _options.size + 'px',
left: _options.center[0],
top: _options.center[1],
marginLeft: sx + 'px',
marginTop: sy + 'px'
})
.appendTo('body')
.animate({
width: '1px',
height: '1px',
marginLeft: ex + 'px',
marginTop: ey + 'px',
opacity: _is_chrome ? 1 : 0
}, _options.decay, 'linear', function () { $(this).remove(); });
// Spawn another sparkle
_timer = setTimeout(function () { _sparkle(); }, _interval);
};
// PUBLIC INTERFACE
// This is what gets returned by "new particle_emitter();"
// Everything above this point behaves as private thanks to closure
return {
start:function () {
clearTimeout(_timer);
_timer = setTimeout(function () { _sparkle(); }, 0);
return(this);
},
stop:function () {
clearTimeout(_timer);
return(this);
},
centerTo:function (x, y) {
_options.center[0] = x;
_options.center[1] = y;
},
offsetTo:function (x, y) {
if ((typeof(x) == 'number') && (typeof(y) == 'number')) {
_options.center[0] = x;
_options.center[1] = y;
}
}
}
};
you probably need something like this: http://www.realcombiz.com/2012/09/customize-blackquote-with-light-bulb.html