KineticJs different angle rotation - javascript

i am using the latest version of kineticJs, right now I am doing puzzle games, which requires my puzzle pieces to rotate after scramble, anyone have any idea how to rotate different angle and not 2-3 pieces rotate of the same angle? thanks :)
fillPatternImage:imageObj,
fillPatternOffsetX :i * pieceWidth,
fillPatternOffsetY :j * pieceHeight,
stroke: "#000000",
strokeWidth: 4,
lineCap: "round",
rotation : Math.PI * 28.5 * Math.floor(Math.random() * 2), <-- rotation part
draggable: true,
offset : [ pieceWidth / 2 + pieceWidth * 0.3,pieceHeight / 2 + pieceHeight * 0.3 ],
x:0+ (Math.random()*6)*((stage.getWidth()+pieceWidth)/16),
y:0+ (Math.random()*4)*((stage.getHeight()+pieceHeight)/16),
My fiddle : http://jsfiddle.net/e70n2693/34/

the code Math.floor(Math.random() * 2) gives either 0 or 1, which is then multiplied by PI*28.5, giving either a rotation of 0 or PI*28.5.
increase the multiplier of Math.random() to desired number of possible rotations.
you may have to change the value multiplying PI also to give a better spread of possible angles (reduce it)
something like below should give a wider range of results
var numberOfDifferentAngles = 50;
var differenceBetweenAngles = Math.PI * 2;
rotation : differenceBetweenAngles
* Math.floor(Math.random() * numberOfDifferentAngles ),

Related

JavaScript: Math.atan2 issue

Let's say I have an arbitrary polar coordinate:
let pc = {theta: 3.1544967, radius: 0.8339594};
Need to do some Cartesian math with that and transform it back to polar one.
However, I have noticed that if I just do this code:
const pc = {theta: 3.1544967, radius: 0.8339594};
let v = {x: pc.radius * Math.cos(pc.theta), y: pc.radius * Math.sin(pc.theta)};
console.log(pc.theta, Math.atan2(v.y, v.x), pc.radius, Math.sqrt(Math.pow(v.x, 2.0) + Math.pow(v.y, 2.0)));
The difference between original theta (3.1544967) and converted back (-3.1286886071795865) is a positive PI and it doesn't really fit Wikipedia conditions (https://en.wikipedia.org/wiki/Atan2#Definition_and_computation), while both v.x and v.y are negative, so atan2 have to be atan(y / x) - PI. And it's anyway -2.356194490192345.
What I should do to get 3.1544967 back?
The function Math.atan2 returns a number in the range
-pi <= result <= pi. The result you expect is not in that range.
Here is an example that calculates how many 2PIs need to be subtracted to get the input number within the negative pi to pi range.
Once atan2 calculates the angle, you can add that many 2PIs back on to get your expected result.
const pc = {theta: 3.1544967, radius: 0.8339594};
let v = {x: pc.radius * Math.cos(pc.theta), y: pc.radius * Math.sin(pc.theta)};
let m = Math.round(pc.theta / (Math.PI * 2));
console.log(pc.theta, Math.atan2(v.y, v.x) + Math.PI * 2 * m, pc.radius, Math.sqrt(Math.pow(v.x, 2.0) + Math.pow(v.y, 2.0)));

Calculate coordinates for 45 degree snap

I have a SVG that draws a line between an origin point and the mouse pointer, what i'd like to do is when shift is depressed (event.shiftKey === true) make the line "snap" to the nearest 45 degree coordinate, the same behaviour you get in photoshop basically.
I've managed to work out the angle in degrees between the two points (so i can decide which angle to snap too, probably using an IF/ELSE tree if needs be) however I don't know how i re-calculate the "end" coordinates based on the new degree's.
I've set up a simplified example here: https://jsbin.com/sohafekije/2/edit?html,js,output
I've also taken a photo of the photoshop behaviour i'm trying to recreate (quality is poor as i had to use a camera as i couldn't screenshot - sorry) just to be 100% clear: http://i.imgur.com/Yo04uxY.jpg
Essentially i'm trying to recreate the behaviour you get in photoshop when you hold the shift key, but my guess is you need to be pretty good with Maths to work out a solution, and i'm not!
Any help is greatly appreciated :)
var app = document.getElementById('app'),
svg = SVG(app),
line = svg.polyline([]).fill('none').stroke({ width: 1 }),
start = [250,250],
end = null,
angleTxt = document.getElementById('angle'),
lineLengthTxt = document.getElementById('linelength');
line.marker('start', 10, 10, function(add) {
add.circle(10).fill('#f06')
})
// On mouse move, redraw the line
svg.on('mousemove', function(e){
end = [e.layerX, e.layerY];
line.plot([start, end]);
calcAngle();
});
function calcAngle() {
var deltaX = end[0] - start[0],
deltaY = end[1] - start[1],
rad = Math.atan2(deltaY, deltaX),
deg = rad * (180/Math.PI),
linelen = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
angleTxt.textContent = deg;
lineLengthTxt.textContent = linelen;
}
#app { border: 1px solid blue; width:100%; height:600px}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script type="text/javascript" src="https://rawgit.com/svgdotjs/svg.js/master/dist/svg.js"></script>
</head>
<body>
<div id="app"></div>
Angle: <span id="angle">-</span><br>
Line Length: <span id="linelength">-</span>
</body>
</html>
I did it !
How use it
You compute the new angle and apply it using cosinus for x value and sinus for y value. Here the angle got to -PI to PI with step of PI/4; If you want to change the step replace 4 in the line 'var newAngle = ...' by other number.
How it's works
First I was thinking about the fact that you need 8 angle position, 4 by PI rad (a cirlce is 2PI rad). So you need to simplify your angle.
newAngle / Math.PI // value is between -1 and 1 (it's a double)
newAngle / Math.PI * 4 // value is between -4 and 4 (it's a double)
Math.round(newAngle / Math.PI * 4) // value is between -4 and 4 (but it's a integer now)
Math.round(newAngle / Math.PI * 4) / 4 // value is between -1 and 1 (with step of 0.25)
Math.round(newAngle / Math.PI * 4) / 4 * Math.PI // value is between -PI and PI with step of 0.25 * PI (PI/4)
Now your new angle is correct. Cosinus return the x value of the angle (look at wikipedia for a graphic explanation) and Sinus the y value of the angle.
By multiplying the COSINUS/SINUS by the length you find the next point.
 
function applyNewAngle() {
var deltaX = end[0] - start[0],
deltaY = end[1] - start[1],
dist = Math.sqrt(Math.pow(deltaX,2) + Math.pow(deltaY,2));
var newAngle = Math.atan2(deltaY, deltaX);
var shiftedAngle = Math.round(newAngle / Math.PI * 4) / 4 * Math.PI;
end = [start[0]+dist*Math.cos(shiftedAngle), start[1]+dist*Math.sin(shiftedAngle)];
}

Custom angular circular progress bar SVG User Interface

I have developed my circular progress bar from angular-circular-progress github.
My current input was:
I need to modify the end of the progress bar with a small CIRCLE and a VALUE CENTRE of the circular progress bar with real animation value based on svg movement. How I can do that? I really need help from you all guys.
My expected output should be:
My current snippet:
angular.module('myModule', ['angular-circular-progress'])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="http://pencil.my/assets/js/circularProgress.js"></script>
<div ng-app="myModule">
<circular-progress
value="80"
max="100"
orientation="1"
radius="100"
stroke="10"
base-color="#fff"
progress-color="#f9991d"
iterations="100"
animation="easeInOutCubic"
></circular-progress>
</div>
Have you look at ProgressBar.js ?
var bar = new ProgressBar.Circle(container, {
enter code herecolor: '#aaa',
// This has to be the same size as the maximum width to
// prevent clipping
strokeWidth: 4,
trailWidth: 1,
easing: 'easeInOut',
duration: 1400,
text: {
autoStyleContainer: false
},
from: { color: '#aaa', width: 1 },
to: { color: '#333', width: 4 },
// Set default step function for all animate calls
step: function(state, circle) {
circle.path.setAttribute('stroke', state.color);
circle.path.setAttribute('stroke-width', state.width);
var value = Math.round(circle.value() * 100);
if (value === 0) {
circle.setText('');
} else {
circle.setText(value);
}
Here is a Fiddle
Regards,
Alex
Create a group that has a transparent object the size of your circle and has the small circle at one edge, then rotate that group around its center. The internals of the SVG would look something like
<g id="pip" transform="rotate({{360/value}}, 50, 50)">
<!--contents of g-->
</g>
This assumes the diameter of the circle is 100.
Here is a function that converts a number from 0 to 100 into the x,y coordinates needed to give the circle object (drawn with canvas tools) a circular path:
function drawCircle(percentage, ctx) {
var angle = percentage / 100.0;
var xPos = 140 * Math.cos((angle * (2 * Math.PI)) - (Math.PI * .5));
var yPos = -140 * Math.sin((angle * (2 * Math.PI)) - (Math.PI * .5) );
ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
ctx.beginPath();
ctx.arc (xPos + 150, 150 - yPos, 10, 0, 2 * Math.PI);
ctx.stroke();
}
Look at this plunker to see it in action:
https://plnkr.co/edit/ePMK7DVLB3OH15oUJzr1?p=preview
This takes the number (from 0 to 100), scales it, converts it to radians, then converts the radians to cartesian coordinates.

Getting "%" into javascript output

could someone please help a complete javascript noob? My google-fu seems to be completely lacking...
I'm trying to convert this...
var $win = jQuery(window),
w = 0,h = 0,
sgcolour = [],
getWidth = function() {
w = $win.width();
h = $win.height();
};
$win.resize(getWidth).mousemove(function(e) {
sgcolour = [
Math.round(e.pageX/w * 255),
Math.round(e.pageY/h * 255),
150,
1
];
jQuery(document.body).css('background','rgba('+sgcolour.join(',')+')');
}).resize();
Here on jsfiddle
from rgba to hsla, with x-axis as hue, y as saturation, & other values fixed.
I think I've got the obvious (change 'rgba', set values from thos appropriate to rgba to those appropriate to hsla), but can't for the life of me work out how to get it to output "%" after the required values...
I hoped I'd be able to work it out for myself, but I'm not sure if I even know enough about it to google the right questions :/
int/int results as an int (so 0 or 1).
You should multiply before dividing:
Math.round(e.pageX * 255 / w),
Math.round(e.pageY * 255 / h),
And you wouldn't need to Round the value, since it's of type int.
(e.pageX * 255 / w),
(e.pageY * 255 / h),
If it's just a string, you can just concatenate '%', so I'm not really sure what the problem is:
...
sgcolour = [
Math.round(e.pageX/w * 360),
Math.round(e.pageY/h * 100) + '%',
'50%',
1
];
jQuery("body").css('background','hsla('+sgcolour.join(',')+')');
Note that this is not a direct conversion at all. If you want it to do that then I would suggest using your current rgb method and then converting it to hsl afterwards.

Raphael custom attribute (Arc) results in deformed circle

I am working on a progress bar plugin for jQuery that utilizes Raphael for smooth graphics.
I tried to transform the attribute function provided by this Raphael example (polar clock).
The problem is, that at first I didn't notice that the Raphael example also has the deformation error there. Relatively larger circles just mitigate it. Looking at smaller ones, it is noticeable.
And yes, I have basicly copy-pasted the function with some minor tweaks, but the end result sport the same error.
I have set up a JSBin where I've added reference circles to my scene, so it's easier to spot the issue: http://jsbin.com/ekovir/1
How do I tune the Arc function to draw proper circle?
I think it's a bug in Chrome's SVG rendering implementation. At least in FireFox and Safari it looks much better.
Also, when selecting the arc-to point, I think it's better to use (center.x + radius * cos(a-0.01), center.y + radius * sin(a-0.01)), instead of (center.x + radius * cos(a) - 0.01, center.y + radius * sin(a)), otherwise the center may shift a bit.
As a workaround, I suggest creating one set of segments for the progress bar and then changing their color as the work is done, instead of drawing new ones over the old. This should look fine in any browser, and I don't think the defects are easy to spot without the contrasting background circle.
I have found what caused the circle to be deformed.
I used stroke-width to set the "fatness" / "cap" of the circle, and the larger it gets, the more it deforms.
At least, those are my observations, it could as well technically be caued by something else.
Anyways, in order to get proper donut, I ended up with this method:
/**
* Donut circle drawing
*
* #param integer start Percentage to start with
* #param float diameter
* #param float fat How fat should the circle bar be
* #return object
*/
var fatDonutArc = function (start, diameter, fat)
{
var center = diameter / 2;
var outerRadius = center;
var innerRadius = center - fat; // subtract fat
var alpha = 360 / 100 * start;
var a = (90 - alpha) * Math.PI / -180; // -180 starts to draw from 12 o'clock
// calculate outer ring point coordinates
var outerX = center + outerRadius * Math.cos(a);
var outerY = center + outerRadius * Math.sin(a);
// calculate inner ring point coordinates
var innerX = center + innerRadius * Math.cos(a);
var innerY = center + innerRadius * Math.sin(a);
// path cache
var path;
if (start !== 100)
{
path = [
// move to start point of inner ring
[
"M",
center,
center - innerRadius
],
// draw a line to outer ring
[
"L",
center,
center - outerRadius
],
// arc to outer ring end
[
"A",
outerRadius,
outerRadius,
0,
+(alpha > 180),
1,
outerX,
outerY
],
// move to inner ring end
[
"L",
innerX,
innerY
],
// arc to inner ring start
[
"A",
innerRadius,
innerRadius,
0,
+(alpha > 180),
0,
center,
center - innerRadius
]
];
}
else
{
path = [
// move to outer ring start
[
"M",
center,
center - outerRadius
],
// arc around the clock
[
"A",
outerRadius,
outerRadius,
0,
+(alpha > 180),
1,
outerX - .1, // subtract, otherwise the path becomes "reset"
outerY
],
// connect
[
"z"
],
// move to inner circle start
[
"M",
innerX,
innerY
],
// arc around the clock
[
"A",
innerRadius,
innerRadius,
0,
+(alpha > 180),
0,
innerX + .1, // subtract, otherwise the path becomes "reset"
innerY
],
// and connect
[
"z"
]
];
}
return {
path : path
};
};
That's a mashup of: raphael.js - converting pie graph to donut graph + http://raphaeljs.com/polar-clock.html
Here I have set up an example, to see it in action: http://jsbin.com/erusos/1
There still is one unanswered question: In Chrome, is it the CSS renderer, that doesn't fully round the circle, or is it the SVG?
Enjoy!

Categories