Hi guys I am having trouble animating a stroke on an SVG where I only want it to be a 3/4 circle as the math is more complex!
Basically I want to pass a percentage in a function (0-100) and have the line animate to the correct place. So 33% would show one quarter of the stoke in green and 100% would show 3/4 of the stoke in green.
I have a pen here and you can change the offset in the JS animate to get different results.
$(".percentage").animate({"stroke-dashoffset":"78"}, 3000);
so "78" would be 100% and "314" would be 0% but I am lost at how I can map this!
CodePen Demo
Any help is appreciated!
var length= 314-78;
fuction toPercentage (number){
return Math.round(((314-number)/length)*100);
}
This was how I did it...
https://codepen.io/anon/pen/kkWRPg
function percentage($percent) {
var offsets = 314.1593 - ($percent * 2.3562);
return offsets;
}
var offset = percentage(75);
$(".percentage").animate({"stroke-dashoffset":offset}, 3000);
0% : radius*2*3.14 (318)
100% : 0 (full circle) (0)
75% : radius*2*3.14*(1-75%) (78)
So you need radius*2*3.14*(1-P*75%) for your result
for example, you need 318*0.5*0.75 for 50%
Here is the (hope it's easy to understand) function for you
function percentage($percent) {
var arc = 0.75;
var radius = 50;
var min = radius*2*3.14/*PI*/;
var max = min*(1-arc);
var multiplier = $percent/100;
var position = min+(max-min)*multiplier;
return position;
}
var offset = percentage(100);
$(".percentage").animate({"stroke-dashoffset":offset}, 3000);
Related
I'm having an issue with snap.svg where whenever I animate a rotation between 269 and 270 degrees the whole thing spins around the entire circle instead of advancing a single degree. Here is a minimal code snippet that recreates the problem:
function testRotation() {
var draw = Snap('#test');
var box = draw.rect(0, 0, 100, 161.5);
var rotation = 268;
var increment = 1;
var transform = 't200,200r'+rotation+',50,80.75';
console.log(transform)
box.attr({
fill: '#000000',
transform: transform});
function rotate() {
if (rotation > 271) increment = -1;
if (rotation < 269) increment = 1;
rotation += increment;
var transform = 't200,200r'+rotation+',50,80.75';
console.log(rotation);
box.animate({transform: transform}, 1000);
setTimeout(rotate, 1000);
}
setTimeout(rotate, 1000)
}
Here is a JSFiddle version where you can see it in action: http://jsfiddle.net/qsmzexut/2/
It starts at 268 degrees and then every second it increases the angle by one degree. When it passes from 269 to 270 it goes all the way around. When it gets up to 272 it goes back down, then back up etc. As you can see this behavior is present in both directions.
Any way to avoid this behavior? I would love to be able to rotate a single degree and not have it swing around the entire circle! Thanks.
in order to move it a bit each time - rotation = rotation - increment;
I'm working on a gradient stroke for a "loading circle" using createJS. However, I only need the gradient effect to be applied on one "joining point" of the two colors, and not apply it on the other joining point.
What I did was this, but it's only giving me a normal gradient effect:
var rd = 64;
timerCount.graphics.setStrokeStyle(8)
/* yellow ,red*/
.beginLinearGradientStroke( ["#F7CC00","#FE1D1E"] ,[0,1] ,0,rd*0.5 ,0,-rd );
Please refer to the image below:
Anyone knows how I can do this?
Here's my code in JSFiddle:
https://jsfiddle.net/flamedenise/gg9aabug/18/
Thank you and Happy New Year ahead!
You are not looking for a radial gradient, but rather a conical gradient (or angle gradient in Photoshop), which Canvas does not support directly. I did a quick search on Angle Gradients, and found a few ideas that might help:
http://www.nixtu.info/2010/08/html5-canvas-gradients-angular-gradient.html
https://gist.github.com/akm2/3721702
Angle gradient in canvas
Best of luck.
I have managed to create a workaround to achieve this! Since beginLinearGradientStroke() only creates a "normal" gradient, I figured out overlaying it with another gradient (with transparent as the second color) would work.
What I did was create the first circle with two colors that appear as "solid" (by setting the ratios and x and y positions accordingly) and then overlaid it with another gradient circle - with one color the combination of the first two colors, and the other one transparent.
Here's the JSFiddle showing the final outcome:
https://jsfiddle.net/flamedenise/n9no9Lgw/
var rd = 64;/*radius*/
var circles = {};
var ic = [
/*0*/{ a:"#FEC331" ,b:"#FB1E24" ,r1:0.5 ,r2:0.5 ,x0:0 ,y0:rd*0.3 ,x1:0 ,y1:-rd},
/*1*/{ a:"#EA6F2B" ,b:"transparent" ,r1:0 ,r2:1 ,x0:-rd ,y0:0 ,x1:rd ,y1:0 }
];
var circleX = [ 0.5 ,0.75 ];
var circleY = [ 0.7 ,0.7 ];
for(var i=0; i<2; i++){
circles[l][i] = new createjs.Shape();
circles[l][i].graphics.setStrokeStyle(8)
.beginLinearGradientStroke( [ ic[k].a ,ic[k].b ], [ic[k].r1, ic[k].r2], ic[k].x0,ic[k].y0 ,ic[k].x1,ic[k].y1 );
circles[l][i].rotation = -90;
circles[l][i].x = ww*circleX[l];
circles[l][i].y = wh*circleY[l];
var arcCommand = circles[l][i].graphics.arc(0, -20, rd, 600 * Math.PI, 0).command;
if (run == 1) {
createjs.Tween.get(arcCommand)
.to({
endAngle: (360 * Math.PI / 180)
}, time * 1000);
}
circleStage.addChild(circles[l][i]);
}/*END for loop*/
I am trying to implement charts using Dimple.js and below is the code that i am trying to animate both the series (Bar and Line here) separately but it looks like line series animates like bar series (from bottom to top). However, i was expecting more like animation performed in here: http://bl.ocks.org/duopixel/4063326
<div id="divBarWithLineChart" class="DimpleChart"></div>
var width = $('#divBarWithLineChart').width();
var height = $('#divBarWithLineChart').height();
var svg = dimple.newSvg("#divBarWithLineChart", width - 20, height);
d3.json("Scripts/Data/Data.json", function (data) {
// Filter the data for a single channel
data = dimple.filterData(data, "Channel", "Hypermarkets");
// Create the chart
var myChart = new dimple.chart(svg, data);
myChart.setBounds(60, 30, 470, 300)
// Add an x and 2 y-axes. When using multiple axes it's
// important to assign them to variables to pass to the series
var x = myChart.addCategoryAxis("x", "Brand");
var y1 = myChart.addMeasureAxis("y", "Price");
var y2 = myChart.addMeasureAxis("y", "Sales Value");
// Order the x axis by sales value desc
x.addOrderRule("Sales Value", true);
// Color the sales bars to be highly transparent
myChart.assignColor("Sales", "#222222", "#000000", 0.1);
// Add the bars mapped to the second y axis
myChart.addSeries("Sales", dimple.plot.bar, [x, y2]);
// Add series for minimum, average and maximum price
var min = myChart.addSeries("Min", dimple.plot.line, [x, y1]);
min.aggregate = dimple.aggregateMethod.min;
myChart.setMargins("70px", "30px", "70px", "70px");
myChart.assignColor("Sales", "#083f65", "#083f65", 1);
myChart.assignColor("Min", "#c62828", "#c62828", 1);
myChart.staggerDraw = true;
myChart.ease = "bounce";
myChart.draw(1000);
Is it possible to animate line series separately? Can anyone please help?
Thanks in advance...
Yes this is possible. If you inspect the svg line in the chrome developer bar, it's an svg path which can be animated with css...the path class name is dimple-line. So just add a bit of css for this class name and when the line is drawn it mimicks the d3 example exactly (tried it at my site http://dimplejs.org) and it worked perfectly...
<style>
.dimple-line {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: dash 5s linear forwards;
}
#keyframes dash {
to {
stroke-dashoffset: 0;
}
}
</style>
or for a dashed effect try this...
.dimple-line {
stroke-dasharray: 20;
stroke-dashoffset: 1000;
animation: dash 5s linear forwards;
}
#keyframes dash {
to {
stroke-dashoffset: 0;
}
}
See this site for other variations of this technique...https://css-tricks.com/svg-line-animation-works/
I'm making a game in Phaser using some large images that I want to scale down in the actual game:
create() {
//Create the sprite group and scale it down to 30%
this.pieces = this.add.group(undefined, "pieces", true);
this.pieces.scale.x = 0.3;
this.pieces.scale.y = 0.3;
//Add the players to the middle of the stage and add them to the 'pieces' group
var middle = new Phaser.Point( game.stage.width/2, game.stage.height/2);
var player_two = this.add.sprite(middle.x - 50, middle.y, 'image1', undefined, this.pieces);
var player_one = this.add.sprite(middle.x, middle.y-50, 'image2', undefined, this.pieces);
}
However because the sprites are scaled in size, their starting location is also scaled, so instead appearing in the middle of the stage, they appear only 30% of the distance to the middle.
How do I scale the sprite image without it affecting their location?
(The code is incidentally in Typescript but I think this particular sample is also javascript so that's probably irrelevant)
Set Sprite.anchor to 0.5 so the physics body is centered on the Sprite, scale the sprite image without it affecting their location.
this.image.anchor.setTo(0.5, 0.5);
Doc Phaser.Image
Anchor example
You can scale your sprite like so:
var scaleX = 2;
var scaleY = 2;
sprite.scale.set(scaleX, scaleY);
then calculate position of sprite:
var positionX = 100;
var positionY = 100;
sprite.x = positionX / scaleX;
sprite.y = positionY / scaleY;
Now your sprite is at position (100, 100).
The problem is that sprite.x got multiplied by with scaleX.
Regarding Phaser, I'd like to add that in the specific case of weapon.bullets or other groups you create yourself you're going to have to do it this way instead:
weapon.bullets.setAll('scale.x', 0.5);
weapon.bullets.setAll('scale.y', 0.5);
I got stuck on this and ended up in this thread, which is closed but in my case just not what I needed. Others will hopefully have some use out of this :)
i'm trying to rotate a square in canvas by javascript using rotation matrix.
here is my code.
function square() {
this.cord=[[0,0],[-25,25],[25,25],[25,-25],[-25,-25]];
}
var a=new square();
function rotate() {
var cos=Math.sqrt(2)/2;
var sin=Math.sqrt(2)/2;
for(var j=0;j<a.cord.length;j++) {
a.cord[j][0]=a.cord[j][0]*cos-(a.cord[j][1])*sin;
a.cord[j][1]=a.cord[j][1]*cos+(a.cord[j][0])*sin;
}
}
but weird things happen and the square shrinks gradually and it doesn't rotate correctly.
what's wrong with my code??
You need to pull out the values a.cord[j][0] and a.cord[j][1] before calculating. Your calculation of a.cord[j][1] is based on the freshly-calculated new value, not the original one.
So:
for(...)
{
var x = a.cord[j][0];
var y = a.cord[j][1];
a.cord[j][0] = x*cos - y*sin;
a.cord[j][1] = y*cos + x*sin;
}