Javascript: Set variable to either 1 or -1 - javascript
I'm trying to get an object that moves in a different direction when you click on it, and each time you click on it it goes faster. I have it almost functioning, but I can't get the program to exclude 0 or do only -1 or 1; I can only do a random number between -1 and 1. This means that if it hits zero, it can't progress.
(The following code is built with a Javascript engine called "Crafty". Non-javascript parts are commented as best as I can.)
Crafty.init(400,320, document.getElementById('game')); // Creates canvas
// Create variables
var speed = 10;
var min = -1;
var max = 1;
// Create a 32px by 32px red box
var square = Crafty.e('2D, Canvas, Color, Mouse, Motion')
.attr({x: 50, y: 50, w: 32, h: 32})
.color('red')
// When the red box is clicked, move it in a random direction. Make it go faster each time.
.bind('Click', function(MouseEvent){
speed *= 2;
var vel = square.velocity();
var direction = ((Math.random() * (max - min)) + min);
vel.x;
vel.y;
vel.x = (speed *= direction);
vel.y = (speed *= direction);
});
Change to this line
var direction = (Math.random()) > .5 ? 1 : -1;
It really comes down to this line:
var direction = ((Math.random() * (max - min)) + min);
If you store the acceptable values (-1 and 1) in an array, you can make the random choose one of those based on the length of the array. By storing the values in an array, you not only make the process simpler, but it is extensible because you can always add new values later, if desired.
function getRandom(){
var acceptable = [-1, 1];
// Get a random number from 0 to 1 (the length of the array, 2, will never be reached)
var direction = Math.floor(Math.random() * acceptable.length);
console.log(acceptable[direction]); // Choose either array element 0 or element 1
}
// Run this code snippet a few times and you'll see that you only get -1 and 1
getRandom();
getRandom();
getRandom();
getRandom();
You can also remove the two lines declaring the max and min variables as they are no longer needed.
Related
Furthest Building You Can Reach Algorithm - JavaScript
I'm trying to create a solution for the problem below in JavaScript. You are given an integer array heights representing the heights of buildings, some bricks, and some ladders. You start your journey from building 0 and move to the next building by possibly using bricks or ladders. While moving from building i to building i+1 (0-indexed), If the current building's height is greater than or equal to the next building's height, you do not need a ladder or bricks. If the current building's height is less than the next building's height, you can either use one ladder or (h[i+1] - h[i]) bricks. Return the furthest building index (0-indexed) you can reach if you use the given ladders and bricks optimally. Input: heights = [4,2,7,6,9,14,12], bricks = 5, ladders = 1 Output: 4 Explanation: Starting at building 0, you can follow these steps: - Go to building 1 without using ladders nor bricks since 4 >= 2. - Go to building 2 using 5 bricks. You must use either bricks or ladders because 2 < 7. - Go to building 3 without using ladders nor bricks since 7 >= 6. - Go to building 4 using your only ladder. You must use either bricks or ladders because 6 < 9. It is impossible to go beyond building 4 because you do not have any more bricks or ladders. My naive solution: var furthestBuilding = function(heights, bricks, ladders) { let pos = 0; while(pos < heights.length) { if(pos === heights.length - 1) break; if(heights[pos+1] > heights[pos]) { const distance = heights[pos+1] - heights[pos]; if(distance <= bricks) bricks -= distance; else if(ladders > 0) ladders--; else break; } pos++; } return pos; }; It does return the expected result for the example above. However, it fails for the input below. heights = [1,5,1,2,3,4,10000] bricks = 4 ladders = 1 My output is 3, but the solution should be 5. Input that crashes for the recursive solution. heights = [253710,459585,71981,223232,977918,148680,123527,250812,260416,554767,473621,88538,966794,644116,865416,590993,550004,374573,105036,568303,460987,24602,757598,519047,263800,315868,963895,266638,598245,713310,489802,364169,742274,973483,807739,253747,564636,472387,598445,675408,626061,527760,922748,244691,41163,108095,953208,54400,191957,182321,801110,526756,11220,560896,782344,565351,570890,931781,511665,108738,357367,853555,674526,388790,686349,554731,102668,335287,461231,496065,489980,525209,693696,140598,784402,564477,743153,156379,370768,94810,121932,338323,972441,553422,865236,627884,673412,16147,858309,802780,150410,657225,761430,916149,644587,364929,661236,207648,507409,209803,663553,296241,51843,758342,448408,310536,733500,390516,580506,313748,729366,961156,766804,752158,713426,946971,433800,611365,806559,950149,831368,871881,132092,644626,150762,487527,365094,316637,684249,740162,605893,272845,416251,905202,984909,602362,424697,686193,566240,159584,600277,767037,211677,441897,586509,965864,393340,497044,881539,145921,159055,866123,603476,657682,284714,85306,470415,534245,641462,472616,159434,421500,843442,634366,625668,444943,657933,129173,914540,215272,598415,457087,437568,490742,172811,212016,435680,599042,789308,279873,689943,369130,618428,524390,877649,118759,60586,37618,20797,492854,946585,583767,944693,62988,358292,708659,23496,966718,557539,131703,358231,215464,771609,375770,855917,147866,543477,786910,760512,468183,542081,373398,979543,126508,361409,842847,872593,746682,893518,457222,978730,161753,697245,205997,363180,807952,795175,808090,462585,658667,186220,858457,923762,700792,294201,584816,514737,261038,327627,205592,221896,444108,979369,129394,44001,790354,353917,72772,330118,360651,635275,849492,966042,843108,158554,406317,995111,147752,121006,486157,678653,217657,4288,573547,820817,164534,921608,308037,373838,385901,343399,813472,58859,346176,68090,539503,322652,958331,832724,585003,75794,228299,31211,302603,601041,362034,300803,347024,650585,172193,876895,603734,165956,796982,786231,738823,562729,158032,364908,988395,775023,671485,424571,572157,623273,772919,914302,661979,920229,614760,934156,511607,889533,382154,82654,973121,549095,639792,412821,305216,74071,571794,969979,932469,335153,898442,938912,729489,872970,874332,8390,345366,901364,245104,315592,895028,533836,427909,737421,161915,510434,768573,179267,237370,562023,650593,869876,544314,464374,701215,789191,746271,871247,385836,788092,890101,286938,367130,635751,295576,607054,913206,556383,512305,253121,461980,951444,192012,897432,140517,842228,924286,268918,765459,344159,347853,592899,247814,379693,421908,295638,672994,774285,78096,886320,998456,10915,581642,549650,905526,186991,586693,320053,829130,465779,191060,238711,415584,273709,35854,55818,305798,667280,334370,121051,665390,230729,51662,904228,971349,7088,567705,265941,380847,760602,280222,351148,518112,609328,381795,46766,301829,886537,338310,130937,813816,446885,126867,578861,996302,56516,316900,648733,457604,903338,974707,336231,878687,776626,583241,353383,591761,438716,892530,231901,959454,915103,50735,453313,519651,940657,68380,38339,339705,19207,844122,483005,582959,592635,870233,208322,862826,598864,989646,583679,219396,371194,111781,493739,313465,383867,545219,171577,761747,992356,973874,497603,976481,136374,138311,918066,787696,929197,589326,801358,944697,28038,211029,752621,210197,491050,939207,254024,145811,767376,922553,796100,15858,899164,950319,728378,563113,532136,705190,290216,359946,214594,327241,641000,385347,786200,700340,576438,227606,498337,451637,425192,286305,472053,335562,587556,683468,290205,997253,868480,320419,392391,128015,674737,410783,136490,46713,154232,574917,904387,99900,490640,268209,994867,135705,390652,412028,404195,490553,184029,624391,836288,619242,570500,367786,908994,934572,226481,281181,469810,376226,354931,55711,43299,487568,853741,556475,842100,133451,371270,820314,735709,859169,992745,981261,506744,573542,544798,335063,71332,345306,551165,522500,148531,323820,525891,571989,109699,540927,391815,383139,528328,941384,577084,148432,537377,589708,613443,589827,688798,501198,304829,719726,181892,891384,237429,447803,49953,555945,69576,765896,194628,866362,533750,798399,369884,258270,964160,796047,420697,486470,781692,825420,689886,392317,278581,151823,184594,295461,723312,604322,248126,43623,91154,600821,55136,709242,990838,263827,564093,735641,174057,932157,750399,807534,338221,830644,171022,156968,351523,814982,403402,975555,955973,400091,523040,382185,577810,257717,544345,243199,509472,450948,839442,387377,553239,145202,822954,478559,487143,514465,587609,575770,547307,386320,410846,81519,599793,874316,730403,913822,800625,96868,913119,843783,699,767204,432828,496436,348230,767865,455134,266270,324004,863226,758456,66451,431182,641607,514915,522399,164590,335706,829719,724524,981933,812770,192582,880771,71867,704720,691726,761694,868674,964177,287148,124076,155241,535262,856554,108951,453851,597675,592745,32413,774791,750298,66826,876820,567338,699491,336474,60148,776819,430070,546456,564666,776689,886534,68830,749993,157504,933346,39836,417088,481438,30183,515310,764031,876787,321614,765291,466180,941767,877507,658149,60699,413225,849839,376668,689777,491763,712459,5768,608757,161358,554199,132368,464770,89566,309794,430979,979239,62376,354441,582188,947427,569030,430121,826059,562654,461350,901008,191328,484599,615686,859104,366550,140695,229053,282037,289028,296120,883539,980557,365526,143257,658629,730361,683520,101817,442395,50455,199765,137552,653983,47041,102020,308470,523274,447051,345263,967056,525031,506873,170405,995568,977216,83193,279492,376521,946443,847471,845107,321145,866307,523882,135730,824806,927733,605908,580895,177233,443804,914175,905847,661407,483093,518439,789231,66585,447439,14824,861841,89137,913636,194682,166773,212398,259259,160638,435374,941416,140851,311224,54813,155003,595354,742575,668942,77310,96783,217826,211522,116834,391751,922905,730508,225636,265187,995541,329461,244649,951125,322487,140958,608238,511144,410963,335698,228967,487748,382037,261094,363854,557078,539851,519352,364988,444038,284404,730251,828294,608545,188095,466810,46659,673970,142329,93794,167913,30119,116528,592075,810599,14144,445947,51745,236481,878706,838520,310352,112640,612690,663852,546444,818881,868195,573845,390221,254379] bricks = 33671263 ladders = 108
Let's say an "ascent" is a height that is either the first in our list or greater than the previous height, and that the magnitude of an ascent is the delta. Use a min_heap to represent ascents via ladder. Keep track of bricks_left and ladders_left, initialized to your inputs. We will maintain the following as we parse the heights array. The ladders will be used for the steepest ascents we've seen up to the number possible, and the bricks will be used for all other ascents. I.e., as long as ladders_left > 0, we add new ascents to the min_heap and subtract one from ladders_left. If ladder_left = 0, we compare the ascent to the top of our min heap. If the smaller of the two is <= bricks_left we can continue, otherwise we're done. Assuming we can continue: if the smaller of the two is the new ascent, subtract it from bricks_left and continue. If the smaller of the two is the top of the min_heap, remove it, add the new ascent to the min_heap, and subtract the former top of the min_heap from bricks_left. -- edit -- The above algorithm is O(log(ladders) * (ascents - ladders)). If we start with not very many ladders and don't like the complexity of a min_heap for some reason, we can sove this in O(ladders * (ascents - ladders)) by replacing the min_heap with an array, and finding the min by scanning the array when we need to.
Approach by using all ladders first and replace the ladders with the smallest delta first to save bricks. /** * #param {number[]} heights * #param {number} bricks * #param {number} ladders * #return {number} */ var furthestBuilding = function (heights, bricks = 0, ladders = 0) { function insert(array, value) { // part for searching the index, taken from // https://stackoverflow.com/a/21822316/1447675 var low = 0, high = array.length; while (low < high) { const mid = (low + high) >>> 1; if (array[mid] < value) low = mid + 1; else high = mid; } array.splice(low, 0, value); } const ladderSizes = []; for (let i = 0, l = heights.length - 1; i < l; i++) { const delta = heights[i + 1] - heights[i]; if (delta <= 0) continue; if (ladders) { insert(ladderSizes, delta); ladders--; continue; } const small = ladderSizes[0]; if (small <= delta && bricks >= small) { bricks -= ladderSizes.shift(); insert(ladderSizes, delta); continue; } if (bricks >= delta) { bricks -= delta; continue; } return i; } return heights.length - 1; }; console.log(furthestBuilding([4, 2, 7, 6, 9, 14, 12], 5, 1)); console.log(furthestBuilding([1, 5, 1, 2, 3, 4, 10000], 4, 1));
Animating a fractal tree inside a Javascript Canvas
After I saw a video from the Coding Train on youtube about fractal trees, I tried to build one myself. Which worked great and I played with some variables to get different results. I would love to see the tree moving like it got hit by some wind. I tried different approaches like rotating the branches a little bit or some minor physics implementations but that failed miserably. So my question is: What would be the best approach to render a fractal tree and give it some sort of "life" like little shakes from wind. Is there some sort of good reference ? Do I need physics ? -> If so where do I have to look ? If not -> How could I fake such an effect? I am glad about every help I can get. Source for the idea: https://www.youtube.com/watch?v=0jjeOYMjmDU
Tree in the wind. The following are some short points re bending a branch in the wind. As the whole solution is complex you will have to get what you can from the code. The code includes a seeded random number functions. A random recursive tree renderer, a poor quality random wind generator, all drawn on canvas using an animation loop. Wind To apply wind you need to add a bending force to each branch that is proportional to the angle of the branch to the wind. So if you have a branch in direction dir and a wind in the direct wDir the amount of scaling the bending force needs is var x = Math.cos(dir); // get normalize vector for the branch var y = Math.sin(dir); var wx = Math.cos(wDir); // get normalize vector for the wind var wy = Math.sin(wDir); var forceScale = x * wy - y * wx; The length of the branch also effects the amount of force to include that you lengthen the vector of the branch to be proportional to its length var x = Math.cos(dir) * length; // get normalize vector for the branch var y = Math.sin(dir) * length; var wx = Math.cos(wDir); // get normalize vector for the wind var wy = Math.sin(wDir); var forceScale = x * wy - y * wx; Using this method ensures that the branches do not bend into the wind. There is also the thickness of the branch, this is a polynomial relationship related to the cross sectional area. This is unknown so is scaled to the max thickness of the tree (an approximation that assumes the tree base can not bend, but the end branches can bend a lot.) Then the elastic force of the bent branch will have a force that moves the branch back to its normal position. This acts like a spring and is very much the same as the wind force. As the computational and memory load would start to overwhelm the CPU we can cheat and use the wind to also recoil with a little bit of springiness. And the tree. The tree needs to be random, yet being fractal you don't want to store each branch. So you will also need a seeded random generator that can be reset at the start of each rendering pass. The tree is rendered randomly with each iteration but because the random numbers start at the same seed each time you get the same tree. The example Draws random tree and wind in gusts. Wind is random so tree may not move right away. Click tree image to reseed the random seed value for the tree. I did not watch the video, but these things are quite standard so the recursive function should not be to far removed from what you may have. I did see the youTube cover image and it looked like the tree had no randomness. To remove randomness set the leng, ang, width min, max to be the same. eg angMin = angMax = 0.4; will remove random branch angles. The wind strength will max out to cyclone strength (hurricane for those in the US) to see the max effect. There are a zillion magic numbers the most important are as constants with comments. const ctx = canvas.getContext("2d"); // click function to reseed random tree canvas.addEventListener("click",()=> { treeSeed = Math.random() * 10000 | 0; treeGrow = 0.1; // regrow tree }); /* Seeded random functions randSeed(int) int is a seed value randSI() random integer 0 or 1 randSI(max) random integer from 0 <= random < max randSI(min, max) random integer from min <= random < max randS() like Math.random randS(max) random float 0 <= random < max randS(min, max) random float min <= random < max */ const seededRandom = (() => { var seed = 1; return { max : 2576436549074795, reseed (s) { seed = s }, random () { return seed = ((8765432352450986 * seed) + 8507698654323524) % this.max }} })(); const randSeed = (seed) => seededRandom.reseed(seed|0); const randSI = (min = 2, max = min + (min = 0)) => (seededRandom.random() % (max - min)) + min; const randS = (min = 1, max = min + (min = 0)) => (seededRandom.random() / seededRandom.max) * (max - min) + min; /* TREE CONSTANTS all angles in radians and lengths/widths are in pixels */ const angMin = 0.01; // branching angle min and max const angMax= 0.6; const lengMin = 0.8; // length reduction per branch min and max const lengMax = 0.9; const widthMin = 0.6; // width reduction per branch min max const widthMax = 0.8; const trunkMin = 6; // trunk base width ,min and max const trunkMax = 10; const maxBranches = 200; // max number of branches const windX = -1; // wind direction vector const windY = 0; const bendability = 8; // greater than 1. The bigger this number the more the thin branches will bend first // the canvas height you are scaling up or down to a different sized canvas const windStrength = 0.01 * bendability * ((200 ** 2) / (canvas.height ** 2)); // wind strength // The wind is used to simulate branch spring back the following // two number control that. Note that the sum on the two following should // be below 1 or the function will oscillate out of control const windBendRectSpeed = 0.01; // how fast the tree reacts to the wing const windBranchSpring = 0.98; // the amount and speed of the branch spring back const gustProbability = 1/100; // how often there is a gust of wind // Values trying to have a gusty wind effect var windCycle = 0; var windCycleGust = 0; var windCycleGustTime = 0; var currentWind = 0; var windFollow = 0; var windActual = 0; // The seed value for the tree var treeSeed = Math.random() * 10000 | 0; // Vars to build tree with var branchCount = 0; var maxTrunk = 0; var treeGrow = 0.01; // this value should not be zero // Starts a new tree function drawTree(seed) { branchCount = 0; treeGrow += 0.02; randSeed(seed); maxTrunk = randSI(trunkMin, trunkMax); drawBranch(canvas.width / 2, canvas.height, -Math.PI / 2, canvas.height / 5, maxTrunk); } // Recusive tree function drawBranch(x, y, dir, leng, width) { branchCount ++; const treeGrowVal = (treeGrow > 1 ? 1 : treeGrow < 0.1 ? 0.1 : treeGrow) ** 2 ; // get wind bending force and turn branch direction const xx = Math.cos(dir) * leng * treeGrowVal; const yy = Math.sin(dir) * leng * treeGrowVal; const windSideWayForce = windX * yy - windY * xx; // change direction by addition based on the wind and scale to // (windStrength * windActual) the wind force // ((1 - width / maxTrunk) ** bendability) the amount of bending due to branch thickness // windSideWayForce the force depending on the branch angle to the wind dir += (windStrength * windActual) * ((1 - width / maxTrunk) ** bendability) * windSideWayForce; // draw the branch ctx.lineWidth = width; ctx.beginPath(); ctx.lineTo(x, y); x += Math.cos(dir) * leng * treeGrowVal; y += Math.sin(dir) * leng * treeGrowVal; ctx.lineTo(x, y); ctx.stroke(); // if not to thing, not to short and not to many if (branchCount < maxBranches && leng > 5 && width > 1) { // to stop recusive bias (due to branch count limit) // random select direction of first recusive bend const rDir = randSI() ? -1 : 1; treeGrow -= 0.2; drawBranch( x,y, dir + randS(angMin, angMax) * rDir, leng * randS(lengMin, lengMax), width * randS(widthMin, widthMax) ); // bend next branch the other way drawBranch( x,y, dir + randS(angMin, angMax) * -rDir, leng * randS(lengMin, lengMax), width * randS(widthMin, widthMax) ); treeGrow += 0.2; } } // Dont ask this is a quick try at wind gusts // Wind needs a spacial component this sim does not include that. function updateWind() { if (Math.random() < gustProbability) { windCycleGustTime = (Math.random() * 10 + 1) | 0; } if (windCycleGustTime > 0) { windCycleGustTime --; windCycleGust += windCycleGustTime/20 } else { windCycleGust *= 0.99; } windCycle += windCycleGust; currentWind = (Math.sin(windCycle/40) * 0.6 + 0.4) ** 2; currentWind = currentWind < 0 ? 0 : currentWind; windFollow += (currentWind - windActual) * windBendRectSpeed; windFollow *= windBranchSpring ; windActual += windFollow; } requestAnimationFrame(update); function update() { ctx.clearRect(0,0,canvas.width,canvas.height); updateWind(); drawTree(treeSeed); requestAnimationFrame(update); } body { font-family : arial; } <canvas id="canvas" width="250" heigth="200"></canvas> Click tree to reseed. Update I just noticed that the wind and branch length are absolute thus drawing the tree on a larger canvas will create a bending force too great and the branches will bend past the wind vector. To scale the sim up either do it via a global scale transform, or reduce the windStrength constant to some smaller value. You will have to play with the value as its a 2nd order polynomial relation. My guess is multiply it with (200 ** 2) / (canvas.height ** 2) where the 200 is the size of the example canvas and the canvas.height is the new canvas size. I have added the calculations to the example, but its not perfect so when you scale you will have to change the value windStrength (the first number) down or up if the bending is too far or not enough.
How to draw a tiled wall between two points on a grid on canvas?
I'm creating a simulator with the Pixijs engine. I have a function that is is to be used to draw a wall using the mouse. But I just can't seem to get it right. This is probably more of a math issue than programming. Anyway, it should work like this: User clicks on a square tile (start position is set) Tink library for Pixi returns the (x,y) position just clicked on relative to the canvas User clicks on second square (in same row or column) and the destination point is set Please take a look at this Fiddle. https://jsfiddle.net/ensf32e0/18/ I can get it to draw from left to right and from top to bottom. But right to left and bottom to top fail me. I'm using an object with booleans to keep track of whether the user is putting down a start position or an end position. I'm not sure this isa good implementation. let wallsObj={ start:{ x:0, y:0, done:false }, end:{ x:1, y:1, done:false } }; drawTile draws a single tile and drawWallLine is the function with the problem. It takes the start and end positions and draws a tiled line between them: function drawWallLine (obj,size) { // Determine whether line is to be drawn horizontally or vertically // if abs(x2-x1) is larger than abs(y2-y1) then horizontal else vertical // assign len the the actual length of line let len = Math.abs(obj.end.x - obj.start.x) > Math.abs(obj.end.y - obj.start.y) ? obj.end.x - obj.start.x : obj.end.y - obj.start.y; console.log('drawWallLine', len); // same as above. If direction is horizontal, mx = 1 and my = 0 and vice versa // this to be used to determine the polarity of size let mx = Math.abs(obj.end.x - obj.start.x) > Math.abs(obj.end.y - obj.start.y) ? 1 : 0; let my = Math.abs(obj.end.x - obj.start.x) < Math.abs(obj.end.y - obj.start.y) ? 1 : 0; console.log("mx, my", mx, my); // Get polarity of size. +size is going down or right while -size is going up or left if (mx === 1) { size = obj.end.x - obj.start.x >= 0 ? size : size * -1; } if (my === 1) { size = obj.end.y- obj.start.y >= 0 ? size : size * -1; } console.log('size', size); // If going down or right then if (size >=0 ) { for (let i = 0; i < Math.abs(len); i+=size) { drawTile({ len: rs, x: obj.start.x - obj.start.x%rs - .5 + i * mx, y: obj.start.y - obj.start.y%rs - .5 + i * my, line:{ width:1, color:0xC2C2C2, alpha:1 }, fill:{ color:0xFFFFFF, alpha:1 } }); } } else { // if going up or left for (let i = Math.abs(len); i > 0; i+=size) { drawTile({ len: rs, x: obj.start.x - obj.start.x%rs - .5 + i * mx, y: obj.start.y - obj.start.y%rs - .5 + i * my, line:{ width:1, color:0xC2C2C2, alpha:1 }, fill:{ color:0xFFFFFF, alpha:1 } }); } } } This is my first time doing something like this so please bear with me. I feel like there's an obvious solution but i'm failing to see it.
Well, a simple fix to your problem is just to make sure that the start x/y is always the lower then the end x/y value. So I added the following code to the beginning of the drawWallLine function: function drawWallLine (obj, size) { if(obj.start.x > obj.end.x){ var temp = obj.start.x; obj.start.x = obj.end.x; obj.end.x = temp; } if(obj.start.y > obj.end.y){ var temp = obj.start.y; obj.start.y = obj.end.y; obj.end.y = temp; } This basically makes sure that the start value is always the lower value by swapping between start and end if start is bigger than end. Here is the updated working fiddle: https://jsfiddle.net/ensf32e0/24/
jquery segment displays wrong number all the time?
I'm trying to create a wheel of fortune type animation using jquery but for some reason the code that i am using always displays the wrong number! here is the jsfiddle: http://jsfiddle.net/wf49mqaa/2/ click on the WHITE AREA in the wheel to see the animation and you will see a wrong number will be shown! at the moment I only have 4 columns and 4 segments in my jquery code but in the future i am will pull the amount of segments from a database and I need this to work correctly at all times and display the correct number. I tried everything from changing the segment = Math.ceil(((percent/100) * 4)), to segment = Math.ceil(((percent/100) * 4) -1), and also segment = Math.ceil(((percent/100) * 5)), and it still display wrong number! could someone please advise on this? Thanks
Part of the Code you use I found in a Non-working demo from sitepoint., digging a bit deeper there are two different errors/ problems to solve the fortune-wheel behavior: First: How to define the degree: // existing code fragment (wrong) var deg = 1500 + Math.round(Math.random() * 1500); This would cause the wheel to stop at a totally random position, but that is not what you need. The wheel should always stop at the marker position, it should just turn around by a random number of segments. // supposing you have a wheel with 4 segments (here the items array): var deg = 0, /* basic degree */ spinbase = 1080, /* basic spinning of the wheel, here 3 times full turn */ items = [1,2,3,4]; // your spinning function... spin: function () { var min = 1, max = 10, rand = Math.floor(min + Math.random()*(max+1-min)); [...] // like this you'll stop at the same position, // but the wheel moved by a random number of segments deg = deg + ( Math.round( 360 / items.length ) * rand) + spinbase; [...] } Second: How to get the correct segment: In short: // where deg is the current degree, and items the array from above. var segmentIndex = Math.ceil( (deg - (360 * parseInt(deg / 360))) / Math.round(360/items.length) ); And when filling the algorithm.. // e.g. deg is (degree of each segment) * random (here 5) + 1080 // deg = 1530 (1080 + ( (360/4) * 5) ) // (1530 - (360 * parseInt( 1530 / 360))) / Math.round(360 / 4); // (1530 - (360 * 4)) / 90; // 90 / 90 = 1 // since we have 4 segments only and the random number is higher, // the wheel did another full turn + 1 (from the starting number) // so we get items[ 1 ] = (result: 2); // due to the ceil/floor/round methods in calculation it can happen // that you reach the extrem values segments.length or less than 0, // to fix this: var segmentIndex = Math.ceil( (deg - (360 * parseInt(deg / 360))) / Math.round(360/items.length) ); if(target < 0 ) { target = segment.length - 1; } if(target === segments.length ) { target = 0; } alert( 'Winning: ' + items[target] ); Putting this together you'll get a working fortune-wheel. I allowed myself to create a new variant of the fortune wheel, which is able to handle different amounts of segments to make it easier to prove the algorithm.
How to bind a timer to a progress ring with JS?
I'm playing around with a progress ring, and I can't seem to get it to run on a timer. I am trying to make the progress ring propagate automatically and take, say, 0.5 seconds to go from 0% to whatever percent I set (65% in this case). I used this progress ring as a base: http://llinares.github.io/ring-progress-bar/ This is my fiddle: http://jsfiddle.net/gTtGW/ I tried using a timer function, but I may not have been integrating that properly. In the fiddle, I have added: for (var i = 0; i< 65; i++){ range += i; setTimeout(timer,800); } However, this breaks the progress ring. I thought that any time the range is updated (with the += i), the draw function would be called. What am I doing wrong? Thank you so much in advance.
If you're not planning to use the input[type=range] element, you can change your code to this: (function (window) { 'use strict'; var document = window.document, ring = document.getElementsByTagName('path')[0], range = 0, text = document.getElementsByTagName('text')[0], Math = window.Math, toRadians = Math.PI / 180, r = 100; function draw() { // Update the wheel giving to it a value in degrees, getted from the percentage of the input value a.k.a. (value * 360) / 100 var degrees = range * 3.5999, // Convert the degrees value to radians rad = degrees * toRadians, // Determine X and cut to 2 decimals x = (Math.sin(rad) * r).toFixed(2), // Determine Y and cut to 2 decimals y = -(Math.cos(rad) * r).toFixed(2), // The another half ring. Same as (deg > 180) ? 1 : 0 lenghty = window.Number(degrees > 180), // Moveto + Arcto descriptions = ['M', 0, 0, 'v', -r, 'A', r, r, 1, lenghty, 1, x, y, 'z']; // Apply changes to the path ring.setAttribute('d', descriptions.join(' ')); // Update the numeric display text.textContent = range; range++; if(range > 100) { clearInterval(timer); } } // Translate the center axis to a half of total size ring.setAttribute('transform', 'translate(' + r + ', ' + r + ')'); var timer = setInterval(draw,100); }(this)); Basically changing range to a simple variable starting at 0, and increasing its value every time draw() is called. Creating an interval (named timer) to run every 0.1 seconds in this case (of course it's up to you), and clearing that interval from draw() when appropriate... JSFiddle Demo
I think you want something like: function inc() { var val = parseInt(range.value, 10) range.value = val + 1; draw(); // updating the value doesn't cause `onchange`. if (val < 100) { // don't go over 100 setTimeout(inc, 100); } } inc();