I want to rotate the compass image according to the degrees I receive. The input degrees are between 0 and 359 so when I rotate -1 degree from 0 , the image rotates one complete round and sets on 359:
function setCompass(degrees){
$("#compass").stop().transition({rotate: -1*degrees +'deg'});
}
I tried to solve the problem by going back to -1 instead of 359 so I changed the code to the following:
function setCompass(degrees){
if (degrees>180){degrees=degrees-360}
$("#compass").stop().transition({rotate: -1*degrees +'deg'});
}
It solved the lag on 0 and 360 but the problem was shifted to 180. Now when I rotate the device from 180 to 181, it rotates a complete negative round to go back to -179 ! Please suggest me how to modify the calculations so I get smooth changes on every degree?
You could use some modulo formula to find out whether to turn clockwise or anti-clockwise. Persist the current angle with jQuery's data method (so you could have more than one such compass if you wanted to), and allow the angle that you pass as CSS value to be outside the 0-359 range.
Here is how it could work:
function setCompass(degrees){
var curr = $("#compass").data("rotation") || 0;
var next = curr + ((degrees - curr)%360 + 180*3) % 360 - 180;
$("#compass").data("rotation", next).stop().transition({rotate: -next + 'deg'});
}
// Demo with randomly generated angles between 0 and 359
setInterval(function() {
setCompass(Math.floor(Math.random()*360));
}, 1000);
<img id="compass" src="https://i.stack.imgur.com/zdHVn.png" width="100px" height="100px">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.transit/0.9.12/jquery.transit.min.js"></script>
Related
I have a ball-game. width of board is 600px. 3 ball at that time coming down and on click it disappearing. but i want to have a one time 3 balls should be coming from different places. top 0 but left amount should be different. i write css
#keyframes ball-move {
0% {
top: 0;
left: 0;
}
For generate random width i make var.
var boardWidth = Math.floor(Math.random() * 600 + 1);
but i am not understanding how can i over right css in JS. i want to have top:0 to enter ball in frame but i want to enter from different width.
i tried with entering in css over ride but.JS is not reading my css.
I have to use only HTML, CSS,j javascript only.
Give each ball a class of ball and select them with javascript to loop through and set custom CSS
document.querySelectAll('.ball').forEach(ball => {
ball.style.left = Math.floor(Math.random() * 600);
}
If you want the ball to fall down from differenct place every time, you may use "on animationiteration". The below will set a new left value to the ball everytime the animation is itreataed.
The line
// Get all ball class element and loop through each
$(".ball").each(function(){
// Set random initial left value for tha ball
let boardWidth = Math.floor(Math.random() * 600);
$(this).css("left", boardWidth + "px");
// Set random left everytime the animation is iterated
$(this).on("animationiteration", function() {
let boardWidth = Math.floor(Math.random() * 600);
$(this).css("left", boardWidth + "px");
})
}
For the function you are using for boardWidth, you may want to consider taking the ball width into account as well, currently your ball may not be shown on the UI when left: 600px.
I have a project in which I have a long SVG path. The SVG path is centered on the page and has a stroke "none" so that it is invisible. Then I have an image of a rocket. The idea is that this rocket should follow the path on scroll. Meaning for each pixel scrolled, it moves one pixel into the direction of the line.
This so far works great. I got the idea for my code from this stackoverflow question.
My problem now is the specific path I created for this. The path has sections in which the path turns sideways or even up (for a looping). The rocket should still follow in these sections, which it does as you can see on the live example here. But when moving through the looping the rocket leaves the view, because it is still moving at the same speed like the scrolling, but just away from the users scroll direction.
Now I would like to speed up the rocket when it is moving upwards through the looping so it doesn't leave out of view. Let's look at my code.
The Project is made in sveltekit, but that is not important right now because for my problem only the JS should be relevant. So for that matter here is the HTML:
<div style="position:absolute; top:0; right:0; left:0; z-index:1000; pointer-events: none;" id="route">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 966 4692" id="svgRoute">
<path id="path" d="M652 0V239.5V317.5C538.333 325.5 312.9 402.4 320.5 646C328.1 889.6 474.667 970.5 547 980.5C573.667 983 632 988.7 652 991.5C677 995 806 993 798 1118.5C791.6 1218.9 628 1275.67 547 1291.5C372.5 1294.67 30.1999 1323.2 56.9999 1412C90.4999 1523 171.5 1565.5 293.5 1607C415.5 1648.5 707 1657 786.5 1931C850.1 2150.2 436.667 2111 222 2064C64.5001 2047.5 -163.9 2094.8 182.5 2416C528.9 2737.2 800.5 2670.5 893 2597C984.5 2452 1061.5 2189 637.5 2297C213.5 2405 390.167 2773.67 531.5 2944.5C665.833 3062 924 3334.1 882 3482.5C829.5 3668 442 3885.5 420 3990C398 4094.5 764.5 4537 774 4691" stroke-width="5" stroke="red" fill="none"/>
<image id="c" x="-20" y="-70" width="40" height="70" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF4AAACqCAYAAAAk0fhhAAAFP0lEQVR4nO2dzWtcZRSH36tjGKdNOkOSFpqk+RAtqVGEtGahWLQQF0JMKBhQqKjVnVu7dK3gqiC4qGDAhQtpCC4kEOgsKooWQWuDYD9i81EH25RGrUlTx3/gnIvvzXWeKfk9y9+de8+dh7M4vPcrqdfrodlIkiTPk0qskP7f96HVtzESDyHxEBIPIfEQEg+RkGOVNzaOjR/LrcbM9JRb3tvQCCfqeAiJh5B4CImHkHiIQiOKxE4vn53+JLfakxN2PjM95Y4uSZL87wtr6ngIiYeQeAiJh5B4iFzXavKaXqpnvndrPLKv1cx79naa+WZxl5lPTrzq1ohd38niUB0PIfEQEg8h8RASDyHxENHjZNpdXnmNjW++9pZb/4Xxl8z8nbft1TBvzCwUS26NFyeOm3meY6Y6HkLiISQeQuIhJB4i10t/vV3tZp5levFY/u2Gmb9/8rSZe9NO/0CvW8P7H3mijoeQeAiJh5B4CImHaMgNTR4rK9fMfOixx6OP5U07zYo6HkLiISQeQuIhJB4CnWo8zv/4g7tt38PxE08zoo6HkHgIiYeQeAiJh5B4iIaMk+X2DjP/4suZ6GN598ffvLZs5qWW5uyt5jyrbYDEQ0g8hMRDSDxEQ6aa7p4uM+/YvcfMdxY23WO1ljbMvFqzb7su3vnHzO3KjUMdDyHxEBIPIfEQEg+BXvq7urBg5qWif1qd5fvN/OLyX2Y+tKsl/sQagDoeQuIhJB5C4iEkHiLXqWZ17U6ehzO5e/ummb/7rH1laj0pmvmvi7+7NRrxP9TxEBIPIfEQEg8h8RASD+GOk1m+t7ejtbK1s9kCV2prZj7QZ5/TqQ/tdx+EEMJPv9Riy5uuvNehh6COx5B4CImHkHgIiYeIXiTr6Xva3bZnb/+WTua/0NkR9/akv9ftG6CycGTUfq/m3Kz7PkoXdTyExENIPITEQ0g8RMFbkxl+cszcoVa7t96ElCdjky9H/X5u1v+snToeQuIhJB5C4iEkHiJ6raa1Yj9Ith3o7rK/N5IFdTyExENIPITEQ0g8hMRDoE/9tZXtm42KD6Ts05ayMScOHhox86WV67nVUMdDSDyExENIPITEQ7hTTblcNvNHB/zXiJ+tnonKb7Vwt3W3baxG7/PUc8/nVl8dDyHxEBIPIfEQEg8RvVazdMn/cEr17Ndm3ldfMvPjz9hvf2wZtCeqEEJ4sP8hM799+aKZb8zb7z746Cv/XQa3KvvNfMfUSXefWNTxEBIPIfEQEg8h8RDuI9/BeUw8C68fHDTzU684O4ymPMR2YMDOL1yy89nLZvzGp36Jj7+b9zdGcGT0mB6pbzYkHkLiISQeQuIhJB7CXSRLG4U80p5yi2F1wf6gSgghVA7E7ZPnxcX2nkOmkycG7XE5DXU8hMRDSDyExENIPEShXrcHkZRXJqKsXbAv5TWC61e/NfM5J09DHQ8h8RASDyHxEBIP4a7VeNNOGt4kdONP+zNxIdyNrrG54N+IFIN/TvFkcaWOh5B4CImHkHgIiYdAH6n/5vPdZj5y1P7AbgghrO7vNfPKz/Y+Xo0Q8ns8PgvqeAiJh5B4CImHkHgIiYdIsizwuAfzLxeaRQ53D5s/fq9vp1tj5Kj9OThvbDxx5Q8zry6ec2uMDw6Zf2R6/rz5ey2S3UNIPITEQ0g8hMRDNGSRzJ8SzpnjwIlgTzshhBA+KDkb4qaXw93DKXdsrfubckIdDyHxEBIPIfEQEg+R61qNW8RZw/HWaqqL9rSThfTpxcabhPJ0pY6HkHgIiYeQeAiJh5B4iH8BrZ8Mhx0ulsYAAAAASUVORK5CYII="/>
</svg>
</div>
The div is id "route" and will be called as such multiple times throughout the JS. The <path> here is the line stretching through the whole page. The <image> is the rocket which I placed directly inside the SVG. The only relevant css is inside the style tag for the div.
Now for the JavaScript/jQuery
jQuery(document).ready(function(){
jQuery(document).scroll(function() {
positionCar();
});
// init the line car position
positionCar();
function positionCar() {
var scrollY = jQuery('#route').scrollTop() || window.pageYOffset;
var maxScrollY = jQuery('#route').prop('scrollHeight');
var path = document.getElementById("path");
// Calculate distance along the path the car should be for the current scroll amount
var pathLen = path.getTotalLength();
var dist = pathLen * scrollY / maxScrollY;
var pos = path.getPointAtLength(dist);
// Calculate position a little ahead of the car (or behind if we are at the end), so we can calculate car angle
var angle = calculateAngle(path, pathLen, dist, pos)
if (angle < 0) {
var pathLen = path.getTotalLength();
var dist = pathLen * scrollY / maxScrollY;
var pos = path.getPointAtLength(dist);
var angle = calculateAngle(path, pathLen, dist, pos)
}
// Position the car at "pos" totated by "angle" (if angle is upwards position further for more speed)
var car = document.getElementById("c");
car.setAttribute("transform", "translate(" + (pos.x) + "," + (pos.y) + ") rotate(" + (rad2deg(angle) + 90) + ")");
}
function calculateAngle(path, pathLen, dist, pos) {
if (dist + 1 <= pathLen) {
var posAhead = path.getPointAtLength(dist + 1);
return Math.atan2(posAhead.y - pos.y, posAhead.x - pos.x);
} else {
var posBehind = path.getPointAtLength(dist - 1);
return Math.atan2(pos.y - posBehind.y, pos.x - posBehind.x);
}
}
function rad2deg(rad) {
return 180 * rad / Math.PI;
}
});
So jQuery checks if document ready and binds a scroll handler which then calls the positionCar() function everytime a scroll happens to place the rocket accordingly. The function basically calculates the position off the car on the path line by scroll position and path length. Then it uses the calculateAngle function to check for the required angle ahead of the path.
The angle is used so the rocket follows the path an turns in the direction of the path. Then the rocket (here called car) is positioned at that position in that specific angle.
The if condition inside the positionCar() function for now does nothing different. It checks if the angle is below zero indicating the path going upwards (for example the looping). My idea now is to implement more speed inside this condition because it tells when the rocket is moving back up instead of down.
How would I accomplish this. I tried playing with the calculations but it just resulted in jumping around. By changing the dist variable I managed to get the rocket faster during upwards movement. This just resulted in the rocket jumping back as soon as the path moves back down. How would I need t implement faster rocket speed only during the upwards movement?
For playing around with it I created a REPL with the full code here: https://svelte.dev/repl/d2e449585ac14ec8aef1fd310fb14548?version=3.46.4
I am trying to make an app where user slides the slider to select a compass direction, but we all know that sliders usually starts at 0 (left) and ends at N (right).
I am trying to replicate this:
Bottomline, I want the slider to start at 270(West) and the center should be 360 and 0(0 degree North) and next should be 0-90(North to East) then 90-180(East to South) and then 180-269(South to West)
Sorry for bad english, not native speaker. If my explanation is not understandable, please refer to the image.
If you start the slider on 270 degrees, then the center would be 90 degrees, because your compass is not centered on the slider range.
You can use negative values to determine the applicable direction with some math:
$('#slider-degrees').change(() => {
let selection = parseInt($('#slider-degrees').val());
let degrees = (selection < 0) ? (360 + selection) : selection;
$('#label-degrees').html(degrees);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="slider-degrees" type="range" min="-90" max="269" value="-90">
<span id="label-degrees"></span>
I am trying to figure out how to use propeller.js to restrict the rotation angle of an image. As of right now, if I spin my image twice, my output would read 720. I would like to make it so the element’s output will reset to 0 when spun over 360. In addition, I would like it to not output negative angles if I spin counterclockwise. For example going from 10 to 280.
Here is a codepen of where I am currently at: http://codepen.io/anon/pen/YyZaXK
$('img').propeller({inertia: 1, speed: 10,onRotate: function(){ console.log(this.angle); }});
Any suggestions?
Thanks!
Figured it out!
Using a Modulo made this work the way I wanted!
Here’s what I added:
(degrees + 360) % 360
Which resulted in:
$('img').propeller({inertia: 1, speed: 10,onRotate: function(){ console.log((this.angle + 360) % 360); }});
Looked in the Propeller.js source, found another solution. You can set zero angle if 360 is reached:
onRotate: function(){
if(this.angle===360)
{
this.virtualAngle = 0;
}
console.log(this.angle);
}
You could also make use of the normalizeAngle() method of Propeller itself:
onRotate: function () {
console.log(this.normalizeAngle(this.angle));
}
That also avoids negative angles.
I'm using the jQuery transit plugin to rotate a block element with 4 navigation controls; each time a nav item is clicked, the rotated block should rotate to the custom data attribute of that nav item (either 0, 90, 180 or 270 degrees).
I can successfully do this (see my jsfiddle: http://jsfiddle.net/xkdgdhbk/, only tested in chrome), but I would like to restrict the rotation to ALWAYS go clockwise. As you can see, if you click 180deg it will go clockwise, but then if you click 90deg, it will go anti-clockwise. I would like the element to rotate clockwise at all times, if possible.
Is there a way to achieve this?
Here's my script from the jsfiddle:
$("span").click(function(){
$(".rotate").transition({ rotate: $(this).attr("data-rotate") + "deg"});
});
You can store the previous rotate value in the $(.rotate) element and use it for each rotation something like this
$().ready(function()
{
$("span").click(function()
{
var lastRotate = $(".rotate").attr("data-rotate");
if(lastRotate ==undefined)
{
lastRotate = 0;
}
lastRotate = parseInt(lastRotate);
var newRotate = lastRotate + parseInt($(this).attr("data-rotate"));
$(".rotate").transition({ rotate:newRotate + "deg"}).attr("data-rotate",newRotate);
});
});